Skip to content

Instantly share code, notes, and snippets.

@JamoCA
Last active August 3, 2022 02:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JamoCA/308df6f2bc927203330a23c1c6678c39 to your computer and use it in GitHub Desktop.
Save JamoCA/308df6f2bc927203330a23c1c6678c39 to your computer and use it in GitHub Desktop.
Extract image metadata (Exif, IPTC, XMP metadata and ICC Profile) using Exiv2 and ColdFusion / CFML
<cfscript>
/* 2016-02-16 Exiv2 (shared on 2022-07-06)
By James Moberg - SunStar Media
Requires command-line version of Exiv2 http://www.exiv2.org/
All data returned in a struct. Based on different filetypes & available metadata, keys may not always exist.
Requirements: CF2016u3+ or Lucee 4.5+
Blog: https://dev.to/gamesover/use-exiv2-to-extract-gps-data-from-images-using-cfml-3maa
Tweet: https://twitter.com/gamesover/status/1544747532881903616
Forum: https://community.adobe.com/t5/coldfusion-discussions/using-imagegetexifmetadata-to-try-to-get-gps-coordinates-of-an-image/m-p/13053016
*/
public struct function exiv2(required string filepath, string exePath="") output=false hint="Extract image metadata (Exif, IPTC, XMP metadata and ICC Profile) using Exiv2" {
local.data = [:];
if ( fileExists(arguments.filepath)) {
// -Pnt = Print Report (P) w/tag name (t) and interpreted (translated) human readable data (t)
cfexecute(arguments="-Pnt #arguments.filepath#", variable="local.raw", name=arguments.exePath, timeout=15);
// 4 Space delimited values. key, datatype,
for (local.line in listToArray(local.raw, chr(10))){
local.line = trim(local.line);
if (listLen(local.line, " ") > 1) {
local.temp = trim(listFirst(local.line, " "));
local.data["#local.temp#"] = trim(listRest(local.line, " "));
}
}
}
// DEBUGGING local.data["raw"] = local.Raw;
if (structCount(local.data)) {
// Add decimal Latitude/Longitude
local.data["Latitude"] = 0;
local.data["Longitude"] = 0;
// Parse sexagesimal latitude/longitude and convert to decimal
if (structKeyExists(local.data, "GPSLatitude") && len(local.data.GPSLatitude) && val(local.data.GPSLatitude)
and structKeyExists(local.data, "GPSLatitudeRef") && len(local.data.GPSLatitudeRef)
and structKeyExists(local.data, "GPSLongitude") && len(local.data.GPSLongitude) && val(local.data.GPSLongitude)
and structKeyExists(local.data, "GPSLongitudeRef") && len(local.data.GPSLongitudeRef)
){
local.latitudeParts = listToArray(replace(replace(local.data["GPSLatitude"],"""",""), "deg",""""), "'""");
local.data["Latitude"] = (local.latitudeParts[1] + (local.latitudeParts[2] / 60) + (local.latitudeParts[3] / 3600));
if ((local.data.GPSLatitudeRef == "South")){
local.data["Latitude"] *= -1;
}
local.longitudeParts = listToArray(replace(replace(local.data["GPSLongitude"],"""",""), "deg",""""), "'""");
local.data["Longitude"] = (local.longitudeParts[1] + (local.longitudeParts[2] / 60) + (local.longitudeParts[3] / 3600));
if ((local.data.GPSLongitudeRef == "West")){
local.data["Longitude"] *= -1;
}
}
// Parse date Exif values to dates. Consolidate GPSDateStamp & GPSTimeStamp (UTC)
for (local.key in local.data) {
if (local.key == "GPSDateStamp" && listLen(local.data[local.key],":") == 3 && isDate(replace(local.data[local.key],":","-", "all"))) {
if (structKeyExists(local.data, "GPSTimeStamp") && listLen(local.data["GPSTimeStamp"],":") == 3) {
local.data["GPSDateStamp"] = dateFormat(parseDateTime(replace(local.data[local.key],":","-", "all")), "yyyy-mm-dd") & " " & local.data["GPSTimeStamp"];
} else {
local.data[local.key] = dateFormat(parseDateTime(replace(local.data[local.key],":","-", "all")), "yyyy-mm-dd") & "00:00:00";
}
} else if (find("DateTime", local.key) && listLen(local.data[local.key],":") == 5 && isDate(replace(replace(local.data[local.key],":","-"),":","-"))) {
local.tempDate = parseDateTime(replace(replace(local.data[local.key],":","-"),":","-"));
local.data[local.key] = dateTimeFormat(local.tempDate,"yyyy-mm-dd") & " " & timeFormat(local.tempDate,"HH:nn:ss");
}
}
} else {
local.data = [
"Error": "Error accessing file"
,"Warning": "Unable to analyze #arguments.filepath#"
,"input": "#arguments.exePath# -Pnt #arguments.filepath#"
,"output": (local.keyExists("raw")) ? local.raw : ""
];
}
return local.data;
}
</cfscript>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment