Skip to content
Advertisement

Java Graphics Invert Color Composite

Basically what I want to do is make a cursor for a JComponent that’s pixels appear as the inverse of the color they are over. For example, take your mouse and hover it over the letters in the url for this page. If you look closely, the pixels of the cursor that are over black pixels of a letter turn white. I know you can invert an RGB color by subtracting the current red, green, and blue colors from 255 for the each corresponding field, but I don’t know how to implement this the way I want.

This is part of a basic paint program I am making. The JComponent I mentioned before is my “canvas” that you can draw on with various tools. I am NOT using java.awt.Cursor to change my cursor because I want the cursor to change dynamically according to what is under it. The “cursor” that I am using is defined as a .png image, and I am creating a BufferedImage from this file that I can then draw on top of the existing BufferedImage of the whole component. I redraw this image using a point defined by a MouseListener.

I looked into AlphaComposite and it looks close to what I want, but there is nothing about inverting the colors underneath the cursor like I want. Please help.

EDIT:

So I just had to do it the hard way with an algorithm because there’s nothing built in for this purpose. Here’s the code a little out of context:

/**
* Changes the color of each pixel under the cursor shape in the image 
* to the complimentary color of that pixel.
*
* @param  points  an array of points relative to the cursor image that
*                 represents each black pixel of the cursor image
* @param  cP      the point relative to the cursor image that is used
*                 as the hotSpot of the cursor
*/
public void drawCursorByPixel(ArrayList<Point> points, Point cP) {
    Point mL = handler.getMouseLocation();
    if (mL != null) {
        for (Point p : points) {
            int x = mL.x + p.x - cP.x;
            int y = mL.y + p.y - cP.y;
            if (x >= 0 && x < image.getWidth() && y >= 0 && y < image.getHeight()) {
                image.setRGB(x, y, getCompliment(image.getRGB(x, y)));
            }
        }
    }
}

public int getCompliment(int c) {
    Color col = new Color(c);
    int newR = 255 - col.getRed();
    int newG = 255 - col.getGreen();
    int newB = 255 - col.getBlue();

    return new Color(newR, newG, newB).getRGB();
}

Advertisement

Answer

I believe what you are looking for is an image filter. It sounds like you even have all the pieces for it built already. Your filter will be the image of the cursor, which will get drawn on top of everything else. The trick is, as you say, to draw each pixel of that cursor such that said pixel’s color is a calculated “opposite” of the pixel color in the drawn space behind the cursor.

I do not know the best way to go about this, but I know one way you might be able to improve on. Paint whatever your background is to a buffered image, then go get the color of the pixels your cursor will hover over using the BufferedImage‘s color model. This example is one I found here from another question.

BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2 = image.createGraphics();
_mainPanel.paint(g2);
image.getColorModel().getRGB(pixel);
g2.dispose();

Ultimately you’ll use this buffered image of your background to get the pixels (and their colors) that your cursor overlaps, and then you can run some algorithm on the colors to invert them in your cursor, then redraw the cursor with the new colors.

This question has a couple of solutions for that algorithm, though I have not personally tried them to see their effects.

Advertisement