0

Storing an image as a JPG does not preserve a pixel's RGB value; PNG does not work either.

Here is my problem,I wrote a java program like so:

BufferedImage img=ImageIO.read(new File("Pathtoimage"));
//changed the pixel values using getRGB() and setRGB()
ImageIO.write(img,"png","pathToTarget");

Then I wrote other code to read the pixel values and I found that they were different.

Everything seems to be alright if I don't store the image. But I do NEED to store the image in a way that the pixels preserve their set RGB values perfectly. Please suggest other file formats (PNG and JPG do not work) or workarounds.

  • If you expect to be able to be able to recover the data _exactly_ as it was, then do not use a lossy compression algo which both PNG and JPG are. – Matt Clark Jan 15 '18 at 22:08
  • PNG is lossless, although it does optionally support lossy compression for reduced file size. Did you do any research, such as searching for "non-lossy image format"? – Jim Garrison Jan 16 '18 at 00:50
  • @MattClark PNG is a lossless format. Yes, it's [possible](https://pngmini.com/lossypng.html) to [reduce](https://pngquant.org/) [quality](https://github.com/foobaz/lossypng) *before* PNG encoding, but you will still get back what was encoded. – Harald K Jan 16 '18 at 09:18
  • @SouritChakraborty What code did you use to test if the RGB values where equal? Note that `BufferedImage.getRGB()/setRGB()` *always* operate on colors in sRGB color space. If your PNG file uses a different color space, or test in an application that uses a different color space, the values will not be exactly what you set. – Harald K Jan 16 '18 at 09:23

1 Answers1

0

Here's a PoC program, that creates a blank image, sets RGB values, stores it as PNG and reads back the exact same values:

public static void main(String[] args) throws IOException {
    BufferedImage image = new BufferedImage(256, 4, BufferedImage.TYPE_INT_ARGB);

    for (int x = 0; x < image.getWidth(); x++) {
        image.setRGB(x, 0, 0x00ffffff | x << 24); // alter alpha
        image.setRGB(x, 1, 0xff000000 | x << 16); // alter red
        image.setRGB(x, 2, 0xff000000 | x <<  8); // alter green
        image.setRGB(x, 3, 0xff000000 | x      ); // alter blue
    }


    File file = File.createTempFile("temp-", ".png");
    if (!ImageIO.write(image, "PNG", file)) {
        System.err.println("Could not write image");
        System.exit(1);
    }

    BufferedImage read = ImageIO.read(file);

    if (read.getWidth() != image.getWidth() || read.getHeight() != image.getHeight()) {
        System.err.println("Dimensions differ!");
        System.exit(1);
    }

    for (int y = 0; y < read.getHeight(); y++) {
        for (int x = 0; x < read.getWidth(); x++) {
            // Uncomment this line, if you want to verify the values
            // System.out.printf("image.getRGB(%3d, %d): #%08x\n", x, y, image.getRGB(x, y));

            if (image.getRGB(x, y) != read.getRGB(x, y)) {
                System.err.printf("pixel differ @ [%3d,%d]: #%08x\n", x, y, read.getRGB(x, y));
            }
        }
    }
}

I get no difference between the original image, and the one that I wrote and read back (using Java 1.8.0_131 on Windows).

Harald K
  • 26,314
  • 7
  • 65
  • 111
  • It was not working yesterday. Today however png is working. I had earlier tried using jpg and maybe there was a problem with the file. But it is working now. Thanks. – Sourit Chakraborty Jan 16 '18 at 13:54