BufferedImage.getData().getPixels() 中的异常

Exception in BufferedImage.getData().getPixels()

我正在寻找将缓冲图像转换为其相应像素值数组的方法。我找到了一个代码:

public static double[] createArrFromIm(BufferedImage im){
      int imWidth = im.getWidth();
      int imHeight = im.getHeight();
      double[] imArr = new double[imWidth* imHeight];
      im.getData().getPixels(0, 0, imWidth, imHeight, imArr);
      return imArr;
}

编写此代码块的原作者还提供了一些非常适合此块的示例图像。但是,当我尝试 运行 此块针对我的图像(图像始终为 125*150)时,该块在行抛出数组索引超出范围异常:

      im.getData().getPixels(0, 0, imWidth, imHeight, imArr);

这件事对我来说似乎很神秘。任何帮助或建议将不胜感激。谢谢

使用光栅执行:

public static double[] createArrFromIm(BufferedImage im){
    int imWidth = im.getWidth();
    int imHeight = im.getHeight();
    double[] imArr = new double[imWidth* imHeight];
    for (int y=0, nb=0 ; y < imHeight ; y++)
        for (int x=0 ; x < imWidth ; x++, nb++)
            imArr[nb] = im.getRaster().getSampleDouble(x, y, 0) ;
    return imArr;
}

正如@haraldK 所指出的,getData() 也有效,但它return是栅格的副本,所以速度较慢。

有一种使用 DataBuffer 的更快方法,但是您必须管理 BufferedImage 编码,因为您可以直接访问像素值。

这就是为什么你所做的没有奏效的答案。 im.getData().getPixels() return 是一个数组,它不会填充您作为参数提供的数组。您作为参数提供的数组仅确定 return 类型。所以如果你想使用 getData(这不是最好的选择),你必须这样做:

double[] imArr = im.getData().getPixels(0, 0, imWidth, imHeight, (double[])null) ;

正如@FiReTiTi 所说,你应该使用 getRaster() 方法而不是 getData() 方法,除非你 真的 想要图像数据的副本.

但是,这不是异常的原因。问题是您的 double 数组只为单个波段分配 space (类似地,FiReTiTi 的版本有效,因为他明确地将最后一个参数保留为 0,只请求第一个波段)。这适用于单波段(灰度)图像,但我假设您使用 RGB、CMYK 或其他具有多个波段的颜色模型。

解决方法是将分配的 space 乘以波段数,如下所示:

public static double[] createArrFromIm(BufferedImage im) {
    int imWidth = im.getWidth();
    int imHeight = im.getHeight();
    int imBands = im.getRaster().getNumBands(); // typically 3 or 4, depending on RGB or ARGB

    double[] imArr = new double[imWidth * imHeight * imBands];
    im.getRaster().getPixels(0, 0, imWidth, imHeight, imArr);

    return imArr;
}