Android 11.0 Camera2 默认选择拍照尺寸修改及流程分析

Posted 安时光Mrsongs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 11.0 Camera2 默认选择拍照尺寸修改及流程分析相关的知识,希望对你有一定的参考价值。

一、前言

最近有一个需求是修改默认的照片尺寸,这篇文章就总结一下Camara 选择默认的拍照尺寸的逻辑吧。

二、定位代码

2.1、根据“照片大小” text 可以定位到布局文件 picturesize_preference.xml.

代码路径:
android\\vendor\\mediatek\\proprietary\\packages\\apps\\Camera2\\feature\\setting\\picturesize\\res\\xml\\picturesize_preference.xml`**

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <com.mediatek.camera.common.preference.Preference
        android:key="key_picture_size"
        android:title="@string/pref_camera_picturesize_title"
        android:persistent="false"
        android:order="40"/>
</PreferenceScreen>

Java 引用文件为:
代码路径: android\\vendor\\mediatek\\proprietary\\packages\\apps\\Camera2\\feature\\setting\\picturesize\\src\\com\\mediatek\\camera\\feature\\setting\\picturesize\\PictureSizeSettingView.java

三、流程逻辑分析

3.1、PictureSizeSettingView 照片尺寸列表值的初始化

PictureSizeSettingView 的 setEntryValues 是传入照片尺寸列表的,这里是在其他地方调用传入值得。
代码路径: android\\vendor\\mediatek\\proprietary\\packages\\apps\\Camera2\\feature\\setting\\picturesize\\src\\com\\mediatek\\camera\\feature\\setting\\picturesize\\PictureSizeSettingView.java


    /**
     * Set the picture sizes supported.
     *
     * @param entryValues The picture sizes supported.
     */
    public void setEntryValues(List<String> entryValues) {
        mEntryValues = entryValues;
    }

3.2、PictureSize.java 设置默认尺寸和可选尺寸

全局搜一下可以发现是在PictureSize.java 中传入EntryValue的
代码路径: vendor/mediatek/proprietary/packages/apps/Camera2/feature/setting/picturesize/src/com/mediatek/camera/feature/setting/picturesize/PictureSize.java

总结一下流程:

1、获取屏幕的尺寸来计算出宽高比作为全屏的宽高比。
2、获取Sensor 传上来的可支持的照片尺寸supportedPictureSize。
3、从supportedPictureSize这里遍历选出可以用的尺寸里面最接近全屏宽高比的尺寸。
4、将全屏宽高比里面尺寸作为默认选中的尺寸。

    /**
     * Invoked after setting's all values are initialized.
     *
     * @param supportedPictureSize Picture sizes which is supported in current platform.
     */
    public void onValueInitialized(List<String> supportedPictureSize) {
        LogHelper.d(TAG, "[onValueInitialized], supportedPictureSize:" + supportedPictureSize);

         //1、这里获取屏幕的尺寸来计算出宽高比作为全屏的宽高比。
        double fullRatio = PictureSizeHelper.findFullScreenRatio(mActivity);
        List<Double> desiredAspectRatios = new ArrayList<>();
        desiredAspectRatios.add(fullRatio);
        desiredAspectRatios.add(PictureSizeHelper.RATIO_4_3);
        PictureSizeHelper.setDesiredAspectRatios(desiredAspectRatios);
        PictureSizeHelper.setFilterParameters(DEGRESSIVE_RATIO, MAX_COUNT);
        if (sFilterPictureSize) {
            supportedPictureSize = PictureSizeHelper.filterSizes(supportedPictureSize);
            LogHelper.d(TAG, "[onValueInitialized], after filter, supportedPictureSize = "
                    + supportedPictureSize);
        }

        ...
        /*
        **已省略部分代码......
        */
        ...
        //2、获取Sensor 传上来的可支持的照片尺寸supportedPictureSize。
        setSupportedPlatformValues(supportedPictureSize);
        setSupportedEntryValues(supportedPictureSize);
        setEntryValues(supportedPictureSize);
        refreshViewEntry();

        String valueInStore = mDataStore.getValue(getKey(), null, getStoreScope());
        Log.d("PictureSize 1,","onValueInitialized valueInStore="+valueInStore);
        if (valueInStore != null
                && !supportedPictureSize.contains(valueInStore)) {
            LogHelper.d(TAG, "[onValueInitialized], value:" + valueInStore
                    + " isn't supported in current platform");
            valueInStore = null;
            mDataStore.setValue(getKey(), null, getStoreScope(), false);
        }
        if (valueInStore == null) {
            // Default picture size is the max full-ratio size.
            List<String> entryValues = getEntryValues();
            //3、这里遍历选出可以用的尺寸里面最接近全屏宽高比的尺寸。
            for (String value : entryValues) {
                if (PictureSizeHelper.getStandardAspectRatio(value) == fullRatio) {
                    valueInStore = value;
                    break;
                }
            }
        }
        // If there is no full screen ratio picture size, use the first value in
        // entry values as the default value.
        if (valueInStore == null) {
            valueInStore = getEntryValues().get(0);
        }
        Log.d("PictureSize 2,","onValueInitialized valueInStore="+valueInStore);
        //4、将全屏宽高比里面尺寸作为默认选中的尺寸。
        setValue(valueInStore);
    }

四、Any question ?

1、全屏的宽高比如何计算的 ?
2、默认的尺寸如果全屏宽高比有好几个怎么选择 ?

4.1、全屏的宽高比如何计算的

在上面提到获取全屏宽高比的地方是 PictureSizeHelper.findFullScreenRatio

//1、这里获取屏幕的尺寸来计算出宽高比作为全屏的宽高比。
        double fullRatio = PictureSizeHelper.findFullScreenRatio(mActivity);

代码路径: android\\vendor\\mediatek\\proprietary\\packages\\apps\\Camera2\\feature\\setting\\picturesize\\src\\com\\mediatek\\camera\\feature\\setting\\picturesize\\PictureSizeHelper.java

在这里可以很清楚的看到计算全屏宽高比的步骤。

1、首选通过Display获取屏幕的尺寸。
2、计算屏幕尺寸的宽高比。
3、根据绝对值函数选取最靠近屏幕宽高比的数值作为全屏宽高比。

   /**
     * Compute full screen aspect ratio.
     *
     * @param context The instance of {@link Context}.
     * @return The full screen aspect ratio.
     */
    public static double findFullScreenRatio(Context context) {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        //1、首选通过Display获取屏幕的尺寸。
        Display display = wm.getDefaultDisplay();
        DisplayMetrics dm = new DisplayMetrics();
        display.getRealMetrics(dm);
        int width = Math.max(dm.widthPixels, dm.heightPixels);
        int height = Math.min(dm.widthPixels, dm.heightPixels);
        //2、计算屏幕尺寸的宽高比。
        double displayRatio = (double) width / (double) height;
        Log.d("PictureSizeHelper",",findFullScreenRatio width="+width+",height="+height+",displayRatio="+displayRatio);
        double find = RATIO_4_3;
        //3、根据绝对值函数选取最靠近屏幕宽高比的数值作为全屏宽高比。
        for (int i = 0; i < RATIOS.length; i++) {
            double ratio = RATIOS[i];
            if (Math.abs(ratio - displayRatio) < Math.abs(find - displayRatio)) {
                find = ratio;
            }
        }
        return find;
    }

4.2、默认的尺寸如果全屏宽高比有好几个怎么选择。

在PictureSize中的 onValueInitialized方法中不考虑各个MODE功能的情况下,根据先来后到原则,最先匹配上全屏宽高比的尺寸作为默认选中的尺寸。看到这里有点失望,本来以为会比较一下比如16:9里面选择最大的作为默认尺寸。


       if (valueInStore == null) {
            // Default picture size is the max full-ratio size.
            List<String> entryValues = getEntryValues();
            for (String value : entryValues) {
                if (PictureSizeHelper.getStandardAspectRatio(value) == fullRatio) {
                    valueInStore = value;
                    break;
                }
            }

五、定制将支持照片尺寸里面选择最大的作为默认尺寸。

diff --git a/vendor/mediatek/proprietary/packages/apps/Camera2/feature/setting/picturesize/src/com/mediatek/camera/feature/setting/picturesize/PictureSize.java b/vendor/mediatek/proprietary/packages/apps/Camera2/feature/setting/picturesize/src/com/mediatek/camera/feature/setting/picturesize/PictureSize.java
index f3a3954b727..77247a04614 100755
--- a/vendor/mediatek/proprietary/packages/apps/Camera2/feature/setting/picturesize/src/com/mediatek/camera/feature/setting/picturesize/PictureSize.java
+++ b/vendor/mediatek/proprietary/packages/apps/Camera2/feature/setting/picturesize/src/com/mediatek/camera/feature/setting/picturesize/PictureSize.java
@@ -48,6 +48,8 @@ import com.mediatek.camera.portability.SystemProperties;
 
 import java.util.ArrayList;
 import java.util.List;
+import android.util.Log;
+
 
 /**
  * Picture size setting item.
@@ -114,6 +116,7 @@ public class PictureSize extends SettingBase implements
             mSettingView.setEntryValues(getEntryValues());
             mSettingView.setEnabled(getEntryValues().size() > 1);
         }
+        
     }
 
     @Override
@@ -245,6 +248,7 @@ public class PictureSize extends SettingBase implements
         refreshViewEntry();
 
         String valueInStore = mDataStore.getValue(getKey(), null, getStoreScope());
+        Log.d("PictureSize 1,","onValueInitialized valueInStore="+valueInStore);
         if (valueInStore != null
                 && !supportedPictureSize.contains(valueInStore)) {
             LogHelper.d(TAG, "[onValueInitialized], value:" + valueInStore
@@ -254,19 +258,23 @@ public class PictureSize extends SettingBase implements
         }
         if (valueInStore == null) {
             // Default picture size is the max full-ratio size.
-            List<String> entryValues = getEntryValues();
+            //add begin...
+            /*List<String> entryValues = getEntryValues();
             for (String value : entryValues) {
                 if (PictureSizeHelper.getStandardAspectRatio(value) == fullRatio) {
                     valueInStore = value;
                     break;
                 }
-            }
+            }*/
+            valueInStore =PictureSizeHelper.getMaxPictureSize(getEntryValues());
+            //add end..
         }
         // If there is no full screen ratio picture size, use the first value in
         // entry values as the default value.
         if (valueInStore == null) {
             valueInStore = getEntryValues().get(0);
         }
+        Log.d("PictureSize 2,","onValueInitialized valueInStore="+valueInStore);
         setValue(valueInStore);
     }
 
@@ -295,6 +303,7 @@ public class PictureSize extends SettingBase implements
         setEntryValues(supportedPictureSize);
         refreshViewEntry();
         setValue(forceChosenPictureSize);
+        Log.d("PictureSize,","onValueInitialized forceChosenPictureSize="+forceChosenPictureSize);
         mDataStore.setValue(getKey(), getValue(), getStoreScope(), false);
         LogHelper.d(TAG, "[onValueInitialized] -");
     }
diff --git a/vendor/mediatek/proprietary/packages/apps/Camera2/feature/setting/picturesize/src/com/mediatek/camera/feature/setting/picturesize/PictureSizeHelper.java b/vendor/mediatek/pro
prietary/packages/apps/Camera2/feature/setting/picturesize/src/com/mediatek/camera/feature/setting/picturesize/PictureSizeHelper.java
index d2f9ec9a33b..06cfe7713b9 100755
--- a/vendor/mediatek/proprietary/packages/apps/Camera2/feature/setting/picturesize/src/com/mediatek/camera/feature/setting/picturesize/PictureSizeHelper.java
+++ b/vendor/mediatek/proprietary/packages/apps/Camera2/feature/setting/picturesize/src/com/mediatek/camera/feature/setting/picturesize/PictureSizeHelper.java
@@ -57,6 +57,7 @@ import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import android.util.Log;
 
 /**
  * Picture size helper to provide util methods.
@@ -109,7 +110,7 @@ public class PictureSizeHelper {
         int width = Math.max(dm.widthPixels, dm.heightPixels);
         int height = Math.min(dm.widthPixels, dm.heightPixels);
         double displayRatio = (double) width / (double) height;
-
+        Log.d("PictureSizeHelper",",findFullScreenRatio width="+width+",height="+height+",displayRatio="+displayRatio);
         double find = RATIO_4_3;
         for (int i = 0; i < RATIOS.length; i++) {
             double ratio = RATIOS[i];
@@ -279,6 +280,23 @@ public class PictureSizeHelper {
         return ratio;
     }
 
+    //add begin.
+    public static String getMaxPictureSize(List<String> supportedEntryValues){
+        int temp=0;
+        int maxSize=0;
+        int maxIndex=0;
+        for (int i=0;i< supportedEntryValues.size();i++) {   
+            Size size = valueToSize(supportedEntryValues.get(i));
+            temp = size.width * size.height;        
+            if (temp > maxSize) {
+                maxSize = temp;
+                maxIndex = i;
+            }
+        }
+        return supportedEntryValues.get(maxIndex);
+    }
+    //add end.
+
     private static List<Size> pickUpToThree(List<Size> sizes) {
         if (sDegressiveRatio == 0 || sMaxCount == 0) {
             return sizes;

六、结语

Okay,So much for this !

以上是关于Android 11.0 Camera2 默认选择拍照尺寸修改及流程分析的主要内容,如果未能解决你的问题,请参考以下文章

Android 11.0 Camera 分辨率从高到低排列

Android 11.0 修复Camera 启用后置摄像头在拍照界面下,白平衡按钮无法点击

Android 11.0 修复Camera 使用闪光灯拍照后,查看图片时详细信息为“未使用闪光灯”状态

Android 11.0 修复:Camera 拍照后,图片详情信息的分辨率和画质信息概率性丢失

Android 11.0 默认打开系统定位

android camera2在5.0以下怎么使用