android 自定义摄像机,Android自定义Camera实现拍照功能

本文记录了用自定义Camera实现的简单拍照功能。

Camera类在5.0以后不推荐使用了,取而代之的是android.hardware.camera2包下的类,本文使用Camera。

我们首先自定义一个View去继承SurfaceView:

public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Camera.AutoFocusCallback {

private SurfaceHolder mHolder;

private Camera mCamera;

private static final int ORIENTATION = 90;

private int mScreenWidth;

private int mScreenHeight;

private boolean isOpen;

public CameraSurfaceView(Context context, AttributeSet attrs) {

super(context, attrs);

getScreenMatrix(context);

mHolder = getHolder();

mHolder.addCallback(this);

mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

}

private void getScreenMatrix(Context context) {

WindowManager WM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

DisplayMetrics outMetrics = new DisplayMetrics();

WM.getDefaultDisplay().getMetrics(outMetrics);

mScreenWidth = outMetrics.widthPixels;

mScreenHeight = outMetrics.heightPixels;

}

public void takePicture(Camera.ShutterCallback mShutterCallback, Camera.PictureCallback rawPictureCallback, Camera.PictureCallback jpegPictureCallback) {

if (mCamera != null)

mCamera.takePicture(mShutterCallback, rawPictureCallback, jpegPictureCallback);

}

public void startPreview() {

mCamera.startPreview();

}

@Override

public void surfaceCreated(SurfaceHolder holder) {

if (!checkCameraHardware(getContext()))

return;

if (mCamera == null) {

isOpen = safeCameraOpen(Camera.CameraInfo.CAMERA_FACING_BACK);

}

if (!isOpen) {

return;

}

mCamera.setDisplayOrientation(ORIENTATION);

try {

mCamera.setPreviewDisplay(holder);

} catch (IOException e) {

e.printStackTrace();

}

}

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

if (mCamera != null) {

setCameraParams(mScreenWidth, mScreenHeight);

mCamera.startPreview();

}

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

releaseCameraAndPreview();

}

private boolean safeCameraOpen(int id) {

boolean qOpened = false;

try {

releaseCameraAndPreview();

mCamera = Camera.open(id);

qOpened = (mCamera != null);

} catch (Exception e) {

e.printStackTrace();

}

return qOpened;

}

private void releaseCameraAndPreview() {

if (mCamera != null) {

mCamera.stopPreview();

mCamera.release();

mCamera = null;

}

}

private boolean checkCameraHardware(Context context) {

if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {

return true;

} else {

return false;

}

}

@Override

public void onAutoFocus(boolean success, Camera camera) {

}

private void setCameraParams(int width, int height) {

Camera.Parameters parameters = mCamera.getParameters();

// 获取摄像头支持的PictureSize列表

List pictureSizeList = parameters.getSupportedPictureSizes();

/**从列表中选取合适的分辨率*/

Camera.Size picSize = getProperSize(pictureSizeList, ((float) height / width));

if (null == picSize) {

picSize = parameters.getPictureSize();

}

// 根据选出的PictureSize重新设置SurfaceView大小

float w = picSize.width;

float h = picSize.height;

parameters.setPictureSize(picSize.width, picSize.height);

this.setLayoutParams(new RelativeLayout.LayoutParams((int) (height * (h / w)), height));

// 获取摄像头支持的PreviewSize列表

List previewSizeList = parameters.getSupportedPreviewSizes();

Camera.Size preSize = getProperSize(previewSizeList, ((float) height) / width);

if (null != preSize) {

parameters.setPreviewSize(preSize.width, preSize.height);

}

parameters.setJpegQuality(100); // 设置照片质量

if (parameters.getSupportedFocusModes().contains(android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {

parameters.setFocusMode(android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);// 连续对焦模式

}

mCamera.setDisplayOrientation(90);// 设置PreviewDisplay的方向,效果就是将捕获的画面旋转多少度显示

mCamera.setParameters(parameters);

}

/**

* 选取合适的分辨率

*/

private Camera.Size getProperSize(List pictureSizeList, float screenRatio) {

Camera.Size result = null;

for (Camera.Size size : pictureSizeList) {

float currentRatio = ((float) size.width) / size.height;

if (currentRatio - screenRatio == 0) {

result = size;

break;

}

}

if (null == result) {

for (Camera.Size size : pictureSizeList) {

float curRatio = ((float) size.width) / size.height;

if (curRatio == 4f / 3) {// 默认w:h = 4:3

result = size;

break;

}

}

}

return result;

}

}

代码没什么难度,在View创建的时候完成Camera的初始化,然后对Camera进行参数的设置(图片尺寸,质量之类的),最后别忘了在View销毁的时候对资源进行释放。

控件定义完了之后我们就要去使用它,在布局文件中添加就OK:

xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/activity_main"

android:layout_width="match_parent"

android:layout_height="match_parent"

>

android:id="@+id/sv_camera"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_weight="4"/>

android:id="@+id/img_take_photo"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentBottom="true"

android:layout_alignParentRight="true"

android:layout_gravity="bottom"

android:layout_marginBottom="10dp"

android:layout_marginRight="10dp"

android:src="@mipmap/icon_camera"/>

然后在Activity中去完成拍照功能:

public class CameraActivity extends AppCompatActivity {

private boolean isClick = true;

private static final String PATH_IMAGES = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "easy_check";

private CameraSurfaceView mCameraSurfaceView;

//拍照快门的回调

private Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback() {

@Override

public void onShutter() {

}

};

//拍照完成之后返回原始数据的回调

private Camera.PictureCallback rawPictureCallback = new Camera.PictureCallback() {

@Override

public void onPictureTaken(byte[] data, Camera camera) {

}

};

//拍照完成之后返回压缩数据的回调

private Camera.PictureCallback jpegPictureCallback = new Camera.PictureCallback() {

@Override

public void onPictureTaken(byte[] data, Camera camera) {

mCameraSurfaceView.startPreview();

saveFile(data);

Toast.makeText(CameraActivity.this, "拍照成功", Toast.LENGTH_SHORT).show();

isClick = true;

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

ImageView img_take_photo = (ImageView) findViewById(R.id.img_take_photo);

mCameraSurfaceView = (CameraSurfaceView) findViewById(R.id.sv_camera);

img_take_photo.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

takePhoto();

}

});

}

public void takePhoto() {

if (isClick) {

isClick = false;

mCameraSurfaceView.takePicture(mShutterCallback, rawPictureCallback, jpegPictureCallback);

}

}

//保存图片到硬盘

public void saveFile(byte[] data) {

String fileName = UUID.randomUUID().toString() + ".jpg";

FileOutputStream outputStream = null;

try {

File file = new File(PATH_IMAGES);

if (!file.exists()) {

file.mkdirs();

}

outputStream = new FileOutputStream(PATH_IMAGES + File.separator + fileName);

BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);

bufferedOutputStream.write(data, 0, data.length);

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

outputStream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

最后记得添加拍照跟磁盘操作权限:

到这一个非常简单的拍照Demo就完成了,只能当做Demo使用,离开发正式使用还有一段的距离,再次特地记录一下。

下载:源码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值