Skip to content

Instantly share code, notes, and snippets.

@ivanionut
Forked from JamoCA/Exiv2_UDF.cfm
Created March 11, 2016 08:57
Show Gist options
  • Save ivanionut/ccdb296756ce16f00dd8 to your computer and use it in GitHub Desktop.
Save ivanionut/ccdb296756ce16f00dd8 to your computer and use it in GitHub Desktop.
ColdFusion wrapper for Exiv2.exe (a command line utility to extract EXIF data). Much faster than ImageGetEXIFMetaData().
<!--- 2/16/2016 Exiv2(filePath, ExePath)
James Moberg - SunStar Media
Requires command-line version of Exiv2 http://www.exiv2.org/
All data returned in a struct. Based on filetype & metadata, keys may not always exist.
Latitude/Longitude keys w/decimal values added. All dates formatted to M/D/YYYY HH:MM:SS format.
Similar to ImageGetEXIFMetaData(imageNew( imageFilePath )), but much faster. (Exiv2 = 16-47ms; CF = 500-920ms)
--->
<cffunction name="Exiv2" returntype="struct" output="no">
<cfargument name="filepath" type="string" required="true">
<cfargument name="EXEpath" default="C:\Exiv2\Exiv2.exe" type="string" required="false">
<cfset var Temp = {temp="", raw="", thisline="", response={}}>
<cfif FileExists(arguments.filepath)>
<cfexecute name="#arguments.EXEpath#" arguments="-Pnt #arguments.filepath#" variable="Temp.Raw" timeout="5"></cfexecute>
<!--- Space delimited values. key, interpreted (translated) data --->
<cfloop list="#Temp.Raw#" index="Temp.ThisLine" delimiters="#CHR(10)#">
<cfset Temp.ThisLine = Trim(Temp.ThisLine)>
<cfif ListLen(Temp.ThisLine, " ") GT 1>
<cfset Temp.Temp = trim(ListFirst(Temp.ThisLine, " "))>
<cfset Temp.Response["#Temp.Temp#"] = trim(ListRest(Temp.ThisLine, " "))>
</cfif>
</cfloop><!---
<CFSET Temp.Response["Raw"] = Temp.Raw> --->
<CFIF StructCount(Temp.Response)>
<!--- Add decimal Latitude/Longitude --->
<CFSET temp.Response["Latitude"] = 0>
<CFSET temp.Response["Longitude"] = 0>
<!--- Parse sexagesimal latitude/longitude and convert to decimal --->
<cfif structKeyExists( Temp.Response, "GPSLatitude" ) AND len( Temp.Response[ "GPSLatitude" ] ) AND VAL(Temp.Response[ "GPSLatitude" ])
AND structKeyExists( Temp.Response, "GPSLatitudeRef" ) AND len( Temp.Response[ "GPSLatitudeRef" ] )
AND structKeyExists( Temp.Response, "GPSLongitude" ) AND len( Temp.Response[ "GPSLongitude" ] ) AND VAL(Temp.Response[ "GPSLongitude" ])
AND structKeyExists( Temp.Response, "GPSLongitudeRef" ) AND len( Temp.Response[ "GPSLongitudeRef" ])>
<cfset temp.latitudeParts = listToArray(replace(replace(Temp.Response["GPSLatitude"],"""",""), "deg",""""), "'""")>
<cfset temp.Response["Latitude"] = (temp.latitudeParts[ 1 ] + (temp.latitudeParts[ 2 ] / 60) + (temp.latitudeParts[ 3 ] / 3600))>
<cfif (Temp.Response[ "GPSLatitudeRef" ] IS "South")>
<cfset temp.Response["Latitude"] *= -1>
</cfif>
<cfset temp.longitudeParts = listToArray(replace(replace(Temp.Response["GPSLongitude"],"""",""), "deg",""""), "'""")>
<cfset Temp.Response["Longitude"] = ( Temp.longitudeParts[ 1 ] + (Temp.longitudeParts[ 2 ] / 60) + (Temp.longitudeParts[ 3 ] / 3600))>
<cfif (Temp.Response[ "GPSLongitudeRef" ] IS "West")>
<cfset Temp.Response["Longitude"] *= -1>
</cfif>
</CFIF>
<!--- Parse date Exif values to dates. Consolidate GPSDateStamp & GPSTimeStamp (UTC) ---->
<CFLOOP COLLECTION="#Temp.Response#" ITEM="Temp.Temp">
<CFIF Temp.Temp IS "GPSDateStamp" AND ListLen(Temp.Response[Temp.Temp],":") IS 3 AND isDate(replace(Temp.Response[Temp.Temp],":","-", "all"))>
<CFIF StructKeyExists(Temp.Response, "GPSTimeStamp") AND ListLen(Temp.Response["GPSTimeStamp"],":") IS 3>
<CFSET Temp.Response["GPSDateStamp"] = DateFormat(parseDateTime(replace(Temp.Response[Temp.Temp],":","-", "all")), "M/D/YYYY") & " " & Temp.Response["GPSTimeStamp"]>
<CFELSE>
<CFSET Temp.Response[Temp.Temp] = DateFormat(parseDateTime(replace(Temp.Response[Temp.Temp],":","-", "all")), "M/D/YYYY") & "00:00:00">
</CFIF>
<CFELSEIF Find("DateTime", Temp.Temp) AND ListLen(Temp.Response[Temp.Temp],":") IS 5 AND isDate(replace(replace(Temp.Response[Temp.Temp],":","-"),":","-"))>
<CFSET Temp.TempDate = parseDateTime(replace(replace(Temp.Response[Temp.Temp],":","-"),":","-"))>
<CFSET Temp.Response[Temp.Temp] = DateFormat(Temp.TempDate,"M/D/YYYY") & " " & TimeFormat(Temp.TempDate,"HH:MM:SS")>
</CFIF>
</CFLOOP>
</CFIF>
</cfif>
<cfreturn Temp.Response>
</cffunction>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment