图像大小在 JAR 中返回 -1,但在 IDE 中返回正确大小。通过 Toolkit 加载的图像....createImage(url)

Posted

技术标签:

【中文标题】图像大小在 JAR 中返回 -1,但在 IDE 中返回正确大小。通过 Toolkit 加载的图像....createImage(url)【英文标题】:Image size returns -1 in JAR but proper size in IDE. Image loaded via Toolkit....createImage(url) 【发布时间】:2015-01-29 09:56:48 【问题描述】:

意图:从资源中获取 BufferedImage(无论是在 IDE 中还是在运行的 JAR 中)。

问题:获取图像始终有效,转换为 BufferedImage 需要知道大小,但大小始终返回 -1,即使在使用 MediaTracker 等待之后也是如此。在 IDE 中,MediaTracker 之后的大小是正确的,之前是-1。使用 while-loop 等待直到 size >-1 似乎永远不会在运行 JAR 时结束。 (尝试使用 JDK/JRE 8 代码语言级别 6 和 8。)

SSCCE 在 IDE 中的输出:

图片:sun.awt.image.ToolkitImage@15975490

宽度:-1

持续时间:38 毫秒

宽度:32

BUFFEREDIMAGE: BufferedImage@6adede5: type = 1 DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=0 IntegerInterleavedRaster: 宽度 = 32 高度 = 32 #Bands = 3 xOff = 0 yOff = 0 dataOffset[0] 0

编辑:MediaTracker 的“isErrorAny()”返回 false。

运行 JAR 时 SSCCE 的输出:

图像:sun.awt.image.ToolkitImage@2a84aee7

宽度:-1

持续时间:23 毫秒

宽度:-1

线程“main”中的异常 java.lang.IllegalArgumentException:宽度(-1)和高度(-1)不能 是

编辑:MediaTracker 的“isErrorAny()”返回 true。但我无法找出错误是什么 - 此外,图像 确实 正确加载,因为它可以通过从中制作 ImageIcon 在 JToolBar 中成功使用。 (我已经尝试过滥用 ImageIcon 的 getIconWidth() 或 getImage() 方法 - 它们根本没有带来任何改进。)

SSCCE:

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.net.URL;

public class ImageSizeProblem 

    public static void main(final String[] args) 

        final Image img = createImageFromResource("test.png");

        System.out.println("IMAGE: " + img);
        System.out.println("WIDTH: " + img.getWidth(null));

        final long startTime = System.currentTimeMillis();
        waitForImage(img);
        final long duration = System.currentTimeMillis() - startTime;
        System.out.println("\nDURATION: " + duration + " ms");

        System.out.println("\nWIDTH: " + img.getWidth(null));

        final BufferedImage buffImg = createBufferedImageFromImage(img, false);
        System.out.println("\nBUFFEREDIMAGE: " + buffImg);

        System.exit(0);
    

    private static Image createImageFromResource(final String resourceFileName_dontForgetToAddItsFolderToClasspath) 

        final Toolkit kit = Toolkit.getDefaultToolkit();
        final URL url = ClassLoader.getSystemResource(resourceFileName_dontForgetToAddItsFolderToClasspath);
        if (url != null) 
            final Image img = kit.createImage(url);
            if (img == null) 
                System.err.println("Image resource could not be loaded.");
                return null;
            
            return img;
         else 
            System.err.println("Image resource not found.");
            return null;
        
    

    private static boolean waitForImage(final Image img) 
        final MediaTracker mediaTracker = new MediaTracker(new JPanel());
        mediaTracker.addImage(img, 1);
        try 
            mediaTracker.waitForID(1);
         catch (InterruptedException ex) 
            ex.printStackTrace();
        
        return !mediaTracker.isErrorAny();
    


    // improved version of http://***.com/a/13605411/3500521
    private static BufferedImage createBufferedImageFromImage(final Image img, final boolean withTransparency) 

        if (img instanceof BufferedImage) 
            return (BufferedImage) img;
         else if (img == null) 
            return null;
        

        final int w = img.getWidth(null);
        final int h = img.getWidth(null);

        final BufferedImage bufferedImage;
        if (withTransparency) 
            bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
         else 
            bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        

        final Graphics2D g = bufferedImage.createGraphics();
        g.drawImage(img, 0, 0, null);
        g.dispose();
        return bufferedImage;
    

请注意,用于测试的图像已通过 JToolBar 中的 new ImageIcon(image) 成功加载并在另一个应用程序中使用。从 ImageIcon 获取大小也会返回 -1,同样来自 ImageIcon.getImage() 返回的图像。

【问题讨论】:

您忽略了waitForImage 的返回值(即mediaTacker.isErrorAny())。这是故意的吗?也许它可以告诉你一些事情? @haraldK:感谢您的回复。是的,我可能应该提到这一点(昨天从各个角度解决了 5 个小时的问题,所以可能有点失明)。在 IDE 中,isErrorAny 返回 false,但在 JAR 中返回 true。但是在kit.createImage执行的图像加载过程完成过程中似乎没有办法找出发生了什么错误。 调试ImageToolkit 图像API 的问题在于它是延迟加载的。在为时已晚之前,您永远不知道是否有问题。您是否尝试过使用ImageIO.read(...) 读取图像,如果没有别的,看看您收到什么错误消息? @haraldK:这可悲的是没用,因为我从来没有让它在 JAR 中工作,它会抛出一个 FileNotFoundException ,其中包含类似于“(拒绝访问)”的文本。然而,上面的方法至少给了我一个工作图像。 这不太可能,因为这两种方法最终都必须从同一个文件系统中读取。但可能有一些我不知道的细节。无论如何,“拒绝访问”异常可能是真正的问题。当然,请随意忽略该建议。 ;-) 【参考方案1】:

问题在于路径深度。

我也尝试过 Avira,因为从技术上讲,问题是程序访问其自己的文件,这看起来很可疑,但在 Avira 卸载时,我尝试了不同位置的可执行文件,路径更短,一切正常魅力。

【讨论】:

算了...我打算评论另一篇文章。睡眠剥夺。我删除了评论。

以上是关于图像大小在 JAR 中返回 -1,但在 IDE 中返回正确大小。通过 Toolkit 加载的图像....createImage(url)的主要内容,如果未能解决你的问题,请参考以下文章

Springboot中IDE支持两种打包方式,即jar包和war包

我是不是需要在 json 响应中返回 ios 的图像尺寸?

如何在 Eclipse IDE 的 Apache Tomcat 服务器中部署创建的 .jar 文件?

C 中的 .BMP 文件 - DIB 标头返回图像大小 0,即使 BMP 标头返回文件大小

为啥 getResourceAsStream() 可以在 IDE 中工作,但不能在 JAR 中工作?

照片框架。 requestImageForAsset 无法返回正确的图像大小