【问题标题】:int array to BufferedImageint 数组到 BufferedImage
【发布时间】:2013-01-19 16:02:21
【问题描述】:

我正在使用Robot 类制作一个打印屏幕,并将 BufferedImage 转换为一个 int 数组。然后我想将 int 数组转换回 bufferedimage 但这会出错。这是我的代码:

Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
BufferedImage printscreen = robot.createScreenCapture(new Rectangle(screen));
int[] pixels = ((DataBufferInt) printscreen.getRaster().getDataBuffer()).getData();

BufferedImage image = new BufferedImage(screen.width, screen.height, BufferedImage.TYPE_INT_RGB);
WritableRaster raster = (WritableRaster) image.getRaster();
raster.setPixels(0, 0, screen.width, screen.height, pixels);

但我得到了错误:ArrayIndexOutOfBoundsException: 2073600 但是为什么?

我在这一行遇到了异常:

raster.setPixels(0, 0, screen.width, screen.height, pixels);

编辑:如果我将第二个缓冲图像类型更改为 TYPE_BYTE_GRAY,它将起作用。

【问题讨论】:

  • 你能分享堆栈跟踪吗?你在哪条线上得到它?
  • 我建议您将所有尺寸都基于screen 的大小。为了尽快获得更好的帮助,请发布SSCCE。似乎这个问题也需要一些基本的代码行跟踪和大小显示。

标签: java bufferedimage pixels


【解决方案1】:
int[] bitMasks = new int[]{0xFF0000, 0xFF00, 0xFF, 0xFF000000};
SinglePixelPackedSampleModel sm = new SinglePixelPackedSampleModel(
        DataBuffer.TYPE_INT, width, height, bitMasks);
DataBufferInt db = new DataBufferInt(pixels, pixels.length);
WritableRaster wr = Raster.createWritableRaster(sm, db, new Point());
BufferedImage image = new BufferedImage(ColorModel.getRGBdefault(), wr, false, null);

【讨论】:

  • 非常好的解决方案。作为记录,这也是页面上唯一对我有用的解决方案。 WritableRaster setPixels() 文档中未说明的部分是传递给 setPixels() 的 int 数组不是作为一个打包的 int-per-pixel 访问的,而是显然每个通道一个 int(即 RGB 需要一个临时数组的大小是他打包的数组的 3 倍,ARGB 是 4 倍——显然不是一个优雅的解决方案,但我对其进行了测试并且它有效)。
【解决方案2】:

改为:

getRaster().getPixels(0, 0, screen.width, screen.height, pixels)

它有效!无论如何感谢您的帮助

【讨论】:

    【解决方案3】:

    ArrayIndexOutOfBounds 异常发生在您尝试访问超出数组大小的索引处的元素时。在这种情况下,您将数组传递给setPixels 方法,根据它的javadocs,它不会显式检查数组的边界或大小。因此,您应该在调用该方法之前明确地执行此操作。例如

        if(x >= 0 && x < arr.length) {
            // some code
        }
    

    这是来自 WritableRaster 使用的SampleModel 类的相关代码。

        public int[] getPixels(int x, int y, int w, int h,
                               int iArray[], DataBuffer data) {
    
            int pixels[];
            int Offset=0;
    
            if (iArray != null)
                pixels = iArray;
            else
                pixels = new int[numBands * w * h];
    
            for (int i=y; i<(h+y); i++) {
                for (int j=x; j<(w+x); j++) {
                    for(int k=0; k<numBands; k++) {
                        pixels[Offset++] = getSample(j, i, k, data);
                    }
                }
            }
    
        return pixels;
    }
    

    【讨论】:

    • 感谢您的回答,但两个 BufferedImage 的高度和宽度相同。那么,如果它具有相同数量的像素,为什么它需要更多的元素呢?
    • 我建议将 JDK 源代码添加到 Eclipse 之类的 IDE 中,并使用调试器检查变量值。这要快得多。
    • 我正在使用 Eclipse。我在您的示例中看到:numBands * w * h numBands 是什么意思?我的像素数组有 2073600 个元素,即 1920*1080。
    【解决方案4】:

    设置BufferedImage.TYPE_INT_RGBraster.setPixels(0, 0, screen.width, screen.height, pixels);pixels的大小应为width*height*3

    【讨论】:

      【解决方案5】:
      BufferedImage image = new BufferedImage(screen.width*3, screen.height,BufferedImage.TYPE_INT_RGB);
      WritableRaster raster = (WritableRaster) image.getRaster();
      
      raster.setPixels(0, 0, screen.width*3, screen.height, pixels);
      

      【讨论】:

      • 请补充说明。
      • 正如@SamirChen 提到的,你有红色、绿色、蓝色、宽度的像素。所以实际宽度是图像宽度的 3 倍。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-14
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      • 2014-05-07
      相关资源
      最近更新 更多