#####GetEXIF.sml Script
#####Written by Brett Colombe
#####MicroImages, Inc. Software Engineer
#####September 25, 2006
####SML script to get a selected JPEG Image's exif header and output to text file of same name in same directory
class FILE textOutput;
class EXIF exifhandle; #EXIF class for EXIF keys and values
class STRINGLIST keyStrings; #String list for key list
clear();
#User select image
string prompt$ = "Select Image";
string filename$=GetInputFileName("", prompt$, ".jpg");
#Create Text file
string textname$=FileNameGetPath(filename$) + "\" + FileNameGetName(filename$) + ".txt";
print("EXIF output: ", textname$);
textOutput=fopen(textname$, "w"); #open text file in write mode
#Write title to first line of text file
fwritestring(textOutput, sprintf("EXIF Header Information for image: %s\n -----------------------------\n", filename$));
#GetEXIFTags takes filename of image as input
#returns hash with key names and values
exifhandle.Open(filename$);
#Get key list from hash, returns as string list
keyStrings = exifhandle.GetKeyList();
local numeric value,i;
local string value$;
#print all keys and values to text file
for i=0 to keyStrings.GetNumItems()-1 {
fwritestring(textOutput, sprintf("\nKey: %i\t%s\n\tValue: %s\n", i, keyStrings[i], exifhandle.GetDatumStr(keyStrings[i])));
################################################################
############# Display detailed information about EXIF Tags #######################
################################################################
#Exif.Photo.Flash
#bit0: 0 flash didn't fire, 1 flash fired
#bit12: 00 no strobe return detection function, 01 reserved, 10 strobe return light not detected, 11 strobe return ligth deteced
#bit34: 00 unknown, 01 Compulsory flash firing, 10 Compulsory flash suppression, 11 auto mode
#bit5: 0 flash function present, 1 no flash function
#bit6: 0 no red eye reduction mode or unknown, 1 red eye reduction supported
if(keyStrings[i]=="Exif.Photo.Flash")
{
value=StrToNum(exifhandle.GetDatumStr("Exif.Photo.Flash"));
if(value>=64)#red eye mode
{
value=value-64;
fwritestring(textOutput, "\tFlash - Red Eye Mode - Red eye reduction supported\n");
}
else
fwritestring(textOutput, "\tFlash - Red Eye Mode - No red eye reduction mode or unknown\n");
if(value>=32)#flash function
{
value=value-32;
fwritestring(textOutput, "\tFlash - Flash Function - No flash function\n");
}
else
fwritestring(textOutput, "\tFlash - Flash Function - Flash function present\n");
if(value>=16)#flash mode
{
value=value-16;
if(value>=8)
{
value=value-8;
fwritestring(textOutput, "\tFlash - Flash Mode - Auto mode\n");
}
else
fwritestring(textOutput, "\tFlash - Flash Mode - Compulsory flash suprression\n");
}
else
{
if(value>=8)
{
value=value-8;
fwritestring(textOutput, "\tFlash - Flash Mode - Compulsory flash firing\n");
}
else
fwritestring(textOutput, "\tFlash - Flash Mode - Unknown mode\n");
}
if(value>=4)#flash return
{
value=value-4;
if(value>=2)
{
value=value-2;
fwritestring(textOutput, "\tFlash - Flash Return - Strobe return light detected\n");
}
else
fwritestring(textOutput, "\tFlash - Flash Return - Strobe return light not detected\n");
}
else
{
if(value>=2)
{
value=value-2;
fwritestring(textOutput, "\tFlash - Flash Return - Reserved\n");
}
else
fwritestring(textOutput, "\tFlash - Flash Return - No strobe return detection function\n");
}
if(value>=1)#flash fired
fwritestring(textOutput, "\tFlash - Flash Fired - Flash did fire\n");
else
fwritestring(textOutput, "\tFlash - Flash Fired - Flash did not fire\n");
}#end Exif.Photo.Flash
#Exif.Photo.ExifVersion
if(keyStrings[i]=="Exif.Photo.ExifVersion")
{
value$=exifhandle.GetDatumStr("Exif.Photo.ExifVersion");
fwritestring(textOutput, sprintf("\tExif Version: %i%i.%i%i\n", StrToNum(GetToken(value$, " ",1))-48, StrToNum(GetToken(value$, " ",2))-48, StrToNum(GetToken(value$, " ",3))-48, StrToNum(GetToken(value$, " ",4))-48));
}
#Exif.Photo.FlashpixVersion
if(keyStrings[i]=="Exif.Photo.FlashpixVersion")
{
value$=exifhandle.GetDatumStr("Exif.Photo.FlashpixVersion");
fwritestring(textOutput, sprintf("\tFlashpix Version: %i%i.%i%i\n", StrToNum(GetToken(value$, " ",1))-48, StrToNum(GetToken(value$, " ",2))-48, StrToNum(GetToken(value$, " ",3))-48, StrToNum(GetToken(value$, " ",4))-48));
}
#Exif.Iop.InteroperabilityVersion
if(keyStrings[i]=="Exif.Iop.InteroperabilityVersion")
{
value$=exifhandle.GetDatumStr("Exif.Iop.InteroperabilityVersion");
fwritestring(textOutput, sprintf("\tInteroperability Version: %i%i.%i%i\n", StrToNum(GetToken(value$, " ",1))-48, StrToNum(GetToken(value$, " ",2))-48, StrToNum(GetToken(value$, " ",3))-48, StrToNum(GetToken(value$, " ",4))-48));
}
#Exif.Image.Orientation
if(keyStrings[i]=="Exif.Image.Orientation" || keyStrings[i]=="Exif.Thumbnail.Orientation")
{
value=StrToNum(exifhandle.GetDatumStr("Exif.Image.Orientation"));
switch(value)
{
case 1: fwritestring(textOutput, sprintf("\tOrientation: The 0th row is at the visual %s of the image, and the 0th column is the visual %s.\n","top","left-hand side")); break;
case 2: fwritestring(textOutput, sprintf("\tOrientation: The 0th row is at the visual %s of the image, and the 0th column is the visual %s.\n","top","right-hand side")); break;
case 3: fwritestring(textOutput, sprintf("\tOrientation: The 0th row is at the visual %s of the image, and the 0th column is the visual %s.\n","bottom","right-hand side")); break;
case 4: fwritestring(textOutput, sprintf("\tOrientation: The 0th row is at the visual %s of the image, and the 0th column is the visual %s.\n","bottom","left-hand side")); break;
case 5: fwritestring(textOutput, sprintf("\tOrientation: The 0th row is at the visual %s of the image, and the 0th column is the visual %s.\n","left-hand side","top")); break;
case 6: fwritestring(textOutput, sprintf("\tOrientation: The 0th row is at the visual %s of the image, and the 0th column is the visual %s.\n","right-hand side","top")); break;
case 7: fwritestring(textOutput, sprintf("\tOrientation: The 0th row is at the visual %s of the image, and the 0th column is the visual %s.\n","right-hand side","bottom")); break;
case 8: fwritestring(textOutput, sprintf("\tOrientation: The 0th row is at the visual %s of the image, and the 0th column is the visual %s.\n","left-hand side","bottom")); break;
}
}
#Exif.Image.ResolutionUnit
if(keyStrings[i]=="Exif.Image.ResolutionUnit" || keyStrings[i]=="Exif.Thumbnail.ResolutionUnit" || keyStrings[i]=="Exif.Photo.FocalPlaneResolutionUnit")
{
value=StrToNum(exifhandle.GetDatumStr("Exif.Image.ResolutionUnit"));
switch(value)
{
case 2: fwritestring(textOutput, sprintf("\tUnit for Resolution: Inches\n")); break;
case 3: fwritestring(textOutput, sprintf("\tUnit for Resolution: Centimeters\n")); break;
}
}
#Exif.Image.YCbCrPositioning
if(keyStrings[i]=="Exif.Image.YCbCrPositioning" || keyStrings[i]=="Exif.Thumbnail.YCbCrPositioning")
{
value=StrToNum(exifhandle.GetDatumStr("Exif.Image.YCbCrPositioning"));
switch(value)
{
case 1: fwritestring(textOutput, sprintf("\tPosition of Chrominance components in relation to Luminance components: centered.\n")); break;
case 2: fwritestring(textOutput, sprintf("\tPosition of Chrominance components in relation to Luminance components: co-sited.\n")); break;
}
}
#Exif.Image.XResolution / YResolution
if(keyStrings[i]=="Exif.Image.XResolution" || keyStrings[i]=="Exif.Image.YResolution" || keyStrings[i]=="Exif.Photo.FocalPlaneXResolution" || keyStrings[i]=="Exif.Photo.FocalPlaneYResolution" || keyStrings[i]=="Exif.Thumbnail.XResolution" || keyStrings[i]=="Exif.Thumbnail.YResolution")
fwritestring(textOutput, sprintf("\tNumber of pixles per resolution unit.\n"));
#Exif.Iop.InteroperabilityIndex
if(keyStrings[i]=="Exif.Iop.InteroperabilityIndex")
{
value$=exifhandle.GetDatumStr("Exif.Iop.InteroperabilityIndex");
switch(value$)
{
case "R98": fwritestring(textOutput, sprintf("\tIndicates a file conforming to R98 file specification of Recommended Exif Interoperability Rules (ExifR98) or to DCF basic file stipulated by Design Rule for Camera File System.\n")); break;
case "THM": fwritestring(textOutput, sprintf("\tIndicates a file conforming to DCF thumbnail file stipulated by Design rule for Camera File System.\n")); break;
}
}
#Exif.Photo.ColorSpace
if(keyStrings[i]=="Exif.Photo.ColorSpace")
{
value$=exifhandle.GetDatumStr("Exif.Photo.ColorSpace");
if(value$=="1")
fwritestring(textOutput, sprintf("\tsRGB (=1) is used to define the color space based on the PC monitor conditions and environment.\n"));
else
fwritestring(textOutput, sprintf("\tUncalibrated.\n"));
}
#Exif.Photo.ExposureMode
if(keyStrings[i]=="Exif.Photo.ExposureMode")
{
value=StrToNum(exifhandle.GetDatumStr("Exif.Photo.ExposureMode"));
switch(value)
{
case 0: fwritestring(textOutput, sprintf("\tAuto exposure.\n")); break;
case 1: fwritestring(textOutput, sprintf("\tManual exposure.\n")); break;
case 2: fwritestring(textOutput, sprintf("\tAuto bracket.\n")); break;
}
}
#Exif.Photo.FileSource
if(keyStrings[i]=="Exif.Photo.FileSource")
{
value=StrToNum(exifhandle.GetDatumStr("Exif.Photo.FileSource"));
if(value==3)
fwritestring(textOutput, sprintf("\tImage recorded on a DSC.\n"));
}
#Exif.Photo.SceneType
if(keyStrings[i]=="Exif.Photo.SceneType")
{
value=StrToNum(exifhandle.GetDatumStr("Exif.Photo.SceneType"));
if(value==1)
fwritestring(textOutput, sprintf("\tA directly photographed image.\n"));
}
#Exif.Photo.ComponentsConfiguration
if(keyStrings[i]=="Exif.Photo.ComponentsConfiguration")
{
value$=exifhandle.GetDatumStr("Exif.Photo.ComponentsConfiguration");
local string line$="";
local numeric k;
for k=1 to 4
{
value=StrToNum(GetToken(value$," ",k));
switch(value)
{
case 0: line$=line$ + sprintf("%i=%s ",value ,"does not exist"); break;
case 1: line$=line$ + sprintf("%i=%s ",value ,"Y"); break;
case 2: line$=line$ + sprintf("%i=%s ",value ,"Cb"); break;
case 3: line$=line$ + sprintf("%i=%s ",value ,"Cr"); break;
case 4: line$=line$ + sprintf("%i=%s ",value ,"R"); break;
case 5: line$=line$ + sprintf("%i=%s ",value ,"G"); break;
case 6: line$=line$ + sprintf("%i=%s ",value ,"B"); break;
}
}
fwritestring(textOutput, sprintf("\tChannels of each component: %s.\n",line$));
}
#Exif.Photo.MeteringMode
if(keyStrings[i]=="Exif.Photo.MeteringMode")
{
value=StrToNum(exifhandle.GetDatumStr("Exif.Photo.MeteringMode"));
switch(value)
{
case 0: fwritestring(textOutput, sprintf("\tMetering Mode: %s.\n","Unknown")); break;
case 1: fwritestring(textOutput, sprintf("\tMetering Mode: %s.\n","Average")); break;
case 2: fwritestring(textOutput, sprintf("\tMetering Mode: %s.\n","Center Weighted Average")); break;
case 3: fwritestring(textOutput, sprintf("\tMetering Mode: %s.\n","Spot")); break;
case 4: fwritestring(textOutput, sprintf("\tMetering Mode: %s.\n","Multi Spot")); break;
case 5: fwritestring(textOutput, sprintf("\tMetering Mode: %s.\n","Pattern")); break;
case 6: fwritestring(textOutput, sprintf("\tMetering Mode: %s.\n","Partial")); break;
case 255: fwritestring(textOutput, sprintf("\tMetering Mode: %s.\n","Other")); break;
}
}
#Exif.Photo.SceneCaptureType
if(keyStrings[i]=="Exif.Photo.SceneCaptureType")
{
value=StrToNum(exifhandle.GetDatumStr("Exif.Photo.SceneCaptureType"));
switch(value)
{
case 0: fwritestring(textOutput, sprintf("\tScene Type: %s.\n","Standard")); break;
case 1: fwritestring(textOutput, sprintf("\tScene Type: %s.\n","Landscape")); break;
case 2: fwritestring(textOutput, sprintf("\tScene Type: %s.\n","Portrait")); break;
case 3: fwritestring(textOutput, sprintf("\tScene Type: %s.\n","Night Scene")); break;
}
}
#Exif.Photo.SensingMethod
if(keyStrings[i]=="Exif.Photo.SensingMethod")
{
value=StrToNum(exifhandle.GetDatumStr("Exif.Photo.SensingMethod"));
switch(value)
{
case 1: fwritestring(textOutput, sprintf("\tImage Sensor Type: %s.\n","Not defined")); break;
case 2: fwritestring(textOutput, sprintf("\tImage Sensor Type: %s.\n","One-chip color area sensor")); break;
case 3: fwritestring(textOutput, sprintf("\tImage Sensor Type: %s.\n","Two-chip color area sensor")); break;
case 4: fwritestring(textOutput, sprintf("\tImage Sensor Type: %s.\n","Three-chip color area sensor")); break;
case 5: fwritestring(textOutput, sprintf("\tImage Sensor Type: %s.\n","Color sequential area sensor")); break;
case 7: fwritestring(textOutput, sprintf("\tImage Sensor Type: %s.\n","Trilinear sensor")); break;
case 8: fwritestring(textOutput, sprintf("\tImage Sensor Type: %s.\n","Color sequential linear sensor")); break;
}
}
#Exif.Photo.WhiteBalance
if(keyStrings[i]=="Exif.Photo.WhiteBalance")
{
value=StrToNum(exifhandle.GetDatumStr("Exif.Photo.WhiteBalance"));
switch(value)
{
case 0: fwritestring(textOutput, sprintf("\tWhite Balance: %s\n", "Auto")); break;
case 1: fwritestring(textOutput, sprintf("\tWhite Balance: %s\n", "Manual")); break;
}
}
#Exif.Thumbnail.Compression
if(keyStrings[i]=="Exif.Thumbnail.Compression")
{
value=StrToNum(exifhandle.GetDatumStr("Exif.Thumbnail.Compression"));
switch(value)
{
case 1: fwritestring(textOutput, sprintf("\t%s\n", "Uncompressed")); break;
case 6: fwritestring(textOutput, sprintf("\t%s\n", "JPEG compression")); break;
}
}
#Exif.Thumbnail.JPEGInterchangeFormat
if(keyStrings[i]=="Exif.Thumbnail.JPEGInterchangeFormat")
fwritestring(textOutput, sprintf("\tThe offset to the start byte (SOI) of JPEG compressed thumbnail data.\n"));
#Exif.Photo.ExposureProgram
if(keyStrings[i]=="Exif.Photo.ExposureProgram")
{
value=StrToNum(exifhandle.GetDatumStr("Exif.Photo.ExposureProgram"));
switch(value)
{
case 0: fwritestring(textOutput, sprintf("\tExposure Program Class: %s.\n","Not defined")); break;
case 1: fwritestring(textOutput, sprintf("\tExposure Program Class: %s.\n","Manual")); break;
case 2: fwritestring(textOutput, sprintf("\tExposure Program Class: %s.\n","Normal Program")); break;
case 3: fwritestring(textOutput, sprintf("\tExposure Program Class: %s.\n","Aperture priority")); break;
case 4: fwritestring(textOutput, sprintf("\tExposure Program Class: %s.\n","Shutter priority")); break;
case 5: fwritestring(textOutput, sprintf("\tExposure Program Class: %s.\n","Creative program (biased toward depth of field)")); break;
case 6: fwritestring(textOutput, sprintf("\tExposure Program Class: %s.\n","Action program (biased toward fast shutter speed")); break;
case 7: fwritestring(textOutput, sprintf("\tExposure Program Class: %s.\n","Portrait mode (for closeup photos with the background out of focus)")); break;
case 8: fwritestring(textOutput, sprintf("\tExposure Program Class: %s.\n","Landscape mode (for landscape photos with the background in focus")); break;
}
}
#Exif.Photo.LightSource
if(keyStrings[i]=="Exif.Photo.LightSource")
{
value=StrToNum(exifhandle.GetDatumStr("Exif.Photo.LightSource"));
switch(value)
{
case 0: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","Unknown")); break;
case 1: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","Daylight")); break;
case 2: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","Fluorescent")); break;
case 3: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","Tungsten (incandescent light)")); break;
case 4: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","Flash")); break;
case 9: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","Fine weather")); break;
case 10: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","Cloudy weather")); break;
case 11: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","Shade")); break;
case 12: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","Daylight fluorescent (D 5700 - 7100K)")); break;
case 13: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","Day white fluorescent (N 4600 - 5400K)")); break;
case 14: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","Cool white fluorescent (W 3900 - 4500K)")); break;
case 15: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","White fluorescent (WW 3200 - 3700K)")); break;
case 17: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","Standard light A")); break;
case 18: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","Standard light B")); break;
case 19: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","Standard light C")); break;
case 20: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","D55")); break;
case 21: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","D65")); break;
case 22: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","D75")); break;
case 23: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","D50")); break;
case 24: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","ISO studio tungsten")); break;
case 255: fwritestring(textOutput, sprintf("\tLight Source: %s.\n","Other light source")); break;
}
}
#Exif.Thumbnail.PhotometricInterpretation
if(keyStrings[i]=="Exif.Image.PhotometricInterpretation" || keyStrings[i]=="Exif.Thumbnail.PhotometricInterpretation")
{
value=StrToNum(exifhandle.GetDatumStr("Exif.Thumbnail.PhotometricInterpretation"));
switch(value)
{
case 2: fwritestring(textOutput, sprintf("\tPixel Composition: %s\n", "RGB")); break;
case 6: fwritestring(textOutput, sprintf("\tPixel Composition: %s\n", "YCbCr")); break;
}
}
#########################################################
}#for
fclose(textOutput);