views:

1254

answers:

5

I'm getting an NPE while trying to read in an image file, and I can't for the life of me figure out why. Here is my line:

BufferedImage source = ImageIO.read(new File(imgPath));

imgPath is basically guaranteed to be valid and right before it gets here it copies the file from the server. When it hits that line, I get this stack trace:

Exception in thread "Thread-26" java.lang.NullPointerException
    at com.ctreber.aclib.image.ico.ICOReader.getICOEntry(ICOReader.java:120)
    at com.ctreber.aclib.image.ico.ICOReader.read(ICOReader.java:89)
    at javax.imageio.ImageIO.read(ImageIO.java:1400)
    at javax.imageio.ImageIO.read(ImageIO.java:1286)
    at PrintServer.resizeImage(PrintServer.java:981)    <---My function
    <Stack of rest of my application here>

Also, this is thrown into my output window:

Can't create ICOFile: Can't read bytes: 2

I have no idea what is going on, especially since the File constructor is succeeding. I can't seem to find anybody who has had a similar problem. Anybody have any ideas? (Java 5 if that makes any difference)

A: 

Have you considered that the file may simply be corrupted, or that ImageIO is trying to read it as the wrong type of file?

Zarkonnen
That's a good thought, but the file is definitely valid...I can go pull it up in an image viewer and looks fine. It is possible that it is trying to read it as the wrong type of file...it's a jpeg but doesn't have a jpeg extension. Could that be an issue?
Morinar
+1  A: 

The File constructor will almost certainly succeed, regardless of whether it points to a valid/existing file. At the very least, I'd check whether your underlying file exists via the exists() method.

Brian Agnew
I dropped the read line inside of an "if file.exists()" block and it made it in there and failed the exact same way.
Morinar
A: 

Googling for the ICOReader class results in one hit: IconsFactory from jide-common.
Apparently they had the same problem:

// Using ImageIO approach results in exception like this.
//    Exception in thread "main" java.lang.NullPointerException
//            at com.ctreber.aclib.image.ico.ICOReader.getICOEntry(ICOReader.java:120)
//            at com.ctreber.aclib.image.ico.ICOReader.read(ICOReader.java:89)
//            at javax.imageio.ImageIO.read(ImageIO.java:1400)
//            at javax.imageio.ImageIO.read(ImageIO.java:1322)
//            at com.jidesoft.icons.IconsFactory.b(Unknown Source)
//            at com.jidesoft.icons.IconsFactory.a(Unknown Source)
//            at com.jidesoft.icons.IconsFactory.getImageIcon(Unknown Source)
//            at com.jidesoft.plaf.vsnet.VsnetMetalUtils.initComponentDefaults(Unknown Source)

//    private static ImageIcon createImageIconWithException(final Class<?> baseClass, final String file) throws IOException {
//        try {
//            InputStream resource =
//                    baseClass.getResourceAsStream(file);
//            if (resource == null) {
//                throw new IOException("File " + file + " not found");
//            }
//            BufferedInputStream in =
//                    new BufferedInputStream(resource);
//            return new ImageIcon(ImageIO.read(in));
//        }
//        catch (IOException ioe) {
//            throw ioe;
//        }
//    }

What did they do instead?

private static ImageIcon createImageIconWithException(
        final Class<?> baseClass, final String file)
        throws IOException {
    InputStream resource = baseClass.getResourceAsStream(file);

    final byte[][] buffer = new byte[1][];
    try {
        if (resource == null) {
            throw new IOException("File " + file + " not found");
        }
        BufferedInputStream in = new BufferedInputStream(resource);
        ByteArrayOutputStream out = new ByteArrayOutputStream(1024);

        buffer[0] = new byte[1024];
        int n;
        while ((n = in.read(buffer[0])) > 0) {

            out.write(buffer[0], 0, n);
        }
        in.close();
        out.flush();
        buffer[0] = out.toByteArray();
    } catch (IOException ioe) {
        throw ioe;
    }

    if (buffer[0] == null) {
        throw new IOException(baseClass.getName() + "/" + file
                + " not found.");
    }
    if (buffer[0].length == 0) {
        throw new IOException("Warning: " + file
                + " is zero-length");
    }

    return new ImageIcon(Toolkit.getDefaultToolkit().createImage(
            buffer[0]));
}

So you might want to try the same approach: read the raw bytes and use Toolkit to create an image from them.

Michael Myers
Hmm...I saw that when I was Googling around, but obviously didn't read the source on that page closely enough to see their commented out problem and their new solution. That certainly looks like it would work, but seems like a lot of code to work around one failed line (which makes me sad).
Morinar
A: 

"it's a jpeg but doesn't have a jpeg extension."

That might be it.

It appears that the library AC.lib-ICO is throwing the NPE. Since this library is intended to read the Microsoft ICO file format, a JPEG might be a problem for it.

Consider explicitly providing the format using an alternative method.

McDowell
+1  A: 

I poked around some more and found that you can specify which ImageReader ImageIO will use and read it in that way. I poked around our codebase and found that we already had a function in place for doing EXACTLY what I was trying to accomplish here. Just for anybody else who runs into a similar issue, here is the crux of the code (some of the crap is defined above, but this should help anybody who tries to do it):

File imageFile = new File(filename);
Iterator<ImageReader> imageReaders = ImageIO.getImageReadersByFormatName("jpeg");
if ( imageReaders.hasNext() ) {
    imageReader = (ImageReader)imageReaders.next();
    stream = ImageIO.createImageInputStream(imageFile);
    imageReader.setInput(stream, true);
    ImageReadParam param = imageReader.getDefaultReadParam();
    curImage = imageReader.read(0, param);
}

Thanks for the suggestions and help all.

Morinar