最接近WeChat的全屏自定義相機(Custom Camera)

代碼地址以下:
http://www.demodashi.com/demo/13271.htmlhtml

1、需求

最接近WeChat的全屏自定義相機(Custom Camera),拍照和預覽都是全屏尺寸。使用Camera API,告別攝像頭PictureSize的限制。android

接觸過相機開發的都知道,Camera.Parameters支持的PreviewSIze和PictureSize是不匹配的。這就致使預覽和拍照的圖像尺寸不一致。通常狀況下PreviewSize支持的尺寸包括手機屏幕尺寸,而PictureSize包含的尺寸就古怪的多了。數組

這就找到了實現全屏拍照的突破口post

監聽預覽,拿到相機預覽圖像數據,轉成bitmapthis

2、程序實現

  • 清單文件添加權限
<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

  • 在onResume()裏初始化相機
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);
  • 關鍵來了,設置Camera.Parameters 這裏很容易出現各類問題

在相機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);

思路流程仍是很清晰的

3、項目文件結構

CustomCamera項目文件截圖
customcamera是自定義相機的庫,方便移植到任何project中使用

4、運行效果演示

customcamera演示1

拍完照顯示照片

5、補充

暫時沒有
最接近WeChat的全屏自定義相機(Custom Camera)

代碼地址以下:
http://www.demodashi.com/demo/13271.html

注:本文著做權歸做者,由demo大師代發,拒絕轉載,轉載須要做者受權

相關文章
相關標籤/搜索