jQuery EXIF data plugin
I've never really used libraries such as jQuery or Prototype and only really know them by name. So, I decided to take a look at jQuery and found that turning something like the EXIF reader into a jQuery plugin was a matter of adding just a few lines.
Using this, you can now do something like:
and then
Now, I've still only looked at jQuery for 30 minutes or so (seems very cool, though!), so bear with me as I stumble through this field of foreign frameworks and let me know if it needs anything.
Check out the jQuery EXIF data demo here where you'll also find download links.
This was really spurred on by a comment on the image effects library, so maybe I'll see if I can turn those into plugins as well.
I've never really used libraries such as jQuery or Prototype and only really know them by name. So, I decided to take a look at jQuery and found that turning something like the EXIF reader into a jQuery plugin was a matter of adding just a few lines.
Using this, you can now do something like:
<img src="image1.jpg" id="img1" exif="true" />
<img src="image2.jpg" id="img2" exif="true" />
<img src="image3.jpg" id="img3" exif="true" />
and then
$("#img1").click(function() {
alert("Taken with a " + $(this).exif("Make") + " " + $(this).exif("Model") + " on " + $(this).exif("DateTimeOriginal"));
// exif(strTagName) returns a string with value for the tag [strTagName]
});
$("#img2").click(function() {
alert($(this).exifPretty());
// exifPretty() returns a string with all tags and values, one tag per line
});
$("#img3").click(function() {
alert($(this).exifAll());
/* exifAll() returns an object holding all tags and their values
* {
* "Make" : "NIKON",
* "Model" : "D100",
* ...
* }
*/
});
Now, I've still only looked at jQuery for 30 minutes or so (seems very cool, though!), so bear with me as I stumble through this field of foreign frameworks and let me know if it needs anything.
Check out the jQuery EXIF data demo here where you'll also find download links.
This was really spurred on by a comment on the image effects library, so maybe I'll see if I can turn those into plugins as well.
Hi Jacob,
November 30, 2008 at 1:27 PM Jacob SeidelinThis seems to by the only EXIF plugin for jQuery. Great job on leading! Unfortunatly only img1 and img2 examples work and only in Firefox. Opera and IE are alerting spaces.
I also notice this example only works on a production server. Localhost alerts spaces.
Thx
PS: Version numbers on your JS helps a lot.
-=Dan=-
Hi Dan,
November 30, 2008 at 11:47 PM Bill LabusThanks for the feedback. The third example is supposed to alert "[object Object]" or something like that, does it not do that?
It works fine for me in IE7. Opera doesn't work and won't work until they fix their XHR to allow access to the raw data.
I'll try to update the jQuery plugin next time I touch the EXIF code.
This looks like a great plugin, but for the life of me, I can't get it to work. I copy it to my root directory, but as soon as I even try to load it, I get an error saying "Object Expected, Line 858".
May 29, 2009 at 11:09 AM Jacob SeidelinSure enough, I go to line 858:
jQuery(document).ready(loadAllImages);
and when I try to right click to follow the 'jQuery' code hyperlink, it says that the link does not exist. However, I do have jquery.js in the same directory as your plugin.
Any ideas?
To anyone reading: Bill's problem was resolved (by Bill himself) and turned out to be due to the order of which the JavaScript files were loaded. Be sure to load jQuery before the EXIF files!
May 29, 2009 at 1:30 PM KJHolidayFirst off, thanks so much for your effort on this plug-in. It was a wonderful starting ground for me.
June 9, 2009 at 11:28 AM KJHolidayI modified your plug-in to load single images on demand. For example, my gallery has one single image in the middle of the screen. I use JavaScript to change the src attribute to load another image. I have a "Photo Details" link that when clicked will get the Exif data for the image currently sitting in my place holder current image slot.
One serious problem I ran into was that Firefox read all of my Exif Data almost instantly. However, IE would take sometimes 20 to 30 seconds to return the data. I started tracing it down and I found that for certain tags that contained arrays of values, it was choking IE. The biggest offender in my images from my Nikon D60 was the "MakerNote" tag. It had 1248 values.
The section of code, specifically for the "MakerNote" tag, causing the slowdown was the following from the readTagValue function:
case 7: // undefined, 8-bit byte, value depending on field
if (iNumValues == 1) {
return oFile.getByteAt(iEntryOffset + 8, bBigEnd);
} else {
var iValOffset = iNumValues > 4 ? iValueOffset : (iEntryOffset + 8);
var aVals = [];
for (var n=0;n<iNumValues;n++) {
aVals[n] = oFile.getByteAt(iValOffset + n);
}
return aVals;
}
break;
My temporary solution was to add the following check in the "readTags" function to skip certain unneeded tags:
var skippedTags = "Undefined,MakerNote,UserComment";
if (!strTag && bDebug) console.log("Unknown tag: " + oFile.getShortAt(iEntryOffset, bBigEnd));
if (skippedTags.indexOf(strTag) == -1) {
oTags[strTag] = readTagValue(oFile, iEntryOffset, iTIFFStart, iDirStart, bBigEnd);
}
I was wondering if you had any thoughts here? Is there a better way to go about this? Experienced this slowdown in IE before?
Edit: In my last comment I misquoted the amount of values in the MakerNote tag for my images. The actual amount of values is 12648 not 1248. Quite a difference.
June 9, 2009 at 11:39 AM Jacob Seidelin@KJHoliday: It's probably due to IE just being much slower at parsing the binary data (there's a bit of separate code for IE). I guess I haven't had any images with that many values in the array fields so that's why I haven't caught it. I'll make a note and see if I can fill the arrays in a more efficient manner but I'm not sure if it can be done. Until then you'll have to make due with your temp solution.
June 9, 2009 at 12:33 PM MateuHi,
June 29, 2009 at 9:40 AM theBrantManGreat work on this, it's nice to see images get more integrated with the web, even if the whole thing is a workaround. ;-)
I'm wondering if it would be more robust to consider an event delegation model like this article so that images added with AJAX can also be processed?
For now, is the best bet to add EXIF.getData(this); to the load() method of the newly-added image?
adéu,
Mateu
So does anyone know why this returns a blank string on localhost?? I even have an apache server set up and it will not read the correct values from the pictures.
July 27, 2009 at 9:16 AM Jacob SeidelinNo idea, it should work just fine on localhost. Got a link to an online example?
July 30, 2009 at 3:20 PM LucifixThis looks like promising plugin but it doesn't work on remote images. Does anyone have any solution for this?
August 11, 2009 at 4:07 AM colinHi, I hope you're still monitoring this page. I love this idea and would like to use it on my site. Any idea why it's not working on this test page in IE 8 -- but it does work when I click the images on your site. I see only empty strings coming back on my page.
October 9, 2009 at 8:10 AM Jacob SeidelinThanks in advance,
Colin
www.colinmitchell.net/test1/new_page_1.htm
@colin: Your image is really big (2+ MB), have you tried resizing it to something more reasonable?
October 13, 2009 at 2:01 AM colin@Jacob,
October 13, 2009 at 10:02 AM Jacob SeidelinI know, I was in a bit of a rush, sorry. Also I wanted to demo a photo straight out of the camera in case my editor (CS3) felt like stripping the exif. I've updated it...still empty strings. I've also noticed that your demo page will return empty strings in this same way, but will work correctly following a page refresh. This is on IE8.
Cheers,
Colin
Ok, I'll investigate. I know there are a few things that need to be handled differently, and I have feeling that's what causing problems.
October 13, 2009 at 10:23 AM AnonymousI'll look into it as soon as I can.
Unfortunately don't work on IE6 ...
December 15, 2009 at 5:23 AM AnonymousHi Jacob,
January 6, 2010 at 7:10 AM JanI noticed that it only works with files in the same folder as the html page:
WORKS:
FAILS:
Any idea how to fix this?
Thanks,
Jan
janmartin AT diy-streetview DOT org
P.S.:
blogger.com does not like the img tag.
Jacob was so nice to answer my email on how to make the plugin work without clicking the image, just automatically:
January 26, 2010 at 5:41 AM Anonymous$("#imgA").load(function() {
$(this).exifLoad(function() {
// exif data should now be ready...
});
}); // end load
You've done it once again! Superb article.
June 14, 2010 at 8:08 AM AnonymousCan anything be done to allow for updating any of the EXIF data values? Reading the data is very handy; but changing the data would be the REAL hot sauce on a plug-in like this!
August 2, 2010 at 8:01 AM Matt BurnsAs mentioned by janmartin above, I can't get this to work with image files that are hosted on a different server.
August 20, 2010 at 4:27 AM Matt BurnsHere is an example page:
http://www.mattburns.co.uk/temp/scf/simplescrape.html
Any ideas?
I asked on stackoverflow (http://stackoverflow.com/questions/3530436/extracting-jpeg-exif-information-using-jquery)
August 20, 2010 at 5:37 AM UnknownBasically, you can't use javascript to fetch files from remote servers. Makes sense. Oh well.
I'm wondering if this can be done with a html file opened as a file, and an image located in the same directory? Anyone know?
August 27, 2010 at 3:32 AM Anonymous- I'd also voice my opinion that having the ability to update and bake the information back into the file would be great. I'm pretty sure that's not possible with just javascript, but I wonder if there are any solutions around for that kind of image information interactivity?
Hi there, I address oneself to up your blog via Google while searching in retribution allowing for regarding gold medal grant-in-aid well-earned to the event that a generosity engage in mel‚e and your temporary looks damned stirring exchange for me
September 4, 2010 at 5:13 PM UnknownHey Jacob (and KJHoliday). I'm using jquery to dynamically load an img src into a placeholder img tag on a page. I'm trying to use the following to load the exif data and it doesn't seem to be working. The image that loads first (extracted from the hash of my url) is the exif data i continually get back. Any thoughts on what I might be doing wrong? Click the image to retrieve the exif data.
October 8, 2010 at 2:27 PM Gilles$("#picContainer img").live('click',function(){ $(this).exifLoad(alert($(this).exif('ImageDescription'))); });
url: http://clients.inbluelight.com/westhill/commercial/
Great stuff Jacob. corey: trying to use this code in a slideshow, I've been wrestling for about a day with this. I thought it'd be nice to post some findings back.
November 30, 2010 at 4:06 AM Jacob SeidelinEXIF.getData checks, whether any data has been read for some specific img object:
if (!imageHasData(oImg)) .
Since this always evaluates to false after the first read, the exif data are never updated for dynamically changed images. The quickest possible dirty hack here is to simply remove this check. Of course, you may get unnecessary reads this way. If this is a problem performance-wise, you'll have to think of some more clever way to save and reuse any previously read data in relation to the actual images.
@Gilles: hasImageData() just checks if there's something in [img].exifdata, so you should be able to just clear that property before swapping images and loading the new data.
November 30, 2010 at 5:29 AM GillesJacob: thanks for the tip. Naturally, yours is the better solution. Excellent job.
December 1, 2010 at 2:50 AM AnonymousСпасибо понравилось ! Thanks !
December 1, 2010 at 3:27 PM AnonymousСпасибо за материалы! :)
December 5, 2010 at 10:56 PM AmaxRespect blog.nihilogic.dk
The code around here seems to have some typing error. Seems that iMarker should be compare to 224, and the iOffset += line should be before the return line.
July 14, 2011 at 7:42 PM ace893if (iMarker == 22400) {
if (bDebug) console.log("Found 0xFFE1 marker");
return readEXIFData(oFile, iOffset + 4, oFile.getShortAt(iOffset+2, true)-2);
iOffset += 2 + oFile.getShortAt(iOffset+2, true);
}
I'm having a hard time getting this to work on images loaded via an ajax call. It looks like there has been some discussion in previous comments about this but I'm having a hard time figuring out what to do.
November 2, 2011 at 8:25 AM ace893My app uploads an image using the Plupload tool. Once the UploadComplete event is fired I want to render the image on the same page using $.append(). I can get the Exif data of an uploaded image if I use your method in your blog post, so I know Plupload isn't messing the the Exif data. Below is the code that is called with the UploadComplete event is fired. Any ideas?
$("#uploader").pluploadQueue().bind("UploadComplete", function(r) {
console.debug("Files Uploaded", r);
for (var i = 0; i
");
$(".uploadedImage").ready(function(event) {
$(this).exifLoad(function(event) {
console.debug($(this).exifPretty());
})
})
}
initThumbnailInterface();
})
So my code example in my last post got butchered by the comment system.
November 2, 2011 at 8:30 AM Anonymous$(".uploadedImage").ready(function(event) {
$(this).exifLoad(function(event) {
console.debug($(this).exifPretty());
})
})
There's stuff in there that would seem to handle images not being fully loaded, so I have no idea why it's not firing. Have you tried it with different images? With several images on the page? That's because the code is running before the page fully loads. You need to use jQuery's "ready" function, which runs only after the DOM is loaded.
March 9, 2012 at 6:03 PM Kevin QuigleyHello,
May 20, 2012 at 7:56 AM Kevin QuigleyOh, I Hope you are still following this thread! Love the potential of this plug-in.
I am using jQuery to create a large number of image tags within $(document).ready() - they do not exist in the HTML of the page until they are created dynamically.
calling ,exifPretty() on the image tag returns noData. My guess is that the data is only checked that first time on page load - so they dynamically-loaded images are never called. Is there a simple way to call loadAllImages after the IMG's are created within my script?
Thanks so much!
Hi,
May 20, 2012 at 8:01 AM KateLove the potential of this Plug-in.
I am creating a large number of image tags dynamically in $(document).ready() and find that they return noData. is there a way to make sure that loadAllImages() or getData() is called after my script creates and .append()'s these images into the page?
note - they are being generated by pulling the background-image URLalso created from a script (based on the id of the div found in the html).
Thanks for doing this work!
Hello! I love and adore this idea, but cannot seem to get it to work with blogger. Will you please help guide me through the steps so I can have such a great tool on my own blog?
June 6, 2012 at 9:12 PM UnknownKind Regards,
Kate
Http://marlowesloft.com
I am developing a site for a charity which has limited server capabilities (i.e no PHP etc). I am having problems getting anything but blank EXIF info. I intend to display a random image on page load. This is fine, with image lists stored a simple array. As WAI is a very important consideration, I would like to extract EXIF data to build a meaningful ALT tag. Any possibility of help with this?
July 8, 2012 at 3:38 PM MarxGreat Work! I'm using jquery.exif.js and unfortunately it does not work on IE9, so I made a few changes:
August 16, 2012 at 7:26 AM semox1.) BinaryAjax.sendRequest
this.binaryResponse = new BinaryFile(typeof(this.responseText)=='string' ? this.responseText : this.responseBody, iDataOffset, iDataLen);
Because IE9 obviously supports XMLHttpRequest.onload, but still does not return a string in responseText for binary data.
Additionally I deleted the header "If-Modified-Since". I think bypassing the cache is not only unnecessary but even can be wrong: We want exactly the same data as the previous downloaded the image, so it should come from the cache.
2.) BinaryFile constructor
else if (typeof strData == "unknown") {
data = new VBArray(strData).toArray();
dataLength = iDataLength || data.length;
this.getByteAt = function(iOffset) {
return data[iOffset + dataOffset];
}
}
Using VBArray instead of VBScript functions is much faster and VBScript injection is no longer needed.
3.) Global
Deleted document.write("...vbscript..."), see 2.
Has somebody made this working with fancybox?
October 19, 2012 at 5:01 AM Coops This comment has been removed by the author. November 19, 2012 at 7:48 AM CoopsNice plugin - but can't get it to work on a number of photos (works on your example ones OK). Any idea why it can't read the exif from this photo: http://coopersphotos.com/var/albums/Colombia/DSC_5335.jpg
November 19, 2012 at 9:09 AM AgeofAquariusCheers.
Hi fellows, I would like to use this and put a div below my pictures with the EXIF info. I cannot find any solution for this. Is it possible with this script?
December 13, 2012 at 12:55 AM TimmRSame as @AgeofAquarius...
December 21, 2012 at 3:20 AM UnknownNo problems getting it to work with a click but even using
$("#imgA").load(function() {
$(this).exifLoad(function() {
document.getElementById('imagediv').innerHTML +=($(this).exifPretty());
});
});
...doesn't work for me :-(
Also, is it possible to drag out xp-title and xp-comment (if present)?
When I query for the latitude and longitude, the "seconds" are always 0. Opening the file in Photoshop shows me that the values are in fact there and they are not 0. Any idea why the third element is always 0?
February 19, 2013 at 2:42 PM UnknownI browsed trough the comments and saw multiple people having trouble with dynamically loaded images returning no data.
May 28, 2013 at 2:33 PM Kuh would have thoughtI couldn't find a working solution.
Did anyone find a solution that works?
FOR IIS (7 and 7.5)
October 8, 2013 at 7:49 AMoHTTP.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 1970 00:00:00 GMT");
must be
oHTTP.setRequestHeader("If-Modified-Since", "Sat, 01 Jan 1970 00:00:00 GMT");
otherwise bad request!