author | Margaret Leibovic <margaret.leibovic@gmail.com> |
Thu, 02 May 2013 11:53:13 -0700 (2013-05-02) | |
changeset 130651 | b036d96c4c87c6c2c718c336431ea258594f4dd3 |
parent 130650 | ebad4b72a6ea110261c5baa265e64d2e1efc5050 |
child 130652 | 27f8c1c2e09e9e0bb77c59fcf211efbb9df037cf |
push id | 24627 |
push user | ryanvm@gmail.com |
push date | Fri, 03 May 2013 01:34:43 +0000 (2013-05-03) |
treeherder | mozilla-central@cdd14d9b3aae [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bnicholson |
bugs | 867249 |
milestone | 23.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/mobile/android/base/gfx/BitmapUtils.java +++ b/mobile/android/base/gfx/BitmapUtils.java @@ -50,58 +50,73 @@ public final class BitmapUtils { return bitmap; } public static int getDominantColor(Bitmap source) { return getDominantColor(source, true); } public static int getDominantColor(Bitmap source, boolean applyThreshold) { - int[] colors = new int[37]; - int[] sat = new int[11]; - int[] val = new int[11]; - int maxH = 0; - int maxS = 0; - int maxV = 0; if (source == null) return Color.argb(255,255,255,255); + // Keep track of how many times a hue in a given bin appears in the image. + // Hue values range [0 .. 360), so dividing by 10, we get 36 bins. + int[] colorBins = new int[36]; + + // The bin with the most colors. Initialize to -1 to prevent accidentally + // thinking the first bin holds the dominant color. + int maxBin = -1; + + // Keep track of sum hue/saturation/value per hue bin, which we'll use to + // compute an average to for the dominant color. + float[] sumHue = new float[36]; + float[] sumSat = new float[36]; + float[] sumVal = new float[36]; + for (int row = 0; row < source.getHeight(); row++) { for (int col = 0; col < source.getWidth(); col++) { int c = source.getPixel(col, row); + // Ignore pixels with a certain transparency. if (Color.alpha(c) < 128) continue; float[] hsv = new float[3]; Color.colorToHSV(c, hsv); - // arbitrarily chosen values for "white" and "black" - if (applyThreshold && hsv[1] <= 0.35f && hsv[2] <= 0.35f) + // If a threshold is applied, ignore arbitrarily chosen values for "white" and "black". + if (applyThreshold && (hsv[1] <= 0.35f || hsv[2] <= 0.35f)) continue; - int h = Math.round(hsv[0] / 10.0f); - int s = Math.round(hsv[1] * 10.0f); - int v = Math.round(hsv[2] * 10.0f); - colors[h]++; - sat[s]++; - val[v]++; + // We compute the dominant color by putting colors in bins based on their hue. + int bin = (int) Math.floor(hsv[0] / 10.0f); - // we only care about the most unique non white or black hue - if threshold is applied - // we also store its saturation and value params to match the color better - if (colors[h] > colors[maxH]) { - maxH = h; - maxS = s; - maxV = v; - } + // Update the sum hue/saturation/value for this bin. + sumHue[bin] = sumHue[bin] + hsv[0]; + sumSat[bin] = sumSat[bin] + hsv[1]; + sumVal[bin] = sumVal[bin] + hsv[2]; + + // Increment the number of colors in this bin. + colorBins[bin]++; + + // Keep track of the bin that holds the most colors. + if (maxBin < 0 || colorBins[bin] > colorBins[maxBin]) + maxBin = bin; } } + + // maxBin may never get updated if the image holds only transparent and/or black/white pixels. + if (maxBin < 0) + return Color.argb(255,255,255,255); + + // Return a color with the average hue/saturation/value of the bin with the most colors. float[] hsv = new float[3]; - hsv[0] = maxH*10.0f; - hsv[1] = (float)maxS/10.0f; - hsv[2] = (float)maxV/10.0f; + hsv[0] = sumHue[maxBin]/colorBins[maxBin]; + hsv[1] = sumSat[maxBin]/colorBins[maxBin]; + hsv[2] = sumVal[maxBin]/colorBins[maxBin]; return Color.HSVToColor(hsv); } /** * Decodes a bitmap from a Base64 data URI. * * @param dataURI a Base64-encoded data URI string * @return the decoded bitmap, or null if the data URI is invalid