I'm creating an image with a custom palette (in other words a custom colormodel):
BufferedImage img = new BufferedImage(orgImg.getWidth(), orgImg.getHeight(),
BufferedImage.TYPE_BYTE_INDEXED,
cm);
Graphics2D g2 = img.createGraphics();
g2.drawImage(orgImg, 0, 0, null);
g2.dispose();
Note that the "cm" variable is a my custom colormodel with a palette of 256 colors.
The "orgImg" variable is a full colored (24 big argb) image.
The above code results in a copy of "orgImg" with 256 colors using the palette defined in the colormodel.
This works nicely.
But java uses dithering to reduce colors. Is it possible to disable this dithering?
Note that i need to use my own palette so that the final images matches a specific color palette.
When drawing an image into a Graphics2D
object, various aspects of the rendering can be controlled using RenderingHint
s. You should be able to disable the dithering using the Graphics2D.setRenderingHint
or setRenderingHints
methods, passing the KEY_DITHERING
and VALUE_DITHER_DISABLE
value as parameters:
Graphics2D g2 = img.createGraphics();
// Disable dithering
g2.setRenderingHint(RenderingHint.KEY_DITHERING, RenderingHint.VALUE_DITHER_DISABLE);
g2.drawImage(orgImg, 0, 0, null);
g2.dispose();
See the Java2D tutorial for more info.
PS: Note that the methods/class are named "hint".
This may not be a problem any more, but in the past I've experienced that disabling the dither using the hint like above did not work. It's also not possible to specify the dithering algorithm to use, typically only a "ordered" or "diamond" pattern dithering is used.
I therefore implemented my own versions of various dithering algorithms for this use. See the CopyDither (which does a closest match lookup for each pixel, probably what you want here) and DiffusionDither (which implements a "Floyd-Steinberg" error diffusion dither). Both of the mentioned implementations rely on a fast reverse lookup of color values. Unfortunately, the default IndexColorModel
doesn't do fast reverse lookups. So I implemented a special class for this case too, see the InverseColorMapIndexColorModel class.
Usage:
BufferedImage img = new BufferedImage(orgImg.getWidth(), orgImg.getHeight(), BufferedImage.TYPE_BYTE_INDEXED, cm);
CopyDither noDither = new CopyDither(new InverseColorMapIndexColorModel(cm)); // cm must be IndexColorModel
noDither.filter(orgImg, img);