Skip to content

Commit

Permalink
Improve visualizer color selection.
Browse files Browse the repository at this point in the history
Make sure to select the color that contrasts the most to the artwork.

Change-Id: I0043463e05132a01f8ff3351565b672825779079
  • Loading branch information
maniac103 committed Apr 27, 2016
1 parent ac7e035 commit 2e0534f
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 17 deletions.
2 changes: 1 addition & 1 deletion src/com/cyanogenmod/eleven/ui/activities/HomeActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ protected BitmapWithColors doInBackground(Void... params) {
@Override
protected void onPostExecute(BitmapWithColors bmc) {
updateVisualizerColor(bmc != null
? bmc.getVibrantColor() : Color.TRANSPARENT);
? bmc.getContrastingColor() : Color.TRANSPARENT);
updateStatusBarColor(bmc != null
? bmc.getVibrantDarkColor() : Color.TRANSPARENT);
}
Expand Down
104 changes: 88 additions & 16 deletions src/com/cyanogenmod/eleven/utils/BitmapWithColors.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,42 @@
import android.graphics.Bitmap;
import android.graphics.Color;
import android.support.v7.graphics.Palette;
import android.support.v7.graphics.Target;
import android.util.LruCache;

public class BitmapWithColors {
private static final class BitmapColors {
public int mVibrantColor;
public int mVibrantDarkColor;
public final int mVibrantColor;
public final int mVibrantDarkColor;
public final int mVibrantLightColor;
public final int mDominantColor;

public BitmapColors(Palette palette) {
mVibrantColor = determineColor(palette.getVibrantSwatch());
mVibrantDarkColor = determineColor(palette.getDarkVibrantSwatch());
mVibrantLightColor = determineColor(palette.getLightVibrantSwatch());
mDominantColor = determineColor(getDominantSwatch(palette));
}

public BitmapColors(int vibrantColor, int vibrantDarkColor) {
mVibrantColor = vibrantColor;
mVibrantDarkColor = vibrantDarkColor;
mVibrantLightColor = Color.TRANSPARENT;
mDominantColor = vibrantColor;
}

private int determineColor(Palette.Swatch swatch) {
return swatch != null ? swatch.getRgb() : Color.TRANSPARENT;
}

private static Palette.Swatch getDominantSwatch(Palette palette) {
Palette.Swatch dominant = null;
for (Palette.Swatch swatch : palette.getSwatches()) {
if (dominant == null || swatch.getPopulation() > dominant.getPopulation()) {
dominant = swatch;
}
}
return dominant;
}
}

Expand Down Expand Up @@ -70,6 +96,59 @@ public int getVibrantDarkColor() {
return mColors.mVibrantDarkColor;
}

public int getContrastingColor() {
loadColorsIfNeeded();

float contrastToDark = computeContrastBetweenColors(mColors.mDominantColor,
mColors.mVibrantDarkColor);
float contrastToLight = computeContrastBetweenColors(mColors.mDominantColor,
mColors.mVibrantLightColor);
float contrastToVibrant = computeContrastBetweenColors(mColors.mDominantColor,
mColors.mVibrantColor);

int bestColor = mColors.mDominantColor;
float bestContrast = -1;
if (contrastToVibrant > bestContrast) {
bestColor = mColors.mVibrantColor;
bestContrast = contrastToVibrant;
}
if (contrastToDark > bestContrast) {
bestColor = mColors.mVibrantDarkColor;
bestContrast = contrastToDark;
}
if (contrastToLight > bestContrast) {
bestColor = mColors.mVibrantLightColor;
bestContrast = contrastToLight;
}

return bestColor;
}

/** Calculates the constrast between two colors, using the algorithm provided by the WCAG v2. */
private static float computeContrastBetweenColors(int bg, int fg) {
if (bg == Color.TRANSPARENT || fg == Color.TRANSPARENT || bg == fg) {
return -1;
}

float bgR = Color.red(bg) / 255f;
float bgG = Color.green(bg) / 255f;
float bgB = Color.blue(bg) / 255f;
bgR = (bgR < 0.03928f) ? bgR / 12.92f : (float) Math.pow((bgR + 0.055f) / 1.055f, 2.4f);
bgG = (bgG < 0.03928f) ? bgG / 12.92f : (float) Math.pow((bgG + 0.055f) / 1.055f, 2.4f);
bgB = (bgB < 0.03928f) ? bgB / 12.92f : (float) Math.pow((bgB + 0.055f) / 1.055f, 2.4f);
float bgL = 0.2126f * bgR + 0.7152f * bgG + 0.0722f * bgB;

float fgR = Color.red(fg) / 255f;
float fgG = Color.green(fg) / 255f;
float fgB = Color.blue(fg) / 255f;
fgR = (fgR < 0.03928f) ? fgR / 12.92f : (float) Math.pow((fgR + 0.055f) / 1.055f, 2.4f);
fgG = (fgG < 0.03928f) ? fgG / 12.92f : (float) Math.pow((fgG + 0.055f) / 1.055f, 2.4f);
fgB = (fgB < 0.03928f) ? fgB / 12.92f : (float) Math.pow((fgB + 0.055f) / 1.055f, 2.4f);
float fgL = 0.2126f * fgR + 0.7152f * fgG + 0.0722f * fgB;

return Math.abs((fgL + 0.05f) / (bgL + 0.05f));
}

private synchronized void loadColorsIfNeeded() {
if (mColors != null) {
return;
Expand All @@ -82,24 +161,17 @@ private synchronized void loadColorsIfNeeded() {
return;
}

final Palette p = Palette.generate(mBitmap);
final Palette p = Palette.from(mBitmap)
.clearTargets()
.addTarget(Target.VIBRANT)
.addTarget(Target.LIGHT_VIBRANT)
.addTarget(Target.DARK_VIBRANT)
.generate();
if (p == null) {
return;
}

int vibrantColor = Color.TRANSPARENT;
int vibrantDarkColor = Color.TRANSPARENT;

Palette.Swatch swatch = p.getDarkVibrantSwatch();
if (swatch != null) {
vibrantDarkColor = swatch.getRgb();
}
swatch = p.getVibrantSwatch();
if (swatch != null) {
vibrantColor = swatch.getRgb();
}

mColors = new BitmapColors(vibrantColor, vibrantDarkColor);
mColors = new BitmapColors(p);
synchronized (sCachedColors) {
sCachedColors.put(mBitmapKey, mColors);
}
Expand Down

0 comments on commit 2e0534f

Please sign in to comment.