Search code examples
javacolorsrgbpixelbufferedimage

Set red value of a pixel, WITHOUT set RGB


I am trying to set either red, green, or blue value of a BufferedImage. After that, i will retrieve that red/green/blue value, and then I will process that value.

But my problem is when I doing this

Color cipherColor = new Color(cipherDecimal[offColor], cipherDecimal[offColor], cipherDecimal[offColor]);

int cipherColorInt = cipherColor.getRGB();
stegoImage.setRGB(x, y, cipherColorInt);

then, I'm curious about the value...so I add some codes to see the RGB value before and after i set the RGB

Color cipherColor = new Color(cipherDecimal[offColor], cipherDecimal[offColor], cipherDecimal[offColor]);

int cipherColorInt = cipherColor.getRGB();
stegoImage.setRGB(x, y, cipherColorInt);
int tesColor = stegoImage.getRGB(x, y);
System.out.println(cipherColorInt + "\t" + tesColor);

Info about stegoImage

BufferedImage stegoImage = new BufferedImage(img.getWidth(null), img.getHeight(null)+h, BufferedImage.TYPE_BYTE_GRAY);

img is just a normal image

It'll set RGB value almost right. ALMOST, because some of value changed. Here it is :

-------- RGB after and before----------
 before      after

-6052957    -6052957
-7303024    -7303024
-10855846   -10855846
-11053225   -11119018 --> changed
-3158065    -3158065
-2500135    -2500135
-13027015   -13092808 --> changed
-5658199    -5658199
-131587 -131587
-12500671   -12566464 --> changed
-5658199    -5658199
-16448251   -16777216 --> changed
-5526613    -5526613
-8553091    -8553091
-1579033    -1579033
-3421237    -3421237

Please help me :) For now, if you know other way to set Red/Green/Value without setRGB or even BufferedImage please tell me. Or perhaps, if you know what makes the value changed or how to fix it, then please tell me.

Thank you


Solution

  • As you know that your image is TYPE_BYTE_GRAY, it will have a linear grayscale color space and a byte databuffer, so you can get the databuffer, cast it to DataBufferByte and access the native gray byte values directly:

    DataBufferByte buffer = (DataBufferByte) stegoImage.getRater().getDataBuffer();
    byte[] data = buffer.getData(); // signed gray values in linear gray space
    
    // Access each pixel
    byte signedGrayPixelValue = data[x + y * stegoImage.getWidth()]; // [-128...127]
    
    // Alternatively
    int grayPixelValue = data[x + y * stegoImage.getWidth()] & 0xff; // [0...255]
    

    The problem with using setRGB/getRGB, is probably that these methods assume the value to be in sRGB color space, and thus not always corresponding to linear gray color space (ie., rounding errors will occur).