blob: 732c115571f849957d0c9ca756b1dbe06b9412e4 [file] [log] [blame]
/*
* 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;
}
}