小米开发平台应用调用Camera预览效果适配说明

由于不同手机屏幕尺寸比例不尽相同,或许应用在调用Camera预览实现方法不标准或第三方SDK维护不及时,提供的预览窗口宽高比例和Camera输出图像的宽高比例不一致

小米开发平台应用调用Camera预览效果适配说明

1.应用中拍摄或扫一扫功能预览页面出现拉伸现象

由于不同手机屏幕尺寸比例不尽相同,或许应用在调用Camera预览实现方法不标准或第三方SDK维护不及时,提供的预览窗口宽高比例和Camera输出图像的宽高比例不一致,以至于应用在使用拍摄或扫一扫功能时预览页面就可能出现拉伸现象。

在此建议应用开发者使用的预览窗口宽高比例和Camera输出图像的宽高比例尽量保持一致,这样预览显示的画面即可以正常显示。为了解决应用频繁适配工作,希望开发者参考标准的Camera预览使用示例实现功能。

2.Camera预览接口使用示例

2.1.获取Camera支持的预览图像输出分辨率

//Camera API1
Camera mCamera = Camera.open(cameraId);
List<Size> supportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes()
 
//Camera API2
Size[] supportedPreviewSizes = CameraManager.getCameraCharacteristics(cameraId).get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(klass)

2.2.根据预览窗口Surface的宽高来选取最佳Camera图像输出尺寸

  • Camera API1:
//获取预览窗口的宽高
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // We purposely disregard child measurements because act as a
    // wrapper to a SurfaceView that centers the camera preview instead
    // of stretching it.
    final int width = resolveSize(getSuggestedMinimumWidth(),
            widthMeasureSpec);
    final int height = resolveSize(getSuggestedMinimumHeight(),
            heightMeasureSpec);
    setMeasuredDimension(width, height);
 
    if (mSupportedPreviewSizes != null) {
        mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width,
                height);
    }
 
    if (mCamera != null) {
      Camera.Parameters parameters = mCamera.getParameters();
      parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
 
      mCamera.setParameters(parameters);
    }
}
//得到最佳Camera图像输出尺寸
public Camera.Size getOptimalSize(@NonNull List<Camera.Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio = (double) w / h;
    Camera.Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;
 
    int targetHeight = h;
 
    for (Camera.Size size : sizes) {
      double ratio = (double) size.width / size.height;
      if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
      if (Math.abs(size.height - targetHeight) < minDiff) {
        optimalSize = size;
        minDiff = Math.abs(size.height - targetHeight);
      }
    }
 
    if (optimalSize == null) {
      minDiff = Double.MAX_VALUE;
      for (Camera.Size size : sizes) {
        if (Math.abs(size.height - targetHeight) < minDiff) {
          optimalSize = size;
          minDiff = Math.abs(size.height - targetHeight);
        }
      }
    }
 
    return optimalSize;
  }

详细实现见:https://cs.android.com/android/platform/superproject/+/master:development/samples/HoneycombGallery/src/com/example/android/hcgallery/CameraFragment.java

  • Camera API2:
//获取预览窗口的宽高
private final TextureView.SurfaceTextureListener mSurfaceTextureListener
        = new TextureView.SurfaceTextureListener() {
 
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
        openCamera(width, height);
    }
 
    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
        configureTransform(width, height);
    }
 
    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
        return true;
    }
 
    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture texture) {
    }
 
};
//得到最佳Camera图像输出尺寸
private static Size chooseOptimalSize(Size[] choices, int textureViewWidth,
        int textureViewHeight, int maxWidth, int maxHeight, Size aspectRatio) {
 
    // Collect the supported resolutions that are at least as big as the preview Surface
    List<Size> bigEnough = new ArrayList<>();
    // Collect the supported resolutions that are smaller than the preview Surface
    List<Size> notBigEnough = new ArrayList<>();
    int w = aspectRatio.getWidth();
    int h = aspectRatio.getHeight();
    for (Size option : choices) {
        if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight &&
                option.getHeight() == option.getWidth() * h / w) {
            if (option.getWidth() >= textureViewWidth &&
                option.getHeight() >= textureViewHeight) {
                bigEnough.add(option);
            } else {
                notBigEnough.add(option);
            }
        }
    }
 
    // Pick the smallest of those big enough. If there is no one big enough, pick the
    // largest of those not big enough.
    if (bigEnough.size() > 0) {
        return Collections.min(bigEnough, new CompareSizesByArea());
    } else if (notBigEnough.size() > 0) {
        return Collections.max(notBigEnough, new CompareSizesByArea());
    } else {
        Log.e(TAG, "Couldn't find any suitable preview size");
        return choices[0];
    }
}

详细实现见:https://cs.android.com/android/platform/superproject/+/master:development/samples/browseable/Camera2Basic/src/com.example.android.camera2basic/Camera2BasicFragment.java

2.3.将获取到的最佳图像输出尺寸设置到Camera

//Camera API1
mCameraParameters.setPreviewSize(size.getWidth(), size.getHeight())
 
//Camera API2
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight())

编辑:yimen,如若转载,请注明出处:https://www.yimenapp.com/kb-yimen/12683/

部分内容来自网络投稿,如有侵权联系立删

(0)
上一篇 2022年11月24日 下午3:11
下一篇 2022年11月24日 下午3:13

相关推荐