So I have an image file that has a volcano on it. Everything else is 0xFFFF00FF (opaque magenta). I want to replace every pixel that contains that color with 0 (transparent)
You can get the pixels[]
array of the buffered image like so
int[] pixels = ((DataBufferInt) newImg().getDataBuffer()).getData();
and then set your colors like so
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
color = pixels[y * width + x];
if (color == target) {
pixels[y * width + x] = preferred;
}
else {
pixels[y * width + x] = color;
}
}
}
This is a slight speed up over using setRGB()
To avoid iterating through the pixels, change the underlying ColorModel. Here is an example. Below is the snippet where the author takes the original BufferedImage and applies the new color model.
private static BufferedImage createImage() {
int width = 200;
int height = 200;
// Generate the source pixels for our image
// Lets just keep it to a simple blank image for now
byte[] pixels = new byte[width * height];
DataBuffer dataBuffer = new DataBufferByte(pixels, width*height, 0);
SampleModel sampleModel = new SinglePixelPackedSampleModel(
DataBuffer.TYPE_BYTE, width, height, new int[] {(byte)0xf});
WritableRaster raster = Raster.createWritableRaster(
sampleModel, dataBuffer, null);
return new BufferedImage(createColorModel(0), raster, false, null);
}
private static ColorModel createColorModel(int n) {
// Create a simple color model with all values mapping to
// a single shade of gray
// nb. this could be improved by reusing the byte arrays
byte[] r = new byte[16];
byte[] g = new byte[16];
byte[] b = new byte[16];
for (int i = 0; i < r.length; i++) {
r[i] = (byte) n;
g[i] = (byte) n;
b[i] = (byte) n;
}
return new IndexColorModel(4, 16, r, g, b);
}
private BufferedImage image = createImage();
image = new BufferedImage(createColorModel(e.getX()), image.getRaster(), false, null);
While I haven't had a chance to test this thoroughly yet, using a LookupOp may well benefit from acceleration:
public class ColorMapper
extends LookupTable {
private final int[] from;
private final int[] to;
public ColorMapper(Color from,
Color to) {
super(0, 4);
this.from = new int[] {
from.getRed(),
from.getGreen(),
from.getBlue(),
from.getAlpha(),
};
this.to = new int[] {
to.getRed(),
to.getGreen(),
to.getBlue(),
to.getAlpha(),
};
}
@Override
public int[] lookupPixel(int[] src,
int[] dest) {
if (dest == null) {
dest = new int[src.length];
}
int[] newColor = (Arrays.equals(src, from) ? to : src);
System.arraycopy(newColor, 0, dest, 0, newColor.length);
return dest;
}
}
Using it is as easy as creating a LookupOp:
Color from = Color.decode("#ff00ff");
Color to = new Color(0, true);
BufferedImageOp lookup = new LookupOp(new ColorMapper(from, to), null);
BufferedImage convertedImage = lookup.filter(image, null);