Friday, June 13, 2008

Java SE JSR 82 Bluetooth Linux implementation

Long title, huh? I just want to spread the word that the excellent and open source bluecove JSR 82 implementation is available for both Linux and Windows. I found it searching for a Linux JSR 82 implementation using BlueZ.
http://snapshot.bluecove.org/

Saturday, June 7, 2008

Java and Jpeg Metadata

How does one get the time of capture from a jpeg image? Sounds easy enough. The answer however was not all too obvious. I always try to find a solution using only the jdk, without adding new libraries to my projects, and this seemingly small issue wasn't going to lead me astray from that goal.

My first few steps was trying ImageIO. To get an iterator of readers for my ImageStream, I used ImageIO.getImageReader(imageStream). Now, I'm not picky so I'll just take the first reader in the iterator with iterator.next(). Then to get to the metadata I used reader.getImageMetadata(0), since I only have one image in my imagestream.

Metadata however comes in different formats. And the metadata object i got from the ImageReader reported it had these format names to offer:

javax_imageio_jpeg_image_1.0
javax_imageio_1.0

To get to the metadata, you use one of the format names as the argument to your IIOMetadata object's getAsTree method. This gives you an XML DOM root node, which you use to traverse a metadata tree. The first format in the list seemed promising with jpeg in its name and all, but all the interesting metadata like time of capture isn't parsed. Instead it is dumped in a DOM node called "unknown". The second format doesn't seem to give you anything useful.

This seemingly hopeless discovery resulted in a lot of googling. Several libraries have been made for parsing exif metadata, with Drew Noakes Metadata Extractor and Sanselan looking like the best options. But as I said earlier, I don't like adding a new library every time I bump into something without an obvious solution.

Apparently, Sun has a project called Java Advanced Imaging Image I/O Tools, which provides plugins for the tiff image format among others. Since the exif metadata inside the jpeg image, really is the same as tiff metadata, I installed the library and tried reading the image with the tiff reader. This resulted in a lot of exception throwing and it didn't seem to want to work. Maybe it would have worked if I had isolated the exif data in some way.

Almost by accident, I noticed that the jpeg reader returned from getImageReader suddenly had another format name to offer:
com_sun_media_imageio_plugins_tiff_image_1.0
When parsing the metadata tree using this format, all the metadata you could ever want suddenly appeared before me. Installing jai-imageio-tools must have added a tiff/exif reader for the jpeg ImageReader.

So the solution for me was to install Java Advanced Imaging Image I/O Tools and use the com_sun_media_imageio_plugins_tiff_image_1.0 metadata format. Technically, this involved adding another library, but it extends the standard java library in such a way that I don't need to import or use a single class outside it.

You should also check out this document to aid you in all your exif parsing activities: http://www.exif.org/Exif2-2.PDF ( It tells you the names and numbers of all the metadata fields ).