代码地址以下:
http://www.demodashi.com/demo/13271.htmlhtml
最接近WeChat的全屏自定义相机(Custom Camera),拍照和预览都是全屏尺寸。使用Camera API,告别摄像头PictureSize的限制。android
接触过相机开发的都知道,Camera.Parameters支持的PreviewSIze和PictureSize是不匹配的。这就致使预览和拍照的图像尺寸不一致。通常状况下PreviewSize支持的尺寸包括手机屏幕尺寸,而PictureSize包含的尺寸就古怪的多了。数组
这就找到了实现全屏拍照的突破口post
监听预览,拿到相机预览图像数据,转成bitmapthis
<uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" />
sdk 25 (android6.0) 以上记得动态获取权限3d
Camera camera = Camera.open(cameraId);// cameraId 为0,是开启后置摄像头;1 是前置摄像头。多摄的状况不在此考虑范围内。 //将预览图像渲染到surfaceView上 mHolder = surfaceView.getHolder(); mHolder.addCallback(this); mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); camera.setPreviewDisplay(mHolder);
在相机API中能够经过setDisplayOrientation()设置相机预览方向。在默认状况下,这个值为0,与图像传感器一致。所以对于横屏应用来讲,因为屏幕方向和预览方向一致,预览图像不会颠倒90度。可是对于竖屏应用,屏幕方向和预览方向垂直,因此会出现颠倒90度现象。为了获得正确的预览画面,必须经过API将相机的预览方向旋转90,保持与屏幕方向一致code
camera.setDisplayOrientation(90); //横向变竖向
这是个人小米6相机支持的预览尺寸orm
preview-size-values parameter: 2160x1080,2048x1536,2048x1080,1920x1440,1920x1080,1920x960,1440x1080,1280x960,1280x720,1280x640,864x480,800x480,768x432,720x480,640x640,640x480,480x640,640x360,576x432,480x360,480x320
咱们须要根据屏幕尺寸找到最适合的预览尺寸htm
private static Point findBestPreviewSizeValue(CharSequence previewSizeValueString, Point screenResolution) { int bestX = 0; int bestY = 0; int diff = Integer.MAX_VALUE; for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) { previewSize = previewSize.trim(); int dimPosition = previewSize.indexOf('x'); if (dimPosition < 0) { Log.w(TAG, "Bad preview-size: " + previewSize); continue; } int newX; int newY; try { newX = Integer.parseInt(previewSize.substring(0, dimPosition)); newY = Integer.parseInt(previewSize.substring(dimPosition + 1)); } catch (NumberFormatException nfe) { Log.w(TAG, "Bad preview-size: " + previewSize); continue; } int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y); if (newDiff == 0) { bestX = newX; bestY = newY; break; } else if (newDiff < diff) { bestX = newX; bestY = newY; diff = newDiff; } } if (bestX > 0 && bestY > 0) { return new Point(bestX, bestY); } return null; }
返回获得一个point,起名叫cameraResolution。 设置给parametersblog
Camera.Parameters parameters = camera.getParameters(); parameters.setPreviewSize(cameraResolution.x, cameraResolution.y); parameters.setPreviewFormat(ImageFormat.NV21);
最后
拍照 不是调用camera.takePicture()
而是设置监听PreviewCallback接口camera.setOneShotPreviewCallback(previewCallback);
在回调方法onPreviewFrame(byte[] data, Camera camera)里处理预览图像字节数组data。data是YUV格式的数据,咱们须要把它转成Android支持的rgb格式
YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21, width, height, null);//android.graphics包下提供的将YUV转成JPEG的API ByteArrayOutputStream baos = new ByteArrayOutputStream(); yuvImage.compressToJpeg(new Rect(0, 0, width, height), 100, baos);//YUV压缩成JPEG BitmapFactory.Options localOptions = new BitmapFactory.Options(); localOptions.inPreferredConfig = Bitmap.Config.RGB_565; //构造位图生成的参数,必须为565。类名+enum Bitmap bitmap = BitmapFactory.decodeByteArray(baos.toByteArray(), 0, baos.toByteArray().length, localOptions);//转成rgb的bitmap baos.close();
这时的bitmap仍是横向的,即便相机转成竖向,那也是预览变正常了。但onPreviewFrame里拿到的数据依然是横向
//转成竖向bitmap Matrix matrix = new Matrix(); matrix.postRotate(270); // 建立新的图片 Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
思路流程仍是很清晰的
customcamera是自定义相机的库,方便移植到任何project中使用
暂时没有
最接近WeChat的全屏自定义相机(Custom Camera)
注:本文著做权归做者,由demo大师代发,拒绝转载,转载须要做者受权