如何解决java.lang.IllegalArgumentException: Width(-1) and height(-1) cannot be <= 0?
How to solve java.lang.IllegalArgumentException: Width (-1) and height (-1) cannot be <= 0?
我最近几个小时一直在尝试解决下面的堆栈跟踪问题。通过对此处 SO 以及 Google 的主要研究,我了解到异常可能意味着几件事:
程序无法通过提供的路径找到请求的图像;
正在渲染图像在生成宽度和高度后,它等于 0 的原因...
我错过了什么吗?我不知道如何解决这个问题...
堆栈
Exception in thread "main" java.lang.IllegalArgumentException: Width
(-1) and height (-1) cannot be <= 0 at
java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1016)
at java.awt.image.BufferedImage.(BufferedImage.java:331) at
tp6.Interface.toBufferedImage(Interface.java:157) at
tp6.Interface.(Interface.java:36) at
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.(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);
}
});
}
我找到了 this 个与您的问题有关的问题。也许您正在使用异步方式加载图像。这意味着当您调用 getWidth(null)
或 getHeight(null)
时,图像可能尚未加载。由于此时可能还没有加载图片,所以宽高可能还不知道。这就是返回 -1
的原因。
如果用 Thread.sleep(1000)
添加一些延迟,也许您会得到正确的结果。我没有调查它,但它绝对不是一个好的解决方案。您可能在某些系统上睡眠时间不够长。在其他系统上,您可能会不必要地长时间睡眠。而且由于我不太了解规范,如果 Thread.sleep
阻止进程读取图像,它甚至可能是 Java 的有效实现(有人知道吗?)。
我会看到两种可以用来解决问题的方法:
第一个解决方案
一种解决方案是使用阻塞 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
}
异常的原因已经解释过了,Image
方法getWidth(null)
和getHeight(null)
都return-1
当图像尺寸不是(还)已知。这是这样实现的,因为 Java 中的旧 Image
API 是 异步 并从当前线程加载图像资源。在你写的时候,也可能是因为找不到图片。
但是,由于您想将图像用作 BufferedImage
s(大概是因为您想在某个阶段修改它们),最好也更容易使用更新的 同步ImageIO
API。大多数情况下,代码会更清晰易懂,更重要的是;如果图像不能 found/loaded.
,您会立即收到错误消息
所以,而不是:
Image map = new ImageIcon("images/main.gif").getImage();
BufferedImage mapmodifiable = toBufferedImage(map);
你可以简单地做:
BufferedImage mapmodifiable = ImageIO.read(new File("images/main.gif"));
PS: 可以像在 toBufferedImage
方法中那样将 Image
转换为 BufferedImage
,并使用 ImageIcon.getImage(..)
应该 确保图像已预加载(ImageIcon
内部使用 MediaTracker
进行预加载)。但是,正如我上面所说,旧的 Image
API 不太擅长错误反馈,因此问题很可能是找不到您的图像。
我也遇到了这个问题。我通过添加一行代码解决了它。在 toBufferedImage() 方法的第一行中,您可以输入
while(image.getWidth() == -1);
此行将一直循环,直到 getWidth() 中除了 -1 之外还有一个值。
我最近几个小时一直在尝试解决下面的堆栈跟踪问题。通过对此处 SO 以及 Google 的主要研究,我了解到异常可能意味着几件事:
程序无法通过提供的路径找到请求的图像;
正在渲染图像在生成宽度和高度后,它等于 0 的原因...
我错过了什么吗?我不知道如何解决这个问题...
堆栈
Exception in thread "main" java.lang.IllegalArgumentException: Width (-1) and height (-1) cannot be <= 0 at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1016) at java.awt.image.BufferedImage.(BufferedImage.java:331) at tp6.Interface.toBufferedImage(Interface.java:157) at tp6.Interface.(Interface.java:36) at 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.(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);
}
});
}
我找到了 this 个与您的问题有关的问题。也许您正在使用异步方式加载图像。这意味着当您调用 getWidth(null)
或 getHeight(null)
时,图像可能尚未加载。由于此时可能还没有加载图片,所以宽高可能还不知道。这就是返回 -1
的原因。
如果用 Thread.sleep(1000)
添加一些延迟,也许您会得到正确的结果。我没有调查它,但它绝对不是一个好的解决方案。您可能在某些系统上睡眠时间不够长。在其他系统上,您可能会不必要地长时间睡眠。而且由于我不太了解规范,如果 Thread.sleep
阻止进程读取图像,它甚至可能是 Java 的有效实现(有人知道吗?)。
我会看到两种可以用来解决问题的方法:
第一个解决方案
一种解决方案是使用阻塞 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
}
异常的原因已经解释过了,Image
方法getWidth(null)
和getHeight(null)
都return-1
当图像尺寸不是(还)已知。这是这样实现的,因为 Java 中的旧 Image
API 是 异步 并从当前线程加载图像资源。在你写的时候,也可能是因为找不到图片。
但是,由于您想将图像用作 BufferedImage
s(大概是因为您想在某个阶段修改它们),最好也更容易使用更新的 同步ImageIO
API。大多数情况下,代码会更清晰易懂,更重要的是;如果图像不能 found/loaded.
所以,而不是:
Image map = new ImageIcon("images/main.gif").getImage();
BufferedImage mapmodifiable = toBufferedImage(map);
你可以简单地做:
BufferedImage mapmodifiable = ImageIO.read(new File("images/main.gif"));
PS: 可以像在 toBufferedImage
方法中那样将 Image
转换为 BufferedImage
,并使用 ImageIcon.getImage(..)
应该 确保图像已预加载(ImageIcon
内部使用 MediaTracker
进行预加载)。但是,正如我上面所说,旧的 Image
API 不太擅长错误反馈,因此问题很可能是找不到您的图像。
我也遇到了这个问题。我通过添加一行代码解决了它。在 toBufferedImage() 方法的第一行中,您可以输入
while(image.getWidth() == -1);
此行将一直循环,直到 getWidth() 中除了 -1 之外还有一个值。