Rich blogged about Firefly embedding MDL molfiles in PNG images, which I found really cool. Rich and Noel later showed how that metadata can be retrieved again, possibly with Python.

But I did not like that Firefly could do this, and JChemPaint not. So, I started hacking. First I discovered I had to get rid of the use of JAI; then I had to adapt the JChemPaintPanel takeSnaphot() API to return a RendererImage; and finally, I had to figure out how to write the extra metadata. Now, Firefly is not opensource (yet), so it took me some time to figure out how that was done, and this is how:

ImageWriter writer = ImageIO.getImageWriters(
  new ImageTypeSpecifier(awtImage), "png"
).next();
ImageTypeSpecifier specifier = new ImageTypeSpecifier(awtImage);
IIOMetadata meta = writer.getDefaultImageMetadata( specifier, null );

Node node = meta.getAsTree( "javax_imageio_png_1.0" );
IIOMetadataNode tExtNode = new IIOMetadataNode("tEXt");
IIOMetadataNode tExtEntryNode = new IIOMetadataNode("tEXtEntry");
tExtEntryNode.setAttribute( "keyword", "molfile" );
tExtEntryNode.setAttribute( "value", mdlMolfile);
tExtNode.appendChild(tExtEntryNode);
node.appendChild(tExtNode);
meta.mergeTree("javax_imageio_png_1.0", node);
ImageOutputStream ios = ImageIO.createImageOutputStream(
  new FileOutputStream(filename)
);
writer.setOutput(ios);
writer.write( meta, new IIOImage(awtImage, null, meta), null );

Now I can create my own test files for the Strigi’s ability to extract chemical metadata from PNG images. Here is the JChemPaint generator PNG image for benzophenone:

Another issue, unrelated to this patch, is that writing PNG images changes the location of the structure in the JChemPaint editor, and that the placing of the element symbol in image writing is seriously broken. But that will soon be solved with Niels’ new renderer.

The metadata looks like:

(Newlines are lost in the XML display.)

JChemPaint does not yet write InChIs, and it also does not open PNG images for input yet (as Firefly does).