1. 概述

在这个教程中,我们将学习如何从Java中的BufferedImage实例获取包含图像信息(RGB值)的像素数组。

2. BufferedImage类是什么?

BufferedImage类是Image类的子类,它描述了一个具有可访问图像数据缓冲区的图形图像。BufferedImage由一个ColorModel和一个Raster组成。

ColorModel描述了颜色如何使用一组组件的组合表示为值的元组。Java中的ColorModel类包含方法,可以为特定像素返回颜色值,例如getBlue(int pixel)返回给定像素的蓝色值。

此外,Raster类以像素数组的形式存储图像数据。Raster类由一个DataBuffer组成,用于存储图像值,以及一个SampleModel,用于描述像素如何存储在DataBuffer中。

3. 使用getRGB()

首先的方法是使用BufferedImage类的getRGB()实例方法。

getRGB()方法将指定像素的RGB值组合成一个整数并返回结果。这个整数包含了可以通过实例的ColorModel访问的RGB值。为了获取图像中每个像素的结果,我们需要遍历它们,并分别对每个像素调用该方法:

public int[][] get2DPixelArraySlow(BufferedImage sampleImage) {
    int width = sampleImage.getWidth();
    int height = sampleImage.getHeight();
    int[][] result = new int[height][width];

    for (int row = 0; row < height; row++) {
        for (int col = 0; col < width; col++) {
            result[row][col] = sampleImage.getRGB(col, row);
        }
    }

    return result;
}

在上述代码片段中,result数组是一个二维数组,其中包含图像中每个像素的RGB值。这种方法更直接但效率较低。

4. 直接从DataBuffer获取值

在这个方法中,我们首先分别获取图像中的所有RGB值,然后手动将它们组合成一个整数。接着,我们像第一种方法一样填充包含像素值的二维数组。这种方法比较复杂,但比第一种方法快得多:

public int[][] get2DPixelArrayFast(BufferedImage image) {
    byte[] pixelData = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
    int width = image.getWidth();
    int height = image.getHeight();
    boolean hasAlphaChannel = image.getAlphaRaster() != null;

    int[][] result = new int[height][width];
    if (hasAlphaChannel) {
        int numberOfValues = 4;
        for (int valueIndex = 0, row = 0, col = 0; valueIndex + numberOfValues - 1 < pixelData.length; valueIndex += numberOfValues) {
            
            int argb = 0;
            argb += (((int) pixelData[valueIndex] & 0xff) << 24); // alpha value
            argb += ((int) pixelData[valueIndex + 1] & 0xff); // blue value
            argb += (((int) pixelData[valueIndex + 2] & 0xff) << 8); // green value
            argb += (((int) pixelData[valueIndex + 3] & 0xff) << 16); // red value
            result[row][col] = argb;

            col++;
            if (col == width) {
                col = 0;
                row++;
            }
        }
    } else {
        int numberOfValues = 3;
        for (int valueIndex = 0, row = 0, col = 0; valueIndex + numberOfValues - 1 < pixelData.length; valueIndex += numberOfValues) {
            int argb = 0;
            argb += -16777216; // 255 alpha value (fully opaque)
            argb += ((int) pixelData[valueIndex] & 0xff); // blue value
            argb += (((int) pixelData[valueIndex + 1] & 0xff) << 8); // green value
            argb += (((int) pixelData[valueIndex + 2] & 0xff) << 16); // red value
            result[row][col] = argb;

            col++;
            if (col == width) {
                col = 0;
                row++;
            }
        }
    }

    return result;
}

在上面的代码片段中,我们首先获取图像中每个像素的单独RGB值,并将它们存储在一个名为pixelData的字节数组中。

例如,假设图像没有Alpha通道(Alpha通道包含图片透明度信息),则pixelData[0]包含图像中第一个像素的蓝色值,而pixelData[1]pixelData[2]分别包含绿色和红色值。类似地,pixelData[3]pixelData[5]包含第二个图像像素的RGB值,以此类推。

获取到值后,我们必须为每个像素将它们组合成一个整数。但在那之前,我们需要确定图像是否有Alpha通道。如果有Alpha通道,我们将需要将四个值(红色、绿色、蓝色和透明度信息)组合成一个整数。如果没有,我们只需要组合RGB值。

将所有值组合成一个整数后,我们将整数放入二维数组的相应位置。

5. 总结

在这篇短文中,我们了解了如何在Java中获取一个二维数组,其中包含图像中每个像素组合的RGB值。

如往常一样,本文中使用的代码示例可在GitHub上找到。