Assuming that OSDetector
is working properly, I was able to get the OP's code to work out of the box on Windows Server 2008R2 64-bit running Oracle JDK 1.8.0_131. The OP omitted the code for getBufferedImage()
, however I suspect it was some variant of the version from this blog.
When I tested the code using the blog's version of getBufferedImage()
on Windows (ignoring the OSDetector
check), I was able to reproduce a variant of the issue where the entire image was black, which turned out to be a timing issue with the asynchronous calls to Image.getWidth()
, Image.getHeight()
, and Graphics.drawImage()
, all of which return immediately and take an observer for async updates. The blog code passes null
(no observer) for all of these invocations, and expects results to be returned immediately, which was not the case when I tested.
Once I modified getBufferedImage()
to use callbacks, I reproduced the exact issue: alpha channels appear black. The reason for this behavior is that the image with the transparency is drawn onto a graphics context that defaults to a black canvas. What you are seeing is exactly what you would see if you viewed the image on a web page with a black background.
To change this, I used a hint from this StackOverflow answer and painted the background white.
I used the ImageSelection
implementation from this site, which simply wraps an Image
instance in a Transferrable
using DataFlavor.imageFlavor
.
Ultimately for my tests, both the original image and the buffered image variants worked on Windows. Below is the code:
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); // You choose the background color
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; // Both buffered and non-buffered worked for me
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);
});
}
}
I hope this helps. Best of luck.