Android Camera2.0 结合ImageReader拍照并解决图片偏转问题
2017-10-25 20:44
1966 查看
前文Android Camera2.0 API实现摄像头预览并获取人脸关键坐标已经介绍了Camera2.0的基础内容,在2.0的API中,要想实现拍照功能,则要借助于ImageReader。
首先在自定义的TextureView.SurfaceTextureListener的实现类中,维护ImageReader的引用
然后在setUpCamera方法中对ImageReader进行初始化
然后将ImageReader的Surface添加进CaptureRequest.Builder中
在startPreview()方法中添加
接下来创建一个类实现ImageReader.OnImageAvailableListener接口,在其中获取每一帧的Image对象,并生成一个Bitmap,并对该Bitmap进行镜像和旋转操作,因为摄像头获取的原始图像和预览中见到的图像是并不一样
上面做的是用ImageReader获取每一帧实时图像,要想实现拍照,调用CameraCaptureSession的capture方法即可
在成员变量中设置ROTATION
首先在自定义的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() baa7 { 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); }
相关文章推荐
- 解决Scaleform中使用AS2.0的UILoader不加载图片的问题
- 解决android有的手机拍照后上传图片被旋转的问题
- 完美解决部分安卓手机调用系统拍照上传时图片旋转问题
- 三星手机拍照,图片旋转问题的解决
- Retrofit2.0与RxJava2.0结合出现的问题解决
- 完美解决拍照裁剪图片完成之后崩溃问题
- 解决android有的手机拍照后上传图片被旋转的问题
- android 拍照遇到图片旋转,照片、相机未找到的问题解决
- 解决android有的手机拍照后上传图片被旋转的问题
- 解决通过Intent调用系统拍照程序,返回图片太小的问题[android]
- Android圆形头像拍照后“无法加载此图片”的问题解决方法(适配Android7.0)
- 解决android有的手机拍照后上传图片被旋转的问题
- android拍照后图片路径的获取(解决不同手机存在拍照后旋转的问题)
- 解决通过Intent调用系统拍照程序,返回图片太小的问题
- Android 自定义拍照,解决图片旋转,拍照参数设置兼容问题
- iOS解决拍照图片 会旋转 打开变形的问题
- 【转】 解决通过Intent调用系统拍照程序,返回图片太小的问题[android]
- Android 通过Intent调用系统拍照程序出现图片太小的问题解决办法
- 解决android有的手机拍照后上传图片被旋转的问题
- android学习笔记----解决android有的手机拍照后上传图片被旋转的问题