为什么在 OSX 上复制和粘贴图像现在 return sun.awt.image.MultiResolutionImage 在 Java 8

Why does copy and paste of images on OSX now return sun.awt.image.MultiResolutionImage in Java 8

从 Web 浏览器(Firefox、Chrome 和 Safari)复制和粘贴图像在我的 OSX 机器上停止工作,在 PC 上没问题。

我追踪到这样一个事实,即我希望具有 image/x-java-image;class=java.awt.Image 风格的数据始终是稍后在我的代码中缓冲图像

我需要它是一个 BufferedImage 这样我就可以找到图像的大小并访问数据。

但是现在它不再返回 BufferedImage,而是 returns sun.awt.image.MultiResolutionCachedImage,要获取缓冲数据,我需要调用 getResolutionVariants 仅在其实现的接口中定义 sun.awt.image.MultiResolutionImage

所以现在我的代码必须直接引用 sun classes,这肯定是错误的吧?

   Image        image       = null;
   ImageCell    imageCell   = null;
   try
   {
        image  = (Image) trans.getTransferData(FileDropTarget.imageFlavor);
   }
   catch(Exception e)
   {
        MainWindow.logger.log(Level.WARNING,"Unable to extract image from drop data:"+e.getMessage(),e);
   }


   if(image!=null && image instanceof sun.awt.image.MultiResolutionImage)
   {
       for(Image i:mri.getResolutionVariants())
       {
           if(i instanceof BufferedImage)
           {
               ImageData imageData = new ImageData((BufferedImage) i, "downloaded:" + new Random().nextInt());
               imageCell = new ImageCell(imageData);
               return imageCell;
           }
       }
   }

如果我进行一些调试,我注意到的另一件事是它总是使用 MultiResolutionCachedImage,即使实际上只有一个图像!

这些 class 似乎确实已添加到 Java 9 中的 java 包中,但我使用的是 Java 8.

你看错方向了。您应该寻找适用于任何 Image 的解决方案,而不是向您错误假设的特殊情况添加另一个特殊情况,因为 image/x-java-image;class=java.awt.Image 的数据风格永远不会保证提供特定类型的图像,因此对接口的引用 java.awt.Image

基于自 1.1 以来应该如何处理的通用解决方案,但利用新的 Java 功能进行了改进,

public static BufferedImage getImage(Image image) {
    if(image instanceof BufferedImage) return (BufferedImage)image;
    Lock lock = new ReentrantLock();
    Condition size = lock.newCondition(), data = lock.newCondition();
    ImageObserver o = (img, infoflags, x, y, width, height) -> {
        lock.lock();
        try {
            if((infoflags&ImageObserver.ALLBITS)!=0) {
                size.signal();
                data.signal();
                return false;
            }
            if((infoflags&(ImageObserver.WIDTH|ImageObserver.HEIGHT))!=0)
                size.signal();
            return true;
        }
        finally { lock.unlock(); }
    };
    BufferedImage bi;
    lock.lock();
    try {
        int width, height=0;
        while( (width=image.getWidth(o))<0 || (height=image.getHeight(o))<0 )
            size.awaitUninterruptibly();
        bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = bi.createGraphics();
        try {
            g.setBackground(new Color(0, true));
            g.clearRect(0, 0, width, height);
            while(!g.drawImage(image, 0, 0, o)) data.awaitUninterruptibly();
        } finally { g.dispose(); }
    } finally { lock.unlock(); }
    return bi;
}

您可以添加其他特殊情况,但您应该始终让回退处理任意 Image 实现。