Android 全局黑白化-模拟颜色空间

news2024/11/15 15:39:45

概述

平台: RK3568 + Android 11

在这里插入图片描述

     在一些特殊的日子,如默哀日、灾难日,纪念日,哀悼日等,许多的APP、网页、海报等都开始使用黑白色主题。Android 的全局黑白实现方案,可以考虑使用模拟颜色空间的方法。

在这里插入图片描述

      借助硬件加速渲染选项,您可以利用基于硬件的选项(如 GPU、硬件层和多重采样抗锯齿 (MSAA)针对目标硬件平台优化应用。

点按模拟颜色空间可以更改整个设备界面的配色方案。此设置下面的选项是指色盲类型。可选项如下:

  • 已停用(无模拟配色方案)
  • 全色盲(配色方案限于黑色、白色和灰色)
  • 绿色弱视(影响显示红色和绿色)
  • 红色弱视(影响显示红色和绿色)
  • 蓝色弱视(影响显示蓝色和黄色)

其中“红色弱视”是指红绿色盲,红色弱视;“绿色弱视”(图 8 所示)是指红绿色盲,绿色弱视。
如果您在模拟颜色空间中截取屏幕截图,它们会正常显示,如同没有更改配色方案。

实现

     在设置的开发选项中可以找到: 设置 > 系统 > 开发者选项 > 模拟颜色空间,

文本来源

rk3568_a11$ grep -r "模拟颜色空间" frameworks/base/packages/SettingsLib/

frameworks/base/packages/SettingsLib/res/values-zh-rCN/strings.xml

	<string name="simulate_color_space" msgid="1206503300335835151">"模拟颜色空间"</string>
    <string name="daltonizer_mode_monochromacy" msgid="362060873835885014">"全色盲"</string>
    <string name="daltonizer_mode_deuteranomaly" msgid="3507284319584683963">"绿色弱视(红绿不分)"</string>
    <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"红色弱视(红绿不分)"</string>
    <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"蓝色弱视(蓝黄不分)"</string>
rk3568_a11$ grep -r "simulate_color_space" packages/apps/Settings
packages/apps/Settings/tests/robotests/src/com/android/settings/development/SimulateColorSpacePreferenceControllerTest.java:        mListValues = mContext.getResources().getStringArray(R.array.simulate_color_space_values);
packages/apps/Settings/src/com/android/settings/development/SimulateColorSpacePreferenceController.java:    private static final String SIMULATE_COLOR_SPACE = "simulate_color_space";
packages/apps/Settings/res/xml/development_settings.xml:            android:entries="@array/simulate_color_space_entries"
packages/apps/Settings/res/xml/development_settings.xml:            android:entryValues="@array/simulate_color_space_values"
packages/apps/Settings/res/xml/development_settings.xml:            android:key="simulate_color_space"
packages/apps/Settings/res/xml/development_settings.xml:            android:title="@string/simulate_color_space" />

packages/apps/Settings/res/xml/development_settings.xml 开发者选项

        <ListPreference
            android:entries="@array/simulate_color_space_entries"
            android:entryValues="@array/simulate_color_space_values"
            android:key="simulate_color_space"
            android:summary="%s"
            android:title="@string/simulate_color_space" />

对应的模式的值

frameworks/base/packages/SettingsLib/res/values/arrays.xml

    <!-- Display color space adjustment modes for developers -->
    <string-array name="simulate_color_space_entries" translatable="false">
        <item>@string/daltonizer_mode_disabled</item>
        <item>@string/daltonizer_mode_monochromacy</item>
        <item>@string/daltonizer_mode_deuteranomaly</item>
        <item>@string/daltonizer_mode_protanomaly</item>
        <item>@string/daltonizer_mode_tritanomaly</item>
    </string-array>

    <!-- Values for display color space adjustment modes for developers -->
    <string-array name="simulate_color_space_values" translatable="false">
        <item>-1</item>
        <item>0</item>
        <item>2</item>
        <item>1</item>
        <item>3</item>
    </string-array>

修改系统设置值, 主要是使能和模式

packages/apps/Settings/src/com/android/settings/development/SimulateColorSpacePreferenceController.java

    private void writeSimulateColorSpace(Object value) {
        final ContentResolver cr = mContext.getContentResolver();
        final int newMode = Integer.parseInt(value.toString());
        if (newMode < 0) {
            Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
                    SETTING_VALUE_OFF);
        } else {
            Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
                    SETTING_VALUE_ON);
            Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, newMode);
        }
    }

服务里监听设置项变化并执行响应

frameworks/base/services/core/java/com/android/server/display/color/ColorDisplayService.java

    /**
     * Apply the accessibility daltonizer transform based on the settings value.
     */
    private void onAccessibilityDaltonizerChanged() {
        if (mCurrentUser == UserHandle.USER_NULL) {
            return;
        }
        final int daltonizerMode = isAccessiblityDaltonizerEnabled()
                ? Secure.getIntForUser(getContext().getContentResolver(),
                    Secure.ACCESSIBILITY_DISPLAY_DALTONIZER,
                    AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY, mCurrentUser)
                : AccessibilityManager.DALTONIZER_DISABLED;

        final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
        if (daltonizerMode == AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY) {
            // Monochromacy isn't supported by the native Daltonizer implementation; use grayscale.
            dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_GRAYSCALE,
                    MATRIX_GRAYSCALE);
            dtm.setDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED);
        } else {
            dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_GRAYSCALE, null);
            dtm.setDaltonizerMode(daltonizerMode);
        }
    }

frameworks/base/services/core/java/com/android/server/display/color/DisplayTransformManager.java

	private static final int SURFACE_FLINGER_TRANSACTION_DALTONIZER = 1014
    /**
     * Sets and applies a current color transform matrix for a given level.
     * <p>
     * Note: all color transforms are first composed to a single matrix in ascending order based on
     * level before being applied to the display.
     *
     * @param level the level used to identify and compose the color transform (low -> high)
     * @param value the 4x4 color transform matrix (in column-major order), or {@code null} to
     * remove the color transform matrix associated with the provided level
     */
    public void setColorMatrix(int level, float[] value) {
        if (value != null && value.length != 16) {
            throw new IllegalArgumentException("Expected length: 16 (4x4 matrix)"
                    + ", actual length: " + value.length);
        }

        synchronized (mColorMatrix) {
            final float[] oldValue = mColorMatrix.get(level);
            if (!Arrays.equals(oldValue, value)) {
                if (value == null) {
                    mColorMatrix.remove(level);
                } else if (oldValue == null) {
                    mColorMatrix.put(level, Arrays.copyOf(value, value.length));
                } else {
                    System.arraycopy(value, 0, oldValue, 0, value.length);
                }

                // Update the current color transform.
                applyColorMatrix(computeColorMatrixLocked());
            }
        }
    }

    /**
     * Sets the current Daltonization mode. This adjusts the color space to correct for or simulate
     * various types of color blindness.
     *
     * @param mode the new Daltonization mode, or -1 to disable
     */
    public void setDaltonizerMode(int mode) {
        synchronized (mDaltonizerModeLock) {
            if (mDaltonizerMode != mode) {
                mDaltonizerMode = mode;
                applyDaltonizerMode(mode);
            }
        }
    }
    /**
     * Propagates the provided Daltonization mode to the SurfaceFlinger.
     */
    private static void applyDaltonizerMode(int mode) {
        final Parcel data = Parcel.obtain();
        data.writeInterfaceToken("android.ui.ISurfaceComposer");
        data.writeInt(mode);
        try {
            sFlinger.transact(SURFACE_FLINGER_TRANSACTION_DALTONIZER, data, null, 0);
        } catch (RemoteException ex) {
            Slog.e(TAG, "Failed to set Daltonizer mode", ex);
        } finally {
            data.recycle();
        }
    }

传到SurfaceFlinger

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

	status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                                    uint32_t flags) {
        //............
        switch (code) {
            case 1014: {
                Mutex::Autolock _l(mStateLock);
                // daltonize
                n = data.readInt32();
                switch (n % 10) {
                    case 1:
                        mDaltonizer.setType(ColorBlindnessType::Protanomaly);
                        break;
                    case 2:
                        mDaltonizer.setType(ColorBlindnessType::Deuteranomaly);
                        break;
                    case 3:
                        mDaltonizer.setType(ColorBlindnessType::Tritanomaly);
                        break;
                    default:
                        mDaltonizer.setType(ColorBlindnessType::None);
                        break;
                }
                if (n >= 10) {
                    mDaltonizer.setMode(ColorBlindnessMode::Correction);
                } else {
                    mDaltonizer.setMode(ColorBlindnessMode::Simulation);
                }

                updateColorMatrixLocked();
                return NO_ERROR;
            }
    //........................

关于 Settings > 色彩校正

实现的原理与黑白色是一样的:
在这里插入图片描述

packages/apps/Settings/res/xml/accessibility_daltonizer_settings.xml

    <PreferenceCategory
        android:title="@string/daltonizer_type"
        android:key="daltonizer_mode_category" >

        <com.android.settingslib.widget.RadioButtonPreference
            android:key="daltonizer_mode_deuteranomaly"
            android:persistent="false"
            android:summary="@string/daltonizer_mode_deuteranomaly_summary"
            android:title="@string/daltonizer_mode_deuteranomaly_title" />

        <com.android.settingslib.widget.RadioButtonPreference
            android:key="daltonizer_mode_protanomaly"
            android:persistent="false"
            android:summary="@string/daltonizer_mode_protanomaly_summary"
            android:title="@string/daltonizer_mode_protanomaly_title" />

        <com.android.settingslib.widget.RadioButtonPreference
            android:key="daltonizer_mode_tritanomaly"
            android:persistent="false"
            android:summary="@string/daltonizer_mode_tritanomaly_summary"
            android:title="@string/daltonizer_mode_tritanomaly_title" />

    </PreferenceCategory>

packages/apps/Settings/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java


    @Override
    protected int getPreferenceScreenResId() {
        return R.xml.accessibility_daltonizer_settings;
    }

packages/apps/Settings/src/com/android/settings/accessibility/DaltonizerRadioButtonPreferenceController.java

    private static final String TYPE = Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER;
    private void putSecureString(String name, String value) {
        Settings.Secure.putString(mContentResolver, name, value);
    }

    private void handlePreferenceChange(String value) {
        putSecureString(TYPE, value);
    }

APP 如何调用?

     普通APP没有调用的权限, 两种调用方法:

  1. App拥有system uid
		final android.content.ContentResolver cr = context.getContentResolver();
        final int newMode = on ? 0 : -1;
        if (newMode < 0) {
            android.provider.Settings.Secure.putInt(cr, "accessibility_display_daltonizer_enabled",
                    0);
        } else {
            android.provider.Settings.Secure.putInt(cr, "accessibility_display_daltonizer_enabled",
                    1);
            //public static final String ACCESSIBILITY_DISPLAY_DALTONIZER =
            //                "accessibility_display_daltonizer";
            android.provider.Settings.Secure.putInt(cr, "accessibility_display_daltonizer", newMode);
        }
  1. 平台已ROOT, 执行命令
settings put secure accessibility_display_daltonizer_enabled 1
settings put secure accessibility_display_daltonizer 0

参考

安卓APP全局黑白化实现方案
Android全局设置APP为黑白模式的两种方案
配置设备上的开发者选项

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/657336.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RabbitMQ高阶使用消息推送

目录 1 从打车开始说起1.1 需要解决的问题1.2 消息推送 2 消息推送2.1 什么是消息推送2.2 方案介绍2.2.1 ajax短轮询2.2.2 长轮询2.2.3 WebSocket 2.3 WS实现消息推送2.3.1 架构介绍2.3.2 暂存数据2.3.2.1 什么是MongoDB2.3.2.2 插入数据2.3.2.3 查询数据 2.4.1 轮询任务2.4.1.…

学生党暑假在家赚钱得方法,足不出户轻松赚取买鞋钱

很多学生党都想在暑假期间赚点零花钱&#xff0c;最好是能在家就赚钱。在家里赚零花钱有许多途径&#xff0c;今天我来和大家分享一些方法。 1、问答在各大平台上非常普遍。 我们可以在各大平台上找到各种各样的问答。 如今&#xff0c;问答平台越来越多&#xff0c;提供的奖…

平凯星辰重磅支持 2023 开放原子全球开源峰会,开源数据库分论坛成功召开

2023 年 6 月 11 日至 13 日&#xff0c;以“开源赋能&#xff0c;普惠未来”为主题的 2023 开放原子全球开源峰会开幕式暨高峰论坛在北京成功举办。企业级开源分布式数据库厂商平凯星辰联合创始人兼 CTO 黄东旭受邀出席峰会参与开源论道圆桌&#xff0c;担任开源数据库分论坛出…

吴恩达ChatGPT课爆火

点上方计算机视觉联盟获取更多干货 没想到时至今日&#xff0c;ChatGPT竟还会犯低级错误&#xff1f; 吴恩达大神最新开课就指出来了&#xff1a; ChatGPT不会反转单词&#xff01; 比如让它反转下lollipop这个词&#xff0c;输出是pilollol&#xff0c;完全混乱。 哦豁&#…

C++14中返回类型推导的使用

使用C14中的auto返回类型&#xff0c;编译器将尝试自动推导(deduce)返回类型: namespace {int xx 1; auto f() { return xx; } // return type is int const auto& f3() { return xx; } // return type is const int&auto multiply(int a, int b) { return (a * b); …

【阅读论文】时间序列数据清洗:一项调查

文章目录 摘要一、引言A.问题陈述B.问题挑战C. 组织 二、基于平滑的清洗算法A.移动平均B.自动注册C.卡尔曼滤波模型D.总结和讨论 三、基于约束的混合算法A. 顺序依赖 (OD)B.序列相关性C.速度约束D.总结和讨论 四、基于统计的CLEANING算法A.最大似然B.马尔可夫模型C.二项抽样D.时…

基于51单片机设计的井下瓦斯监控系统

一、项目介绍 井下瓦斯监控系统是煤矿安全生产中非常重要的一部分,防止井下瓦斯爆炸事故的发生,保障煤矿工人的人身安全。由于地下环境特殊,需要特殊的监测系统来实时监测瓦斯浓度等关键指标,并及时报警以便采取措施进行处理。 瓦斯气体,又称沼气,是一种轻质烃类气体,…

基于的滤波器设计

一,带通滤波器设计指标。 1&#xff0c;中心频率。中心频率:通常定义为带通滤波器&#xff08;或带阻滤波器&#xff09;频率的几何平均值&#xff0c;在对数坐标下&#xff0c;即为两个3dB点之间的中点&#xff0c;一般用两个3dB点的算术平均来表示。滤波器通频带中间的频率&…

网工大题题型总结(1)-------网络安全方面考察

&#xff08;1&#xff09;2018年上半年 试题二 &#xff08;3&#xff09;常见的无线网络安全隐患有 IP 地址欺骗、数据泄露、(8)、(9)、双络通信被窃听等; 为保护核心业务数据区域的安全&#xff0c;网络管理员在设备①处部署(10)实现核心业务区域边界 防护;在设备②处部署…

C++11特性之左值引用和右值引用

3.1二者的对比之内置类型 内置类型的无名对象&#xff08;右值&#xff09;为纯右值&#xff0c;其值本身不可改变 int main() {int a10;const int b20;int& raa;//ok,左值引用const int& rbb;//ok&#xff0c;常性左值引用const int& crv30;//ok,也叫万能引用&a…

网络安全竞赛——综合靶机渗透测试ZHCS-2全过程解析教程

任务一:综合靶机渗透测试 任务环境说明: 服务器场景:ZHCS-2(关闭连接)服务器场景操作系统:版本不详扫描目标靶机将靶机开放的所有端口,当作flag提交(例:21,22,23) FLAG:22,80 扫描目标靶机将靶机的http服务版本信息当作flag提交(例:apache 2.3.4) FLAG: ligh…

Vue3 Hooks函数使用及封装思想

目录 一. 什么是hooks函数&#xff1f; 二、如何封装一个hooks函数 三、Hooks 常用 Demo &#xff08;1&#xff09;验证码倒计时 &#xff08;2&#xff09;防抖 &#xff08;3&#xff09;节流 一. 什么是hooks函数&#xff1f; 专业解释&#xff1a;Vue 3中的Hooks函数…

Nucleo-F411RE (STM32F411)LL库体验 8 - PWM的使用

Nucleo-F411RE &#xff08;STM32F411&#xff09;LL库体验 8 - PWM的使用 1、简述 LD2连接PA5&#xff0c;而PA5可以映射TIM2_CH1&#xff0c;配合TIM2&#xff0c;可以输出PWM。 本片文章大量工作是添加了shell命令&#xff0c;可以通过pwm命令开关pwm以及设置pwm的频率&am…

数字图像处理期末考点整理(全)

计算&#xff1a;傅里叶变换&#xff0c;双线性插值&#xff0c;直方图均衡化&#xff0c;灰度共生矩阵&#xff0c;霍夫曼编码&#xff0c;区域增长/合并&#xff0c;中值滤波 简答&#xff1a;窗口/模板处理&#xff0c;BMP文件存储格式&#xff0c;滤波器和平滑算子的特点&…

Servlet (上篇)

哥几个来学 Servlet 啦 ~~ 目录 &#x1f332;一、什么是 Servlet &#x1f333;二、第一个 Servlet 程序 &#x1f347;1. 创建项目 &#x1f348;2. 引入依赖 &#x1f349;3. 创建目录 &#x1f34a;4. 编写代码 &#x1f34b;5. 打包程序 &#x1f96d;6. 部署程序…

client-go的Indexer三部曲之二:性能测试

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 本篇概览 本文是《client-go的Indexer》系列的第二篇&#xff0c;在前文咱们通过实例掌握了client-go的Indexer的基本功能&#xff0c;本篇咱们尝试对下面这…

css小兔鲜项目搭建

目录 精灵图 精灵图的使用步骤 背景图片大小 background连写 文字阴影 盒子阴影 过渡 骨架标签 SEO三大标签 版心的介绍 css书写顺序 项目结构搭建 精灵图 场景&#xff1a;项目中将多张小图片&#xff0c;合并成一张大图片&#xff0c;这张大图片称之为精灵图 优点…

c语言实现 顺序存储和链式存储(几种链表)

目录 一、简介 二、一些问题 1、递归free 2、free单向循环链表&#xff1a; 3、free单向链表 4、free双向循环链表 5、free使用数组实现链式存储结构 6、sizeof&#xff08;&#xff09;求字符串大小的问题 三、总结 一、简介 花了几天的时间从头开始使用c语言…

UnityVR--UIManager--UI管理2

目录 前言 UIManger的实现 1. 需要用到的变量和数据 2. 在构造中的工作 3. 初始化面板 4. 显示面板 5. 隐藏面板和隐藏所有面板 6. 其他小工具 在场景中实现 1. 不同面板的类型设置 2. 场景中的设置 前言 接前篇&#xff0c;上一篇已经有了UITools.cs其中定义了UI面板需…

Web服务器群集:部署LAMP平台

目录 一、理论 1.LAMP平台 2.Apache网址服务基础 2.httpd服务器的基本配置 3.构建虚拟Web主机 4.MySQL服务 5.构建PHP运行环境 二、实验 1.LAMP架构DISCUZ论坛应用 三、问题 1.虚拟机内存分配上限问题&#xff0c;内存上限只能加到3G。 2.虚拟机CPU如何设置才更加合…