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应用开发学习笔记的完整目录