Skip to main content

BMPImageReader fails if the Destination is set

2 replies [Last post]
swpalmer
Offline
Joined: 2003-06-10

I tried the code below with a 24bit BMP file saved from the "Paint" program on Windows XP. There are no ImageIO readers installed beyond what is included in the JRE/JDK.
The reader that fails is com.sun.imageio.plugins.bmp.BMPImageReader
This fails on Java 5 and Mustang.

<br />
import java.awt.Graphics;<br />
import java.awt.image.BufferedImage;<br />
import java.io.File;<br />
import java.util.Iterator;</p>
<p>import javax.imageio.ImageIO;<br />
import javax.imageio.ImageReadParam;<br />
import javax.imageio.ImageReader;<br />
import javax.imageio.stream.FileImageInputStream;</p>
<p>/*<br />
 * Created on 25-May-2006<br />
 *<br />
 */</p>
<p>public class ImageIoBug<br />
{</p>
<p>	/**<br />
	 * @param args<br />
	 *            the path to an image file use a .BMP to fail.<br />
	 */<br />
	public static void main(String[] args) throws Exception<br />
	{<br />
		BufferedImage testImage = null;<br />
		if (args.length > 0)<br />
		{<br />
			String path = args[0];<br />
			String ext = path.substring(path.lastIndexOf('.') + 1);<br />
			System.out.println("Readers claiming to handle this format:");</p>
<p>			for (Iterator ri = ImageIO.getImageReaders(new FileImageInputStream(new File(path))); ri.hasNext();)<br />
				System.out.println("  " + ri.next().getClass().getCanonicalName());<br />
			Iterator readerIt = ImageIO.getImageReadersBySuffix(ext);<br />
			if (readerIt.hasNext()) /* This code fails for BMP files */<br />
			{<br />
				System.out.println("Using reader for \"" + ext + "\" suffix");<br />
				ImageReader reader = (ImageReader) readerIt.next();<br />
				System.out.println(reader.getClass().getCanonicalName());<br />
				reader.setInput(new FileImageInputStream(new File(path)));<br />
				int width = reader.getWidth(0);<br />
				int height = reader.getHeight(0);<br />
				System.out.printf("Image is %d x %d", width, height);<br />
				testImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);<br />
				ImageReadParam param = new ImageReadParam();<br />
				/* Setting the destination image makes the BMP reader fail! */<br />
				if (true)  /* Change to false to see that the .BMP file CAN be read */<br />
					param.setDestination(testImage);<br />
				/* this method will throw some exceptions not mentioned in<br />
				 * the Java docs */<br />
				reader.read(0, param);<br />
			}<br />
			else /* the work-around */<br />
			{<br />
				System.out.println("ImageIO.read() then copy - the path that works.");<br />
				testImage = ImageIO.read(new File(path));<br />
				/* But I need the image data to be in INT_BGR form */<br />
				if (testImage != null && testImage.getType() != BufferedImage.TYPE_INT_BGR)<br />
				{<br />
					BufferedImage testDest = new BufferedImage(<br />
						testImage.getWidth(),<br />
						testImage.getHeight(),<br />
						BufferedImage.TYPE_INT_BGR);<br />
					Graphics g = testDest.getGraphics();<br />
					g.drawImage(testImage, 0, 0, null);<br />
					g.dispose();<br />
					testImage = testDest;<br />
				}<br />
			}<br />
		}<br />
		else<br />
		{<br />
			System.out.println("Usage: java ImageIoBug ");<br />
		}<br />
	}</p>
<p>}<br />

.. so I guess it's a trip to the bug reporter for me...

[pre]Readers claiming to handle this format:
com.sun.imageio.plugins.bmp.BMPImageReader
Using reader for "bmp" suffix
com.sun.imageio.plugins.bmp.BMPImageReader
plugin pattern is 800 x 600Exception in thread "main" java.lang.NullPointerException
at javax.imageio.stream.ImageInputStreamImpl.readFully(Unknown Source)
at com.sun.imageio.plugins.bmp.BMPImageReader.read24Bit(Unknown Source)
at com.sun.imageio.plugins.bmp.BMPImageReader.read(Unknown Source)
at ImageIoBug.main(ImageIoBug.java:48)[/pre]

Message was edited by: swpalmer

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
bae
Offline
Joined: 2005-03-02

It seems to me that before set TYPE_INT_BGR image as
destination, it worth to check whether image reader
is able to use it.

Please take a look to the setDestioantion method
description: at the time of reading, the destination
image is checked to verify that its ColorModel and
SampleModel correspond to one of the ImageTypeSpecifiers
returned from the ImageReader's getImageTypes method.
If it does not, the reader will throw an IIOException.

According to this, only image form list of supported image
types can be used as reading destination.

Of course, current behavior of BMPImageReader is wrong
(actually, BMP reader works in assumption that destination
image is created according to structure of decoded image).
However, the fix could be just some verification of
destination image type and throwing an IIOException if
destination image does not correspond to one of supported
image types.

Thanks,
Andrew.

swpalmer
Offline
Joined: 2003-06-10

Yes, I see that the BMPImageReader only supports TYP_3BYTE_BGR. It's too bad that the generic Image IO framework doesn't handle the sample model conversion to read into a generic BufferedImage automatically. Either way, as you say, it isn't failing with the proper exception.