Search code examples
javapixel

Editing Pixel Values in java


I have a class Pixel that has methods getRed, getBlue, getGreen, setRed, setBlue, setGreen (r,g,b) and so far everything works individually but when i put it TOGETHER setGreen and setBlue don't work. Am I doing something wrong with the masking?

public class Pixel {
    int pixel;
    public Pixel (int pixel) {
        this.pixel = pixel;
    }
    public int getRed() {
        int red = pixel >> 16;
        red = red & (0xFF);
        return red;   
    }
    public int getGreen() {
        int green = pixel >> 8;
        green = green & (0xFF);
        return green;
    }
    public int getBlue() {
        int blue = pixel;
        blue = blue & (0xFF);
        return blue;
    }
    public void setRed(int red) {
        pixel = (pixel & ~(0xFFFF0000)) << 16;
        pixel= ((red << 16))|pixel ;   
    }
    public void setGreen(int value) {
        pixel = (pixel & ~(0xFF00FF00)) << 8;
        pixel= (value << 8) |pixel; 
    }
    public void setBlue(int value) {
        pixel = (pixel & ~(0xFFFFFF00));
        pixel= (value) |pixel; 
    }
    public static void main(String[] args) {
        Pixel p3 = new Pixel(0xFF000000);
        System.out.printf("rgb = (%d, %d, %d)\n", p3.getRed(), p3.getGreen(), p3.getBlue());

        p3.setRed(42);
        p3.setGreen(18);
        p3.setBlue(225);
        System.out.printf("rgb = (%d, %d, %d)\n", p3.getRed(), p3.getGreen(), p3.getBlue());

        p3.setRed(-1);
        p3.setGreen(500);
        p3.setBlue(1000);
        System.out.printf("rgb = (%d, %d, %d)\n", p3.getRed(), p3.getGreen(), p3.getBlue());
    }   
}

I should be getting this as my result:

rgb = (0, 0, 0)
rgb = (42, 18, 225)
rgb = (255, 244, 232)

but this is what im getting

rgb = (0, 0, 0)
rgb = (0, 0, 225)
rgb = (0, 3, 232)

Solution

  • Consider for example your setGreen method:

    public void setGreen(int value) {
        pixel = (pixel & ~(0xFF00FF00)) << 8;
        pixel = (value << 8) | pixel; 
    }
    

    Initially, your pixel is AARRGGBB. First, you are setting the GG part in the current value of pixel to 0 correctly (ignoring alpha for now). (pixel & ~(0xFF00FF00)) == (AARRGGBB & 0x00FF00FF) == 00RR00BB. However, next you shift that value 8 bits to the left, so you get RR00BB00. Next, you are (correctly) left-shifting the green value you got as a parameter. You'll get (000000GG << 8) == 0000GG00. And finally, you are or'ing that with the value from before: (RR00BB00 | 0000GG00) == RR00XX00 where the Xes are some garbage that originate from or'ing together the old blue with the new green bits. Can you see what to fix?

    There is another issue in the setBlue method. (pixel & ~(0xFFFFFF00)) == (AARRGGBB & 000000FF) == 000000BB. Compare that with the (correct) mask for setGreen above.

    Finally, your methods seem to be supposed to handle invalid values (–1, 500, 1000) gracefully. So you should set all but the last 8 bits of your arguments to 0. I'm only suggesting that because your required output seems to ask for that. In a well-written Java program, it would b better to throw an exception if out-of-range values are passed, rather than silently ignoring the invalid bits. Alternatively, you could change your methods to accept a byte instead of an int. This would be the best solution since now it would be outright impossible to pass an invalid argument.

    Putting this together, here is how it could work. I have also polished the code a little so we can hopefully see more easily what is going on. The shifts by 0 bits are of course useless but I include them for optical reasons.

    public final class Pixel {
    
        private int value;
    
        public Pixel (int rgb) {
            this.value = value;
        }
    
        public int getRed() {
            return (this.value >> 16) & 0xFF;
        }
    
        public int getGreen() {
            return (this.value >>  8) & 0xFF;
        }
    
        public int getBlue() {
            return (this.value >>  0) & 0xFF;
        }
    
        public void setRed(final int r) {
            this.value = (this.value & 0xFF00FFFF) | ((r & 0xFF) << 16);
        }
    
        public void setGreen(final int g) {
            this.value = (this.value & 0xFFFF00FF) | ((g & 0xFF) <<  8);
        }
    
        public void setBlue(final int b) {
            this.value = (this.value & 0xFFFFFF00) | ((b & 0xFF) <<  0);
        }
    
        @Override
        public String toString() {
            return String.format("rgb = (%3d, %3d, %3d)",
                                 this.getRed(),
                                 this.getGreen(),
                                 this.getBlue());
        }
    
        public static void main(String[] args) {
            final Pixel pixel = new Pixel(0);
            System.out.println(pixel);
            pixel.setRed(42);
            pixel.setGreen(18);
            pixel.setBlue(225);
            System.out.println(pixel);
            pixel.setRed(-1);
            pixel.setGreen(500);
            pixel.setBlue(1000);
            System.out.println(pixel);
        }
    }
    

    Output of running the above program:

    rgb = (  0,   0,   0)
    rgb = ( 42,  18, 225)
    rgb = (255, 244, 232)