代碼地址以下:
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大師代發,拒絕轉載,轉載須要做者受權