Question

Below is the following code that reads in RGB values using BufferedImage, and then simply writes them back out again to file. The resultant image is perfect, and looks good. No worries there.

I run a print test to print out the first 10 RBG int values. This is to test the "test.png" file, and then to test the resultant image - "new-test.png". For some reason I am getting different RBG values between the two files.

E.g. (The first 3 RGB int values)

test.png : -16704215, -16704215, -16704215

new-test.png : -16638935, -16638935, -16573142

Can anyone identify to why I am getting different RBG values that printed out for both test files?

    try
    { 
    BufferedImage imgBuf = ImageIO.read(new File("test.png"));//also testing with GIFs, JPEGs
    int w = imgBuf.getWidth();
    int h = imgBuf.getHeight();
    int[] RGBarray = imgBuf.getRGB(0,0,w,h,null,0,w);

    //Arrays to store their respective component values
    int [][] redPixels = new int [h][w]; 
    int [][] greenPixels = new int [h][w]; 
    int [][] bluePixels = new int [h][w];

    for(int i=0; i<=10; i++)
    {
       //print out the first 10 RGB int values - testing purposes
       System.out.println(RGBarray[i]);
    }

    //Separate the RGB int values into 3 array, red, green and blue ....
    int x=0;
    for(int row=0; row<h; row++)
    {
       for(int col=0; col<w; col++)
       {
          redPixels[row][col] = ((RGBarray[x]>>16)&0xff);
          greenPixels[row][col] = ((RGBarray[x]>>8)&0xff);
          bluePixels[row][col] = (RGBarray[x]&0xff);
          x++;
       }
    }

    //set pixels back using the setRBG() ...
    BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);

    for(int row=0; row<h; row++) 
    {
       for(int col=0; col<w; col++)
       {
          //use bit shifting to re-form the RGB int again
          int rgb = (redPixels[row][col] & 0xff) << 16 | (greenPixels[row][col] & 0xff) << 8 | (bluePixels[row][col] & 0xff);

          bufferedImage.setRGB(col, row, rgb);
       }
    }
  }
  catch(IOException i){}; // This exception format is only temporary !
Was it helpful?

Solution

Here is small modification of your code that also saves the image and then reads it back again. With this code I get exactly the same int values before and after.

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import org.junit.Test;


public class PngReadWriteTest {

@Test
public void test(){
    try
    { 
    BufferedImage imgBuf = ImageIO.read(new File("test.png"));//also testing with GIFs, JPEGs
    int w = imgBuf.getWidth();
    int h = imgBuf.getHeight();
    int[] RGBarray = imgBuf.getRGB(0,0,w,h,null,0,w);

    //Arrays to store their respective component values
    int [][] redPixels = new int [h][w]; 
    int [][] greenPixels = new int [h][w]; 
    int [][] bluePixels = new int [h][w];

    System.out.println("IMAGE FIRST READ:");
    printPixelValues(imgBuf);

    //Separate the RGB int values into 3 array, red, green and blue ....
    int x=0;
    for(int row=0; row<h; row++)
    {
       for(int col=0; col<w; col++)
       {
          redPixels[row][col] = ((RGBarray[x]>>16)&0xff);
          greenPixels[row][col] = ((RGBarray[x]>>8)&0xff);
          bluePixels[row][col] = (RGBarray[x]&0xff);
          x++;
       }
    }

    //set pixels back using the setRBG() ...
    BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);

    for(int row=0; row<h; row++)
    {
       for(int col=0; col<w; col++)
       {
          //use bit shifting to re-form the RGB int again
          int rgb = (redPixels[row][col] & 0xff) << 16 | (greenPixels[row][col] & 0xff) << 8 | (bluePixels[row][col] & 0xff);

          bufferedImage.setRGB(col, row, rgb);
       }
    }

    System.out.println("IMAGE BEFORE SAVE:");
    printPixelValues(bufferedImage);

    //Save image as png
    ImageIO.write(bufferedImage, "png", new File("new-test.png"));

    BufferedImage newImage = ImageIO.read(new File("new-test.png"));//also testing with GIFs, JPEGs

    System.out.println("IMAGE AFTER SECOND READ:");
    printPixelValues(newImage);

  }
  catch(IOException i){}; // This exception format is only temporary !
}

private void printPixelValues(BufferedImage image){
    int w = image.getWidth();
    int h = image.getHeight();
    int[] RGBarray = image.getRGB(0,0,w,h,null,0,w);

    for(int i=0; i<=10; i++)
    {
        //print out the first 10 RGB int values - testing purposes
        System.out.println(RGBarray[i]);
    }
}

}

This will only work if you use PNG since it is lossless. If you use JPG you will not get the same result since it is lossy. when you save the file as a JPG it will not result in a file containing the exact same bytes as in your first image. The level of compression will affect the image. So even if the files looks just the same by eye, they will not be exactly the same.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top