简体   繁体   中英

Reading an image into an array of pixels and then writing back to a file

I am doing a sample program to read an image file and store the pixel details into an integer array and then write the data back to another file.

But when I open the generated output file then it is showing just some random color instead of showing the original image.

Here is my program:

import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class MainApp {

    public static void main(String[] args) throws IOException {
        String filename = "input.jpeg";

        // Reading the image into byte array
        BufferedImage bimg = ImageIO.read(new File(filename));
        int width = bimg.getWidth();
        int height = bimg.getHeight();

        Raster raster = bimg.getData();

        byte[] byteArray = readImageToArray(bimg);
        // Convert the byte array into integer array           
        int[] array = raster.getPixels(0, 0, width,height,new int[byteArray.length]);

        // Writing the image to another file.
        writeImageFromArray(array, width, height);
    }

    public static byte[] readImageToArray(BufferedImage bimg){
        DataBufferByte data = (DataBufferByte) bimg.getRaster().getDataBuffer();
        byte[] byteArray = data.getData();
        return byteArray;

    }

    public static void writeImageFromArray(int[] pixels, int width, int height) {
        BufferedImage image = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_ARGB);

        File outputfile = new File("image.jpg");
        try {
            ImageIO.write(image, "jpg", outputfile);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

I am completely new to image processing, please help me where I am doing mistake in this code.

Update:

I have modified my code that writes an image file like this:

   public static void writeImageFromArray(int[] pixels, int width, int height) {
        File outputfile = new File("output.jpeg");
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        WritableRaster raster = (WritableRaster) image.getData();
        raster.setPixels(0,0,width,height,pixels);

        try {
            ImageIO.write(image, "jpeg", outputfile);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

But now I am getting an exception as :

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 151194
    at java.awt.image.SinglePixelPackedSampleModel.setPixels(SinglePixelPackedSampleModel.java:685)
    at java.awt.image.WritableRaster.setPixels(WritableRaster.java:565)
    at MainApp.writeImageFromArray(MainApp.java:40)
    at MainApp.main(MainApp.java:27)

The reason is that the underlying SampleModel is incompatible. BufferedImage actually uses IntegerInterleavedRaster with SinglePixelPackedSampleModel as sample model, but I wouldn't rely on it because it may very well be implementation-dependent.

Instead, I would suggest creating a data raster from the pixel data using the same sample model as the buffered image, then feeding it to the buffered image. Further, this way you also don't need to get and cast the internal data raster of the buffered image (= type safe).

public static void writeImageFromArray(int[] pixels, int width, int height) throws IOException {
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    Raster raster = Raster.createRaster(image.getSampleModel(), new DataBufferInt(pixels, pixels.length), null);
    image.setData(raster);
    File outputFile = new File("output.jpeg");
    ImageIO.write(image, "jpeg", outputFile);
}

I had come along the same exception message and had solved the problem in the above mentioned manner.


I just noticed that your image reading code also has some minor mistakes. For instance, the method readImageToArray does effectively not do anything. Of course, you have to make sure that the image type of the input image is TYPE_INT_ARGB, too. Otherwise, you have to convert the bytes accordingly.

// open the image
File inputFile = new File("input.jpeg");
BufferedImage image = ImageIO.read(file);
int width = image.getWidth();
int height = image.getHeight();
// get the pixel data as integer array, presumingly ARGB
int[] pixels = (int[]) image.getData().getDataElements(0, 0, width, height, null);
// do something with the pixels
...

In your case, using getPixels will actually return an array four times the size of all pixels, because for each pixel four entries (R, G, B, A) are being added. Again, beware that this depends on the color model of the input image. For instance, a gray-scale image has typically only one color channel. Just as a note, you don't have to create the output array yourself.

// get the pixel component data as integer array, presumingly RGBA
int[] pixelComponents = image.getData().getPixels(0, 0, width, height, (int[]) null);

Another possiblity is to use the getRGB and setRGB methods of BufferedImage. In this case, the pixel format is always ARGB, no matter what the underlying color model of the image is. Therefore, this is presumably the safest way to manipulate pixel data on a binary level.

// open the image
File inputFile = new File("input.jpeg");
BufferedImage image = ImageIO.read(file);
int width = image.getWidth();
int height = image.getHeight();
// get the pixel data as integer array (always ARGB)
int[] pixels = image.getRGB(0, 0, width, height, null, 0, width);
// do something with the pixels
...
// optionally create a new image instance
// image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
// write back the pixel data (always ARGB)
image.setRGB(0, 0, width, height, pixels, 0, width);
// save the image
File outputFile = new File("output.jpeg");
ImageIO.write(image, "jpeg", outputFile);

Lastly, I want to point out that you could also use 2D graphics drawing to manipulate the image directly.

Graphics2D graphics = (Graphics2D) image.getGraphics();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM