博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Camara 自定义预览效果
阅读量:5753 次
发布时间:2019-06-18

本文共 12359 字,大约阅读时间需要 41 分钟。

hot3.png

  通过List<Integer> list = Camera.Parameters.getSupportedPreviewFormats();这个方法来判断手机支持哪种类型的PixelFormat,一般情况下是 NV21 即值为17. BitmapFactory.decodeByteArray这个方法是不能直接解析NV21格式的byte[],返回的是null,所以需要对NV21格式的byte[]进行转换.

  最后:sdk 2.2提供了类YuvImage 通过方法compressToJpeg进行转换,但是sdk2.1没有现成的api进行此操作(或者是说我没找到,找到了给说一下),所以需要自己进行格式的转换.

\

 

        MainActivity

 package cn.itcast.picture;import java.io.File;import java.io.FileOutputStream;import java.util.List;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.PixelFormat;import android.graphics.Bitmap.CompressFormat;import android.hardware.Camera;import android.hardware.Camera.PictureCallback;import android.os.Bundle;import android.os.Environment;import android.util.Log;import android.view.Display;import android.view.KeyEvent;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.Window;import android.view.WindowManager;public class MainActivity extends Activity {    private static final String TAG = "MainActivity";    private SurfaceView surfaceView;    private Camera camera;    Bitmap mBitmap;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        Window window = getWindow();        requestWindowFeature(Window.FEATURE_NO_TITLE);// 没有标题        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,                        WindowManager.LayoutParams.FLAG_FULLSCREEN);// 设置全屏        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);// 高亮        setContentView(R.layout.main);        surfaceView = (SurfaceView) findViewById(R.id.surfaceView);        surfaceView.getHolder().setFixedSize(176, 144); // 设置分辨率        /* 下面设置Surface不维护自己的缓冲区,而是等待屏幕的渲染引擎将内容推送到用户面前 */        // surfaceView.getHolder()        // .setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);        surfaceView.getHolder().addCallback(new SurfaceCallback());    }    private final class SurfaceCallback implements SurfaceHolder.Callback {        private boolean preview;        public void surfaceChanged(SurfaceHolder holder, int format, int width,                                   int height) {        }        public void surfaceCreated(SurfaceHolder holder) {            // 打开摄像头            camera = Camera.open();            WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);            Display display = wm.getDefaultDisplay();            Camera.Parameters parameters = camera.getParameters();            parameters.setPreviewSize(display.getWidth(), display.getHeight());// 设置预览照片的大小            parameters.setPreviewFrameRate(3);// 每秒3帧            parameters.setPictureFormat(PixelFormat.JPEG);// 设置照片的输出格式            parameters.set("jpeg-quality", 85);// 照片质量            // parameters.setPreviewFormat(PixelFormat.JPEG);//必须底层驱动支持,设置才有效。            // parameters.setPictureSize(display.getWidth(),            // display.getHeight());// 设置照片的大小            camera.setParameters(parameters);            // try {            // camera.setPreviewDisplay(surfaceView.getHolder());//            // 通过SurfaceView显示取景画面            camera.setPreviewCallback(new PreviewCallBack());            camera.startPreview();            preview = true;            // } catch (IOException e) {            // Log.e(TAG, e.toString());            // }        }        public void surfaceDestroyed(SurfaceHolder holder) {            if (camera != null) {                if (preview) {                    camera.stopPreview();                }                camera.release();            }        }    }    @Override    public boolean onKeyDown(int keyCode, KeyEvent event) {        if (camera != null && event.getRepeatCount() == 0) {            switch (keyCode) {            case KeyEvent.KEYCODE_SEARCH:// 搜索键                // 自动对焦                camera.autoFocus(null);                return true;            case KeyEvent.KEYCODE_CAMERA:// 拍照键            case KeyEvent.KEYCODE_DPAD_CENTER:// 确定键                camera.takePicture(null, null, new TakePictureCallback());                return true;            }        }        return super.onKeyDown(keyCode, event);    }    private final class TakePictureCallback implements PictureCallback {        public void onPictureTaken(byte[] data, Camera camera) {            try {                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,                                                              data.length);                File file = new File(Environment.getExternalStorageDirectory(),                        System.currentTimeMillis() + ".jpg");                FileOutputStream outStream = new FileOutputStream(file);                bitmap.compress(CompressFormat.JPEG, 100, outStream);                outStream.close();                camera.stopPreview();                camera.startPreview();            } catch (Exception e) {                Log.e(TAG, e.toString());            }        }    }    private final class PreviewCallBack implements Camera.PreviewCallback {        /*         * (non-Javadoc)         *         * @see android.hardware.Camera.PreviewCallback#onPreviewFrame(byte[],         * android.hardware.Camera)         */        public void onPreviewFrame(byte[] data, Camera camera) {            Camera.Parameters parameters = camera.getParameters();            int format = parameters.getPreviewFormat();            List
list = parameters.getSupportedPreviewFormats();            for (Integer i : list) {                // 查看camara驱动支持的format.                // Log.e(TAG, "suport format:" + i);            }            // Log.e(TAG, "format:" + format);            if (mBitmap != null) {                mBitmap.recycle();                mBitmap = null;            }            // YUV formats require more conversion            if (format == PixelFormat.YCbCr_420_SP                || format == PixelFormat.YCbCr_422_I) {                int w = parameters.getPreviewSize().width;                int h = parameters.getPreviewSize().height;                // Get the YuV image 由于此方法适用于android 2.2版本,所以此处不能用。                // YuvImage yuv_image = new YuvImage(data, format, w, h, null);                // // Convert YuV to Jpeg                // Rect rect = new Rect(0, 0, w, h);                // ByteArrayOutputStream output_stream = new                // ByteArrayOutputStream();                // yuv_image.compressToJpeg(rect, 100, output_stream);                // // Convert from Jpeg to Bitmap                // bitmap2 = BitmapFactory.decodeByteArray(output_stream                // .toByteArray(), 0, output_stream.size());                int[] i = new int[data.length];                decodeYUV420SP(i, data, w, h);                mBitmap = Bitmap.createBitmap(i, w, h, Bitmap.Config.RGB_565);                // mBitmap = renderCroppedGreyscaleBitmap(data, w, h);            }            // Jpeg and RGB565 are supported by BitmapFactory.decodeByteArray            else if (format == PixelFormat.JPEG                     || format == PixelFormat.RGB_565) {                mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);            }            Bitmap bitmap = BitmapFactory.decodeResource(MainActivity.this                    .getResources(), R.drawable.test);            // Log.e(TAG, "mBitmap:" + mBitmap + "format:" + format);            Canvas canvas = surfaceView.getHolder().lockCanvas();            // 判断非null,才能drawBitmap.            if (mBitmap != null) {                canvas.drawBitmap(mBitmap, 0, 0, null);            }            canvas.drawBitmap(bitmap, 0, 0, null);            surfaceView.getHolder().unlockCanvasAndPost(canvas);        }    }    static public void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width,                                      int height) {        final int frameSize = width * height;        for (int j = 0, yp = 0; j < height; j++) {            int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;            for (int i = 0; i < width; i++, yp++) {                int y = (0xff & ((int) yuv420sp[yp])) - 16;                if (y < 0)                    y = 0;                if ((i & 1) == 0) {                    v = (0xff & yuv420sp[uvp++]) - 128;                    u = (0xff & yuv420sp[uvp++]) - 128;                }                int y1192 = 1192 * y;                int r = (y1192 + 1634 * v);                int g = (y1192 - 833 * v - 400 * u);                int b = (y1192 + 2066 * u);                if (r < 0)                    r = 0;                else if (r > 262143)                    r = 262143;                if (g < 0)                    g = 0;                else if (g > 262143)                    g = 262143;                if (b < 0)                    b = 0;                else if (b > 262143)                    b = 262143;                rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000)                          | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);            }        }    }    /**     * 此方法来源于网络,效果太差。     *     * @param yuvData     * @param width     * @param height     * @return     */    public Bitmap renderCroppedGreyscaleBitmap(byte[] yuvData, int width,                                               int height) {        int[] pixels = new int[width * height];        byte[] yuv = yuvData;        int inputOffset = 0 * 320 + 40;        for (int y = 0; y < height; y++) {            int outputOffset = y * width;            for (int x = 0; x < width; x++) {                int grey = yuv[inputOffset + x] & 0xff;                pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101);            }            inputOffset += 320;        }        Bitmap bitmap = Bitmap.createBitmap(width, height,                                            Bitmap.Config.ARGB_8888);        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);        return bitmap;    }    /**     * 此方法来源于网络,经验证不好用。     *     * @param rgbBuf     * @param yuv420sp     * @param width     * @param height     */    static public void decodeYUV420SP(byte[] rgbBuf, byte[] yuv420sp,                                      int width, int height) {        final int frameSize = width * height;        if (rgbBuf == null)            throw new NullPointerException("buffer 'rgbBuf' is null");        if (rgbBuf.length < frameSize * 3)            throw new IllegalArgumentException("buffer 'rgbBuf' size "                                               + rgbBuf.length + " < minimum "                                               + frameSize * 3);        if (yuv420sp == null)            throw new NullPointerException("buffer 'yuv420sp' is null");        if (yuv420sp.length < frameSize * 3 / 2)            throw new IllegalArgumentException("buffer 'yuv420sp' size "                                               + yuv420sp.length                                               + " < minimum " + frameSize * 3                                               / 2);        int i = 0, y = 0;        int uvp = 0, u = 0, v = 0;        int y1192 = 0, r = 0, g = 0, b = 0;        for (int j = 0, yp = 0; j < height; j++) {            uvp = frameSize + (j >> 1) * width;            u = 0;            v = 0;            for (i = 0; i < width; i++, yp++) {                y = (0xff & ((int) yuv420sp[yp])) - 16;                if (y < 0)                    y = 0;                if ((i & 1) == 0) {                    v = (0xff & yuv420sp[uvp++]) - 128;                    u = (0xff & yuv420sp[uvp++]) - 128;                }                y1192 = 1192 * y;                r = (y1192 + 1634 * v);                g = (y1192 - 833 * v - 400 * u);                b = (y1192 + 2066 * u);                if (r < 0)                    r = 0;                else if (r > 262143)                    r = 262143;                if (g < 0)                    g = 0;                else if (g > 262143)                    g = 262143;                if (b < 0)                    b = 0;                else if (b > 262143)                    b = 262143;                rgbBuf[yp * 3] = (byte) (r >> 10);                rgbBuf[yp * 3 + 1] = (byte) (g >> 10);                rgbBuf[yp * 3 + 2] = (byte) (b >> 10);            }        }    }}
 

转载:http://www.adobex.com/android/source/details/00000391.htm

转载于:https://my.oschina.net/androidcode/blog/104717

你可能感兴趣的文章
Confluence 6 注册外部小工具
查看>>
excel进行矩阵计算
查看>>
基于Android平台的动态生成控件和动态改变控件位置的方法
查看>>
linux 死机分析
查看>>
BOM
查看>>
LeetCode:Nim Game - 尼姆博弈
查看>>
Alpha冲刺&总结报告(12/12)(麻瓜制造者)
查看>>
iOS: Block的循环引用
查看>>
mysql实战02 | 日志系统:一条SQL更新语句是如何执行的?
查看>>
Xamarin.Android 引导页
查看>>
LINUX系统、磁盘与进程的相关命令
查看>>
测试九 赛后感受
查看>>
ECC椭圆曲线详解(有具体实例)
查看>>
关于WechatApp学习总结
查看>>
Linux常见命令(二)
查看>>
document.write()的用法和清空的原因
查看>>
【EXLUCAS模板】【拓展卢卡斯详解】【组合数高级篇】LuoGu P4720
查看>>
PyCharm切换解释器
查看>>
一些基本的灰度变换函数
查看>>
12.12日个人工作总结
查看>>