Getting Exif data using ImageScience
May 2nd, 2008In my current rails project I need to upload photos and save some exif data taken from them. I use attachment_fu as uploading system that let me choose which image processor to use. Using rmagick and mini_magick I can extract exif data with the following code:
# rmagick image = Magick::ImageList.new(filename).first puts image['EXIF:Model'] # The camera model used to take the picture # mini_magick image = MiniMagick::Image.from_file(filename) puts image["EXIF:Model"]
The problem is that I can’t do the same thing with image_science, because it has no methods that return exif data, so I want to add a method to the ImageScience class to do that.
Looking the FreeImage documentation I found some helpful functions, FreeImage_GetMetadata and FreeImage_TagToString. With these 2 functions I’m able to get an exif tag and convert it to a readable string. Each one of the available tags belongs to one of the following meta models:
FI_ENUM(FREE_IMAGE_MDMODEL) { FIMD_NODATA = -1, FIMD_COMMENTS = 0, // single comment or keywords FIMD_EXIF_MAIN = 1, // Exif-TIFF metadata FIMD_EXIF_EXIF = 2, // Exif-specific metadata FIMD_EXIF_GPS = 3, // Exif GPS metadata FIMD_EXIF_MAKERNOTE = 4, // Exif maker note metadata FIMD_EXIF_INTEROP = 5, // Exif interoperability metadata FIMD_IPTC = 6, // IPTC/NAA metadata FIMD_XMP = 7, // Abobe XMP metadata FIMD_GEOTIFF = 8, // GeoTIFF metadata FIMD_ANIMATION = 9, // Animation metadata FIMD_CUSTOM = 10 // Used to attach other metadata types to a dib };
Ok, now I can extract the model of the camera:
FreeImage_GetMetadata(FIMD_EXIF_MAIN, bitmap, "Model", &tag); printf(FreeImage_TagToString(FIMD_EXIF_MAIN, tag, NULL));
As you can see, I need to pass the model of the “Model” tag. But if I don’t know which model to use, I can loop through all of them until the returned value of the FreeImage_GetMetadata function is not NULL:
for(model = 0; model < 11; model++) { if(FreeImage_GetMetadata(model, bitmap, tagName, &tag)) return rb_str_new2(FreeImage_TagToString(model, tag, NULL)); }
Finally I can write a ruby module that extends ImageScience and adds the ability to get an exif tag:
module ImageScienceExifData def [](key) if key =~ /^EXIF:(\w+)?/ get_exif($1) end end inline do |builder| if test ?d, "/opt/local" then builder.add_compile_flags "-I/opt/local/include" builder.add_link_flags "-L/opt/local/lib" end builder.add_link_flags "-lfreeimage" builder.add_link_flags "-lstdc++" # only needed on PPC for some reason. lame builder.include '"FreeImage.h"' builder.prefix <<-"END" #define GET_BITMAP(name) FIBITMAP *(name); Data_Get_Struct(self, FIBITMAP, (name)); if (!(name)) rb_raise(rb_eTypeError, "Bitmap has already been freed") END builder.c <<-"END" VALUE get_exif(char *tagName) { GET_BITMAP(bitmap); FITAG *tag = NULL; const char *value; int model; for(model = 0; model < 11; model++) { if(FreeImage_GetMetadata(model, bitmap, tagName, &tag)) return rb_str_new2(FreeImage_TagToString(model, tag, NULL)); } return Qnil; } END end end ImageScience.send(:include, ImageScienceExifData) ImageScience.with_image(filename) do |img| puts img["EXIF:Model"] end
The output with the picture I used is the following :
NIKON COOLPIX S3 2006:12:10 12:09:17
It doesn’t work with all the exif names but for now it’s ok for my needs. The next step is to add the code above in my rails application and use it with attachment_fu. I’ll write another post about that soon.














1:45 am on May 3rd, 2008:
Very cool, I’ve missed this too. Have you submitted the patches to the imagescience team? If not, please do.
10:59 am on May 6th, 2008:
Hmm, you might want to check out the exifr gem, which does all this without using freeimage, and without actually doing any work.
http://rubyforge.org/projects/exifr/
11:07 am on May 6th, 2008:
Jonas, I know exifr, but I want to extract exif data without open the image 2 times. In this way I can open an image, create a thumb and extract exif. All without use other libraries. Anyway exifr is very cool!
11:53 pm on June 9th, 2008:
Hey,
wow. thanks for sharing this code. I’ve missed this, too.
Do you know how to write the exif data and other header information? Is this possible?
I haven’t had a close look at that, yet.
5:47 pm on June 28th, 2008:
Hey Andrea,
It would be really cool if you could expose this data to Radiant’s Gallery extension. (hint, hint
8:50 am on July 14th, 2008:
Michael: I didn’t try to write exif data. I’ll try asap
Ben: I’ll add soon this feature to the radiant gallery.