MTK推送来的原生Camera2应用拍照之后生成的预览图(Thumbnail)居然是马赛克!!
但如果点击预览图之后再退出,就又是正常的。
Camera2对于更新预览图的操作位于:
vendor/mediatek/proprietary/packages/apps/Camera2/host/src/com/mediatek/camera/ui/ThumbnailViewManager.java
这个函数对于传入的位图数据进行最后的处理并显示。
public void updateThumbnail(Bitmap bitmap) {
updateThumbnailView(bitmap);
if (bitmap != null) {
doAnimation(mAnimationView);
} else {
// for security camera not query db.
mThumbnailView.setImageDrawable(mRoundDrawable);
mIsNeedQueryDB = false;
}
}
vendor/mediatek/proprietary/packages/apps/Camera2/common/src/com/mediatek/camera/common/mode/photo/PhotoMode.java
bitmap就是在这里传进去的。
public void onPostViewCallback(byte[] data) {
... //createBitmapFromYuv
mIApp.getAppUi().updateThumbnail(bitmap);
}
CameraSysTrace.onEventSystrace(POST_VIEW_CALLBACK, false, true);
}
一步一步追查数据的来源会发现原来位图是通过Camera的YUV数据转换而来。
createBitmapFromYuv -> covertYuvDataToJpeg
可以将covertYuvDataToJpeg前的YUV数据和之后的jpeg数据保存成对应的图片来进行对比会发现,YUV数据是正常的,但是jpeg图片就已经变成了马赛克。问题一定是出在了转换的时候。
vendor/mediatek/proprietary/packages/apps/Camera2/common/src/com/mediatek/camera/common/utils/BitmapCreator.java
public static byte[] covertYuvDataToJpeg(byte[] data, int imageFormat,
int yuvWidth, int yuvHeight) {
byte[] jpeg;
Rect rect = new Rect(0, 0, yuvWidth, yuvHeight);
YuvImage yuvImg = new YuvImage(data, imageFormat, yuvWidth, yuvHeight,
null);
ByteArrayOutputStream outputstream = new ByteArrayOutputStream();
int jpegQuality = CameraProfile
.getJpegEncodingQualityParameter(CameraProfile.QUALITY_HIGH);
yuvImg.compressToJpeg(rect, jpegQuality, outputstream);
jpeg = outputstream.toByteArray();
return jpeg;
}
在这个函数中很明显看到一个控制图片质量的参数jpegQuality,打印这个值发现居然是0。去检查jpegQuality的范围是0-100,很显然只要将参数改成100,问题就解决了。
diff --git a/common/src/com/mediatek/camera/common/utils/BitmapCreator.java b/common/src/com/mediatek/camera/common/utils/BitmapCreator.java
index ac4dcd0..2294301 100755
--- a/common/src/com/mediatek/camera/common/utils/BitmapCreator.java
+++ b/common/src/com/mediatek/camera/common/utils/BitmapCreator.java
@@ -415,9 +415,11 @@ public class BitmapCreator {
YuvImage yuvImg = new YuvImage(data, imageFormat, yuvWidth, yuvHeight,
null);
ByteArrayOutputStream outputstream = new ByteArrayOutputStream();
+ /*
int jpegQuality = CameraProfile
.getJpegEncodingQualityParameter(CameraProfile.QUALITY_HIGH);
- yuvImg.compressToJpeg(rect, jpegQuality, outputstream);
+ */
+ yuvImg.compressToJpeg(rect, 100, outputstream);
jpeg = outputstream.toByteArray();
return jpeg;
}
这种方法同样可以控制预览图的质量。