Package com.bbn.openmap.image

Source Code of com.bbn.openmap.image.ColorReducer

package com.bbn.openmap.image;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import java.awt.image.WritableRaster;
import java.util.Arrays;

import com.bbn.openmap.omGraphics.OMColor;

import doppelt.Quantize;
import doppelt.Quantize32;

/**
* A with some static methods to reduce the number of colors in a
* {@link BufferedImage}.
*
* @author halset
*/
public class ColorReducer {

    private ColorReducer() {
    }

    /**
     * Reduce a 24 bit image to the given number of colors. Support fully
     * transparent pixels, but not partially transparent pixels.
     *
     * @param bi
     * @param colors
     * @return
     */
    public static BufferedImage reduce24(BufferedImage bi, int colors) {
        int width = bi.getWidth();
        int height = bi.getHeight();
        int[][] pixels = new int[width][height];
        boolean[][] transparent = new boolean[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);

                // decide if pixel is transparent or not
                transparent[x][y] = (a < 128) ? true : false;
            }
        }

        int[] palette = Quantize.quantizeImage(pixels, colors - 1);

        byte[] r = new byte[colors];
        byte[] g = new byte[colors];
        byte[] b = new byte[colors];
        byte[] a = new byte[colors];

        // need to have full(256) size array to get rid of ugly rare erros msg
        // from GIFImageWriter. We also need the *first* entry to be
        // transparent.
        Arrays.fill(r, (byte) OMColor.clear.getRed());
        Arrays.fill(g, (byte) OMColor.clear.getGreen());
        Arrays.fill(b, (byte) OMColor.clear.getBlue());
        Arrays.fill(a, (byte) OMColor.clear.getAlpha());

        for (int i = 0; i < palette.length; i++) {
            Color c = new Color(palette[i], true);
            r[i + 1] = (byte) c.getRed();
            g[i + 1] = (byte) c.getGreen();
            b[i + 1] = (byte) c.getBlue();
            a[i + 1] = (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++) {
                // add 1 as transparent is first
                int value = transparent[x][y] ? 0 : (pixels[x][y] + 1);
                raster.setSample(x, y, 0, value);
            }
        }

        return reducedImage;
    }

    /**
     * Reduce a 32 bit image to the given number of colors. Support partially
     * transparent pixels.
     *
     * @param bi
     * @param colors
     * @return
     */
    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;
    }

}
TOP

Related Classes of com.bbn.openmap.image.ColorReducer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.