Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BufferedImage unexpectedly changing color

I have following code, which creates grayscale BufferedImage and then sets random colors of each pixel.

import java.awt.image.BufferedImage;

public class Main {

    public static void main(String[] args) {
        BufferedImage right = new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY);
        int correct = 0, error = 0;
        for (int i = 0; i < right.getWidth(); i++) {
            for (int j = 0; j < right.getHeight(); j++) {
                int average = (int) (Math.random() * 255);
                int color = (0xff << 24) | (average << 16) | (average << 8) | average;
                right.setRGB(i, j, color);
                if(color != right.getRGB(i, j)) {
                    error++;
                } else {
                    correct++;
                }
            }
        }
        System.out.println(correct + ", " + error);
    }
}

In approximately 25-30% pixels occurs weird behaviour, where I set color and right afterwards it has different value than was previously set. Am I setting colors the wrong way?

like image 406
Glissinda Avatar asked Oct 19 '22 09:10

Glissinda


2 Answers

Here is your solution: ban getRGB and use the Raster (faster and easier than getRGB) or even better DataBuffer (fastest but you have to handle the encoding):

import java.awt.image.BufferedImage;

public class Main
{

public static void main(String[] args)
    {
    BufferedImage right = new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY);
    int correct = 0, error = 0;
    for (int x=0 ; x < right.getWidth(); x++)
        for (int j = 0; j < right.getHeight(); j++)
            {
            int average = (int) (Math.random() * 255) ;
            right.getRaster().setSample(x, y, 0, average) ;
            if ( average != right.getRaster().getSample(x, y, 0) ) error++ ;
            else correct++;
            }
    System.out.println(correct + ", " + error);
    }
}

In your case getRGB is terrible, because the encoding is an array of byte (8 bits), and you have to manipulate RGB values with getRGB. The raster does all the work of conversion for you.

like image 151
FiReTiTi Avatar answered Oct 21 '22 07:10

FiReTiTi


I think your issue has to do with the image type (third parameter for BufferedImage constructor). If you change the type to BufferedImage.TYPE_INT_ARGB, then you will get 100% correct results.

Looking at the documentation for BufferedImage.getRGB(int,int) there is some conversion when you get RGB that is not the default color space

Returns an integer pixel in the default RGB color model (TYPE_INT_ARGB) and default sRGB colorspace. Color conversion takes place if this default model does not match the image ColorModel.

So you're probably seeing the mismatches due to the conversion.

like image 27
FriedSaucePots Avatar answered Oct 21 '22 09:10

FriedSaucePots