public static BufferedImage reduce32(BufferedImage bi, int colors) {
int width = bi.getWidth();
int height = bi.getHeight();
int[][] pixels = new int[width][height];
WritableRaster r1 = bi.getRaster();
int[] argb = new int[4];
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
// this is easier than bi.getRGB, but still heavy
argb = r1.getPixel(x, y, argb);
int a = argb[3];
int r = argb[0];
int g = argb[1];
int b = argb[2];
pixels[x][y] = (a << 24) | (r << 16) | (g << 8) | (b);
}
}
int[] palette = Quantize32.quantizeImage(pixels, colors);
colors = palette.length;
// ImageIO (at least on Mac) does not like to *read* png images with
// only a single color in the color index
boolean useExtraColors = false;
int minimumColors = 2;
if (colors < minimumColors) {
colors = minimumColors;
useExtraColors = true;
}
byte[] r = new byte[colors];
byte[] g = new byte[colors];
byte[] b = new byte[colors];
byte[] a = new byte[colors];
if (useExtraColors) {
// can not be clear as ArcGIS does not handle PNG with multiple
// clear entries in the color index
Arrays.fill(r, (byte) OMColor.green.getRed());
Arrays.fill(g, (byte) OMColor.green.getGreen());
Arrays.fill(b, (byte) OMColor.green.getBlue());
Arrays.fill(a, (byte) OMColor.green.getAlpha());
}
for (int i = 0; i < palette.length; i++) {
Color c = new Color(palette[i], true);
r[i] = (byte) c.getRed();
g[i] = (byte) c.getGreen();
b[i] = (byte) c.getBlue();
a[i] = (byte) c.getAlpha();
}
IndexColorModel colorModel = new IndexColorModel(8, r.length, r, g, b, a);
// create a image with the reduced colors
BufferedImage reducedImage = new BufferedImage(width, height,
BufferedImage.TYPE_BYTE_INDEXED, colorModel);
// manipulate raster directly for best performance & color match
WritableRaster raster = reducedImage.getRaster();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int value = pixels[x][y];
raster.setSample(x, y, 0, value);
}
}
return reducedImage;
}