【发布时间】:2022-01-29 01:01:30
【问题描述】:
我希望能够将图像的数据作为数组进行修改,然后使用该数组创建修改后的图像。这是我尝试过的:
public class Blue {
public static void main (String [] args) throws AWTException, IOException {
Robot robot = new Robot ();
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
BufferedImage img = robot.createScreenCapture(new Rectangle(0,0,d.width,d.height));
int[] pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
int[] newPixels = IntStream.range(0,pixels.length).parallel().filter(i ->{
int p = pixels[i];
// get red
int r = (p >> 16) & 0xff;
// get green
int g = (p >> 8) & 0xff;
// get blue
int b = p & 0xff;
return b >= 200;
}).toArray();
int[] output = new int[pixels.length];
for(int i = 0; i<newPixels.length; i++) {
output[newPixels[i]] = 0x0000FF;
}
File f = new File("Result.jpg");
ByteBuffer byteBuffer = ByteBuffer.allocate(output.length * 4);
for (int i = 0; i< output.length; i++) {
byteBuffer.putInt(output[i]);
}
byte[] array = byteBuffer.array();
InputStream stream = new ByteArrayInputStream(array);
BufferedImage image1 = ImageIO.read(stream);
System.out.println(image1.getWidth());
ImageIO.write(image1, "png", f);
}
}
这是它的工作原理。
- 机器人对屏幕进行截屏,然后将其存储到 BufferedImage 中。
- 图像的数据存储在一个整数数组中
- 一个 int 流用于选择与足够蓝色像素相对应的所有像素位置
- 这些蓝色像素被放置在一个称为输出的数组中,它们位于相同的位置。但是,数组的其余部分的值为 0。
- 为我修改后的图像创建了一个目标文件
- 我创建了一个 4 倍于输出数组长度的字节缓冲区,并将输出数组中的数据放入其中。
- 我从缓冲区创建一个字节数组,然后用它创建一个输入流
- 最后,我读取流并从中创建图像
- 我使用 System.out.println() 从图像中打印一些数据以查看图像是否存在。
第 9 步是问题出现的地方。 我不断收到 NullPointerException,这意味着图像不存在,它为空。 我不明白我做错了什么。 我尝试使用 ByteArrayInputStream 而不是 InputStream,但效果不佳。然后,我认为可能前几个字节编码了图像的编码信息,所以我尝试将其复制到输出数组,但这也没有解决问题。我不确定为什么我的字节数组没有变成图像。
【问题讨论】:
-
修改第 4 步,将像素值复制回
pixels,并清除数组中的所有其他索引。然后跳过第 6、7 和 8 步。最后,修改第 9 步以打印并写入您的原始图像img,它现在包含您修改后的蓝色像素。 ???更快,可能更容易推理并希望是正确的。 -
(您的版本不工作的原因是因为
ImageIO.read()是用于读取定义文件格式的图像,而不是读取像素)。 -
@HaraldK 清除索引是指将它们设置为 0,对吗?
-
@HaraldK 另外,“写下你的原始图像”是什么意思?
-
1:是的。或者
0xFF000000如果您的图像包含透明度。 2:“您的原始图像”是指img(屏幕截图)。要编写它,请将最后一行替换为:ImageIO.write(img, "png", f);。
标签: java image-processing file-io nullpointerexception