Reading JPEG Exif data with ColdFusion and Java

Exif data, a brief intro.
Exif data (and IPTC) is information about the image that is stored in JPEG image files. This information can be created by a digital camera or added to the image with programs such as PhotoShop. Data such as the image size, who took the shot, where it was taken, image title, width and height, copyright material etc can be stored along with the image.
 
The advantage of gaining access to this data is that information about the image can be displayed along with the image, on the fly, without having to enter and store it in a separate place: in a database or hard coded along with the image display.

 

Exif Java Class.
Looking at this problem, retrieving the data from a JPEG file, when having to code it I thought there is no way I am going to be able to learn about the layout of Exif data and play with extracting it from a binary file (I only had two days to come up with a solution, excuses I know but...).
 
So Java to the rescue!
 
After a little Google I found an open source Java class that does the job perfectly from this bloke: http://www.drewnoakes.com/code/exif/ there is a lot of data here about the class if you are interested.

 

ColdFusion to Java.
To get ColdFusion to talk to the Java class and vice versa I have written a separate class, in the downloadable jar file (119kb), providing methods to return the correct data, so you don't have to play with the Java side. As this is Easy CFM I will not go into the Java here.

 

Hooking it all Together - Registering the Class Path
 
Download the Java .jar file from here (119kb).
Here is a demo image if you need it: tester image
 
Now that we have jar file that does what we want we need to shoe horn it into ColdFusion.
 

Save the downloaded CFreadExif.jar file in a directory on your server under the ColdFusion directory structure.

For me it is in c:\CfusionMX\wwwroot\javaClasses

 
Now we need to register the path with the server so the class can be found, follow the steps below.
  • Go to the CF administrator and login
  • Click Java and JVM from the menu. fig 001
  • Check that the Java Virtual Machine Path is set fig 002
  • Then in the middle of the page, in the text box below Class Path enter the directory, where you saved the downloaded .jar file. You do not need to put the name of the .jar file just the directory it is sitting in. fig 003
figure 001
fig 001
figure 002
fig 002
figure 003
fig 003
There is one thing I don't like about adding Java class paths you need to restart the server once one is added. So restart the server to register the path. (if you have problems stop and then start the service instead of restart)
 
(If you do not have access to the administrator you should be able to add classes through your host's server control panel, if that is how they work. Most hosts allow for the addition of tags or classes speak to your admin.)

 

Calling the Class from ColdFusion.
Now we should have the Java class ready for use by ColdFusion. First we need to kick start the Java object and assign it to a variable so that it can be called.
<cfscript>
<!--- first create the java object --->
exifReader = createObject("java"," com.drew.imaging.coldfusion.CFreadExif");
<!--- call the init function to get it started --->
exifReader.init();
<!--- call the method in the java object that loads an image for reading --->
exifReader.loadImage('C:\CFusionMX\wwwroot\testing\graphics\ testerImage.jpg');
</cfscript>
What we did here was to:
  • Call the wrapper class that I wrote, a class called CfreadExif, stored in the .jar file
  • The wrapper class is stored in the directory com\drew\imaging\coldfusion which is the structure in the .jar file.
  • Then we call init() to kick start the object we have created.
  • Then we load the image into the class so it can read the data.
The path, in the loadImage() method call, needs to be an absolute path on the server to your image. Mine, as you can see, is in a folder called testing\graphics in the ColdFusion webroot.
 
Now we have the object, and it has read an image, we can dump it out to see what we have.
<cfdump var="#exifReader#">
Running this cfdump code should give you something like below. But if you get a null pointer error from ColdFusion check your path to the image. The null pointer is saying it cannot find any data because it can't find the image to read any data.
 
object of com.drew.imaging.coldfusion.CFreadExif
Methods getCountry (returns java.lang.String)
getDescription (returns java.lang.String)
loadImage (returns void)
getArtist (returns java.lang.String)
getCopyright (returns java.lang.String)
getMakeDate (returns java.lang.String)
getImgWidth (returns java.lang.String)
getImgHeight (returns java.lang.String)
getReportTitle (returns java.lang.String)
getCity (returns java.lang.String)
getPhotoID (returns java.lang.String)
getPlace (returns java.lang.String)
getAllData (returns java.util.ArrayList)
getAllMethods (returns java.lang.String)
hashCode (returns int)
getClass (returns java.lang.Class)
wait (returns void)
wait (returns void)
wait (returns void)
equals (returns boolean)
notify (returns void)
notifyAll (returns void)
toString (returns java.lang.String)
imageToRead C:\CFusionMX\wwwroot\testing\graphics\testerImage.jpg
desc [undefined value]
imageFile [undefined value]
exifMeta class com.drew.metadata.Metadata
exifDirectory class com.drew.metadata.Directory
iptcDirectory class com.drew.metadata.Directory
As you can see there are a number of methods to call. All the getBlahBlah() methods return data contained in the image.
 
You can call any of the methods in this way:
<cfoutput>
<!--- call the object.then the method --->
#exifReader.getDescription()#
</cfoutput>
 
The above will return the description found in the JPEG file, if one exists.
<cfoutput>
#exifReader.getArtist()# <!--- gives you the photographer --->
#exifReader.getMakeDate()# <!--- date shot --->
#exifReader.getImgWidth()# <!--- image width --->
#exifReader.getReportTitle()# <!--- image title --->
<!--- And so on. --->
</cfoutput>
Writing this:
<cfoutput>
#exifReader.getAllMethods()#
</cfoutput>
Will output descriptions of all the getBlahBlah() methods so you can see what you might want.
 
All the getBlahBlah() methods return strings apart from one: the getAllData() method, which returns an array of all the data that can be found in the JPEG file.
 
You can dump it to see what information is in the image, what might differ from the image I have used:
<cfdump var="#exifReader.getAllData()#">
The above dump code will give you a large array, you may have data such as camera make, model, and loads of stuff in there. You can then access an individual bit of data that you fancy like this:
<cfset arData =exifReader.getAllData()>
<cfoutput>
#arData[1]#
</cfoutput>
The above will give you the first row of data.

 

Summary.
I hope you find this useful all the thanks needs to go to the man who wrote the Exif Java class; Mr Drew Noakes. All I have done here is to demonstrate a technique for utilising high powered Java classes in your ColdFusion applications. It makes CF 10 times more powerful than without.
 
If anyone is interested I can write another tutorial describing how to write the Java wrapper to open up a Java class for ColdFusion use.

Thanks for reading,
cheers Martin (Non Stop Loop)

About This Tutorial
Author: Martin Thorpe
Skill Level: Advanced 
 
 
 
Platforms Tested: CFMX
Total Views: 110,212
Submission Date: September 16, 2005
Last Update Date: June 05, 2009
All Tutorials By This Autor: 1
Discuss This Tutorial
  • I fixed the problem I had: It was because I copied the code verbatim from this site and there is an extra space before com in this line: exifReader = createObject("java"," com.drew.imaging.coldfusion.CFreadExif"); Once I removed the extra space, the code worked. Thanks again for making this available.

  • I am getting an "OBJECT INSTANTIATION ERROR: Class not found: com.drew.imaging.coldfusion.CFreadExif " with ColdFusion MX7. I am new to using Java, so I don't have any clue what I am doing wrong. Was I supposed to download drew nokes java files too, or just yours? If so, where would I put those files? Any other ideas appreciated. Your tutorial was really easy, I am just clueless.

  • I left the date formatting to as it comes from the java so that people can choose what they want to do with it. In the case of the application the data was not being inserted directly into a database but just displayed. I think Oracle uses a different date format for an isert too, dd-mmm-yyy, correct me if I am wrong. I just left it open so that the class is not tailored to one function but can be used in different ways. The lengths of the arrays returned will be different for different images, different cameras record different data for instance. Hope this helps, thanks for the comments. cheers Martin

  • Another handy thing would be a function to format the EXIF date's in a formatable date format. e.g., regex'ing 2005:10:22 14:00:00 EXIF into 2005-10-22 14:00:00 ODBC directly in the class. This way, anyone could reference that date in the EXIF output without having to massage it after pulling out the data. I also noticed different images generate different arraylen()'s. Is it possible to keep the array consistant even if those positions are empty?

  • Hey Martin. Thanks for the reply. I'm glad your using cfscript. Not enough people use it. I think you got on the boat, but just incase, the 0 & 1's in positions 31-41 I have no idea what they reference in the EXIF data. I could go through each item manually and pinpoint them to the correct EXIF item but thought it might be handy to incorporate the references? That would be quite nice. Keep up the good work.

  • Hello Matt. Thanks for the comments. With the java class path you are correct, I just had to put it in a seperate directory for the environment, request from the system guys, so I thought I would include it. Yeah sorry about the comments in the cfscript being incorrect, you are right just me getting involved in the tutorial. Thanks for the heads up Matt. About the values in positions do you mean how to get the descriptions of the array positions? I do not have the code in front of me, it is at work, but I don't think I did that although I could probably adapt the jar to give an array of descriptions too. The methods to do this are available in the original class so to write a wrapper would be simple enough. When I get some time I will do it. If I have missed the boat on what you mean drop another note and I will endeavour to answer. Cheers for the interest, thanks. P.S. if you are interested here is the docs for the original class. http://www.drewnoakes.com/code/exif/sampleUsage.html

  • Is there a way or list of what item your referencing? Such as the values in positions [31:41]?

  • Neat and clean tutorial. I never bought the one on CommunityMX site that used the same component? Does it have any extra info? Couple notes on this tutorial... You don't need to add the .jar path to your JVM settings. It only needs to be in ${cfmx_root}/wwwroot/WEB-INF/lib/ directory and server restarted to invoke methods from the JARs classes. Similiar to how CF knows where to look for custom tags. And people probably already noticed that you can't have



Website Designed and Developed by Pablo Varando.