Android应用开发(24)启用广色域(wideColorGamut)

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。对于消费者而言,广色域能让照片看上去更加真实。

一、查看广色域支持情况

1. 查看设备是否支持广色域

如果是debug,可以使用adb shell dumpsys SurfaceFlinger --wide-color

使用xiaomi 13 Ultra(android 13 API 级别 33)运行命令输出如下:

Android应用开发(24)启用广色域(wideColorGamut)_第1张图片

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

Android应用开发(24)启用广色域(wideColorGamut)_第2张图片

显示屏是否支持广色域,请调用 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

 2. 查看图片资源是否是广色域

图片文件,使用 EXIF信息查看器(图虫EXIF查看器),看如果是否是P3广色域图片

Android应用开发(24)启用广色域(wideColorGamut)_第3张图片

        ImageDecoder.Source source = ImageDecoder.createSource(getResources(), R.drawable.id);
        try {
            Bitmap bitmap = ImageDecoder.decodeBitmap(source,
                    new ImageDecoder.OnHeaderDecodedListener() {
                        @Override
                        public void onHeaderDecoded(ImageDecoder decoder,
                                                    ImageDecoder.ImageInfo info,
                                                    ImageDecoder.Source source) {
                            ColorSpace cs = info.getColorSpace();
                            // Do something...
                            Log.d(TAG, "getColorSpace: " + cs.toString());
                        }
                    });
        } catch (IOException e) {
            // handle exception.
        }

二、启用广色域模式

为了妥善处理图片,除上述必要check之外,如果是一个图像类应用,可用通过如下方式启用广色域模式,来实现图片的全彩色域显示:

  1.  AndroidManifest.xml 在 activity 文件中的 colorMode 属性设定为 wideColorGamut

  2. 调用API setColorMode(ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT);

1. AndroidManifest.xml 中配置android:colorMode="wideColorGamut"

如需在 activity 中启用广色域,请将 AndroidManifest.xml 文件中的 colorMode 属性设定为 wideColorGamut。请注意,您需要为每一个启用广色域模式的 activity 重复以上设置。


        
            ...
        

        
            ...
        

2. 调用setColorMode(int)方法并传入COLOR_MODE_WIDE_COLOR_GAMUT

通过代码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());

广色域启用为可选,因它需更多系统资源(可能致应用性能下降),开发者文档强调:

启用广色域模式时活动窗口用更多内存GPU处理能力进行画面组合。启用广色域模式前应仔细考虑活动能否真正从中受益。全屏显示照片活动很适合采用广色域模式而显示缩略图界面不够适合。

代码简单分析:

//frameworks/base/core/java/android/view/Window.java
    /**
     * 

Sets the requested color mode of the window. The requested the color mode might * override the window's pixel {@link WindowManager.LayoutParams#format format}.

* *

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}.

* *

The requested color mode is not guaranteed to be honored. Please refer to * {@link #getColorMode()} for more information.

* * @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.widecolorgamuttest;

import ...

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        boolean isWcgSupport = getResources().getConfiguration().isScreenWideColorGamut();

        Display display = getWindowManager().getDefaultDisplay();
        Log.d(TAG, "display.isWideColorGamut(): " + display.isWideColorGamut());

        Log.d(TAG, "getWindow().getColorMode(): " + getWindow().getColorMode());

        mImageView = (ImageView)findViewById(R.id.imageView);
        imageView.setImageResource(R.drawable.android_p3);

        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);
    }

    @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:

Android应用开发(24)启用广色域(wideColorGamut)_第4张图片

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

Android应用开发(24)启用广色域(wideColorGamut)_第5张图片

Android应用开发(24)启用广色域(wideColorGamut)_第6张图片

完整源码

百度网盘链接:百度网盘 请输入提取码 提取码:test 

WideColorGamutTest目录

对比测试

左边:xiaomi 13 Ultra(android 13 API 级别 33)      右边:MIX 2S(android API 级别 29)

Android应用开发(24)启用广色域(wideColorGamut)_第7张图片

点此查看Android应用开发学习笔记的完整目录

你可能感兴趣的:(Android应用开发学习笔记,android,android,studio)