Skip to content

Commit

Permalink
Code improvements for android extractor
Browse files Browse the repository at this point in the history
  • Loading branch information
sangupta committed Apr 12, 2019
1 parent d8f6291 commit a13db91
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@
import java.util.ArrayList;
import java.util.List;

import com.sangupta.colors.extract.android.Bitmap;
import com.sangupta.colors.extract.android.ColorCutQuantizer;
import com.sangupta.colors.extract.android.Palette;
import com.sangupta.colors.extract.android.Target;
import com.sangupta.colors.Swatch;
import com.sangupta.colors.model.RGB;

/**
* This class is based on the Android source code to extract colors from a given
Expand All @@ -39,12 +37,12 @@
public class AndroidColorExtractor {

static final int DEFAULT_RESIZE_BITMAP_AREA = 112 * 112;

static final int DEFAULT_CALCULATE_NUMBER_COLORS = 16;

private final List<PaletteSwatch> mSwatches;
private final List<PaletteSwatch> swatches;

private final Bitmap mBitmap;
private final Bitmap bitmapImage;

private final List<Target> targets = new ArrayList<Target>();

Expand All @@ -57,23 +55,26 @@ public class AndroidColorExtractor {
private final List<PaletteFilter> filters = new ArrayList<PaletteFilter>();

/**
* Construct a new {@link Builder} using a source {@link Bitmap}
*
* @param bitmap
*/
public AndroidColorExtractor(Bitmap bitmap) {
if (bitmap == null) {
throw new IllegalArgumentException("Bitmap is not valid");
}
filters.add(PaletteFilter.DEFAULT_FILTER);
mBitmap = bitmap;
mSwatches = null;

this.filters.add(PaletteFilter.DEFAULT_FILTER);

this.bitmapImage = bitmap;
this.swatches = null;

// Add the default targets
targets.add(Target.LIGHT_VIBRANT);
targets.add(Target.VIBRANT);
targets.add(Target.DARK_VIBRANT);
targets.add(Target.LIGHT_MUTED);
targets.add(Target.MUTED);
targets.add(Target.DARK_MUTED);
this.targets.add(Target.LIGHT_VIBRANT);
this.targets.add(Target.VIBRANT);
this.targets.add(Target.DARK_VIBRANT);
this.targets.add(Target.LIGHT_MUTED);
this.targets.add(Target.MUTED);
this.targets.add(Target.DARK_MUTED);
}

/**
Expand All @@ -85,7 +86,7 @@ public AndroidColorExtractor(Bitmap bitmap) {
* faces then this value should be increased to ~24.
*/
public AndroidColorExtractor maximumColorCount(int colors) {
maxColors = colors;
this.maxColors = colors;
return this;
}

Expand All @@ -104,8 +105,8 @@ public AndroidColorExtractor maximumColorCount(int colors) {
* should cover, or any value &lt;= 0 to disable resizing.
*/
public AndroidColorExtractor resizeBitmapArea(final int area) {
resizeArea = area;
resizeMaxDimension = -1;
this.resizeArea = area;
this.resizeMaxDimension = -1;
return this;
}

Expand All @@ -114,7 +115,7 @@ public AndroidColorExtractor resizeBitmapArea(final int area) {
* automatically by {@link Palette}.
*/
public AndroidColorExtractor clearFilters() {
filters.clear();
this.filters.clear();
return this;
}

Expand All @@ -128,6 +129,7 @@ public AndroidColorExtractor addFilter(PaletteFilter filter) {
if (filter != null) {
filters.add(filter);
}

return this;
}

Expand All @@ -139,8 +141,8 @@ public AndroidColorExtractor addFilter(PaletteFilter filter) {
* </p>
*/
public AndroidColorExtractor addTarget(final Target target) {
if (!targets.contains(target)) {
targets.add(target);
if (!this.targets.contains(target)) {
this.targets.add(target);
}
return this;
}
Expand All @@ -150,8 +152,8 @@ public AndroidColorExtractor addTarget(final Target target) {
* automatically by {@link Palette}.
*/
public AndroidColorExtractor clearTargets() {
if (targets != null) {
targets.clear();
if (this.targets != null) {
this.targets.clear();
}
return this;
}
Expand All @@ -162,26 +164,26 @@ public AndroidColorExtractor clearTargets() {
public Palette generate() {
List<PaletteSwatch> swatches;

if (mBitmap != null) {
if (this.bitmapImage != null) {
// We have a Bitmap so we need to use quantization to reduce the number of
// colors

// First we'll scale down the bitmap if needed
final Bitmap bitmap = scaleBitmapDown(mBitmap);
final Bitmap bitmap = scaleBitmapDown(this.bitmapImage);

// Now generate a quantizer from the Bitmap
final ColorCutQuantizer quantizer = new ColorCutQuantizer(getPixelsFromBitmap(bitmap), maxColors,
filters.isEmpty() ? null : filters.toArray(new PaletteFilter[filters.size()]));
final ColorCutQuantizer quantizer = new ColorCutQuantizer(getPixelsFromBitmap(bitmap), this.maxColors,
this.filters.isEmpty() ? null : this.filters.toArray(new PaletteFilter[this.filters.size()]));

swatches = quantizer.getQuantizedColors();

} else {
// Else we're using the provided swatches
swatches = mSwatches;
swatches = this.swatches;
}

// Now create a Palette instance
final Palette palette = new Palette(swatches, targets);
final Palette palette = new Palette(swatches, this.targets);
// And make it generate itself
palette.generate();

Expand All @@ -198,15 +200,15 @@ private int[] getPixelsFromBitmap(Bitmap bitmap) {
private Bitmap scaleBitmapDown(final Bitmap bitmap) {
double scaleRatio = -1;

if (resizeArea > 0) {
if (this.resizeArea > 0) {
final int bitmapArea = bitmap.getWidth() * bitmap.getHeight();
if (bitmapArea > resizeArea) {
scaleRatio = Math.sqrt(resizeArea / (double) bitmapArea);
if (bitmapArea > this.resizeArea) {
scaleRatio = Math.sqrt(this.resizeArea / (double) bitmapArea);
}
} else if (resizeMaxDimension > 0) {
} else if (this.resizeMaxDimension > 0) {
final int maxDimension = Math.max(bitmap.getWidth(), bitmap.getHeight());
if (maxDimension > resizeMaxDimension) {
scaleRatio = resizeMaxDimension / (double) maxDimension;
if (maxDimension > this.resizeMaxDimension) {
scaleRatio = this.resizeMaxDimension / (double) maxDimension;
}
}

Expand All @@ -215,7 +217,8 @@ private Bitmap scaleBitmapDown(final Bitmap bitmap) {
return bitmap;
}

return Bitmap.createScaledBitmap(bitmap, (int) Math.ceil(bitmap.getWidth() * scaleRatio), (int) Math.ceil(bitmap.getHeight() * scaleRatio));
return Bitmap.createScaledBitmap(bitmap, (int) Math.ceil(bitmap.getWidth() * scaleRatio),
(int) Math.ceil(bitmap.getHeight() * scaleRatio));
}

/**
Expand All @@ -229,10 +232,10 @@ private Bitmap scaleBitmapDown(final Bitmap bitmap) {
* @return A Color Hex String
*/
public static int getColor(BufferedImage image) {
if(image == null) {
if (image == null) {
throw new IllegalArgumentException("Image cannot be null");
}

AndroidColorExtractor extractor = new AndroidColorExtractor(new Bitmap(image));
Palette palette = extractor.generate();
PaletteSwatch swatch = palette.getVibrantSwatch();
Expand All @@ -248,5 +251,40 @@ public static int getColor(BufferedImage image) {
int color = swatch.getRgb();
return color;
}


/**
* Get a {@link Swatch} of all dominant colors.
*
* @param image the {@link BufferedImage} to use
*
* @return
*/
public static Swatch<RGB> getSwatch(BufferedImage image) {
if (image == null) {
throw new IllegalArgumentException("Image cannot be null");
}

AndroidColorExtractor extractor = new AndroidColorExtractor(new Bitmap(image));
Palette palette = extractor.generate();

Swatch<RGB> swatch = new Swatch<>();
addToSwatch(swatch, palette.getVibrantColor());

return swatch;
}

/**
* Convert android swatch color to {@link RGB} color and add it to the
* {@link Swatch}.
*
* @param swatch
* @param color
*/
private static void addToSwatch(Swatch<RGB> swatch, int color) {
if (color < 0) {
return;
}

swatch.add(new RGB(color));
}
}
Loading

0 comments on commit a13db91

Please sign in to comment.