|
Android Camera2.0 结合ImageReader拍照并解决图片偏转问题 在Camera 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 .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) ;
} |
----------------------------
原文链接:https://blog.csdn.net/SakuraMashiro/article/details/78346419
程序猿的技术大观园:www.javathinker.net
[这个贴子最后由 flybird 在 2020-03-10 13:01:14 重新编辑]
|
|