/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.systemui.statusbar.notification; import android.graphics.Bitmap; import android.graphics.Color; import androidx.palette.graphics.Palette; import java.util.List; /** * A gutted class that now contains only a color extraction utility used by the * MediaArtworkProcessor, which has otherwise supplanted this. * * TODO(b/182926117): move this into MediaArtworkProcessor.kt */ public class MediaNotificationProcessor { /** * The population fraction to select a white or black color as the background over a color. */ private static final float POPULATION_FRACTION_FOR_WHITE_OR_BLACK = 2.5f; private static final float BLACK_MAX_LIGHTNESS = 0.08f; private static final float WHITE_MIN_LIGHTNESS = 0.90f; private static final int RESIZE_BITMAP_AREA = 150 * 150; private MediaNotificationProcessor() { } /** * Finds an appropriate background swatch from media artwork. * * @param artwork Media artwork * @return Swatch that should be used as the background of the media notification. */ public static Palette.Swatch findBackgroundSwatch(Bitmap artwork) { return findBackgroundSwatch(generateArtworkPaletteBuilder(artwork).generate()); } /** * Finds an appropriate background swatch from the palette of media artwork. * * @param palette Artwork palette, should be obtained from {@link generateArtworkPaletteBuilder} * @return Swatch that should be used as the background of the media notification. */ public static Palette.Swatch findBackgroundSwatch(Palette palette) { // by default we use the dominant palette Palette.Swatch dominantSwatch = palette.getDominantSwatch(); if (dominantSwatch == null) { return new Palette.Swatch(Color.WHITE, 100); } if (!isWhiteOrBlack(dominantSwatch.getHsl())) { return dominantSwatch; } // Oh well, we selected black or white. Lets look at the second color! List swatches = palette.getSwatches(); float highestNonWhitePopulation = -1; Palette.Swatch second = null; for (Palette.Swatch swatch : swatches) { if (swatch != dominantSwatch && swatch.getPopulation() > highestNonWhitePopulation && !isWhiteOrBlack(swatch.getHsl())) { second = swatch; highestNonWhitePopulation = swatch.getPopulation(); } } if (second == null) { return dominantSwatch; } if (dominantSwatch.getPopulation() / highestNonWhitePopulation > POPULATION_FRACTION_FOR_WHITE_OR_BLACK) { // The dominant swatch is very dominant, lets take it! // We're not filtering on white or black return dominantSwatch; } else { return second; } } /** * Generate a palette builder for media artwork. * * For producing a smooth background transition, the palette is extracted from only the left * side of the artwork. * * @param artwork Media artwork * @return Builder that generates the {@link Palette} for the media artwork. */ public static Palette.Builder generateArtworkPaletteBuilder(Bitmap artwork) { // for the background we only take the left side of the image to ensure // a smooth transition return Palette.from(artwork) .setRegion(0, 0, artwork.getWidth() / 2, artwork.getHeight()) .clearFilters() // we want all colors, red / white / black ones too! .resizeBitmapArea(RESIZE_BITMAP_AREA); } private static boolean isWhiteOrBlack(float[] hsl) { return isBlack(hsl) || isWhite(hsl); } /** * @return true if the color represents a color which is close to black. */ private static boolean isBlack(float[] hslColor) { return hslColor[2] <= BLACK_MAX_LIGHTNESS; } /** * @return true if the color represents a color which is close to white. */ private static boolean isWhite(float[] hslColor) { return hslColor[2] >= WHITE_MIN_LIGHTNESS; } }