简体   繁体   English

将图像读入像素数组,然后写回文件

[英]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.原因是底层的 SampleModel 不兼容。 BufferedImage actually uses IntegerInterleavedRaster with SinglePixelPackedSampleModel as sample model, but I wouldn't rely on it because it may very well be implementation-dependent. BufferedImage 实际上使用 IntegerInterleavedRaster 和 SinglePixelPackedSampleModel 作为示例模型,但我不会依赖它,因为它很可能依赖于实现。

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.例如,方法 readImageToArray 实际上没有做任何事情。 Of course, you have to make sure that the image type of the input image is TYPE_INT_ARGB, too.当然,您必须确保输入图像的图像类型也是 TYPE_INT_ARGB。 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.在您的情况下,使用 getPixels 实际上将返回一个四倍于所有像素大小的数组,因为对于每个像素,将添加四个条目(R、G、B、A)。 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.另一种可能是使用 BufferedImage 的 getRGB 和 setRGB 方法。 In this case, the pixel format is always ARGB, no matter what the underlying color model of the image is.在这种情况下,无论图像的底层颜色模型是什么,像素格式始终为 ARGB。 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.最后,我想指出您也可以使用 2D 图形绘制来直接操作图像。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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