How to replace color with another color in BufferedImage

前端 未结 3 1245
甜味超标
甜味超标 2021-01-14 08:22

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)

相关标签:
3条回答
  • 2021-01-14 08:39

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

    0 讨论(0)
  • 2021-01-14 08:43

    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);
    
    0 讨论(0)
  • 2021-01-14 08:45

    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);
    
    0 讨论(0)
提交回复
热议问题