| /* |
| * 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<Palette.Swatch> 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; |
| } |
| } |