11

I was looking at the ImageConverter class, trying to figure out how to convert a BufferedImage to 8-bit color, but I have no idea how I would do this. I was also searching around the internet and I could find no simple answer, they were all talking about 8 bit grayscale images. I simply want to convert the colors of an image to 8 bit... nothing else, no resizing no nothing. Does anyone mind telling me how to do this.

Zach Sugano
  • 1,567
  • 5
  • 22
  • 41
  • You probably have to choose a quantization algorithm, ie. something that transform the range of colors of your images into a 256 entry palette. – PhiLho Jun 16 '12 at 09:01
  • What do you mean by converting the colors of an image to 8-bit? I guess you want to reduce the color space? Do you want to perform Color quantization? – Behe Jun 16 '12 at 09:05
  • Could you guys point me to a library/API of some sort? I have no idea what you're talking about. That also sounds like I would be able to create my own palette which would be event better if possible. – Zach Sugano Jun 16 '12 at 09:08

3 Answers3

5

You can use JAI (Java Advanced Imaging), the official Sun (now Oracle) image library to do that.

The ColorQuantizerDescriptor shows the choice of quantization processes you can apply.

PhiLho
  • 40,535
  • 6
  • 96
  • 134
3

This code snippet from the article "Transparent gifs in Java" at G-Man's Uber Software Engineering Blog works well:

public static void main(String[] args) throws Exception {
    BufferedImage src = convertRGBAToIndexed(ImageIO.read(new File("/src.jpg")));
    ImageIO.write(src, "gif", new File("/dest.gif"));
}

public static BufferedImage convertRGBAToIndexed(BufferedImage src) {
    BufferedImage dest = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_BYTE_INDEXED);
    Graphics g = dest.getGraphics();
    g.setColor(new Color(231, 20, 189));

    // fill with a hideous color and make it transparent
    g.fillRect(0, 0, dest.getWidth(), dest.getHeight());
    dest = makeTransparent(dest, 0, 0);

    dest.createGraphics().drawImage(src, 0, 0, null);
    return dest;
}

public static BufferedImage makeTransparent(BufferedImage image, int x, int y) {
    ColorModel cm = image.getColorModel();
    if (!(cm instanceof IndexColorModel))
        return image; // sorry...
    IndexColorModel icm = (IndexColorModel) cm;
    WritableRaster raster = image.getRaster();
    int pixel = raster.getSample(x, y, 0); // pixel is offset in ICM's palette
    int size = icm.getMapSize();
    byte[] reds = new byte[size];
    byte[] greens = new byte[size];
    byte[] blues = new byte[size];
    icm.getReds(reds);
    icm.getGreens(greens);
    icm.getBlues(blues);
    IndexColorModel icm2 = new IndexColorModel(8, size, reds, greens, blues, pixel);
    return new BufferedImage(icm2, raster, image.isAlphaPremultiplied(), null);
}
creemama
  • 6,559
  • 3
  • 21
  • 26
2

You can use the convert8 method in the ConvertUtil class.

For details have a look here.

JHS
  • 7,761
  • 2
  • 29
  • 53
  • I could not use ConvertUtil.convert8, so I would have to import that class, but I could not find what the import code was. Do you by chance do what/where it is? – Dak31 Nov 23 '16 at 00:08