Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0166d057 authored by Lucas Dupin's avatar Lucas Dupin Committed by Android (Google) Code Review
Browse files

Merge changes I561ba44b,Icaebd98e,Ic0bd4afc,Ia0f98434 into sc-dev

* changes:
  Move Wu check for max colors earlier.
  Ignore transparent pixels during WSMeans
  Fix create colors in Wu quantizer
  Fix initializing clusters with random randoms
parents e343ba69 7ef64c07
Loading
Loading
Loading
Loading
+4 −5
Original line number Original line Diff line number Diff line
@@ -22,20 +22,19 @@ import java.util.Random;
 * Represents a centroid in Kmeans algorithms.
 * Represents a centroid in Kmeans algorithms.
 */
 */
public class Mean {
public class Mean {
    private static final Random RANDOM = new Random(0);

    public float[] center;
    public float[] center;


    /**
    /**
     * Constructor.
     * Constructor.
     *
     *
     * @param upperBound maximum value of a dimension in the space Kmeans is optimizing in
     * @param upperBound maximum value of a dimension in the space Kmeans is optimizing in
     * @param random used to generate a random center
     */
     */
    Mean(int upperBound) {
    Mean(int upperBound, Random random) {
        center =
        center =
                new float[]{
                new float[]{
                        RANDOM.nextInt(upperBound + 1), RANDOM.nextInt(upperBound + 1),
                        random.nextInt(upperBound + 1), random.nextInt(upperBound + 1),
                        RANDOM.nextInt(upperBound + 1)
                        random.nextInt(upperBound + 1)
                };
                };
    }
    }


+21 −2
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.HashSet;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.Set;




@@ -57,13 +58,27 @@ public class WSMeansQuantizer implements Quantizer {
        }
        }


        if (maxColors > means.length) {
        if (maxColors > means.length) {
            // Always initialize Random with the same seed. Ensures the results of quantization
            // are consistent, even when random centroids are required.
            Random random = new Random(0x42688);
            int randomMeansToCreate = maxColors - means.length;
            int randomMeansToCreate = maxColors - means.length;
            for (int i = 0; i < randomMeansToCreate; i++) {
            for (int i = 0; i < randomMeansToCreate; i++) {
                mMeans[means.length + i] = new Mean(100);
                mMeans[means.length + i] = new Mean(100, random);
            }
            }
        }
        }


        for (int pixel : pixels) {
        for (int pixel : pixels) {
            // These are pixels from the bitmap that is being quantized.
            // Depending on the bitmap & downscaling, it may have pixels that are less than opaque
            // Ignore those pixels.
            ///
            // Note: they don't _have_ to be ignored, for example, we could instead turn them
            // opaque. Traditionally, including outside Android, quantizers ignore transparent
            // pixels, so that strategy was chosen.
            int alpha = (pixel >> 24);
            if (alpha < 255) {
                continue;
            }
            Integer currentCount = mCountByColor.get(pixel);
            Integer currentCount = mCountByColor.get(pixel);
            if (currentCount == null) {
            if (currentCount == null) {
                currentCount = 0;
                currentCount = 0;
@@ -105,8 +120,12 @@ public class WSMeansQuantizer implements Quantizer {
    /** Create random starting centroids for K-means. */
    /** Create random starting centroids for K-means. */
    public static float[][] randomMeans(int maxColors, int upperBound) {
    public static float[][] randomMeans(int maxColors, int upperBound) {
        float[][] means = new float[maxColors][];
        float[][] means = new float[maxColors][];

        // Always initialize Random with the same seed. Ensures the results of quantization
        // are consistent, even when random centroids are required.
        Random random = new Random(0x42688);
        for (int i = 0; i < maxColors; i++) {
        for (int i = 0; i < maxColors; i++) {
            means[i] = new Mean(upperBound).center;
            means[i] = new Mean(upperBound, random).center;
        }
        }
        return means;
        return means;
    }
    }
+8 −7
Original line number Original line Diff line number Diff line
@@ -78,7 +78,12 @@ public class WuQuantizer implements Quantizer {
        // All of the sample Wu implementations are reimplementations of a snippet of C code from
        // All of the sample Wu implementations are reimplementations of a snippet of C code from
        // the early 90s. They all cap the maximum # of colors at 256, and it is impossible to tell
        // the early 90s. They all cap the maximum # of colors at 256, and it is impossible to tell
        // if this is a requirement, a consequence of QUANT_SIZE, or arbitrary.
        // if this is a requirement, a consequence of QUANT_SIZE, or arbitrary.
        this.mMaxColors = Math.min(MAX_COLORS, maxColorCount);
        //
        // Also, the number of maximum colors should be capped at the number of pixels - otherwise,
        // If extraction is run on a set of pixels whose count is less than max colors,
        // then colors.length < max colors, and accesses to colors[index] throw an
        // ArrayOutOfBoundsException.
        this.mMaxColors = Math.min(Math.min(MAX_COLORS, maxColorCount), colors.length);
        Box[] cube = new Box[mMaxColors];
        Box[] cube = new Box[mMaxColors];
        int red, green, blue;
        int red, green, blue;


@@ -119,17 +124,13 @@ public class WuQuantizer implements Quantizer {
            }
            }
        }
        }


        // If extraction is run on a set of pixels whose count is less than the
        for (k = 0; k < mMaxColors; ++k) {
        // number of max colors, then colors.length < max colors, and accesses
        // to colors[index] inside the for loop throw an ArrayOutOfBoundsException.
        int numColorsToCreate = (int) Math.min(mMaxColors, colors.length);
        for (k = 0; k < numColorsToCreate; ++k) {
            weight = getVolume(cube[k], mWt);
            weight = getVolume(cube[k], mWt);
            if (weight > 0) {
            if (weight > 0) {
                red = (int) (getVolume(cube[k], mMr) / weight);
                red = (int) (getVolume(cube[k], mMr) / weight);
                green = (int) (getVolume(cube[k], mMg) / weight);
                green = (int) (getVolume(cube[k], mMg) / weight);
                blue = (int) (getVolume(cube[k], mMb) / weight);
                blue = (int) (getVolume(cube[k], mMb) / weight);
                colors[k] = ((red & 0x0ff) << 16) | ((green & 0x0ff) << 8) | (blue & 0x0ff);
                colors[k] = (255 << 24) | (red << 16) | (green << 8) | blue;
            } else {
            } else {
                colors[k] = 0;
                colors[k] = 0;
            }
            }