Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4bbdff6 authored by Vinit Nayak's avatar Vinit Nayak
Browse files

Use median instead of mean for sampling border luma

Using median of the luma for all border pixels
gives a more accurate indication of dominant
background color to use during the screen
rotation animation than does using the average.

fixes: 150056201
Test: Existing tests pass
Also can visually see the change in Google
Photos app where you have a bright image on
the black background. Now background stays
as black instead of being gray.

Change-Id: I87bc87930aff48f90f271fc1783e70caf61dc7f4
parent 0b66590f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -205,7 +205,7 @@ class ScreenRotationAnimation {
            SurfaceControl.ScreenshotGraphicBuffer gb =
                    mService.mDisplayManagerInternal.screenshot(displayId);
            if (gb != null) {
                mStartLuma = RotationAnimationUtils.getAvgBorderLuma(gb.getGraphicBuffer(),
                mStartLuma = RotationAnimationUtils.getMedianBorderLuma(gb.getGraphicBuffer(),
                        gb.getColorSpace());
                try {
                    surface.attachAndQueueBufferWithColorSpace(gb.getGraphicBuffer(),
+17 −11
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ import android.view.Display;
import android.view.Surface;
import android.view.SurfaceControl;

import java.util.Arrays;


/** Helper functions for the {@link com.android.server.wm.ScreenRotationAnimation} class*/
public class RotationAnimationUtils {
@@ -35,31 +37,35 @@ public class RotationAnimationUtils {
     * luminance at the borders of the bitmap
     * @return the average luminance of all the pixels at the borders of the bitmap
     */
    public static float getAvgBorderLuma(GraphicBuffer graphicBuffer, ColorSpace colorSpace) {
    public static float getMedianBorderLuma(GraphicBuffer graphicBuffer, ColorSpace colorSpace) {
        Bitmap hwBitmap = Bitmap.wrapHardwareBuffer(graphicBuffer, colorSpace);
        if (hwBitmap == null) {
            return 0;
        }

        Bitmap swaBitmap = hwBitmap.copy(Bitmap.Config.ARGB_8888, false);
        float totalLuma = 0;
        int height = swaBitmap.getHeight();
        int width = swaBitmap.getWidth();
        float[] borderLumas = new float[2 * width + 2 * height];
        int i;
        for (i = 0; i < width; i++) {
            totalLuma += swaBitmap.getColor(i, 0).luminance();
            totalLuma += swaBitmap.getColor(i, height - 1).luminance();
        int index = 0;
        for (i = 0; i < width; i++, index += 2) {
            borderLumas[index] = swaBitmap.getColor(i, 0).luminance();
            borderLumas[index + 1] = swaBitmap.getColor(i, height - 1).luminance();
        }
        for (i = 0; i < height; i++) {
            totalLuma += swaBitmap.getColor(0, i).luminance();
            totalLuma += swaBitmap.getColor(width - 1, i).luminance();
        for (i = 0; i < height; i++, index += 2) {
            borderLumas[index] = swaBitmap.getColor(0, i).luminance();
            borderLumas[index + 1] = swaBitmap.getColor(width - 1, i).luminance();
        }
        return totalLuma / (2 * width + 2 * height);
        // Oh, is this too simple and inefficient for you?
        // How about implementing a O(n) solution? https://en.wikipedia.org/wiki/Median_of_medians
        Arrays.sort(borderLumas);
        return borderLumas[borderLumas.length / 2];
    }

    /**
     * Gets the average border luma by taking a screenshot of the {@param surfaceControl}.
     * @see #getAvgBorderLuma(GraphicBuffer, ColorSpace)
     * @see #getMedianBorderLuma(GraphicBuffer, ColorSpace)
     */
    public static float getLumaOfSurfaceControl(Display display, SurfaceControl surfaceControl) {
        if (surfaceControl ==  null) {
@@ -75,7 +81,7 @@ public class RotationAnimationUtils {
            return 0;
        }

        return RotationAnimationUtils.getAvgBorderLuma(buffer.getGraphicBuffer(),
        return RotationAnimationUtils.getMedianBorderLuma(buffer.getGraphicBuffer(),
                buffer.getColorSpace());
    }

+19 −7
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ public class RotationAnimationUtilsTest {
    public void blackLuma() {
        Bitmap swBitmap = createBitmap(0);
        GraphicBuffer gb = swBitmapToGraphicsBuffer(swBitmap);
        float borderLuma = RotationAnimationUtils.getAvgBorderLuma(gb, mColorSpace);
        float borderLuma = RotationAnimationUtils.getMedianBorderLuma(gb, mColorSpace);
        assertEquals(0, borderLuma, 0);
    }

@@ -58,7 +58,15 @@ public class RotationAnimationUtilsTest {
    public void whiteLuma() {
        Bitmap swBitmap = createBitmap(1);
        GraphicBuffer gb = swBitmapToGraphicsBuffer(swBitmap);
        float borderLuma = RotationAnimationUtils.getAvgBorderLuma(gb, mColorSpace);
        float borderLuma = RotationAnimationUtils.getMedianBorderLuma(gb, mColorSpace);
        assertEquals(1, borderLuma, 0);
    }

    @Test
    public void unevenBitmapDimens() {
        Bitmap swBitmap = createBitmap(1, BITMAP_WIDTH + 1, BITMAP_HEIGHT + 1);
        GraphicBuffer gb = swBitmapToGraphicsBuffer(swBitmap);
        float borderLuma = RotationAnimationUtils.getMedianBorderLuma(gb, mColorSpace);
        assertEquals(1, borderLuma, 0);
    }

@@ -67,7 +75,7 @@ public class RotationAnimationUtilsTest {
        Bitmap swBitmap = createBitmap(1);
        setBorderLuma(swBitmap, 0);
        GraphicBuffer gb = swBitmapToGraphicsBuffer(swBitmap);
        float borderLuma = RotationAnimationUtils.getAvgBorderLuma(gb, mColorSpace);
        float borderLuma = RotationAnimationUtils.getMedianBorderLuma(gb, mColorSpace);
        assertEquals(0, borderLuma, 0);
    }

@@ -76,7 +84,7 @@ public class RotationAnimationUtilsTest {
        Bitmap swBitmap = createBitmap(0);
        setBorderLuma(swBitmap, 1);
        GraphicBuffer gb = swBitmapToGraphicsBuffer(swBitmap);
        float borderLuma = RotationAnimationUtils.getAvgBorderLuma(gb, mColorSpace);
        float borderLuma = RotationAnimationUtils.getMedianBorderLuma(gb, mColorSpace);
        assertEquals(1, borderLuma, 0);
    }

@@ -123,9 +131,13 @@ public class RotationAnimationUtilsTest {
    }

    private Bitmap createBitmap(float luma) {
        Bitmap bitmap = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, ARGB_8888);
        for (int i = 0; i < BITMAP_WIDTH; i++) {
            for (int j = 0; j < BITMAP_HEIGHT; j++) {
        return createBitmap(luma, BITMAP_WIDTH, BITMAP_HEIGHT);
    }

    private Bitmap createBitmap(float luma, int width, int height) {
        Bitmap bitmap = Bitmap.createBitmap(width, height, ARGB_8888);
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                bitmap.setPixel(i, j, Color.argb(1, luma, luma, luma));
            }
        }