将Image对象复制到剪贴板时出错

时间:2019-12-02 14:23:02

标签: java clipboard

我试图将Image对象放入剪贴板,但出现一个奇怪的错误。

这是问题所在。

ByteArrayInputStream bis = new ByteArrayInputStream(clipboardObject.data);
try(ObjectInput in = new ObjectInputStream(bis)) {
    ImageIcon img = (ImageIcon) in.readObject();
    ImageTransferable t = new ImageTransferable(img.getImage());
    Toolkit.getDefaultToolkit().getSystemClipboard()
            .setContents(t, null);
} catch(Exception e) {
    e.printStackTrace();
}

这是我的ImageTransferable班。

static class ImageTransferable implements Transferable
{
    private Image image;

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

    public Object getTransferData(DataFlavor flavor)
            throws UnsupportedFlavorException
    {
        if (isDataFlavorSupported(flavor))
        {
            return image;
        }
        else
        {
            throw new UnsupportedFlavorException(flavor);
        }
    }

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

    public DataFlavor[] getTransferDataFlavors ()
    {
        return new DataFlavor[] { DataFlavor.imageFlavor };
    }
}

这是我遇到的错误。

java.io.IOException: Registered service providers failed to encode BufferedImage@5f341870: type = 2 DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=ff000000 IntegerInterleavedRaster: width = 2227 height = 2225 #Bands = 4 xOff = 0 yOff = 0 dataOffset[0] 0 to image/jpeg
at java.desktop/sun.awt.datatransfer.DataTransferer.imageToStandardBytesImpl(Unknown Source)
at java.desktop/sun.awt.datatransfer.DataTransferer.imageToStandardBytes(Unknown Source)
at java.desktop/sun.awt.windows.WDataTransferer.imageToPlatformBytes(Unknown Source)
at java.desktop/sun.awt.datatransfer.DataTransferer.translateTransferable(Unknown Source)
at java.desktop/sun.awt.windows.WDataTransferer.translateTransferable(Unknown Source)
at java.desktop/sun.awt.windows.WClipboard.setContentsNative(Unknown Source)
at java.desktop/sun.awt.datatransfer.SunClipboard.setContents(Unknown Source)
at com.bruhclp.ClipboardManager.setData(ClipboardManager.java:75)
at com.bruhclp.Main.main(Main.java:12)

2 个答案:

答案 0 :(得分:1)

这不是错误,只是调试信息

请注意,控制台中显示的此异常实际上不是错误,并且实际上不是从Toolkit.getDefaultToolkit().getSystemClipboard().setContents(t, null);方法调用中引发的。

Java中的JPEG现在不支持透明度(https://bugs.openjdk.java.net/browse/JDK-8204188),但是实际上将复制的图像压缩为PNG(或其他某种格式),并且即使使用BufferedImage.TYPE_INT_ARGB图像类型也可以正确设置剪贴板。至少它对JDK 14有用。

因此,控制台中的此异常只是调试信息(我已经调查了数小时以了解它并发现它确实有效)。答案是在OpenJDK sun.awt.windows.WClipboard.setContentsNative(Transferable contents)方法中:

         for (Long format : formatMap.keySet()) {
            DataFlavor flavor = formatMap.get(format);

            try {
                byte[] bytes = WDataTransferer.getInstance().
                    translateTransferable(contents, flavor, format);
                publishClipboardData(format, bytes);
            } catch (IOException e) {
                // Fix 4696186: don't print exception if data with
                // javaJVMLocalObjectMimeType failed to serialize.
                // May remove this if-check when 5078787 is fixed.
                if (!(flavor.isMimeTypeEqual(DataFlavor.javaJVMLocalObjectMimeType) &&
                      e instanceof java.io.NotSerializableException)) {
                    e.printStackTrace();
                }
            }
        }

我希望可以节省一个人的时间。

答案 1 :(得分:0)

进行了一些研究,似乎OpenJDK实现不再支持JPEG图像的alpha通道。因此,您必须将要放入剪贴板的图像转换为List<List<String>> lis = new ArrayList(); stream.collect(Collectors.groupingBy(s -> getAnagramKey(s))) .values().stream() .sorted(Collections.reverseOrder(Comparator.comparingInt(List::size))) .limit(15) .forEach(e -> { lis.add(e); }); final int maxSize = lis.stream().map(List::size).max(Integer::compare).orElse(0); lis.stream() .filter(e -> e.size() == maxSize) .forEach(System.out::println );

这是您可以执行的操作。

BufferedImage.TYPE_INT_RGB