繁体   English   中英

Java透明PNG到剪贴板

[英]Java transparent PNG to clipboard

我正在尝试将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);
}

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

这是正确的答案吗? 你试过这个吗?

    public void doCopyToClipboardAction()
{
  // figure out which frame is in the foreground
  MetaFrame activeMetaFrame = null;
  for (MetaFrame mf : frames)
  {
    if (mf.isActive()) activeMetaFrame = mf;
  }
  // get the image from the current jframe
  Image image = activeMetaFrame.getCurrentImage();
  // place that image on the clipboard
  setClipboard(image);
}


// code below from exampledepot.com
//This method writes a image to the system clipboard.
//otherwise it returns null.
public static void setClipboard(Image image)
{
   ImageSelection imgSel = new ImageSelection(image);
   Toolkit.getDefaultToolkit().getSystemClipboard().setContents(imgSel, null);
}


// This class is used to hold an image while on the clipboard.
static class ImageSelection implements Transferable
{
  private Image image;

  public ImageSelection(Image image)
  {
    this.image = image;
  }

  // Returns supported flavors
  public DataFlavor[] getTransferDataFlavors()
  {
    return new DataFlavor[] { DataFlavor.imageFlavor };
  }

  // Returns true if flavor is supported
  public boolean isDataFlavorSupported(DataFlavor flavor)
  {
    return DataFlavor.imageFlavor.equals(flavor);
  }

  // Returns image
  public Object getTransferData(DataFlavor flavor)
      throws UnsupportedFlavorException, IOException
  {
    if (!DataFlavor.imageFlavor.equals(flavor))
    {
      throw new UnsupportedFlavorException(flavor);
    }
    return image;
  }
}

资料来源: http//alvinalexander.com/java/java-copy-image-to-clipboard-example

我自己也没试过,我不确定。 希望你得到正确的答案。

这是一个非常简单,自包含的例子。 阅读或创建图像取决于您。 此代码只是在alpha类型的BufferedImage上创建一个红色圆圈。 当我将其粘贴到任何支持透明度的程序中时,它会正确显示。 希望能帮助到你。

import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.image.BufferedImage;
import java.io.IOException;

public class CopyImageToClipboard {
    public void createClipboardImageWithAlpha() {
        //Create a buffered image of the correct type, with alpha.
        BufferedImage image = new BufferedImage(600, 600, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = image.createGraphics();
        //Draw in the buffered image.
        g2d.setColor(Color.red);
        g2d.fillOval(10, 10, 580, 580);

        //Add the BufferedImage to the clipboard with transferable image flavor.
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        Transferable transferableImage = getTransferableImage(image);
        clipboard.setContents(transferableImage, null);
    }

    private Transferable getTransferableImage(final BufferedImage bufferedImage) {
        return new Transferable() {
            @Override
            public DataFlavor[] getTransferDataFlavors() {
                return new DataFlavor[] { DataFlavor.imageFlavor };
            }

            @Override
            public boolean isDataFlavorSupported(DataFlavor flavor) {
                return DataFlavor.imageFlavor.equals(flavor);
            }

            @Override
            public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
                if (DataFlavor.imageFlavor.equals(flavor)) {
                    return bufferedImage;
                }
                return null;
            }
        };
    }
}

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

当我在Windows上使用博客版本的getBufferedImage()测试代码时(忽略OSDetector检查),我能够重现整个图像为黑色的问题的变体,这对异步的时间问题来说是个问题。调用Image.getWidth()Image.getHeight()Graphics.drawImage() ,所有这些都立即返回并带一个观察者进行异步更新。 博客代码为所有这些调用传递null (无观察者),并期望立即返回结果,这在我测试时不是这种情况。

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

为了改变这种情况,我使用了StackOverflow答案的提示并将背景涂成了白色。

我使用了这个站点ImageSelection实现,它只是使用DataFlavor.imageFlavorImage实例包装在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); // 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);
        });
    }
}

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM