代码之家  ›  专栏  ›  技术社区  ›  Mark Doe

如何解决java.lang.IllegalArgumentException:宽度(-1)和高度(-1)不能小于等于0?

  •  3
  • Mark Doe  · 技术社区  · 10 年前

    我花了最后几个小时试图解决下面的堆栈跟踪问题。通过对SO和谷歌的重大研究,我理解例外可能意味着几件事:

    • 程序无法找到具有所提供路径的请求图像;

    • 正在渲染图像 之后 生成宽度和高度,原因是它等于0。。。

    我错过了什么吗?我想不出怎么解决这个问题。。。

    堆栈

    线程“main”java.lang.IllegalArgumentException异常:宽度 (-1)和高度(-1)不能<=0位于 java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1016) 位于java.awt.image.BufferedImage.(BufferedImage.java:331) tp6.Interface.toBufferedImage(Interface.java:157)位于 tp6.Interface.(Interface.java:36)位于 tp6.Interface.main(Interface.java:171)

    tp6.Interface.toBufferedImage(Interface.java:157):

    public BufferedImage toBufferedImage(Image image) {
    
            if( image instanceof BufferedImage ) {
    
                    return( (BufferedImage)image );
            } else {
    
                    image = new ImageIcon(image).getImage();
    
                    BufferedImage bufferedImage = new BufferedImage(
                                                          image.getWidth(null),
                                                          image.getHeight(null),
                                                          BufferedImage.TYPE_INT_RGB );
                    Graphics g = bufferedImage.createGraphics();
                    g.drawImage(image,0,0,null);
                    g.dispose();
                    return( bufferedImage );
            }
    }
    

    tp6.接口(Interface.java:36)

    //IMAGE JPANEL
    Image map=new ImageIcon("images/main.gif").getImage();
        Image digi=new ImageIcon("images/digits.gif").getImage();
        BufferedImage mapmodifiable= toBufferedImage(map);
        BufferedImage digits= toBufferedImage(digi);
    

    tp6.Interface.main(Interface.java:171)

    public static void main(String[] args)
        {
            Window windowintro = new Window( 440, 400, 1);
            //INTERFACE GRAPHIC
            Interface graphic=new Interface();
    
            graphic.addWindowListener(new WindowAdapter() {
                            @Override
                public void windowClosing(WindowEvent evt) {
                    System.exit(0);
                }
            });
        }
    
    3 回复  |  直到 10 年前
        1
  •  3
  •   Harald K    10 年前

    异常的原因已经解释过, Image 方法 getWidth(null) getHeight(null) 两个返回 -1 当图像尺寸未知时。这是如此实现的,因为旧的 形象 Java中的API是 异步的 并从当前线程加载图像资源。在您编写时,也可能因为找不到图像而发生这种情况。

    但是,当您想将图像用作 BufferedImage s(可能是因为您想在某个阶段修改它们),使用最近的 同步的 ImageIO 应用程序编程接口。在大多数情况下,代码会更清晰、更容易理解,更重要的是;如果无法找到/加载图像,您将立即收到错误消息。

    因此,代替:

    Image map = new ImageIcon("images/main.gif").getImage();
    BufferedImage mapmodifiable = toBufferedImage(map);
    

    您可以简单地执行以下操作:

    BufferedImage mapmodifiable = ImageIO.read(new File("images/main.gif"));
    

    PS:它 可以将 形象 缓冲图像 就像你在你的 toBufferedImage 方法和使用 ImageIcon.getImage(..) 应该 确保图像已预加载( ImageIcon 内部使用 MediaTracker 用于预加载)。然而,正如我上面所说 形象 API不擅长错误反馈,所以问题很可能是找不到您的图像。

        2
  •  1
  •   Lauryn Jefferson    8 年前

    我也有这个问题。我通过添加一行代码来解决这个问题。在toBufferedImage()方法的第一行中,可以将

    while(image.getWidth() == -1);
    

    此行将一直循环,直到getWidth()中除了-1之外还有一个值。

        3
  •  0
  •   Community Mohan Dere    9 年前

    我发现 this 关于你的问题的问题。也许您正在使用异步方式加载图像。这意味着当您调用时,图像可能尚未加载 getWidth(null) getHeight(null) 由于此时可能无法加载图像,因此可能还不知道宽度和高度。这就是为什么 -1 返回。

    如果你加上一些延迟,也许你会得到正确的结果 Thread.sleep(1000) 我没有对此进行调查,但这绝对不是一个好的解决方案。在某些系统上,你可能睡得不够长。在其他系统上,你可能会睡不必要的长时间。由于我不太了解该规范,如果 Thread.sleep 阻止过程读取图像(有人知道吗?)。

    我认为有两种方法可以用来解决这个问题:

    第一个解决方案

    一种解决方案是使用阻塞IO加载图像。就像在 linked question .

    第二种解决方案

    另一个解决方案是使用 ImageObserver :

    int width = getWidth(new ImageObserver() {
        @Override
        public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
            // TODO use the width when the image is loaded and the size is known
        }
    });
    if (width != -1) {
        // TODO use the width, it is already known
    }