Android Color Mode软件架构分析

 

       本文档基于AndroidQ,因为暂时没有Q的代码连接,代码引用连接是AndroidP.

       打开你Android手机“设置”界面,点击“显示”=>“高级”=>“颜色”,你可以看到手机生产商为你定制的显示效果选项。如果是Google原生系统的话,则一般有三个选项,如下是Pixel4的Color Modes设置界面:


1. APP和Framework Java层相关代码:

       从下面Android代码看,Google在应用层定义了4个ColorMode,分别是自然色模式COLOR_MODE_NATURAL(0)、效果增强模式COLOR_MODE_BOOSTED(1)、鲜艳模式 COLOR_MODE_SATURATED(2) 、和自动调节模式COLOR_MODE_AUTOMATIC(3)。

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/com/android/internal/app/ColorDisplayController.java

88    /**
89     * Color mode with natural colors.
90     *
91     * @see #setColorMode(int)
92     */
93    public static final int COLOR_MODE_NATURAL = 0;
94    /**
95     * Color mode with boosted colors.
96     *
97     * @see #setColorMode(int)
98     */
99    public static final int COLOR_MODE_BOOSTED = 1;
100    /**
101     * Color mode with saturated colors.
102     *
103     * @see #setColorMode(int)
104     */
105    public static final int COLOR_MODE_SATURATED = 2;
106    /**
107     * Color mode with automatic colors.
108     *
109     * @see #setColorMode(int)
110     */
111    public static final int COLOR_MODE_AUTOMATIC = 3;

       从图1可以看出,Pixel4在设置中给出了3个ColorModes,分别是自然色、效果增强和自动调节。这个界面的colorModes选项,可以通过以下config来配置,一般放到项目本身的overlay目录。

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/res/res/values/symbols.xml#2967

961    <!-- Indicate available ColorDisplayController.COLOR_MODE_xxx. -->
962    <integer-array name="config_availableColorModes">
963        <!-- Example:
964        <item>0</item>
965        <item>1</item>
966        <item>3</item>
967        -->

       设置UI中的colorModes是怎么实现的呢?看DisplayTransformManager.java中的setColorMode函数。有两个接口很关键,它们是applySaturation()和setDisplayColor()。他们分别调用了SurfaceFlinger的transact code 1022/1023,用来设置饱和度和colorSetting,从而综合得出一个colorMode的效果。代码如下图。顺便提下,除了colorMode外,Android显示效果中的夜晚模式以及颜色反转等,是通过另外一个接口setColorTransform配置不同的matrix来实现的。

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

327      public boolean setColorMode(int colorMode, float[] nightDisplayMatrix) {
328          if (colorMode == ColorDisplayManager.COLOR_MODE_NATURAL) {
329              applySaturation(COLOR_SATURATION_NATURAL);
330              setDisplayColor(DISPLAY_COLOR_MANAGED);
331          } else if (colorMode == ColorDisplayManager.COLOR_MODE_BOOSTED) {
340              applySaturation(COLOR_SATURATION_BOOSTED);
341              setDisplayColor(DISPLAY_COLOR_MANAGED);
343          } else if (colorMode == ColorDisplayManager.COLOR_MODE_SATURATED) {
344              applySaturation(COLOR_SATURATION_NATURAL);
345              setDisplayColor(DISPLAY_COLOR_UNMANAGED);
346          } else if (colorMode == ColorDisplayManager.COLOR_MODE_AUTOMATIC) {
347              applySaturation(COLOR_SATURATION_NATURAL);
348              setDisplayColor(DISPLAY_COLOR_ENHANCED);
349          } else if (colorMode >= ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MIN
350                  && colorMode <= ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MAX) {
351              applySaturation(COLOR_SATURATION_NATURAL);
352              setDisplayColor(colorMode);
353          }
354   }

       可以看出,除了效果增强模式COLOR_MODE_BOOSTED使用了110%(COLOR_SATURATION_BOOSTED)的饱和度,其他模式都是使用100%(COLOR_SATURATION_NATURAL )的饱和度。几个相关定义如下:

    //用来调用surfaceFlinger的transact code如下
    //SurfaceFlinger global saturation factor.
    private static final int SURFACE_FLINGER_TRANSACTION_SATURATION = 1022;
    //SurfaceFlinger display color (managed, unmanaged, etc.).
    private static final int SURFACE_FLINGER_TRANSACTION_DISPLAY_COLOR = 1023;
    private static final int SURFACE_FLINGER_TRANSACTION_COLOR_MATRIX = 1015;

    //Google饱和度初设值
    private static final float COLOR_SATURATION_NATURAL = 1.0f;
    private static final float COLOR_SATURATION_BOOSTED = 1.1f;

    //Google定义的colorSetting值,在native层会转化为renderIntent,用来区分相同colorSpace的不同底层colorMode
    private static final int DISPLAY_COLOR_MANAGED = 0;
    private static final int DISPLAY_COLOR_UNMANAGED = 1;
    private static final int DISPLAY_COLOR_ENHANCED = 2;


2. SurfaceFlinger相关代码

       上面我们讲了app层的代码,知道DisplayTransformManager会调用SurfaceFlinger来配置saturation和colorSetting。上层应用可以随时设置saturation和colorSetting,并记为mGlobalSaturationFactormDisplayColorSetting,但真正的colorMode生效是实际的layer更新时才向HAL层传递的。mGlobalSaturationFactor会更新mDrawingState.colorMatrix并通过setColorTransform()来生效。

frameworks/native

  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android倒车轨迹线的实现方法可以分为两种,一种是使用Camera2 API获取摄像头预览画面并在上面绘制轨迹线,另一种是使用第三方库实现。 1. 使用Camera2 API获取摄像头预览画面并在上面绘制轨迹线 首先需要在AndroidManifest.xml文件中添加摄像头权限: ```xml <uses-permission android:name="android.permission.CAMERA" /> ``` 然后在布局文件中添加TextureView控件用于预览摄像头画面: ```xml <TextureView android:id="@+id/textureView" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 接下来,在Activity中获取TextureView控件并打开后置摄像头: ```java private TextureView textureView; private CameraDevice cameraDevice; private CameraCaptureSession cameraCaptureSession; private CaptureRequest.Builder captureRequestBuilder; private HandlerThread backgroundThread; private Handler backgroundHandler; private Size imageDimension; private void openCamera() { CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { String cameraId = manager.getCameraIdList()[0]; CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); imageDimension = map.getOutputSizes(SurfaceTexture.class)[0]; manager.openCamera(cameraId, stateCallback, null); } catch (CameraAccessException e) { e.printStackTrace(); } } private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice camera) { cameraDevice = camera; createCameraPreview(); } @Override public void onDisconnected(@NonNull CameraDevice camera) { cameraDevice.close(); } @Override public void onError(@NonNull CameraDevice camera, int error) { cameraDevice.close(); cameraDevice = null; } }; private void createCameraPreview() { SurfaceTexture texture = textureView.getSurfaceTexture(); texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight()); Surface surface = new Surface(texture); try { captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); captureRequestBuilder.addTarget(surface); cameraDevice.createCaptureSession(Collections.singletonList(surface), new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession session) { if (cameraDevice == null) return; cameraCaptureSession = session; updatePreview(); } @Override public void onConfigureFailed(@NonNull CameraCaptureSession session) { } }, null); } catch (CameraAccessException e) { e.printStackTrace(); } } private void updatePreview() { if (cameraDevice == null) return; captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); try { cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } ``` 以上代码中,首先通过CameraManager获取后置摄像头的ID,然后获取该摄像头的特性和输出尺寸,在onOpened()方法中创建CameraCaptureSession并设置预览画面,最后在updatePreview()方法中更新预览画面。 接下来,可以在预览画面上绘制倒车轨迹线。通过TextureView控件获取画布并绘制轨迹线: ```java private void drawPath() { Paint paint = new Paint(); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(5); paint.setColor(Color.RED); Bitmap bitmap = textureView.getBitmap(); Canvas canvas = textureView.lockCanvas(); canvas.drawBitmap(bitmap, 0, 0, null); Path path = new Path(); path.moveTo(0, textureView.getHeight() / 2); path.lineTo(textureView.getWidth(), textureView.getHeight() / 2); canvas.drawPath(path, paint); textureView.unlockCanvasAndPost(canvas); } ``` 以上代码中,首先获取TextureView控件的Bitmap对象,然后获取画布并绘制预览画面,最后绘制轨迹线并释放画布。 2. 使用第三方库实现 除了使用Camera2 API自行实现倒车轨迹线外,也可以使用第三方库实现。常用的第三方库有CameraView和CameraKit-Android。 以CameraView为例,首先需要在build.gradle文件中添加依赖: ```groovy implementation 'com.otaliastudios:cameraview:2.7.2' ``` 然后在布局文件中添加CameraView控件: ```xml <com.otaliastudios.cameraview.CameraView android:id="@+id/cameraView" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 接下来,在Activity中获取CameraView控件并设置预览画面: ```java private CameraView cameraView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); cameraView = findViewById(R.id.cameraView); cameraView.setLifecycleOwner(this); cameraView.addFrameProcessor(frame -> drawPath()); } ``` 以上代码中,首先获取CameraView控件并设置生命周期,然后添加FrameProcessor用于在预览画面上绘制倒车轨迹线。 最后,实现drawPath()方法绘制倒车轨迹线: ```java private void drawPath() { Paint paint = new Paint(); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(5); paint.setColor(Color.RED); Bitmap bitmap = cameraView.getBitmap(); Canvas canvas = cameraView.getPreviewCanvas(); Path path = new Path(); path.moveTo(0, cameraView.getHeight() / 2); path.lineTo(cameraView.getWidth(), cameraView.getHeight() / 2); canvas.drawPath(path, paint); } ``` 以上代码中,首先获取CameraView控件的Bitmap对象,然后获取预览画面的画布并绘制轨迹线。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值