How to use ColorQuantizerDescriptor?
Asked Answered
C

1

2

Following the idea of @PhiLho's answer to How to convert a BufferedImage to 8 bit?, I want to use ColorQuantizerDescriptor to convert a BufferedImage, imageType TYPE_INT_RGB, but RenderedOp#getColorModel() is throwing the following exception:

java.lang.IllegalArgumentException: The specified ColorModel is incompatible with the image SampleModel.
    at javax.media.jai.PlanarImage.setImageLayout(PlanarImage.java:541)
    at javax.media.jai.RenderedOp.createRendering(RenderedOp.java:878)
    at javax.media.jai.RenderedOp.getColorModel(RenderedOp.java:2253)

This is the code that I am attempting to use:

final RenderedOp medianCutQuantizerOp = ColorQuantizerDescriptor.create(rgbImage, ColorQuantizerDescriptor.MEDIANCUT, 256, null, null, null, null, null);
final BufferedImage bi = medianCutQuantizerOp.getAsBufferedImage(null, medianCutQuantizerOp.getColorModel());

How do I use ColorQuantizerDescriptor?

Crouch answered 9/3, 2013 at 16:16 Comment(2)
I find it hard to believe that a getter is throwing the exception. Try breaking out the call to getColorModel on its own line then pass that var into the getAsBufferedImage call. I think you'll see the error comes from the getAsBufferedImage call. From download.java.net/media/jai/javadoc/1.1.3/jai-apidocs/javax/…, java.awt.image.ColorModel) - "The caller is responsible for supplying a ColorModel that is compatible with the image's SampleModel. "Diondione
@Diondione getColorModel() can throw an exception (though it is not documented!) because it can create a rendering of the Op in order to get the model.Arletha
D
3

The following example has been modified from http://code.google.com/p/color-reduction-experiments/source/browse/trunk/it/geosolutions/mapproducers/MapProducersTest.java?r=2

public class Main {
    public static void main(String[] args) throws Exception {

        BufferedImage original = ImageIO.read(new File("/Users/Nick/Desktop/with_flowers.jpg"));
         // 300 seems to be a good number
        final RenderedOp cqImage = ColorQuantizerDescriptor.create(
           original, ColorQuantizerDescriptor.OCTTREE,
           new Integer(255), new Integer(300), null, new Integer(2),
           new Integer(2), null);

        assert cqImage.getColorModel() instanceof IndexColorModel;
        final BufferedImage converted = cqImage.getAsBufferedImage();
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                final JFrame f = new JFrame();
                f.setTitle("Test");
                f.getContentPane().add((new ScrollingImagePanel(converted, 300, 300)));
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.pack();
                f.setVisible(true);
            }
        });
    }
}

Works for me:Using octree

Edit: tried with your median cut and seems to work as well, though much slower.

Using median cut

Diondione answered 9/3, 2013 at 17:34 Comment(4)
Interesting. The image type of original when I run this is 5 (TYPE_3BYTE_BGR). If I modify the code to create a new BufferedImage, TYPE_INT_RGB, and drawImage() the original into the TYPE_INT_RGB image, then cqImage.getAsBufferedImage() throws "IllegalArgumentException: The specified ColorModel is incompatible with the image SampleModel". Apparently some image types work but others do not?Crouch
It might be helpful if you upload the image you can't get to work.Diondione
The image is generated and I don't think that I can release it. It's okay, though. I think this answers my question in that yes, this is how ColorQuantizerDescriptor is used, but there are some restrictions.Crouch
I had a similar problem with screenshots (probably generated with AWT's Robot), and solved it by drawing the image on a TYPE_3BYTE_BGR BufferedImage before quantizing it.Arletha

© 2022 - 2024 — McMap. All rights reserved.