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

Java 将图像读入像素数组,然后写回文件,java,image,Java,Image,我正在做一个示例程序来读取一个图像文件,并将像素细节存储到一个整数数组中,然后将数据写回另一个文件 但是当我打开生成的输出文件时,它只是显示一些随机颜色,而不是显示原始图像 这是我的节目: import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; import java.awt.image.Raster; import java.awt.image.WritableRaster; import java.

我正在做一个示例程序来读取一个图像文件,并将像素细节存储到一个整数数组中,然后将数据写回另一个文件

但是当我打开生成的输出文件时,它只是显示一些随机颜色,而不是显示原始图像

这是我的节目:

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();
        }
    }
}
我是一个全新的图像处理,请帮助我在这段代码中犯了什么错误

更新:

我修改了我的代码,编写了如下图像文件:

   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();
        }
    }
但现在我得到了一个例外:

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)

原因是底层SampleModel不兼容。BuffereImage实际上使用IntegerinerLeavedRaster和SinglePixelPackedSampleModel作为示例模型,但我不依赖它,因为它很可能依赖于实现

相反,我建议使用与缓冲图像相同的样本模型从像素数据创建数据光栅,然后将其提供给缓冲图像。此外,通过这种方式,您也不需要获取和强制转换缓冲图像的内部数据光栅(=类型安全)

我收到了相同的异常消息,并以上述方式解决了问题


我刚刚注意到你的图像读取代码也有一些小错误。例如,readImageToArray方法实际上什么都不做。当然,您必须确保输入图像的图像类型也是type_INT_ARGB。否则,必须相应地转换字节

// 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
...
在您的例子中,使用getPixels实际上将返回一个数组,该数组的大小是所有像素的四倍,因为对于每个像素,将添加四个条目(R、G、B、A)。再次提醒,这取决于输入图像的颜色模型。例如,灰度图像通常只有一个颜色通道。请注意,您不必自己创建输出数组

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

另一种可能性是使用BuffereImage的getRGB和setRGB方法。在这种情况下,无论图像的基础颜色模型是什么,像素格式始终为ARGB。因此,这大概是在二进制级别操作像素数据的最安全的方法

// 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);
最后,我想指出的是,您也可以使用2D图形绘制来直接操作图像

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

您的
writeImageFromArray
方法没有对它接收到的
pixels
参数执行任何操作。@VGR,是的,我知道了,我如何在方法中使用像素?我没有看到任何采用整数数组的
buffereImage
的setter方法或构造函数。返回可写光栅。但是,我想您会发现,一个图像的样本无法写入另一个图像的样本,除非它们具有相同的SampleModels。@VGR,我只是试图创建原始图像的副本,但通过读取像素详细信息,我不确定什么是
SampleModels
。请您推荐一些书籍或在线文档,让我在哪里学习Java中的图像处理。@VGR,当我使用getRaster方法并尝试写入像素时,我遇到异常,如更新的问题中所示。
Graphics2D graphics = (Graphics2D) image.getGraphics();