1、獲取相機支持的預覽和保存照片的尺寸
- 獲取 mPreviewSizes 和 mPictureSizes 的代碼
/**
* 打開攝像頭
*/
private void openCamera() {
if (mCamera != null) {
releaseCamera();
}
mCamera = Camera.open(mCameraId);
mCameraParameters = mCamera.getParameters();
// Supported preview sizes
mPreviewSizes.clear();
for (Camera.Size size : mCameraParameters.getSupportedPreviewSizes()) {
mPreviewSizes.add(new Size(size.width, size.height));
}
// Supported picture sizes;
mPictureSizes.clear();
for (Camera.Size size : mCameraParameters.getSupportedPictureSizes()) {
mPictureSizes.add(new Size(size.width, size.height));
}
// AspectRatio
if (mAspectRatio == null) {
mAspectRatio = Constants.DEFAULT_ASPECT_RATIO;
}
adjustCameraParameters();
mCamera.setDisplayOrientation(calcDisplayOrientation(mDisplayOrientation));
mCallback.onCameraOpened();
if (null != mRecordVideoManager) {
mRecordVideoManager.onCameraOpened(mFacing);
}
}
- 某360手機支持的預覽尺寸和保存尺寸,分組依據是寬高比,比如4:3和16:9
- 再來看某華爲平板支持的預覽尺寸和保存尺寸,分組依據是寬高比,比如4:3和16:9
說的這裏就有個問題了,之前公司開發認爲有個bug是這款華爲平板拍照保存的照片尺寸太小,條件是分辨率≤1920 * 1080,但是他們限制了寬高比爲4:3所以取到的只有value[1]的4個分辨率,符合條件的最大分辨率爲640 * 480,導致照片不夠清晰以及一些其他問題,後來把寬高比限制爲4:3 or 16:9,就可以取到最符合的分辨率1920 * 1080了。
2、獲取滿足條件的預覽和保存照片的尺寸
我們獲取4:3 or 16:9的分辨率尺寸,我的最佳分辨率的算法是,在該設備下(屏幕固定),並限定寬高比的條件下,利用分辨率的面積(寬*高,可以理解爲像素的個數)和目標的分辨率面積,進行比對差值最小的即爲最佳分辨率。
//用來比對的絕對值
private int mPictureAbs = -1;
/**
* 設定相機相關參數,比如預覽和保存的圖片大小
*/
private void adjustCameraParameters() {
SortedSet<Size> previewSizes = new TreeSet<>();
SortedSet<Size> pictureSizes = new TreeSet<>();
AspectRatio aspectRatio4_3 = checkAspectRatio(Constants.DEFAULT_ASPECT_RATIO);
AspectRatio aspectRatio16_9 = checkAspectRatio(Constants.SECOND_ASPECT_RATIO);
//預覽圖片尺寸集合
previewSizes.addAll(mPreviewSizes.sizes(aspectRatio4_3));
previewSizes.addAll(mPreviewSizes.sizes(aspectRatio16_9));
//保存圖片尺寸集合
pictureSizes.addAll(mPictureSizes.sizes(aspectRatio4_3));
pictureSizes.addAll(mPictureSizes.sizes(aspectRatio16_9));
//預覽的尺寸集合,選擇最佳的預覽尺寸
Size previewSize = chooseOptimalSize(previewSizes);
// Always re-apply camera parameters
if (mShowingPreview) {
stopPreview();
}
Size pictureSize = pictureSizes.last();
if (null == mRecordVideoManager) {
for (Size tempSize : pictureSizes) {
//根據像素點(面積)計算最符合目標的分辨率
int referencePixels = MultiMediaConfig.MAX_PIC_WIDTH * MultiMediaConfig.MAX_PIC_HEIGHT;
int picturePixels = tempSize.getWidth() * tempSize.getHeight();
int abs = Math.abs(referencePixels - picturePixels);
if (mPictureAbs < 0 || mPictureAbs > abs) {
mPictureAbs = abs;
pictureSize = tempSize;
} else {
mPictureAbs = -1;
break;
}
}
mCameraParameters.setPictureFormat(ImageFormat.JPEG);
mCameraParameters.setJpegQuality(100);
mCameraParameters.setPictureSize(pictureSize.getWidth(), pictureSize.getHeight());
} else {
mRecordVideoManager.setPreviewSize(previewSize);
}
mCameraParameters.setPreviewSize(previewSize.getWidth(), previewSize.getHeight());
mCameraParameters.setRotation(calcCameraRotation(mDisplayOrientation));
setAutoFocusInternal(mAutoFocus);
setFlashInternal(mFlash);
mCamera.setParameters(mCameraParameters);
if (mShowingPreview) {
startPreview();
}
}
檢查相機是否支持該寬高比
/**
* 檢查相機是否支持該寬高比
*
* @param mAspectRatio
* @return
*/
private AspectRatio checkAspectRatio(AspectRatio mAspectRatio) {
AspectRatio r = null;
for (AspectRatio ratio : mPreviewSizes.ratios()) {
r = ratio;
if (ratio.equals(mAspectRatio)) {
return ratio;
}
}
return r;
}
獲取最佳的預覽尺寸
//用來比對的絕對值
private int mPreviewAbs = -1;
/**
* 設置最佳顯示尺寸
*
* @param sizes
* @return
*/
@SuppressWarnings("SuspiciousNameCombination")
private Size chooseOptimalSize(SortedSet<Size> sizes) {
if (!mPreview.isReady()) { // Not yet laid out
return sizes.last(); // Return the smallest size
}
int surfaceWidth = mPreview.getWidth();
int surfaceHeight = mPreview.getHeight();
Size result = sizes.last();
for (Size size : sizes) {
//根據像素點(面積)計算最符合目標的分辨率
int referencePixels = surfaceWidth * surfaceHeight;
int picturePixels = size.getWidth() * size.getHeight();
int abs = Math.abs(referencePixels - picturePixels);
if (mPreviewAbs < 0 || mPreviewAbs > abs) {
mPreviewAbs = abs;
result = size;
} else {
mPreviewAbs = -1;
break;
}
}
return result;
}