Java透明PNG到剪贴板

Chr*_*ris 9 java clipboard png transparent

我正在尝试将png文件复制到程序中的剪贴板,并在粘贴到另一个程序(例如ms office,paint,photoshop)时保持其alpha通道.问题是,在大多数程序中alpha通道变黑.我一直在网上搜索几个小时,但找不到解决方案.我正在使用的代码:

setClipboard(Toolkit.getDefaultToolkit().getImage(parent.getSelectedPicturePath()));

public static void setClipboard(Image image) {
    ImageSelection imgSel;
if (OSDetector.isWindows()) {
    imgSel = new ImageSelection(image);
} else {
    imgSel = new ImageSelection(getBufferedImage(image));
}
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(imgSel, null);
}
Run Code Online (Sandbox Code Playgroud)

有没有办法在Java中维护alpha通道?我已经尝试将png转换为BufferedImage,Image等,并将其粘贴到剪贴板,但没有任何效果.

Ale*_*aca 2

假设OSDetector工作正常,我能够让 OP 的代码在运行 Oracle JDK 1.8.0_131 的 Windows Server 2008R2 64 位上开箱即用。OP 省略了代码,但我怀疑它是该博客getBufferedImage()版本的某些变体。

getBufferedImage()当我在 Windows 上使用博客版本(忽略OSDetector检查)测试代码时,我能够重现整个图像为黑色的问题的变体,结果证明这是异步调用Image.getWidth(), Image.getHeight(),和Graphics.drawImage(),所有这些都立即返回并采用观察者进行异步更新。博客代码通过null(无观察者)所有这些调用,并期望立即返回结果,但我测试时情况并非如此。

一旦我修改getBufferedImage()为使用回调,我就重现了确切的问题:Alpha 通道显示为黑色。出现此行为的原因是具有透明度的图像被绘制到默认为黑色画布的图形上下文上。您所看到的正是您在黑色背景网页上查看图像时所看到的。

为了改变这一点,我使用了StackOverflow 答案中的提示,并将背景漆成白色。

我使用了这个站点ImageSelection的实现,它只是将一个实例包装在using中。ImageTransferrableDataFlavor.imageFlavor

最终,对于我的测试,原始图像和缓冲图像变体都可以在 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); // 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);
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助。祝你好运。