您的位置:首页 > 移动开发 > Android开发

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

2017-10-25 20:44 1966 查看
前文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()
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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息