Android Camera2.0 结合ImageReader拍照并解决图片偏转问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SakuraMashiro/article/details/78346419

前文Android Camera2.0 API实现摄像头预览并获取人脸关键坐标已经介绍了Camera2.0的基础内容,在2.0的API中,要想实现拍照功能,则要借助于ImageReader。

首先在自定义的TextureView.SurfaceTextureListener的实现类中,维护ImageReader的引用

private ImageReader mImageReader ;

然后在setUpCamera方法中对ImageReader进行初始化

/**
     * 设置camera2.0的初始化参数
     */
    private void setUpCamera() {
        cameraManager = (CameraManager)mContext.getSystemService(Context.CAMERA_SERVICE);
        try{
            for (String id : cameraManager.getCameraIdList()) {

                //获取代表摄像头特征类characteristics
                characteristics = cameraManager.getCameraCharacteristics(id);

                //如果是前置摄像头
                if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) {
                    mCameraId = id ;

                    StreamConfigurationMap streamConfigurationMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

                    sizes = streamConfigurationMap.getOutputSizes(SurfaceHolder.class);

                    //设置预览大小
                    mPreviewSize = sizes[0];

                    //imageReader初始化
                    mImageReader = ImageReader.newInstance(mPreviewSize.getWidth(),
                            mPreviewSize.getHeight(),
                            ImageFormat.JPEG,
                            2 );
                    mImageReader.setOnImageAvailableListener(onImageAvailableListener , mBackgroundHandler);

                    //获取人脸检测参数
                    int[] FD =characteristics.get(CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES);
                    int maxFD=characteristics.get(CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT);

                    if (FD.length>0) {
                        List<Integer> fdList = new ArrayList<>();
                        for (int FaceD : FD
                                ) {
                            fdList.add(FaceD);
                            Log.e(TAG, "setUpCameraOutputs: FD type:" + Integer.toString(FaceD));
                        }
                        Log.e(TAG, "setUpCameraOutputs: FD count" + Integer.toString(maxFD));

                        if (maxFD > 0) {
                            mFaceDetectSupported = true;
                            mFaceDetectMode = Collections.max(fdList);
                        }
                    }
                }
            }
        } catch ( CameraAccessException e ){
            e.printStackTrace();
        }
    }

然后将ImageReader的Surface添加进CaptureRequest.Builder中
在startPreview()方法中添加

previewRequestBuilder.addTarget(mImageReader.getSurface());

接下来创建一个类实现ImageReader.OnImageAvailableListener接口,在其中获取每一帧的Image对象,并生成一个Bitmap,并对该Bitmap进行镜像和旋转操作,因为摄像头获取的原始图像和预览中见到的图像是并不一样

/**
*OnImageAvailableListener实现类
*/

   private final ImageReader.OnImageAvailableListener onImageAvailableListener = new ImageReader.OnImageAvailableListener() {
        @Override
        public void onImageAvailable(ImageReader reader) {

            Image image = reader.acquireNextImage() ;

            ByteBuffer byteBuffer = image.getPlanes()[0].getBuffer();
            byte[] bytes = new byte[byteBuffer.remaining()];
            byteBuffer.get(bytes);

            try {
                Bitmap temp = BitmapFactory.decodeByteArray(bytes,0,bytes.length);
                Bitmap newBitmap = Bitmap.createBitmap(mPreviewSize.getWidth(),mPreviewSize.getWidth(),temp.getConfig());

                Canvas canvas = new Canvas(newBitmap);
                Paint paint = new Paint();
                Matrix matrix = new Matrix();
                //图片镜像并旋转90度
                matrix.setScale(-1, 1);
                matrix.postTranslate(temp.getWidth(), 0);
                matrix.postRotate(90 ,temp.getWidth()/2,temp.getHeight()/2);
                matrix.postTranslate(0,(temp.getWidth()-temp.getHeight())/2);

                canvas.drawBitmap(temp, matrix , paint );

                File newFile = new File( Environment.getExternalStorageDirectory() , "345.jpg");
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile));
                newBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
                bos.flush();
                bos.close();
                temp.recycle();
                newBitmap.recycle();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                image.close();
                byteBuffer.clear();
            }

            image.close();



        }
    };

上面做的是用ImageReader获取每一帧实时图像,要想实现拍照,调用CameraCaptureSession的capture方法即可

public void captureStillImage(){
        try {

            CaptureRequest.Builder captureStillBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            captureStillBuilder.addTarget(mImageReader.getSurface());
            // 设置自动对焦模式
            captureStillBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                    CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            // 设置自动曝光模式
            captureStillBuilder.set(CaptureRequest.CONTROL_AE_MODE,
                    CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);

            int rotation = ((Activity)mContext).getWindowManager().getDefaultDisplay().getRotation();
            captureStillBuilder.set( CaptureRequest.JPEG_ORIENTATION ,
                    ORIENTATIONS.get(rotation));

            CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {
                @Override
                public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
                    super.onCaptureCompleted(session, request, result);

                    Toast.makeText(mContext,"Image Captured" , Toast.LENGTH_SHORT).show();
                }



            };

            captureSession.stopRepeating();
            captureSession.capture( captureStillBuilder.build() , captureCallback , null );
            captureSession.setRepeatingRequest(captureRequest, new CameraCaptureSession.CaptureCallback() {
                @Override
                public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) {
                    super.onCaptureStarted(session, request, timestamp, frameNumber);
                }
            },mBackgroundHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

在成员变量中设置ROTATION

//设置Surface旋转角
    private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
    static {
        ORIENTATIONS.append(Surface.ROTATION_0,90);
        ORIENTATIONS.append(Surface.ROTATION_90,0);
        ORIENTATIONS.append(Surface.ROTATION_180,270);
        ORIENTATIONS.append(Surface.ROTATION_270,180);
    }

猜你喜欢

转载自blog.csdn.net/SakuraMashiro/article/details/78346419