Leonardo
Leonardo

Reputation: 43

How to draw a RGB Color Wheel in Java

I am trying to draw a RGB color wheel in Java, but I can't get the gradient by a circular shape. I just want to draw it on screen, with no user interaction at all.

This is all I have for now:

public void paint (Graphics g){
        super.paint(g);

        int red = 255;
        int green = 0;
        int blue = 0;
        int x1 = 500;
        int y1 = 305;
        int x2 = 500;
        int y2 = 50;

        while (green != 255){
            g.setColor(new Color(red, green, blue));
            green++;
            g.drawLine(x1, y1, x2, y2);
            x2++;
            if (y2 < y1){
                y2++;
            }
        }
        while (red != 0){
            g.setColor(new Color(red, green, blue));
            red--;
            g.drawLine(x1, y1, x2, y2);
            x2--;
            y2++;
        }
        x2 = 500;
        while (blue != 255){
            g.setColor(new Color(red, green, blue));
            blue++;
            g.drawLine(x1, y1, x2, y2);
            x2--;
            if (y2 > y1){
                y2--;
            }
        }

        while (red != 255){
            green--;
            g.setColor(new Color(red, green, blue));
            red++;
            g.drawLine(x1, y1, x2, y2);
            x2++;
            y2--;
        }
    }                
}

Which draws the gradient like this

This is what I want

Upvotes: 2

Views: 7193

Answers (3)

Cipriano Valdezate
Cipriano Valdezate

Reputation: 1

The color wheel is easy if we use HSB instead of RGB. We must define every single pixel. The hue is set by the angle, so, first we calculate the angle with the atan2 function, and then the hue is angle / 2pi. The saturation is set by the distance to the center, then, saturation = distance / radius. Brightness is equal for every pixel, so we say 1. With these three values, we can convert the color to RGB with the HSBtoRGB function. This is my code:

    BufferedImage createWheelBuffer(int radius) {
        final int diameter = radius * 2;
        final double radius2 = radius * radius;
        float hue, sat;
        final double PI2 = 2 * Math.PI;
        double dist2;
        int rgb;
        BufferedImage buffer = new BufferedImage(diameter, diameter, BufferedImage.TYPE_INT_ARGB);
        for (int x = 0; x < diameter; x++) {
            for (int y = 0; y < diameter; y++) {
                dist2 = distance2(x, y, radius, radius);
                // if the point is not inside the circle we go to the next point
                if (dist2 > radius2) continue;
                hue = (float) (Math.atan2(y - radius, x - radius) / PI2);
                sat = (float) Math.sqrt((float) dist2) / (float) radius;
                rgb = Color.HSBtoRGB(hue, sat, 1);
                buffer.setRGB(x, y, rgb);
            }
        }
        return buffer;
    }

    int distance2(int x1, int y1, int x2, int y2) {
        int a = x2 - x1;
        int b = y2 - y1;
        return a * a + b * b;
    }

And in the paintComponent event:

    protected void paintComponent(Graphics gr) {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D) gr;
        BufferedImage buffer = createWheelBuffer(radius);
        g.drawImage(buffer, x, y, this);
    }

The wheel

Upvotes: 0

mryamz
mryamz

Reputation: 454

Here is my solution for drawing a RGB Color Wheel in Java:

public class Main {

    public static void main(String[] args) {
        int rad = 1024;
        BufferedImage img = new BufferedImage(rad, rad, BufferedImage.TYPE_INT_RGB);

        // Center Point (MIDDLE, MIDDLE)
        int centerX = img.getWidth() / 2;
        int centerY = img.getHeight() / 2;
        int radius = (img.getWidth() / 2) * (img.getWidth() / 2);

        // Red Source is (RIGHT, MIDDLE)
        int redX = img.getWidth();
        int redY = img.getHeight() / 2;
        int redRad = img.getWidth() * img.getWidth();

        // Green Source is (LEFT, MIDDLE)
        int greenX = 0;
        int greenY = img.getHeight() / 2;
        int greenRad = img.getWidth() * img.getWidth();

        // Blue Source is (MIDDLE, BOTTOM)
        int blueX = img.getWidth() / 2;
        int blueY = img.getHeight();
        int blueRad = img.getWidth() * img.getWidth();

        for (int i = 0; i < img.getWidth(); i++) {
            for (int j = 0; j < img.getHeight(); j++) {
                int a = i - centerX;
                int b = j - centerY;

                int distance = a * a + b * b;
                if (distance < radius) {
                    int rdx = i - redX;
                    int rdy = j - redY;
                    int redDist = (rdx * rdx + rdy * rdy);
                    int redVal = (int) (255 - ((redDist / (float) redRad) * 256));

                    int gdx = i - greenX;
                    int gdy = j - greenY;
                    int greenDist = (gdx * gdx + gdy * gdy);
                    int greenVal = (int) (255 - ((greenDist / (float) greenRad) * 256));

                    int bdx = i - blueX;
                    int bdy = j - blueY;
                    int blueDist = (bdx * bdx + bdy * bdy);
                    int blueVal = (int) (255 - ((blueDist / (float) blueRad) * 256));

                    Color c = new Color(redVal, greenVal, blueVal);

                    float hsbVals[] = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null);

                    Color highlight = Color.getHSBColor(hsbVals[0], hsbVals[1], 1);

                    img.setRGB(i, j, RGBtoHEX(highlight));
                } else {
                    img.setRGB(i, j, 0xFFFFFF);
                }
            }
        }

        try {
            ImageIO.write(img, "png", new File("wheel.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static int RGBtoHEX(Color color) {
        String hex = Integer.toHexString(color.getRGB() & 0xffffff);
        if (hex.length() < 6) {
            if (hex.length() == 5)
                hex = "0" + hex;
            if (hex.length() == 4)
                hex = "00" + hex;
            if (hex.length() == 3)
                hex = "000" + hex;
        }
        hex = "#" + hex;
        return Integer.decode(hex);
    }
}

Upvotes: 3

Laurel
Laurel

Reputation: 6173

Changing Brightness

From here, it seems like the easiest way to brighten a color is by converting it to HSB.

float hsbVals[] = Color.RGBtoHSB( originalColor.getRed(),
                                   originalColor.getGreen(),
                                   originalColor.getBlue(), null );

    Color highlight = Color.getHSBColor( hsbVals[0], hsbVals[1], 
      0.5f * ( 1f + hsbVals[2] )); // Play with this part to modify rate of change

Making it circular

From what you have, it looks like you essentially need to erase all but a circular region in the middle.

From this answer, it seems like the Area class is easiest.

 public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D)g.create();
        Rectangle2D rectangleNotToDrawIn = new Rectangle2D.Double(100, 100, 20, 30); 
           // You will need to find out what size ellipse you need
        Area outside = calculateOutside(rectangleNotToDrawIn);

        // draw color wheel here

        g2.setPaint(Color.black); // assuming you want black
        g2.setClip(outside);
        g2.drawLine(0, 0, getWidth(), getHeight());

    }

// Change this method to take in an ellipse shape.
    private Area calculateOutside(Rectangle2D r) {
        Area outside = new Area(new Rectangle2D.Double(0, 0, getWidth(), getHeight()));
        outside.subtract(new Area(r));
        return outside;
    }

Upvotes: 2

Related Questions