假设
OSDetector
正常工作,我能够在运行 Oracle JDK 1.8.0_131 的 Windows Server 2008R2 64 位操作系统上直接使用 OP 的代码而无需修改。OP 忽略了
getBufferedImage()
的代码,但我猜测它是从
这篇博客中的某个变种版本。
当我在 Windows 上使用博客中的
getBufferedImage()
版本进行测试(忽略了
OSDetector
检查),我能够重现问题的一个变体,整个图像都是黑色的,这实际上是一个关于异步调用
Image.getWidth()
、
Image.getHeight()
和
Graphics.drawImage()
的时间问题,所有这些方法都会立即返回并且需要 observer 进行异步更新。博客中的代码为所有这些调用传递了
null
(没有 observer)并期望结果立即返回,但在我测试时不是这种情况。
一旦我修改了
getBufferedImage()
来使用回调函数,我就能够复现精确的问题:alpha 通道会变成黑色。造成这种行为的原因是将带有透明度的图像绘制到了默认为黑色画布的图形上下文中。你看到的正是你在黑色背景的网页上查看图像时能够看到的内容。
为了解决这个问题,我使用了
这个 StackOverflow 答案中的提示,并将背景绘制成白色。
我使用
这个站点 中的
ImageSelection
实现,它只是使用
DataFlavor.imageFlavor
将一个
Image
实例包装在一个
Transferrable
中。
最后,在我的测试中,原始图像和缓冲图像变体都在 Windows 上工作。下面是代码:
public static void getBufferedImage(Image image, Consumer<Image> imageConsumer) {
image.getWidth((img, info, x, y, w, h) -> {
if (info == ImageObserver.ALLBITS) {
BufferedImage buffered = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = buffered.createGraphics();
g2.setColor(Color.WHITE);
g2.fillRect(0, 0, w, h);
if (g2.drawImage(img, 0, 0, w, h, (img2, info2, x2, y2, w2, h2) -> {
if (info2 == ImageObserver.ALLBITS) {
g2.dispose();
imageConsumer.accept(img2);
return false;
}
return true;
})) {
g2.dispose();
imageConsumer.accept(buffered);
}
return false;
}
return true;
});
}
public static void setClipboard(Image image) {
boolean testBuffered = true;
if (!testBuffered) {
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new ImageSelection(image), null);
} else {
getBufferedImage(image, (buffered) -> {
ImageSelection imgSel = new ImageSelection(buffered);
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(imgSel, null);
});
}
}
我希望这能有所帮助。祝你好运。