Graphics.drawImage 将 BufferedImage 留空

Graphics.drawImage leaves BufferedImage empty

我正在尝试提取 BufferedImage 的 10 像素正方形部分并将它们添加到新的 BufferedImage,这与 this drawImage tutorial 中显示的混乱示例非常相似。但是,在调用 drawImage 之后,我的 BufferedImage 似乎仍然是空的。如果我调用 drawString,我会看到 String 是正常绘制的。

Graphics.drawImage 的文档中,有语句

This method returns immediately in all cases, even if the image area to be drawn has not yet been scaled, dithered, and converted for the current output device. If the current output representation is not yet complete then drawImage returns false. As more of the image becomes available, the process that loads the image notifies the specified image observer.

我需要 ImageObserver 来等待输出吗?如果是这样,我应该使用什么实现 class ?如果不是,正确的解决方案是什么?

MCVE

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class TestImageScale {

    public static void main(String[] args) throws IOException {
        BufferedImage img = ImageIO.read(new File(
                "example.jpeg"));

        //Randomly generate some coordinates to grab pixels from
        int minDim = Math.min(img.getHeight(), img.getWidth()) - 10;
        int[][] coordMatch = new int[5][3];
        for (int i = 0; i < 5; i++) {
            coordMatch[i][0] = (int) Math.floor(Math.random() * minDim + 5);
            coordMatch[i][1] = (int) Math.floor(Math.random() * minDim + 5);
            coordMatch[i][2] = 5;
        }

        BufferedImage simImg = new BufferedImage(10, 10 * 5, BufferedImage.TYPE_INT_ARGB);
        Graphics g = simImg.getGraphics();

        for (int i = 0; i < 5; i++) {
            int x = coordMatch[i][0];
            int y = coordMatch[i][1];
            int r = coordMatch[i][2];
            //Print statement to show that we are in the for loop
            System.out.println(String.format("%s,%s,%s", x, y, r));
            //g.drawImage should write the pixels from img to simImg
            g.drawImage(img, x - r, y - r, x + r, y + r, 0, i * 10, 10, i * 10 + 10, null);
        }
        //I draw the string "hello" on simImg to show that g is working
        g.drawString("hello", 0, 10);

        ImageIO.write(simImg, "png", new File("output.png"));
    }


}

在测试 运行 中,我得到了行

322,228,5
118,186,5
285,351,5
21,213,5
144,48,5

打印到控制台,保存的文件看起来像

此输出显示已进入 for 循环并且 Graphics 对象 g 已连接到正确的 BufferedImage。但是来自 img 的像素没有被复制到 simImg.

根据要求,用于测试的示例图像,来自 Matlab 的演示图像。但实际上,我测试过的每张图像都以这种方式表现。

我认为您对 drawImage 的一些论点顺序错误。

Javadoc for the drawImage method you are using提到目标矩形的坐标在源矩形的坐标之前。在我看来,您好像是在调用此方法时首先使用源坐标,然后使用目标坐标。

而不是

        g.drawImage(img, x - r, y - r, x + r, y + r, 0, i * 10, 10, i * 10 + 10, null);

尝试

        g.drawImage(img, 0, i * 10, 10, i * 10 + 10, x - r, y - r, x + r, y + r, null);

我没有你的测试图片,所以我用了另一张图片。在进行此修改和 运行 您的 class 之后,我得到了一个不完全空白的输出图像,并且看起来已经从我的示例图像中复制了像素。