Alexandru Marian Obaj
Alexandru Marian Obaj

Reputation: 83

Why ImageIO.write() method modifies pixel values?

I am trying to run a simple Java program that tries to do the following : Extract pixel data from a given image. Then use this data to create a new image of the same type. The problem is that when I read the pixel data of this created image, the pixel values differ from the ones I have written into it. This happens not only or .jpg images but also for some .png images(so it's not even restricted to image type). Here is my code:

package com.alex;

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

import javax.imageio.ImageIO;

public class Test {

    public static void main(String[] args) {
        try{
            // Read source image
            BufferedImage img = ImageIO.read(new File("D:/field.png")); 


            int width = img.getWidth();
            int height = img.getHeight();
            int[] imagePixels = new int[width*height];
            img.getRGB(0, 0, width, height, imagePixels, 0, width);

            // Create copy image
            BufferedImage destImg = new BufferedImage(img.getWidth(), img.getHeight(), img.getType());
            destImg.setRGB(0, 0, img.getWidth(), img.getHeight(), imagePixels, 0, img.getWidth());
            File out = new File("D:/test.png");
            ImageIO.write(destImg, "png", out);

            // Extract copy image pixels
            BufferedImage copy = ImageIO.read(new File("D:/test.png"));
            int width1 = copy.getWidth();
            int height1 = copy.getHeight();
            int[] extractedPixels = new int[width1*height1];
            copy.getRGB(0, 0, width1, height1, extractedPixels, 0, width1);

            System.out.println("The 2 dimensions are " + imagePixels.length + " " + extractedPixels.length );

            // Compare the piels from the 2 images
            int k=0;
            for(int i=0; i<imagePixels.length; i++) {
                if(imagePixels[i] != extractedPixels[i]) {
                    k++;
                }
            }
            System.out.println("Number of different pixels was: " + k);
            }catch(IOException e) {
            System.out.println("Exception was thrown during reading of image: " + e.getMessage());
            }

        }
}

Unfortunately quite often and impredictable the 2 images pixel data differ. Could someone please help me find a method so that, at least for an image type, the values don't get modiied ? Edit Here is an image that fails in the above process

For this image the background color is changed

Upvotes: 3

Views: 1639

Answers (2)

Shadmman Muhammed
Shadmman Muhammed

Reputation: 16

Try this First print same index in two array If the result is not same means your problem in your color mode, But if same means your comparision is not work.

Upvotes: 0

WeaponsGrade
WeaponsGrade

Reputation: 878

Make sure you are using the correct color model for reading and writing.

According to the BufferedImage.getRGB() documentation,

Returns an array of integer pixels in the default RGB color model (TYPE_INT_ARGB) and default sRGB color space, from a portion of the image data. Color conversion takes place if the default model does not match the image ColorModel. There are only 8-bits of precision for each color component in the returned data when using this method. With a specified coordinate (x, y) in the image, the ARGB pixel can be accessed in this way:

pixel = rgbArray[offset + (y-startY)*scansize + (x-startX)];

[Edit]

You need to use the constructor BufferedImage(width, height, type, ColorModel), as indicated in the Javadoc for your image type (TYPE_BYTE_BINARY):

When this type is used as the imageType argument to the BufferedImage constructor that takes an imageType argument but no ColorModel argument, a 1-bit image is created with an IndexColorModel with two colors in the default sRGB ColorSpace: {0, 0, 0} and {255, 255, 255}.

Images with 2 or 4 bits per pixel may be constructed via the BufferedImage constructor that takes a ColorModel argument by supplying a ColorModel with an appropriate map size.

(emphasis mine)

Upvotes: 3

Related Questions