将 Image 对象复制到剪贴板时出错
Error copying an Image object to the 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
class。
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)
经过一些研究,OpenJDK 实现似乎不再支持 JPEG 图像的 alpha 通道。因此,您必须将要放入剪贴板的图像转换为 BufferedImage.TYPE_INT_RGB
.
这就是您可以做到这一点的方法。
ByteArrayInputStream bis = new ByteArrayInputStream(clipboardObject.data);
try(ObjectInput in = new ObjectInputStream(bis)) {
ImageIcon img = (ImageIcon) in.readObject();
Image original = img.getImage();
BufferedImage newImage = new BufferedImage(
original.getWidth(null), original.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(original, 0, 0, null);
g.dispose();
ImageTransferable t = new ImageTransferable(newImage);
Toolkit.getDefaultToolkit().getSystemClipboard()
.setContents(t, null);
}catch(Exception e)
{
e.printStackTrace();
}
这不是错误,只是调试信息
请注意,控制台中显示的这个异常实际上并不是错误,它并不是真正从 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(t, null);
方法调用中抛出的。
Java 中的 JPEG 现在不支持透明度 (https://bugs.openjdk.java.net/browse/JDK-8204188),但复制的图像实际上被压缩为 PNG(或可能是其他格式)并且剪贴板设置正确,即使 BufferedImage.TYPE_INT_ARGB
图片类型。至少它对我有用 JDK 14.
所以控制台中的这个异常只是一个调试信息(我调查了几个小时来理解它并发现它确实有效)。答案在OpenJDKsun.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();
}
}
}
我希望能节省一些人的时间。
我正在尝试将 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
class。
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)
经过一些研究,OpenJDK 实现似乎不再支持 JPEG 图像的 alpha 通道。因此,您必须将要放入剪贴板的图像转换为 BufferedImage.TYPE_INT_RGB
.
这就是您可以做到这一点的方法。
ByteArrayInputStream bis = new ByteArrayInputStream(clipboardObject.data);
try(ObjectInput in = new ObjectInputStream(bis)) {
ImageIcon img = (ImageIcon) in.readObject();
Image original = img.getImage();
BufferedImage newImage = new BufferedImage(
original.getWidth(null), original.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(original, 0, 0, null);
g.dispose();
ImageTransferable t = new ImageTransferable(newImage);
Toolkit.getDefaultToolkit().getSystemClipboard()
.setContents(t, null);
}catch(Exception e)
{
e.printStackTrace();
}
这不是错误,只是调试信息
请注意,控制台中显示的这个异常实际上并不是错误,它并不是真正从 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(t, null);
方法调用中抛出的。
Java 中的 JPEG 现在不支持透明度 (https://bugs.openjdk.java.net/browse/JDK-8204188),但复制的图像实际上被压缩为 PNG(或可能是其他格式)并且剪贴板设置正确,即使 BufferedImage.TYPE_INT_ARGB
图片类型。至少它对我有用 JDK 14.
所以控制台中的这个异常只是一个调试信息(我调查了几个小时来理解它并发现它确实有效)。答案在OpenJDKsun.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();
}
}
}
我希望能节省一些人的时间。