Android グローバル白黒 - シミュレートされた色空間

概要

平台: RK3568 + Android 11

ここに画像の説明を挿入

沈黙の日、災害の日、記念日、追悼の日などの特別な日には、多くのアプリ、Web ページ、ポスターなどが白黒の     テーマを使用し始めます。Android のグローバルな白黒実装の場合は、色空間をシミュレートする方法の使用を検討できます。

ここに画像の説明を挿入

      ハードウェア アクセラレーション レンダリング オプションを使用すると、GPU、ハードウェア レイヤー、マルチサンプル アンチエイリアシング (MSAA) などのハードウェア ベースのオプションを利用して、ターゲット ハードウェア プラットフォームに合わせてアプリケーションを最適化できます。

[色空間のシミュレート]をタップして、デバイス インターフェイス全体の配色を変更します。この設定の下にあるオプションは、色覚異常のタイプを示します。オプションは次のとおりです。

  • 無効 (シミュレートされたカラースキームなし)
  • アクロマトプシア(配色は黒、白、グレーに限定)
  • 第二色 (赤と緑の表示に影響を与える)
  • Protomaly (赤と緑の表示に影響します)
  • 顕色異常(青と黄色の表示に影響を与える)

このうち、「前色覚異常」は赤緑色盲、第一色覚異常を指し、「第二色覚異常」(図 8 に示す)は赤緑色覚異常、第二色覚異常を指します。
シミュレートされた色空間でスクリーンショットを撮ると、配色が変更されていないかのように正常に表示されます。

達成

     これは、設定の開発オプションにあります: [設定] > [システム] > [開発者向けオプション] > [シミュレーション色空間]

テキストソース

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

フレームワーク/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" />

package/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" />

対応するモードの値

フレームワーク/ベース/パッケージ/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>

システム設定を変更します(主に有効化とモード)

パッケージ/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 に渡す

フレームワーク/ネイティブ/サービス/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;
            }
    //........................

設定 > 色補正について

実装の原則は白黒と同じです。
ここに画像の説明を挿入

パッケージ/apps/設定/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>

パッケージ/apps/Settings/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java


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

パッケージ/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には呼び出し権限がありません。呼び出し方法は2つあります。

  1. アプリにはシステム 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

参考

Android APP グローバル白黒実装スキーム
Android グローバル設定 APP を白黒モードに設定する 2 つのソリューション デバイス
で開発者向けオプションを構成する

おすすめ

転載: blog.csdn.net/ansondroider/article/details/131112051