2

So I need to replace a colour in an image with another colour. Ive considered iterating through all of the pixels and changing them one by one if they match the specified colour but this approach is too slow. Ive looked into using ColorModels but I don't really understand it although it seems like exactly what I need.

I've been playing around with this example and I only just reailzed that the resulting colormodel is only 4 bits (I might even be wrong about that). How to replace color with another color in BufferedImage

Anyway Ive been wrestling with this example for the last two days with very little to show. Can someone show me how to change this

enter image description here

Into this... (the red has changed to blue)

enter image description here

Please help, I'm really stuck with this. I would like to use ColorModels but if there's another option which doesn't involve iterating through pixels and is very fast as well then let me know.

Community
  • 1
  • 1
Supercreature
  • 441
  • 6
  • 25
  • Some useful examples of `LookupOp` are cited [here](http://stackoverflow.com/a/3528196/230513), for [example](http://stackoverflow.com/a/21764828/230513). – trashgod Dec 28 '15 at 17:58

1 Answers1

0

I don't know how useful this would be for your purpose, and I don't know how quick is "quick enough", but this is some code I thought of that would be relatively quick (it took 8ms in a test run I just did with it).

//Demonstration main method
public static void main(String[] args) {
        BufferedImage img = new BufferedImage(900, 900, BufferedImage.TYPE_INT_RGB);
        initImage(img);
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JPanel panel = new JPanel() {
                public void paintComponent(Graphics g) {
                    super.paintComponent(g);
                    g.drawImage(img, 0, 0, null);
                }
            };
            panel.setPreferredSize(new Dimension(img.getWidth(), img.getHeight()));
            frame.add(panel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
            new Thread( () -> {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                iterateThroughColorRaster(img);
                panel.repaint();
            }).start();
        });
    }

 //Actual code you were asking for a solution to
public static int testColour(int rgb) {
    int red = (rgb >> 16) & 0xFF;
    int green = (rgb >> 8) & 0xFF;
    int blue = rgb & 0xFF;
    int newRed;
    int newGreen = green;
    int newBlue;
    //This could be changed to a "threshold" if you don't want only exact red  colours to be changed, e.g. (if red > 230 && others < 30) or similar
    if (red == 255 && blue == 0 && green == 0) {
        newRed = 0;
        newBlue = 255;
    } else {
        newRed = red;
        newBlue = blue;
    }
    return (newRed << 16) | (newGreen << 8) | newBlue;
}

//Create some colours
private static void initImage(BufferedImage img) {
    int[] initialBuf = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
    Random rand = new Random();
    for (int i = 0; i < initialBuf.length; i++) {
        if (rand.nextInt(3) == 2) {
            initialBuf[i] = toRGB(255, 0, 0);
        } else {
            initialBuf[i] = toRGB(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
        }
    }
}

//Get the raster array, iterate through, checking each pixel
public static void iterateThroughColorRaster(BufferedImage img) {
    long before = System.currentTimeMillis();
    int[] buf = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
    buf = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
    for (int i = 0; i < buf.length; i++) {
        buf[i] = testColour(buf[i]);
    }
    System.out.println(System.currentTimeMillis() - before);
}


//For convenience
public static int toRGB(int red, int green, int blue) {
    return (red << 16) | (green << 8) | blue;
}
dbrown93
  • 344
  • 2
  • 10