
Recently I wanted to read programmatically some image meta data. After several tests and coding I came across three libraries that I decided to have a closer look at. This article describes my experiences and some results I figured out. It is neither a full fletched comparison of the three mentioned libraries nor a description of how to read image meta data with java. Please also note: the sample source code does not show all posssible details.
The three libraries I worked with are:
ImageIO
Reading Imagedata using javax.imageIO package requires ImageInputStreams and Readers.
Once an Inputstream using an image file is created, this stream is set as input to a reader.
The reader reads the image file and returns an IIOImage object. This object can be utilized to read the meta data.
pseudocode:
ImageInputStream iis = ImageIO.createImageInputStream( new BufferedInputStream( new FileInputStream(file))); Iterator readers = ImageIO.getImageReadersByMIMEType("image/jpeg"); IIOImage image = null; if (readers.hasNext()) { ImageReader reader = readers.next(); reader.setInput(iis, true); try { image = reader.readAll(0, null); } catch (javax.imageio.IIOException iioex) {...} IIOMetadata metadata = image.getMetadata(); String[] names = metadata.getMetadataFormatNames(); for (int i = 0; i < length; i++) { if (log.isDebugEnabled()) { log.debug("Format name: " + names[ i]); log.debug(displayMetadata(metadata.getAsTree(names[i]))); } } }
The displayMetadata method iterates over the tree of nodes and writes the content in an easy fashion to the log.
Sanselan
Reading meta data using the Sanselan library requires an IImageMetadata object. You get such an object by calling the getMetadata method of Sanselan. The IImageMetadata object is casted to JpegImageMetadata because I wanted to extract jpeg metadata. Properties of this object contain lists of meta data that can be read.
pseudocode:
IImageMetadata sanselanmetadata = Sanselan.getMetadata(file); if (sanselanmetadata instanceof JpegImageMetadata) { JpegImageMetadata jpegMetadata = (JpegImageMetadata) sanselanmetadata; if (log.isDebugEnabled()) { log.debug("jpegMetadata: " + jpegMetadata.toString()); } printMetadataList(jpegMetadata.getItems()); TiffImageMetadata tiffImageMetadata = jpegMetadata.getExif(); if (log.isDebugEnabled()) { log.debug("tiffImageMetadata: " + tiffImageMetadata.toString()); } ... } ... private static void printMetadataList(List items) { Object item; for (int i = 0; i < items.size(); i++) { item = items.get(i); log.debug(item: " + item + " - class: " + item.getClass()); if (item instanceof org.apache.sanselan.common.ImageMetadata.Item) { Item tf_item = (Item) item; log.debug(tf_item.getKeyword() + " - " + tf_item.getText()); } else { log.debug("item: " + item.toString()); } } }
Metadata Extractor
Reading meta data using the Metadata Extractor is quite easy compared to the two samples above.
Just initiate a Metadata object by calling the method readMetadata.
Within this metadata object are so called directories that you can iterate over. Directories contain tags that are iteratable as well. Both, metadata and directory objects, contain appropriate getter methods (getDirectories, getTags) to get meta data.
pseudocode:
Metadata drewmetadata = null; try { drewmetadata = ImageMetadataReader.readMetadata(imgfile); } catch (ImageProcessingException ipx) { ... } if (drewmetadata != null) { for (Directory directory : drewmetadata.getDirectories()) { log.debug("directory: " + directory); for (Tag tag : directory.getTags()) { log.debug(" tag: " + tag); } } }
In order to decide what library to use for me there are some more important details to keep in mind apart from the developer experience described above:
- Reading through the sanselan project page I realized the last release dates back to 2009.
- There is only one developer who is in charge of Metadata extractor on google code. However google code defines his activity as medium.
- For me as a maven user it was extra effort to download the Metadata extractor jars and add them manually to my local maven repository:
mvn install:install-file -Dfile=..\libs\metadata-extractor-2.5.0-RC3\metadata-extractor-2.5.0-RC3.jar -DgroupId=com.google.code -DartifactId=metadata-extractor -Dversion=2.5.0-RC3 -Dpackaging=jar mvn install:install-file -Dfile=..\libs\metadata-extractor-2.5.0-RC3\xmpcore.jar -DgroupId=com.google.code -DartifactId=xmpcore -Dversion=2.5.0-RC3 -Dpackaging=jar
com.google.code metadata-extractor 2.5.0-RC3 com.google.code xmpcore 2.5.0-RC3
- Working with javax.ImageIO package does not require an extra library if you use Oracle´s Java SDK. Nonetheless this library produced in some of my tests errors similar to BugID 4924909 in Sun’s/Oracle’s bug database . Even the proposed workaround (scroll down to the most up to data comments) of rugarciap did not fix the issues I had with some of my test images.
Conclusion
My favourite library to read image meta data is Metadata Extractor because:
- Coding is simple and straight forward.
- I experienced no error with the availbale test images.
- I hope the maven integration will be introduced soon.
Sanselan is second on my fav list of libraries because:
- Coding is not as straight forward as with metadata extractor.
- 2009 was last release (actually I am unsure if the project is still under development).
- As with Metadata Extractor I did not experienced error working with Sanselan.
Last on my list of favs is Javax.ImageIO unfortunately because:
- Bugs similar to bug 4924909 crashed my test code often. This might be caused by the test images I picked, however I could not find a suitable fix or workaround.
- The developer experience is not as good as with Metadata Extractor and comparable with Sanselan.
this article and the regarding code is inspired by:
I created sample source code that you can run using maven: readImageMetadata.zip .
Update 20120110: you can access the source code on github as well.
Leave a Reply