Android应用开发学习笔记——目录索引
参考android官网:
使用广色域内容增强图形效果 | Android 开发者 | Android Developers
ColorSpace | Android Developers
Wide Color Photos Are Coming to Android: Things You Need to Know to be Prepared
- 广色域图片下载
Android 现已迎来新一轮的图像革新, Android 8.0(API 级别 26)或更高的 Android 版本上,应用可为 Activity 启用广色域颜色模式,色域更宽的画面意味着,能给用户呈现更加实景的丰富的色彩。
切入正题之前,让我先解答一下大家的疑惑: 为什么要支持广色域呢?实际上,移动设备的屏幕与摄像头传感器每年都在更新换代,越来越多的新机型即将搭载校准显示面板,其中部分还会提供广色域支持。现代摄像头感应器能够捕捉到 sRGB 范围以外的颜色,然后生成广色域图片。屏幕与传感器的双重升级将带给用户端到端的摄影体验,让他们用更鲜明的色彩留影真实世界。
从技术层面来说,这意味着应用需要处理的图片与之前不同了。图片内嵌的 ICC 配置文件将不再采用 sRGB 色彩空间,而是转用其它色域更加丰富的格式,如 Display P3 和 Adobe RGB。对于消费者而言,广色域能让照片看上去更加真实。
一、check广色域支持情况
如果是debug,可以使用adb shell dumpsys SurfaceFlinger --wide-color
使用xiaomi 13 Ultra(android 13 API 级别 33)运行命令输出如下:

使用MIX 2S(android API 级别 29)运行命令输出如下:

显示屏是否支持广色域,请调用 isWideColorGamut() 方法。
应用还可以调用 isScreenWideColorGamut()
mDisplay = getWindowManager().getDefaultDisplay();
Log.d(TAG, "isWideColorGamut(): " + mDisplay.isWideColorGamut());
boolean isWcgSupport = 
        getResources().getConfiguration().isScreenWideColorGamut();
Log.d(TAG, "isScreenWideColorGamut(): " + isWcgSupport);使用xiaomi 13 Ultra(android 13 API 级别 33)log打印:
07-31 00:21:49.959 13998 13998 D lzl-test: isWideColorGamut(): true
07-31 00:21:49.959 13998 13998 D lzl-test: isScreenWideColorGamut(): true
使用MIX 2S(android API 级别 29)log打印:
07-31 00:17:49.405 13998 13998 D lzl-test: isWideColorGamut(): false
07-31 00:17:49.405 13998 13998 D lzl-test: isScreenWideColorGamut(): false
二、启用广色域模式
为了妥善处理图片,除上述必要check之外,如果是一个图像类应用,可用通过如下方式启用广色域模式,来实现图片的全彩色域显示:
-  AndroidManifest.xml 在 activity 文件中的 colorMode 属性设定为 wideColorGamut 
-  调用API setColorMode(ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT); 
如需在 activity 中启用广色域,请将 AndroidManifest.xml 文件中的 colorMode 属性设定为 wideColorGamut。请注意,您需要为每一个启用广色域模式的 activity 重复以上设置。
        <activity
            android:name=".WideColorActivity"
            android:colorMode="wideColorGamut"
            android:exported="true">
            ...
        </activity>
        <activity
            android:name=".WideColorActivity2"
            android:colorMode="wideColorGamut"
            android:exported="false">
            ...
        </activity>通过代码setColorMode(ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT)设置一个 Display P3 surface,来实现图片的全彩色域显示。
getWindow().setColorMode(ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT);
Log.d(TAG, "getWindow().getColorMode(): " + getWindow().getColorMode());代码简单分析:
//frameworks/base/core/java/android/view/Window.java
    /**
     * <p>Sets the requested color mode of the window. The requested the color mode might
     * override the window's pixel {@link WindowManager.LayoutParams#format format}.</p>
     *
     * <p>The requested color mode must be one of {@link ActivityInfo#COLOR_MODE_DEFAULT},
     * {@link ActivityInfo#COLOR_MODE_WIDE_COLOR_GAMUT} or {@link ActivityInfo#COLOR_MODE_HDR}.</p>
     *
     * <p>The requested color mode is not guaranteed to be honored. Please refer to
     * {@link #getColorMode()} for more information.</p>
     *
     * @see #getColorMode()
     * @see Display#isWideColorGamut()
     * @see Configuration#isScreenWideColorGamut()
     */
    public void setColorMode(@ActivityInfo.ColorMode int colorMode) {
        final WindowManager.LayoutParams attrs = getAttributes();
        attrs.setColorMode(colorMode);
        dispatchWindowAttributesChanged(attrs);
    }
    protected void dispatchWindowAttributesChanged(WindowManager.LayoutParams attrs) {
        if (mCallback != null) {
            mCallback.onWindowAttributesChanged(attrs);
        }
    }
// frameworks/base/core/java/android/view/WindowManager.java
        public void setColorMode(@ActivityInfo.ColorMode int colorMode) {
            mColorMode = colorMode;
        }
// Activity.java (android\frameworks\base\core\java\android\app)
    public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
        // Update window manager if: we have a view, that view is
        // attached to its parent (which will be a RootView), and
        // this activity is not embedded.
        if (mParent == null) {
            View decor = mDecor;
            if (decor != null && decor.getParent() != null) {
                getWindowManager().updateViewLayout(decor, params);
                if (mContentCaptureManager != null) {
                    mContentCaptureManager.updateWindowAttributes(params);
                }
            }
        }
    }
    
// WindowManagerImpl.java (android\frameworks\base\core\java\android\view)
    public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        android.util.SeempLog.record_vg_layout(384,params);
        applyTokens(params);
        mGlobal.updateViewLayout(view, params);
    }
// WindowManagerGlobal.java (android\frameworks\base\core\java\android\view)
    public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
        view.setLayoutParams(wparams);
        synchronized (mLock) {
            int index = findViewLocked(view, true);
            ViewRootImpl root = mRoots.get(index);
            mParams.remove(index);
            mParams.add(index, wparams);
            root.setLayoutParams(wparams, false);
        }
    }
// ViewRootImpl.java (android\frameworks\base\core\java\android\view)
    public void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {
...三、测试程序
package com.example.displaycolormodetest;
import ...
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private static final String TAG = "lzl-test";
    private Display mDisplay;
    private ImageView mImageView;
    private TextView mTextView;
    private Button mButton_srgb;
    private Button mButton_p3;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        boolean isWcgSupport = getResources().getConfiguration().isScreenWideColorGamut();
        Log.d(TAG, "getResources().getConfiguration().isScreenWideColorGamut(): " + isWcgSupport);
        mDisplay = getWindowManager().getDefaultDisplay();
        Log.d(TAG, "display.isWideColorGamut(): " + mDisplay.isWideColorGamut());
        Log.d(TAG, "display.getPreferredWideGamutColorSpace(): " + mDisplay.getPreferredWideGamutColorSpace());
        Log.d(TAG, "getWindow().getColorMode(): " + getWindow().getColorMode());
        mImageView = (ImageView)findViewById(R.id.imageView);
        getWindow().setColorMode(ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT);
        mTextView = (TextView)findViewById(R.id.textView);
        mTextView.setText("P3色域图片使用P3色域显示");
        mTextView.setTextColor(Color.RED);
        mButton_srgb = (Button)findViewById(R.id.button_srgb);
        mButton_srgb.setOnClickListener(this);
        mButton_p3 = (Button)findViewById(R.id.button_p3);
        mButton_p3.setOnClickListener(this);
        Button button_goto = (Button)findViewById(R.id.button_goto);
        button_goto.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        Button button = (Button)v;
        if (button == mButton_srgb) {
            // COLOR_MODE_DEFAULT for colorMode indicating that the activity
            // should use the default color mode (sRGB, low dynamic range).
            getWindow().setColorMode(ActivityInfo.COLOR_MODE_DEFAULT);
            mTextView.setText("P3色域图片使用sRGB色域显示");
            Log.d(TAG, "getWindow().getColorMode(): " + getWindow().getColorMode());
        } else if (button == mButton_p3) {
            // COLOR_MODE_WIDE_COLOR_GAMUT of colorMode indicating that the activity
            // should use a wide color gamut if the presentation display supports it.
            getWindow().setColorMode(ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT);
            mTextView.setText("P3色域图片使用P3色域显示");
            Log.d(TAG, "getWindow().getColorMode(): " + getWindow().getColorMode());
        } else {
            Log.e(TAG, "Unknown button id!");
        }
    }
}使用xiaomi 13 Ultra运行
使用adb shell dumpsys SurfaceFlinger --wide-color命令确认当前的Display color mode:

使用adb shell dumpsys SurfaceFlinger命令确认input layer的datespace是DISPLAY_P3:

完整源码
百度网盘链接:百度网盘 请输入提取码 提取码:test
github下载地址:
GitHub - liuzhengliang1102/AndroidStudio-LearnAppDevelopment
DisplayColorModeTest目录
点此查看Android应用开发学习笔记的完整目录




















