Question

The sample code is below. The code works perfect and creates an image accurately. But the created image (when reading back, and taking the pixels in), the pixels seem to be 1 or 2 values off. I am doing simple testing by printing the pixels as they are read in, and before they are saved back to file. I then run another tester on the new image and the printed pixels are, as I said 1 or 2 values off (in pixels, such as '24', to '25'). But most pixels are accurately, just a few are not. Is it something to do with how the image is written back?

try
{
    //Read in image 
    BufferedImage  imgBuf = ImageIO.read(new File("image.jpg"));

    //take in pixels etc., and simply do nothing with them - testing puposes

    //Write back the image
    BufferedImage bufferedImage = new BufferedImage(imagePixelArray[0].length, imagePixelArray.length, BufferedImage.TYPE_INT_RGB);

    ImageIO.write(bufferedImage, "jpeg", new File("new-image.jpg"));
}
catch(IOException i){};

EDIT

Below is the code of how the pixels are split into arrays, and then re-assigned back into an array using bit shifting. Again, don't worry about the logic of the program. I need to make sure that these these pixels (represented as redPixels, greenPixels and bluePixels) are the same when reading back the new created image. The code below uses the code above using BufferedImage. I did use GIF files. But I know that there is someway of properly encoding JPEGs (rather than compressing the data)

    int i=0;
      //Loop through RGBarray[] assigning their respecctive colour components using bit shifting
      //jpegPixels[255][255][3] - the third part of the array is their colour comonents
      //0 - red
      //1 - green
      //2 - blue
      for(int row=0; row<h; row++)
      {
         for(int col=0; col<w; col++)
         {
            jpegPixels[row][col][0] = ((RGBarray[i]>>16)&0xff);
            jpegPixels[row][col][1] = ((RGBarray[i]>>8)&0xff);
            jpegPixels[row][col][2] = (RGBarray[i]&0xff);
            i++;
         }
      }

//3 arrays - redPixels, greenPixels and bluePixels are assigned from jpegPixels[][][]

//loop again returning back the pixel information using bit shifting
for(int row=0; row<reconstructedJPEG.length; row++)
      {
         for(int col=0; col<reconstructedJPEG[0].length; col++)
         {
            int rgb = (redPixels[row][col] & 0xff) << 16 | (greenPixels[row][col] & 0xff) << 8 | (bluePixels[row][col] & 0xff);

            bufferedImage.setRGB(col, row, rgb);
         }
      }
Was it helpful?

Solution

JPG uses lossy compression, and thus pixels are never exact with this type of file format. If you look at JPG files that have been copied several times, you'll start seeing an accumulation of errors, often at the borders and edges within the image. If you want perfect storage of pixels, use a different image file format type that uses either no compression or lossless compression such as PNG.


As an aside, code like this:

catch(IOException i){};

Should never be present, even in "just a sample code to illustrate ...".


Edit
You state:

No I am not doing any compression to the pixels at all. For testing purposes I am just reading the pixels in, and writing them back out against using BufferedImage. As in, the pixel values itself are being altered slightly by 1 or 2 values. I don't know wyhy. From testing and testing, it now seems to do with writing the values back to file ?

You're using JPG -- and so again, you are compressing whether you know it or not.

Again, have you tried your experiment with PNG formatted images?


Edit 2
You state:

But that doesn't explain why only some pixels are unchanged, but there odd ones, are being altered.

The amount of altering and the number of pixels potentially altered will depend on the compression level (inverse of the quality level) used by the ImageWriter. This can be set if you extract out the actual ImageWriter used for jpg images. Check out this question for instance.

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