CameraAPI中的 自定义照相功能

CameraAPI中的 自定义照相功能,第1张

概述前几天的项目需要使用CameraAPI自己定义照相机,之前用过的二维码也要自己写底层代码,于是总结一下使用CameraAPI的几点事项。现在由于JDK7.0及其以上版本的官方文档已经不再推荐使用cam

前几天的项目需要使用CameraAPI自己定义照相机,之前用过的二维码也要自己写底层代码,于是总结一下使用CameraAPI的几点事项。现在由于JDK7.0及其以上版本的官方文档已经不再推荐使用camera包而是camera2包,但这次还是先讲camera的使用,至于camera2等以后再讲。

首先是添加照相机权限,在清单文件中必须添加摄像头硬件权限和使用功能,其中功能可以根据项目需求选择性放入。

 1     <uses-permission androID:name="androID.permission.CAMERA"/> 2     <!--使用摄像头硬件功能--> 3     uses-feature ="androID.harDWare.camera" 4     自动对焦功能 5     ="androID.harDWare.camera.autofocus" 6     闪光灯功能 7     ="androID.harDWare.camera.flash" 8     前置摄像头 9     ="androID.harDWare.camera.front"/>

关于权限和对应的功能可以参考文章 http://www.cnblogs.com/BobGo/articles/5646751.HTML;

我在项目中需要两个功能,一是在显示摄像头的SurfaceVIEw上添加一层ImageVIEw,可以在ImageVIEw上绘制不同的遮罩层;还有一个功能是摄像头拍摄照片之后显示及保存图片。

第一是摄像头简单的使用,在这里可能会遇到在SurfaceVIEw中摄像头的预览出现变形问题,下面会提到解决措施:

1         SurfaceHolder surfaceHolder = surfaceVIEw.getHolder();2         surfaceHolder.addCallback(this);3         surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

在当前类中实现SurfaceHolder.Callback 接口,重写三个方法 surfaceCreated(),surfaceChanged(),surfaceDestroy(),这三个方法就是SurfaceVIEw对应的生命周期;

surfaceCreated()中执行Camera.open()返回一个Camera对象,打开摄像头硬件,在surfaceDestroy()中,Camera对象调用release()释放摄像头;在surfaceChanged()中,设置摄像头参数,其中getBestSize()是确定手机摄像头硬件可以使用的最合适大小,这个算法是官方提供的。我在之前不采用这个算法而直接设置大小,导致在测试机运行时SurfaceVIEw显示的图片出现变形。

 1 @OverrIDepublic voID surfaceCreated(SurfaceHolder holder) { 3         camera = Camera.open(); 4     } 5  6     @OverrIDevoID surfaceChanged(SurfaceHolder holder,int format,1)">int wIDth,1)">int height) { 8         //已经获得Surface的wIDth和height,设置Camera的参数 9         Camera.Parameters parameters = camera.getParameters();10         Camera.Size size=getBestSize(parameters.getSupportedPrevIEwSizes());11         int w=size.wIDth;12         int h=size.height;13         parameters.setPrevIEwSize(w,h);14         parameters.setPictureSize(w,1)">15         List<Camera.Size> vSizeList = parameters.getSupportedPictureSizes();16         for (int num = 0; num < vSizeList.size(); num++) {17             Camera.Size vSize = vSizeList.get(num);18         }19         if (t?his.getResources().getConfiguration().orIEntation != Configuration.ORIENTATION_LANDSCAPE) {20             强制竖屏模式21             parameters.set("orIEntation","portrait"22             在2.2以上可以使用,预览显示旋转9023         parameters.setRotation(90);24             camera.setdisplayOrIEntation(9025         } else {26             parameters.set("orIEntation","landscape");27             在2.2以上可以使用28             camera.setdisplayOrIEntation(90);29         }30         camera.setParameters(parameters);31         try {32             设置显示33             camera.setPrevIEwdisplay(holder);34         } catch (IOException exception) {35             camera.release();36             camera = null;37 38         开始预览39         camera.startPrevIEw();40         设置自动对焦41         camera.autoFocus(new Camera.autoFocusCallback() {42             @OverrIDe43             voID onautoFocus(boolean success,Camera camera) {44                 if (success) {45                      success为true表示对焦成功,改变对焦状态图像46                 }47             }48         });49 50 51     private Camera.Size getBestSize(List<Camera.Size> supportedPrevIEwSizes) {52         Camera.Size largestSize=supportedPrevIEwSizes.get(053         int largestArea= supportedPrevIEwSizes.get(0).height*supportedPrevIEwSizes.get(0).wIDth;54         for (Camera.Size s:supportedPrevIEwSizes){55             int area=s.wIDth*s.height;56             if(area>largestArea){57                 largestArea=area;58                 largestSize=s;59 60 61         return largestSize;62 63 64 65 66      surfaceDestroyed(SurfaceHolder holder) {67          释放手机摄像头68         camera.release();69     }

 也可以在surfaceChanged()中设置闪光灯等功能:

1 parameters.setFlashMode(isChecked?Camera.Parameters.FLASH_MODE_ON:Camera.Parameters.FLASH_MODE_OFF);

最后在需要摄像的点击监听中调用takePicture(Camera.ShutterCallback,Camera.PictureCallback,Camera.PictureCallback)函数来完成拍照,这个函数中可以四个回调接口,ShutterCallback是快门按下的回调,在这里我们可以设置播放“咔嚓”声之类的 *** 作,后面有三个PictureCallback接口,分别对应三份图像数据:原始图像、缩放和压缩图像和JPG图像,图像数据可以在PictureCallback接口的voID onPictureTaken(byte[] data,Camera camera)中获得,三份数据相应的三个回调正好按照参数顺序调用,通常我们只关心JPG图像数据,此时前面两个PictureCallback接口参数可以直接传null

每次调用takePicture() 获取图像后,摄像头会停止预览,假如需要继续拍照,则我们需要在上面的PictureCallbackonPictureTaken() 函数末尾,Camera对象再次调用startPrevIEw() 函数;在不需要拍照的时候,Camera对象需要主动调用stopPrevIEw() 停止预览功能;

第二个功能是摄像图片的显示和保存,在这个功能中可能会出现两个问题,一个是拍摄图片横屏显示,另一个是将上边SurfaceVIEw上方的ImageVIEw遮罩层一同保存到用户手机,实现类似于图像合成的效果;

关于图片横屏显示的问题,是因为AndroID官方认为手机横屏才是摄像头的正确打开方式,所以保存的图片也是横屏保存的,所以如果想竖屏显示图片,就要把图片顺时针旋转90度,调整到竖屏显示模式,具体代码如下:

1 private voID setimageByte(ImageVIEw showImage,1)">byte[] data) {2         Bitmap bitmap= BitmapFactory.decodeByteArray(data,0,data.length);3         showImage.setimageBitmap(bitmap);4         Matrix matrix = showImage.getimageMatrix();5         matrix.setRotate(906         showImage.setimageBitmap(Bitmap.createBitmap(bitmap,bitmap.getWIDth(),bitmap.getHeight(),matrix,1)">true));7     }

还有一个问题是解决两个控件内容同时保存的问题,这个其实想到了方法就很简单了,自定义一个FrameLayout的子布局,在该布局中只加入一个方法

1     public Bitmap getBitmap(){2         设置缓存3         setDrawingCacheEnabled(4         buildDrawingCache();5         从缓存中获取当前屏幕的图片6          getDrawingCache();7     }

然后在上文用到的xml布局中将该布局作为要同时保存图像的父控件。

最后在java代码中需要保存合成图片的地方,只需要实例化刚刚自定义的FrameLayout对象调用getBitmap(),就能返回合成之后的Bitmap对象;

所以我们的功能就能完全实现了。

 

总结

以上是内存溢出为你收集整理的CameraAPI中的 自定义照相功能全部内容,希望文章能够帮你解决CameraAPI中的 自定义照相功能所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1119347.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-29
下一篇 2022-05-29

发表评论

登录后才能评论

评论列表(0条)

保存