如何在BufferedImage中用另一种颜色替换颜色

所以我有一个有火山的图像文件。 其他一切都是0xFFFF00FF(不透明洋红色)。 我想用0(透明)替换包含该颜色的每个像素。 到目前为止我的方法看起来像这样:

public static BufferedImage replace(BufferedImage image, int target, int preferred) { int width = image.getWidth(); int height = image.getHeight(); BufferedImage newImage = new BufferedImage(width, height, image.getType()); int color; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { color = image.getRGB(i, j); if (color == target) { newImage.setRGB(i, j, preferred); } else { newImage.setRGB(i, j, color); } } } return newImage; } 

这工作正常,但似乎很慢。 我见过有人这样做,但我不知道发生了什么。 如果有人知道更好的方法,我非常想听听。

为避免迭代像素,请更改基础ColorModel 。 这是一个例子。 下面是作者采用原始BufferedImage并应用新颜色模型的片段。

  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); 

虽然我还没有机会彻底测试这个,但使用LookupOp可能会从加速中受益:

 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; } } 

使用它就像创建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); 

您可以像这样获取缓冲图像的pixels[]数组

 int[] pixels = ((DataBufferInt) newImg().getDataBuffer()).getData(); 

然后设置你的颜色

 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; } } } 

这比使用setRGB()略微加快