#!/bin/sh # MetaCard 2.4 stack # The following is not ASCII text, # so now would be a good time to q out of more exec mc $0 "$@" libEXIF A Mlocal lexifEndian -- set to either I for Intel or M for Motorola local lexifBaseOffset local lexifData local maxLimitOnSizeOfUnknown = 200 local replaceLimitOnSizeOfUnknown = 10 function exifProcessFile pData -- pAllTags -- pData should already contain the entire file (e.g. put URL "binfile:the.jpg" into tData) before calling -- pAllTags - true if should return all tags, otherwise (default = false) return only known tags local allTags if paramcount() < 2 then put false into pAllTags else put param(2) into pAllTags end if put exifProcessHeader(pData) into tIFDs if tIFDs < 0 then return tIFDs put 1 into counter repeat for each word tW in tIFDs -- if tW = 0 - continue (allows loeading 0 to avoid negative values clashing with error returns if tW < 0 then -- process a Base JPEG item (e.g. COM) put processMarker(-tW) after allTags end if if tW > 0 then -- IFD - decode it switch counter case 1 put "Image " into tIFDName break case 2 put "Thumbnail " into tIFDName break default put "IFD "& counter into tIFDName end switch put exifDecodeIFD(tW, tIFDName, "ExifTags") into ifdTags put empty into exifTags put empty into intrTags put empty into gpsTags -- EXIF IFD put lineOffset("Exifoffset", ifdTags) into tExifOffset if tExifOffset > 0 then put exifDecodeIFD(item 3 of line tExifOffset of ifdTags, "EXIF ") into exifTags put lineOffset("EXIF SubIFD InteroperabilityOffset", exifTags) into tIntrOffset -- Interoperability IFD contained in EXIF IFD if tIntrOffset > 0 then put exifDecodeIFD(item 3 of line tIntrOffset of exifTags, "EXIF Interoperability ", "IntrTags") into intrTags end if end if -- GPS IFD put lineOffset("GPSInfo", ifdTags) into tGPSOffset if tGPSOffset > 0 then put exifDecodeIFD(item 3 of line tGPSOffset of ifdTags, "GPS ", "GPSTags") into exifTags end if put ifdTags & exifTags & intrTags & gpsTags after allTags end if add 1 to counter end repeat -- and now we have them all if not pAllTags then filter allTags without "*Tag *" filter allTags without "*Undefined*" end if return allTags end exifProcessFile function exifProcessHeader pData -- pData should already contain the entire file (e.g. put URL "binfile:the.jpg" into tData) before calling -- returns a line containing the IFDs (offset within the file relative to lexifBaseOffset) -- returns -1 if pFilePath not a suitable open file (no longer relevant) -- -2 if not recognized as a file that libEXIF can decode -- -3 JFIF and other un-handled data local tHex, tJ, tFirstIFD, tIFDs, i put pData into lexifData put empty into tIFDs -- temp debugging put 1000 into tLimit repeat for each char c in lexifData subtract 1 from tLimit if tLimit <= 0 then exit repeat put binaryDecode("H2", c, tHex) into tJ put tHex & space after debuglexifData end repeat -- end of temp debugging put binaryDecode("H8", lexifData, tHex) into tJ switch case tHex = "49492a00" -- TIFF file in Intel format put "I" into lexifEndian put 1 into lexifBaseOffset break case tHex = "4c4c2a00" -- TIFF file in Motorola format put "M" into lexifEndian put 1 into lexifBaseOffset break case char 1 to 4 of tHex = "ffd8" put 3 into markerOffset repeat for 20 times repeat for 7 times put char markerOffset of lexifData into t put binaryDecode("H2", t, marker) into tJ if marker <> "FF" then exit repeat add 1 to markerOffset end repeat if marker = "FF" then return "" -- too many padding bytes ------ offset_frame = file.tell() add 1 to markerOffset put chartonum(char (markerOffset) of lexifData) into lh put chartonum(char (markerOffset+1) of lexifData) into ll put lh*256 + ll into itemLen ------ data = file.read(itemlen-2) switch marker case the markerCOM of stack "libEXIF" put 0 & space & -(markerOffset-1) & space after tIFDs break case the markerJFIF of stack "libEXIF" break case the markerSOS of stack "libEXIF" # Start of Stream (of pixel data) put 0 into endian return tIFDs case the markerEXIF of stack "libEXIF" if char (markerOffset+2) to (markerOffset+5) of lexifData = "Exif" then put markerOffset+8 into lexifBaseOffset -- 2 length, 4 Exif, 2 ?? put char lexifBaseOffset of lexifData into lexifEndian exit repeat else return tIFDs end switch add itemlen to markerOffset end repeat break default return "-2" end switch put s2n(4,4) into tFirstIFD put tFirstIFD into i repeat while i > 0 put i & space after tIFDs put s2n(i, 2) into tEntries put i+2+12*tEntries into tNext put s2n(tNext, 4) into i end repeat return tIFDs end exifProcessHeader function exifDecodeIFD pIFD, pIFDName if paramcount() < 3 then put customProperties["ExifTags"] of stack me into TagDict else put param(3) into pDict put customProperties[pDict] of stack me into TagDict end if -- put the customProperties["ExifTags"] of stack me into TagDict put empty into tTags put s2n(pIFD, 2) into tEntries put empty into tTag -- to ensure it already exists repeat with i = 1 to tEntries put pIFD+2+12*(i-1) into tEntry put "x" & lexifBaseOffset-1+tEntry & "H4" into t -- put binaryDecode(t, lexifData, tJunk, tTag) into tJ put format("%04x", s2n(tEntry, 2)) into tTag put s2n(tEntry+2, 2) into tFieldType -- figure out tag name put TagDict[tTag] into tTagEntry if tFieldType < 1 or tFieldType > the number of lines in the FieldTypes of stack me then throw "Unknown field type" & tFieldType & " in tag " & tTag end if put the first item of line (tFieldType+1) of the FieldTypes of me into typelen put s2n(tEntry+4, 4) into count put tEntry+8 into tOffset if count*typelen > 4 then -- not the value but a pointer to the value put s2n(tOffset, 4) into tOffset end if put tOffset into tFieldOffset if tFieldType = 2 then -- special case null-terminated ASCII string if count <> 0 then -- read from file lexifFilePath at lexifBaseOffset+tOffset for count put "x" & lexifBaseOffset+tOffset-1 & "a" & count into t put binaryDecode(t, lexifData, tJunk, tValues) into tJ -- ?? replace nulls ?? if offset(numtochar(0), tValues) > 0 then delete char offset(numtochar(0), tValues) to -1 of tValues end if else put "" into tValues end if else put empty into tValues if tFieldType = 6 or tFieldType = 8 or tFieldType = 9 or tFieldType = 10 then put 1 into tSigned else put 0 into tSigned end if put count into numToDo if count > maxLimitOnSizeOfUnknown then put replaceLimitOnSizeOfUnknown into numToDo -- AGT ????? repeat with j = 1 to numToDo if tFieldType = 5 or tFieldType = 10 then put exifRatio(s2n(tOffset, 4, tSigned), s2n(tOffset+4, 4, tSigned)) & space after tValues else put s2n(tOffset, typelen, tSigned) & space after tValues end if add typelen to tOffset end repeat if count > maxLimitOnSizeOfUnknown then put " trunc " & count after tValues -- AGT ????? end if -- strip leading or trailing spaces put word 1 to -1 of tValues into tValues if count = 1 and tFieldType <> 2 then put tValues into tPrintable -- ?? was str() in Python else put tValues into tPrintable end if if tTagEntry <> "" then put the first item of tTagEntry into tTagName if the number of items in tTagEntry > 1 then put 1 into junk if item 2 of tTagEntry = "numToChar" then if tFieldType = 7 then -- not really "Undefined" - it's a length-defined string put 11 into tFieldType end if put empty into tResult repeat for each word W in tValues if W is a number and W <> 0 then put numToChar(W) after tResult end repeat put tResult into tValues put tValues into tPrintable else put item 2 to -1 of tTagEntry into tEnumerated split tEnumerated by comma and ":" put tENumerated[tValues] into tValues put tValues into tPrintable end if end if else put "Tag " & tTag into tTagName end if put pIFDName & COMMA & tTagName & COMMA & tPrintable & COMMA & item 3 of line (tFieldType+1) of the FieldTypes of me & COMMA & tFieldOffset & CR after tTags put tTags into gdebugalltags end repeat return tTags end exifDecodeIFD function exifIFD_Tag pPrintable, pTag, pFieldType, pValues, pFieldOffset, countypelen return item 3 of line (pFieldType+1) of the FieldTypes of me & COMMA && pPrintable & ",@" && pFieldOffset end exifIFD_Tag function processMarker pOffset put char pOffset of lexifData into t put binaryDecode("H2", t, marker) into tJ put chartonum(char (pOffset+1) of lexifData) into lh put chartonum(char (pOffset+2) of lexifData) into ll put lh*256 + ll into itemLen switch marker case the markerCOM of stack "libEXIF" put empty into tComment repeat with a = 1 to itemlen put char (pOffset+2+a) of lexifData into ch if chartonum(ch) = 0 then exit repeat if ch = CR and char (pOffset+2+a) of lexifData = LF then next repeat if chartonum(ch) >= 32 or ch = LF or ch = TAB then put ch after tComment else put "?" after tComment end if end repeat return "JPEG," & tComment & ",String", pOffset default return "" end switch end processMarker function exifRatio a, b put exifGCD(a,b) into tDivisor if tDivisor <> 1 then divide a by tDivisor divide b by tDivisor end if return a & "/" & b end exifRatio function exifGCD a, b if b = 0 then return a else return exifGCD(b, a mod b) end if end exifGCD function s2n poffset, plength, psigned put char (lexifBaseOffset+poffset) to (lexifBaseOffset+poffset+plength-1) of lexifData into tVar if lexifEndian = "I" then put s2n_intel(tVar) into tVal else put s2n_motorola(tVar) into tVal end if return tVal end s2n -- extract multibyte integer in Motorola format (little endian) function s2n_motorola pStr put 0 into x put empty into c1 repeat for each char c in pStr put binaryDecode("C", c, c1) into tJ put (x * 256) bitXor c1 into x end repeat return x end s2n_motorola -- extract multibyte integer in Intel format (big endian) function s2n_intel pStr put 0 into x put 1 into y put empty into c1 repeat for each char c in pStr put binaryDecode("C", c, c1) into tJ put x bitXor (c1*y) into x multiply y by 256 end repeat return x end s2n_intel on exifResetTags -- only needs to be called when new tags are added (or fixed) set the ExifTags["0100"] of stack "libEXIF" to "ImageWidth" set the ExifTags["0101"] of stack "libEXIF" to "ImageLength" set the ExifTags["0102"] of stack "libEXIF" to "BitsPerSample" set the ExifTags["0103"] of stack "libEXIF" to "Compression,1:Uncompressed TIFF,6:JPEG Compressed" set the ExifTags["0106"] of stack "libEXIF" to "PhotometricInterpretation" set the ExifTags["010a"] of stack "libEXIF" to "FillOrder" set the ExifTags["010d"] of stack "libEXIF" to "DocumentName" set the ExifTags["010e"] of stack "libEXIF" to "ImageDescription" set the ExifTags["010f"] of stack "libEXIF" to "Make" set the ExifTags["0110"] of stack "libEXIF" to "Model" set the ExifTags["0111"] of stack "libEXIF" to "StripOffsets" set the ExifTags["0112"] of stack "libEXIF" to "Orientation" set the ExifTags["0115"] of stack "libEXIF" to "SamplesPerPixel" set the ExifTags["0116"] of stack "libEXIF" to "RowsPerStrip" set the ExifTags["0117"] of stack "libEXIF" to "StripByteCounts" set the ExifTags["011a"] of stack "libEXIF" to "XResolution" set the ExifTags["011b"] of stack "libEXIF" to "YResolution" set the ExifTags["011c"] of stack "libEXIF" to "PlanarConfiguration" set the ExifTags["0128"] of stack "libEXIF" to "ResolutionUnit,1:Not Absolute,2:Pixels/Inch,3:Pixels/Centimeter" set the ExifTags["012d"] of stack "libEXIF" to "TransferFunction" set the ExifTags["0131"] of stack "libEXIF" to "Software" set the ExifTags["0132"] of stack "libEXIF" to "DateTime" set the ExifTags["013b"] of stack "libEXIF" to "Artist" set the ExifTags["013e"] of stack "libEXIF" to "WhitePoint" set the ExifTags["013f"] of stack "libEXIF" to "PrimaryChromaticities" set the ExifTags["0156"] of stack "libEXIF" to "TransferRange" set the ExifTags["0200"] of stack "libEXIF" to "JPEGProc" set the ExifTags["0201"] of stack "libEXIF" to "JPEGInterchangeFormat" set the ExifTags["0202"] of stack "libEXIF" to "JPEGInterchangeFormatLength" set the ExifTags["0211"] of stack "libEXIF" to "YCbCrCoefficients" set the ExifTags["0212"] of stack "libEXIF" to "YCbCrSubSampling" set the ExifTags["0213"] of stack "libEXIF" to "YCbCrPositioning" set the ExifTags["0214"] of stack "libEXIF" to "ReferenceBlackWhite" set the ExifTags["828d"] of stack "libEXIF" to "CFARepeatPatternDim" set the ExifTags["828e"] of stack "libEXIF" to "CFAPattern" set the ExifTags["828f"] of stack "libEXIF" to "BatteryLevel" set the ExifTags["8298"] of stack "libEXIF" to "Copyright" set the ExifTags["829a"] of stack "libEXIF" to "ExposureTime" set the ExifTags["829d"] of stack "libEXIF" to "FNumber" set the ExifTags["83bb"] of stack "libEXIF" to "IPTC/NAA" set the ExifTags["8769"] of stack "libEXIF" to "ExifOffset" set the ExifTags["8773"] of stack "libEXIF" to "InterColorProfile" set the ExifTags["8822"] of stack "libEXIF" to "ExposureProgram,0:Unidentified,1:Manual,2:Program Normal,3:Aperture Priority,4:Shutter Priority,5:Program Creative,6:Program Action,7:Portrait Mode,8:Landscape Mode" set the ExifTags["8824"] of stack "libEXIF" to "SpectralSensitivity" set the ExifTags["8825"] of stack "libEXIF" to "GPSInfo" set the ExifTags["8827"] of stack "libEXIF" to "ISOSpeedRatings" set the ExifTags["8828"] of stack "libEXIF" to "OECF" set the ExifTags["9000"] of stack "libEXIF" to "ExifVersion,numToChar" set the ExifTags["9003"] of stack "libEXIF" to "DateTimeOriginal" set the ExifTags["9004"] of stack "libEXIF" to "DateTimeDigitized" set the ExifTags["9101"] of stack "libEXIF" to "ComponentsConfiguration,0:,1:Y,2:Cb,3:Cr,4:Red,5:Green,6:Blue" set the ExifTags["9102"] of stack "libEXIF" to "CompressedBitsPerPixel" set the ExifTags["9201"] of stack "libEXIF" to "ShutterSpeedValue" set the ExifTags["9202"] of stack "libEXIF" to "ApertureValue" set the ExifTags["9203"] of stack "libEXIF" to "BrightnessValue" set the ExifTags["9204"] of stack "libEXIF" to "ExposureBiasValue" set the ExifTags["9205"] of stack "libEXIF" to "MaxApertureValue" set the ExifTags["9206"] of stack "libEXIF" to "SubjectDistance" set the ExifTags["9207"] of stack "libEXIF" to "MeteringMode,0:Unidentified,1:Average,2:CenterWeightedAverage,3:Spot,4:MultiSpot" set the ExifTags["9208"] of stack "libEXIF" to "LightSource,0:Unknown,1:Daylight,2:Fluorescent,3:Tungsten,10:Flash,17:Standard Light A,18:Standard Light B,19:Standard Light C,20:D55,21:D65,22:D75,255:Other" set the ExifTags["9209"] of stack "libEXIF" to "Flash,0:No,1:Fired,5:Fired (?),7:Fired (!),9:Fill Fired,13:Fill Fired (?),15:Fill Fired (!),16:Off,24:Auto Off,25:Auto Fired,29:Auto Fired (?),31:Auto Fired (!),32:Not Available" set the ExifTags["920a"] of stack "libEXIF" to "FocalLength" set the ExifTags["927c"] of stack "libEXIF" to "MakerNote" set the ExifTags["9286"] of stack "libEXIF" to "UserComment,numToChar" set the ExifTags["9290"] of stack "libEXIF" to "SubSecTime" set the ExifTags["9291"] of stack "libEXIF" to "SubSecTimeOriginal" set the ExifTags["9292"] of stack "libEXIF" to "SubSecTimeDigitized" set the ExifTags["a000"] of stack "libEXIF" to "FlashPixVersion,numToChar" set the ExifTags["a001"] of stack "libEXIF" to "ColorSpace" set the ExifTags["a002"] of stack "libEXIF" to "ExifImageWidth" set the ExifTags["a003"] of stack "libEXIF" to "ExifImageLength" set the ExifTags["a005"] of stack "libEXIF" to "InteroperabilityOffset" set the ExifTags["a20b"] of stack "libEXIF" to "FlashEnergy,)" set the ExifTags["a20c"] of stack "libEXIF" to "SpatialFrequencyResponse" set the ExifTags["a20e"] of stack "libEXIF" to "FocalPlaneXResolution" set the ExifTags["a20f"] of stack "libEXIF" to "FocalPlaneYResolution" set the ExifTags["a210"] of stack "libEXIF" to "FocalPlaneResolutionUnit" set the ExifTags["a214"] of stack "libEXIF" to "SubjectLocation" set the ExifTags["a215"] of stack "libEXIF" to "ExposureIndex" set the ExifTags["a217"] of stack "libEXIF" to "SensingMethod" set the ExifTags["a300"] of stack "libEXIF" to "FileSource,3:Digital Camera" set the ExifTags["a301"] of stack "libEXIF" to "SceneType,1:Directly Photographed" set the IntrTags["0001"] of stack "libEXIF" to "InteroperabilityIndex" set the IntrTags["0002"] of stack "libEXIF" to "InteroperabilityVersion" set the IntrTags["1000"] of stack "libEXIF" to "RelatedImageFileFormat" set the IntrTags["1001"] of stack "libEXIF" to "RelatedImageWidth" set the IntrTags["1002"] of stack "libEXIF" to "RelatedImageLength" set the GPSTags["0000"] of stack "libEXIF" to "GPSVersionID" set the GPSTags["0001"] of stack "libEXIF" to "GPSLatitudeRef" set the GPSTags["0002"] of stack "libEXIF" to "GPSLatitude" set the GPSTags["0003"] of stack "libEXIF" to "GPSLongitudeRef" set the GPSTags["0004"] of stack "libEXIF" to "GPSLongitude" set the GPSTags["0005"] of stack "libEXIF" to "GPSAltitudeRef" set the GPSTags["0006"] of stack "libEXIF" to "GPSAltitude" set the GPSTags["0007"] of stack "libEXIF" to "GPSTimeStamp" set the GPSTags["0008"] of stack "libEXIF" to "GPSSatellites" set the GPSTags["0009"] of stack "libEXIF" to "GPSStatus" set the GPSTags["000a"] of stack "libEXIF" to "GPSMeasureMode" set the GPSTags["000b"] of stack "libEXIF" to "GPSDOP" set the GPSTags["000c"] of stack "libEXIF" to "GPSSpeedRef" set the GPSTags["000d"] of stack "libEXIF" to "GPSSpeed" set the GPSTags["000e"] of stack "libEXIF" to "GPSTrackRef" set the GPSTags["000f"] of stack "libEXIF" to "GPSTrack" set the GPSTags["0010"] of stack "libEXIF" to "GPSImgDirectionRef" set the GPSTags["0011"] of stack "libEXIF" to "GPSImgDirection" set the GPSTags["0012"] of stack "libEXIF" to "GPSMapDatum" set the GPSTags["0013"] of stack "libEXIF" to "GPSDestLatitudeRef" set the GPSTags["0014"] of stack "libEXIF" to "GPSDestLatitude" set the GPSTags["0015"] of stack "libEXIF" to "GPSDestLongitudeRef" set the GPSTags["0016"] of stack "libEXIF" to "GPSDestLongitude" set the GPSTags["0017"] of stack "libEXIF" to "GPSDestBearingRef" set the GPSTags["0018"] of stack "libEXIF" to "GPSDestBearing" set the GPSTags["0019"] of stack "libEXIF" to "GPSDestDistanceRef" set the GPSTags["001a"] of stack "libEXIF" to "GPSDestDistance" set the markerCOM of stack "libEXIF" to "FE" set the markerSOS of stack "libEXIF" to "C0" set the markerJFIF of stack "libEXIF" to "E0" set the markerEXIF of stack "libEXIF" to "E1" end exifResetTags FieldTypes 0,X,Proprietary 1,B,Byte 1,A,ASCII 2,S,Short 4,L,Long 8,R,Ratio 1,SB,Signed Byte 1,U,Undefined 2,SS,Signed Short 4,SL,Signed Long 8,SR,Signed Ratio -1,STR,String markerCOM FEmarkerJFIF E0 helpInfo markerEXIF E1 markerSOS C0versionNumber 0.9 U Tahoma U Geneva cREVOnline fingerprint Mbu51XERWZh5GHiMsUpfzA ExifTags R8773 InterColorProfile8298 Copyright9201 ShutterSpeedValue9202 ApertureValue9203 BrightnessValue9204 ExposureBiasValue9205 MaxApertureValue9206 SubjectDistance9207 PMeteringMode,0:Unidentified,1:Average,2:CenterWeightedAverage,3:Spot,4:MultiSpot9208 LightSource,0:Unknown,1:Daylight,2:Fluorescent,3:Tungsten,10:Flash,17:Standard Light A,18:Standard Light B,19:Standard Light C,20:D55,21:D65,22:D75,255:Other9209 Flash,0:No,1:Fired,5:Fired (?),7:Fired (!),9:Fill Fired,13:Fill Fired (?),15:Fill Fired (!),16:Off,24:Auto Off,25:Auto Fired,29:Auto Fired (?),31:Auto Fired (!),32:Not Available0100 ImageWidth0101 ImageLength0102 BitsPerSample0103 1Compression,1:Uncompressed TIFF,6:JPEG Compressed0106 PhotometricInterpretation0110 Model0111 StripOffsets0112 Orientationa20b FlashEnergy,)a20c SpatialFrequencyResponse0115 SamplesPerPixela20e FocalPlaneXResolution0116 RowsPerStripa20f FocalPlaneYResolution0117 StripByteCounts8822 ExposureProgram,0:Unidentified,1:Manual,2:Program Normal,3:Aperture Priority,4:Shutter Priority,5:Program Creative,6:Program Action,7:Portrait Mode,8:Landscape Mode828d CFARepeatPatternDim8824 SpectralSensitivity828e CFAPattern8825 GPSInfo828f BatteryLevel8827 ISOSpeedRatings8828 OECF0128 ?ResolutionUnit,1:Not Absolute,2:Pixels/Inch,3:Pixels/Centimeter829a ExposureTime0131 Software0132 DateTime829d FNumber9101 =ComponentsConfiguration,0:,1:Y,2:Cb,3:Cr,4:Red,5:Green,6:Blue9102 CompressedBitsPerPixel920a FocalLengtha300 FileSource,3:Digital Cameraa301 !SceneType,1:Directly Photographed010a FillOrder0156 TransferRange010d DocumentName010e ImageDescription010f Makea000 FlashPixVersion,numToChara001 ColorSpacea002 ExifImageWidth011a XResolutiona003 ExifImageLength011b YResolution011c PlanarConfigurationa005 InteroperabilityOffset9286 UserComment,numToChar9290 SubSecTime9291 SubSecTimeOriginal9292 SubSecTimeDigitized012d TransferFunction013b Artist013e WhitePoint9000 ExifVersion,numToChar0200 JPEGProc013f PrimaryChromaticities0201 JPEGInterchangeFormat0202 JPEGInterchangeFormatLength9003 DateTimeOriginal9004 DateTimeDigitized0211 YCbCrCoefficients0212 YCbCrSubSampling0213 YCbCrPositioning0214 ReferenceBlackWhite83bb IPTC/NAAa210 FocalPlaneResolutionUnit927c MakerNotea214 SubjectLocationa215 ExposureIndexa217 SensingMethod8769 ExifOffset cREVGeneral scriptChecksum zC?0D% debugObjects 'stack "card id 1002" stack "libURLEXIF"breakPoints handlerList exifProcessFile exifProcessHeader exifDecodeIFD exifIFD_Tag processMarker exifRatio exifGCD s2n s2n_motorola s2n_intel exifResetTagsscriptSelection char 1 to 0 bookmarks prevHandler exifDecodeIFDtempScript script
local lexifEndian -- set to either I for Intel or M for Motorola
local lexifBaseOffset
local lexifData
local maxLimitOnSizeOfUnknown = 200
local replaceLimitOnSizeOfUnknown = 10
function exifProcessFile pData -- pAllTags
-- pData should already contain the entire file (e.g. put URL "binfile:the.jpg" into tData) before calling
-- pAllTags - true if should return all tags, otherwise (default = false) return only known tags
local allTags
if paramcount() < 2 then
put false into pAllTags
else
put param(2) into pAllTags
end if
put exifProcessHeader(pData) into tIFDs
if tIFDs < 0 then return tIFDs
put 1 into counter
repeat for each word tW in tIFDs
-- if tW = 0 - continue (allows loeading 0 to avoid negative values clashing with error returns
if tW < 0 then -- process a Base JPEG item (e.g. COM)
put processMarker(-tW) after allTags
end if
if tW > 0 then -- IFD - decode it
switch counter
case 1
put "Image " into tIFDName
break
case 2
put "Thumbnail " into tIFDName
break
default
put "IFD "& counter into tIFDName
end switch
put exifDecodeIFD(tW, tIFDName, "ExifTags") into ifdTags
put empty into exifTags
put empty into intrTags
put empty into gpsTags
-- EXIF IFD
put lineOffset("Exifoffset", ifdTags) into tExifOffset
if tExifOffset > 0 then
put exifDecodeIFD(item 3 of line tExifOffset of ifdTags, "EXIF ") into exifTags
put lineOffset("EXIF SubIFD InteroperabilityOffset", exifTags) into tIntrOffset
-- Interoperability IFD contained in EXIF IFD
if tIntrOffset > 0 then
put exifDecodeIFD(item 3 of line tIntrOffset of exifTags, "EXIF Interoperability ", "IntrTags") into intrTags
end if
end if
-- GPS IFD
put lineOffset("GPSInfo", ifdTags) into tGPSOffset
if tGPSOffset > 0 then
put exifDecodeIFD(item 3 of line tGPSOffset of ifdTags, "GPS ", "GPSTags") into exifTags
end if
put ifdTags & exifTags & intrTags & gpsTags after allTags
end if
add 1 to counter
end repeat
-- and now we have them all
if not pAllTags then
filter allTags without "*Tag *"
filter allTags without "*Undefined*"
end if
return allTags
end exifProcessFile
function exifProcessHeader pData
-- pData should already contain the entire file (e.g. put URL "binfile:the.jpg" into tData) before calling
-- returns a line containing the IFDs (offset within the file relative to lexifBaseOffset)
-- returns -1 if pFilePath not a suitable open file (no longer relevant)
-- -2 if not recognized as a file that libEXIF can decode
-- -3 JFIF and other un-handled data
local tHex, tJ, tFirstIFD, tIFDs, i
put pData into lexifData
put empty into tIFDs
-- temp debugging
put 1000 into tLimit
repeat for each char c in lexifData
subtract 1 from tLimit
if tLimit <= 0 then exit repeat
put binaryDecode("H2", c, tHex) into tJ
put tHex & space after debuglexifData
end repeat
-- end of temp debugging
put binaryDecode("H8", lexifData, tHex) into tJ
switch
case tHex = "49492a00"
-- TIFF file in Intel format
put "I" into lexifEndian
put 1 into lexifBaseOffset
break
case tHex = "4c4c2a00"
-- TIFF file in Motorola format
put "M" into lexifEndian
put 1 into lexifBaseOffset
break
case char 1 to 4 of tHex = "ffd8"
put 3 into markerOffset
repeat for 20 times
repeat for 7 times
put char markerOffset of lexifData into t
put binaryDecode("H2", t, marker) into tJ
if marker <> "FF" then exit repeat
add 1 to markerOffset
end repeat
if marker = "FF" then return "" -- too many padding bytes
------ offset_frame = file.tell()
add 1 to markerOffset
put chartonum(char (markerOffset) of lexifData) into lh
put chartonum(char (markerOffset+1) of lexifData) into ll
put lh*256 + ll into itemLen
------ data = file.read(itemlen-2)
switch marker
case the markerCOM of stack "libEXIF"
put 0 & space & -(markerOffset-1) & space after tIFDs
break
case the markerJFIF of stack "libEXIF"
break
case the markerSOS of stack "libEXIF" # Start of Stream (of pixel data)
put 0 into endian
return tIFDs
case the markerEXIF of stack "libEXIF"
if char (markerOffset+2) to (markerOffset+5) of lexifData = "Exif" then
put markerOffset+8 into lexifBaseOffset -- 2 length, 4 Exif, 2 ??
put char lexifBaseOffset of lexifData into lexifEndian
exit repeat
else return tIFDs
end switch
add itemlen to markerOffset
end repeat
break
default
return "-2"
end switch
put s2n(4,4) into tFirstIFD
put tFirstIFD into i
repeat while i > 0
put i & space after tIFDs
put s2n(i, 2) into tEntries
put i+2+12*tEntries into tNext
put s2n(tNext, 4) into i
end repeat
return tIFDs
end exifProcessHeader
function exifDecodeIFD pIFD, pIFDName
if paramcount() < 3 then
put customProperties["ExifTags"] of stack me into TagDict
else
put param(3) into pDict
put customProperties[pDict] of stack me into TagDict
end if
-- put the customProperties["ExifTags"] of stack me into TagDict
put empty into tTags
put s2n(pIFD, 2) into tEntries
put empty into tTag -- to ensure it already exists
repeat with i = 1 to tEntries
put pIFD+2+12*(i-1) into tEntry
put "x" & lexifBaseOffset-1+tEntry & "H4" into t
-- put binaryDecode(t, lexifData, tJunk, tTag) into tJ
put format("%04x", s2n(tEntry, 2)) into tTag
put s2n(tEntry+2, 2) into tFieldType
-- figure out tag name
put TagDict[tTag] into tTagEntry
if tFieldType < 1 or tFieldType > the number of lines in the FieldTypes of stack me then
throw "Unknown field type" & tFieldType & " in tag " & tTag
end if
put the first item of line (tFieldType+1) of the FieldTypes of me into typelen
put s2n(tEntry+4, 4) into count
put tEntry+8 into tOffset
if count*typelen > 4 then
-- not the value but a pointer to the value
put s2n(tOffset, 4) into tOffset
end if
put tOffset into tFieldOffset
if tFieldType = 2 then
-- special case null-terminated ASCII string
if count <> 0 then
-- read from file lexifFilePath at lexifBaseOffset+tOffset for count
put "x" & lexifBaseOffset+tOffset-1 & "a" & count into t
put binaryDecode(t, lexifData, tJunk, tValues) into tJ
-- ?? replace nulls ??
if offset(numtochar(0), tValues) > 0 then
delete char offset(numtochar(0), tValues) to -1 of tValues
end if
else
put "" into tValues
end if
else
put empty into tValues
if tFieldType = 6 or tFieldType = 8 or tFieldType = 9 or tFieldType = 10 then
put 1 into tSigned
else
put 0 into tSigned
end if
put count into numToDo
if count > maxLimitOnSizeOfUnknown then put replaceLimitOnSizeOfUnknown into numToDo -- AGT ?????
repeat with j = 1 to numToDo
if tFieldType = 5 or tFieldType = 10 then
put exifRatio(s2n(tOffset, 4, tSigned), s2n(tOffset+4, 4, tSigned)) & space after tValues
else
put s2n(tOffset, typelen, tSigned) & space after tValues
end if
add typelen to tOffset
end repeat
if count > maxLimitOnSizeOfUnknown then put " trunc " & count after tValues -- AGT ?????
end if
-- strip leading or trailing spaces
put word 1 to -1 of tValues into tValues
if count = 1 and tFieldType <> 2 then
put tValues into tPrintable -- ?? was str() in Python
else
put tValues into tPrintable
end if
if tTagEntry <> "" then
put the first item of tTagEntry into tTagName
if the number of items in tTagEntry > 1 then
put 1 into junk
if item 2 of tTagEntry = "numToChar" then
if tFieldType = 7 then
-- not really "Undefined" - it's a length-defined string
put 11 into tFieldType
end if
put empty into tResult
repeat for each word W in tValues
if W is a number and W <> 0 then put numToChar(W) after tResult
end repeat
put tResult into tValues
put tValues into tPrintable
else
put item 2 to -1 of tTagEntry into tEnumerated
split tEnumerated by comma and ":"
put tENumerated[tValues] into tValues
put tValues into tPrintable
end if
end if
else
put "Tag " & tTag into tTagName
end if
put pIFDName & COMMA & tTagName & COMMA & tPrintable & COMMA & item 3 of line (tFieldType+1) of the FieldTypes of me & COMMA & tFieldOffset & CR after tTags
put tTags into gdebugalltags
end repeat
return tTags
end exifDecodeIFD
function exifIFD_Tag pPrintable, pTag, pFieldType, pValues, pFieldOffset, countypelen
return item 3 of line (pFieldType+1) of the FieldTypes of me & COMMA && pPrintable & ",@" && pFieldOffset
end exifIFD_Tag
function processMarker pOffset
put char pOffset of lexifData into t
put binaryDecode("H2", t, marker) into tJ
put chartonum(char (pOffset+1) of lexifData) into lh
put chartonum(char (pOffset+2) of lexifData) into ll
put lh*256 + ll into itemLen
switch marker
case the markerCOM of stack "libEXIF"
put empty into tComment
repeat with a = 1 to itemlen
put char (pOffset+2+a) of lexifData into ch
if chartonum(ch) = 0 then exit repeat
if ch = CR and char (pOffset+2+a) of lexifData = LF then next repeat
if chartonum(ch) >= 32 or ch = LF or ch = TAB then
put ch after tComment
else
put "?" after tComment
end if
end repeat
return "JPEG," & tComment & ",String", pOffset
default
return ""
end switch
end processMarker
function exifRatio a, b
put exifGCD(a,b) into tDivisor
if tDivisor <> 1 then
divide a by tDivisor
divide b by tDivisor
end if
return a & "/" & b
end exifRatio
function exifGCD a, b
if b = 0 then
return a
else
return exifGCD(b, a mod b)
end if
end exifGCD
function s2n poffset, plength, psigned
put char (lexifBaseOffset+poffset) to (lexifBaseOffset+poffset+plength-1) of lexifData into tVar
if lexifEndian = "I" then
put s2n_intel(tVar) into tVal
else
put s2n_motorola(tVar) into tVal
end if
return tVal
end s2n
-- extract multibyte integer in Motorola format (little endian)
function s2n_motorola pStr
put 0 into x
put empty into c1
repeat for each char c in pStr
put binaryDecode("C", c, c1) into tJ
put (x * 256) bitXor c1 into x
end repeat
return x
end s2n_motorola
-- extract multibyte integer in Intel format (big endian)
function s2n_intel pStr
put 0 into x
put 1 into y
put empty into c1
repeat for each char c in pStr
put binaryDecode("C", c, c1) into tJ
put x bitXor (c1*y) into x
multiply y by 256
end repeat
return x
end s2n_intel
on exifResetTags
-- only needs to be called when new tags are added (or fixed)
set the ExifTags["0100"] of stack "libEXIF" to "ImageWidth"
set the ExifTags["0101"] of stack "libEXIF" to "ImageLength"
set the ExifTags["0102"] of stack "libEXIF" to "BitsPerSample"
set the ExifTags["0103"] of stack "libEXIF" to "Compression,1:Uncompressed TIFF,6:JPEG Compressed"
set the ExifTags["0106"] of stack "libEXIF" to "PhotometricInterpretation"
set the ExifTags["010a"] of stack "libEXIF" to "FillOrder"
set the ExifTags["010d"] of stack "libEXIF" to "DocumentName"
set the ExifTags["010e"] of stack "libEXIF" to "ImageDescription"
set the ExifTags["010f"] of stack "libEXIF" to "Make"
set the ExifTags["0110"] of stack "libEXIF" to "Model"
set the ExifTags["0111"] of stack "libEXIF" to "StripOffsets"
set the ExifTags["0112"] of stack "libEXIF" to "Orientation"
set the ExifTags["0115"] of stack "libEXIF" to "SamplesPerPixel"
set the ExifTags["0116"] of stack "libEXIF" to "RowsPerStrip"
set the ExifTags["0117"] of stack "libEXIF" to "StripByteCounts"
set the ExifTags["011a"] of stack "libEXIF" to "XResolution"
set the ExifTags["011b"] of stack "libEXIF" to "YResolution"
set the ExifTags["011c"] of stack "libEXIF" to "PlanarConfiguration"
set the ExifTags["0128"] of stack "libEXIF" to "ResolutionUnit,1:Not Absolute,2:Pixels/Inch,3:Pixels/Centimeter"
set the ExifTags["012d"] of stack "libEXIF" to "TransferFunction"
set the ExifTags["0131"] of stack "libEXIF" to "Software"
set the ExifTags["0132"] of stack "libEXIF" to "DateTime"
set the ExifTags["013b"] of stack "libEXIF" to "Artist"
set the ExifTags["013e"] of stack "libEXIF" to "WhitePoint"
set the ExifTags["013f"] of stack "libEXIF" to "PrimaryChromaticities"
set the ExifTags["0156"] of stack "libEXIF" to "TransferRange"
set the ExifTags["0200"] of stack "libEXIF" to "JPEGProc"
set the ExifTags["0201"] of stack "libEXIF" to "JPEGInterchangeFormat"
set the ExifTags["0202"] of stack "libEXIF" to "JPEGInterchangeFormatLength"
set the ExifTags["0211"] of stack "libEXIF" to "YCbCrCoefficients"
set the ExifTags["0212"] of stack "libEXIF" to "YCbCrSubSampling"
set the ExifTags["0213"] of stack "libEXIF" to "YCbCrPositioning"
set the ExifTags["0214"] of stack "libEXIF" to "ReferenceBlackWhite"
set the ExifTags["828d"] of stack "libEXIF" to "CFARepeatPatternDim"
set the ExifTags["828e"] of stack "libEXIF" to "CFAPattern"
set the ExifTags["828f"] of stack "libEXIF" to "BatteryLevel"
set the ExifTags["8298"] of stack "libEXIF" to "Copyright"
set the ExifTags["829a"] of stack "libEXIF" to "ExposureTime"
set the ExifTags["829d"] of stack "libEXIF" to "FNumber"
set the ExifTags["83bb"] of stack "libEXIF" to "IPTC/NAA"
set the ExifTags["8769"] of stack "libEXIF" to "ExifOffset"
set the ExifTags["8773"] of stack "libEXIF" to "InterColorProfile"
set the ExifTags["8822"] of stack "libEXIF" to "ExposureProgram,0:Unidentified,1:Manual,2:Program Normal,3:Aperture Priority,4:Shutter Priority,5:Program Creative,6:Program Action,7:Portrait Mode,8:Landscape Mode"
set the ExifTags["8824"] of stack "libEXIF" to "SpectralSensitivity"
set the ExifTags["8825"] of stack "libEXIF" to "GPSInfo"
set the ExifTags["8827"] of stack "libEXIF" to "ISOSpeedRatings"
set the ExifTags["8828"] of stack "libEXIF" to "OECF"
set the ExifTags["9000"] of stack "libEXIF" to "ExifVersion,numToChar"
set the ExifTags["9003"] of stack "libEXIF" to "DateTimeOriginal"
set the ExifTags["9004"] of stack "libEXIF" to "DateTimeDigitized"
set the ExifTags["9101"] of stack "libEXIF" to "ComponentsConfiguration,0:,1:Y,2:Cb,3:Cr,4:Red,5:Green,6:Blue"
set the ExifTags["9102"] of stack "libEXIF" to "CompressedBitsPerPixel"
set the ExifTags["9201"] of stack "libEXIF" to "ShutterSpeedValue"
set the ExifTags["9202"] of stack "libEXIF" to "ApertureValue"
set the ExifTags["9203"] of stack "libEXIF" to "BrightnessValue"
set the ExifTags["9204"] of stack "libEXIF" to "ExposureBiasValue"
set the ExifTags["9205"] of stack "libEXIF" to "MaxApertureValue"
set the ExifTags["9206"] of stack "libEXIF" to "SubjectDistance"
set the ExifTags["9207"] of stack "libEXIF" to "MeteringMode,0:Unidentified,1:Average,2:CenterWeightedAverage,3:Spot,4:MultiSpot"
set the ExifTags["9208"] of stack "libEXIF" to "LightSource,0:Unknown,1:Daylight,2:Fluorescent,3:Tungsten,10:Flash,17:Standard Light A,18:Standard Light B,19:Standard Light C,20:D55,21:D65,22:D75,255:Other"
set the ExifTags["9209"] of stack "libEXIF" to "Flash,0:No,1:Fired,5:Fired (?),7:Fired (!),9:Fill Fired,13:Fill Fired (?),15:Fill Fired (!),16:Off,24:Auto Off,25:Auto Fired,29:Auto Fired (?),31:Auto Fired (!),32:Not Available"
set the ExifTags["920a"] of stack "libEXIF" to "FocalLength"
set the ExifTags["927c"] of stack "libEXIF" to "MakerNote"
set the ExifTags["9286"] of stack "libEXIF" to "UserComment,numToChar"
set the ExifTags["9290"] of stack "libEXIF" to "SubSecTime"
set the ExifTags["9291"] of stack "libEXIF" to "SubSecTimeOriginal"
set the ExifTags["9292"] of stack "libEXIF" to "SubSecTimeDigitized"
set the ExifTags["a000"] of stack "libEXIF" to "FlashPixVersion,numToChar"
set the ExifTags["a001"] of stack "libEXIF" to "ColorSpace"
set the ExifTags["a002"] of stack "libEXIF" to "ExifImageWidth"
set the ExifTags["a003"] of stack "libEXIF" to "ExifImageLength"
set the ExifTags["a005"] of stack "libEXIF" to "InteroperabilityOffset"
set the ExifTags["a20b"] of stack "libEXIF" to "FlashEnergy,)"
set the ExifTags["a20c"] of stack "libEXIF" to "SpatialFrequencyResponse"
set the ExifTags["a20e"] of stack "libEXIF" to "FocalPlaneXResolution"
set the ExifTags["a20f"] of stack "libEXIF" to "FocalPlaneYResolution"
set the ExifTags["a210"] of stack "libEXIF" to "FocalPlaneResolutionUnit"
set the ExifTags["a214"] of stack "libEXIF" to "SubjectLocation"
set the ExifTags["a215"] of stack "libEXIF" to "ExposureIndex"
set the ExifTags["a217"] of stack "libEXIF" to "SensingMethod"
set the ExifTags["a300"] of stack "libEXIF" to "FileSource,3:Digital Camera"
set the ExifTags["a301"] of stack "libEXIF" to "SceneType,1:Directly Photographed"
set the IntrTags["0001"] of stack "libEXIF" to "InteroperabilityIndex"
set the IntrTags["0002"] of stack "libEXIF" to "InteroperabilityVersion"
set the IntrTags["1000"] of stack "libEXIF" to "RelatedImageFileFormat"
set the IntrTags["1001"] of stack "libEXIF" to "RelatedImageWidth"
set the IntrTags["1002"] of stack "libEXIF" to "RelatedImageLength"
set the GPSTags["0000"] of stack "libEXIF" to "GPSVersionID"
set the GPSTags["0001"] of stack "libEXIF" to "GPSLatitudeRef"
set the GPSTags["0002"] of stack "libEXIF" to "GPSLatitude"
set the GPSTags["0003"] of stack "libEXIF" to "GPSLongitudeRef"
set the GPSTags["0004"] of stack "libEXIF" to "GPSLongitude"
set the GPSTags["0005"] of stack "libEXIF" to "GPSAltitudeRef"
set the GPSTags["0006"] of stack "libEXIF" to "GPSAltitude"
set the GPSTags["0007"] of stack "libEXIF" to "GPSTimeStamp"
set the GPSTags["0008"] of stack "libEXIF" to "GPSSatellites"
set the GPSTags["0009"] of stack "libEXIF" to "GPSStatus"
set the GPSTags["000a"] of stack "libEXIF" to "GPSMeasureMode"
set the GPSTags["000b"] of stack "libEXIF" to "GPSDOP"
set the GPSTags["000c"] of stack "libEXIF" to "GPSSpeedRef"
set the GPSTags["000d"] of stack "libEXIF" to "GPSSpeed"
set the GPSTags["000e"] of stack "libEXIF" to "GPSTrackRef"
set the GPSTags["000f"] of stack "libEXIF" to "GPSTrack"
set the GPSTags["0010"] of stack "libEXIF" to "GPSImgDirectionRef"
set the GPSTags["0011"] of stack "libEXIF" to "GPSImgDirection"
set the GPSTags["0012"] of stack "libEXIF" to "GPSMapDatum"
set the GPSTags["0013"] of stack "libEXIF" to "GPSDestLatitudeRef"
set the GPSTags["0014"] of stack "libEXIF" to "GPSDestLatitude"
set the GPSTags["0015"] of stack "libEXIF" to "GPSDestLongitudeRef"
set the GPSTags["0016"] of stack "libEXIF" to "GPSDestLongitude"
set the GPSTags["0017"] of stack "libEXIF" to "GPSDestBearingRef"
set the GPSTags["0018"] of stack "libEXIF" to "GPSDestBearing"
set the GPSTags["0019"] of stack "libEXIF" to "GPSDestDistanceRef"
set the GPSTags["001a"] of stack "libEXIF" to "GPSDestDistance"
set the markerCOM of stack "libEXIF" to "FE"
set the markerSOS of stack "libEXIF" to "C0"
set the markerJFIF of stack "libEXIF" to "E0"
set the markerEXIF of stack "libEXIF" to "E1"
end exifResetTags
GPSTags 6'0011' GPSImgDirection', 0000 GPSVersionID'0003' GPSLongitudeRef', 0001 GPSLatitudeRef0002 GPSLatitude'000E' GPSTrackRef', 0003 GPSLongitudeRef0004 GPSLongitude0005 GPSAltitudeRef0006 GPSAltitude0007 GPSTimeStamp0008 GPSSatellites'0019' GPSDestDistanceRef', 0010 GPSImgDirectionRef0009 GPSStatus'0012' GPSMapDatum', 0011 GPSImgDirection'0004' GPSLongitude', 0012 GPSMapDatum0013 GPSDestLatitudeRef'000F' GPSTrack', 0014 GPSDestLatitude0015 GPSDestLongitudeRef0016 GPSDestLongitude0017 GPSDestBearingRef0018 GPSDestBearing0019 GPSDestDistanceRef'0013' GPSDestLatitudeRef', '0005' GPSAltitudeRef', '0014' GPSDestLatitude', '0006' GPSAltitude', '000A' GPSMeasureMode', '0015' GPSDestLongitudeRef', '0007' GPSTimeStamp', '0000' GPSVersionID', '000B' GPSDOP', '0016' GPSDestLongitude', '0008' GPSSatellites', '0001' GPSLatitudeRef', '001A' GPSDestDistance', 000a GPSMeasureMode'000C' GPSSpeedRef', 000b GPSDOP000c GPSSpeedRef000d GPSSpeed000e GPSTrackRef000f GPSTrack'0017' GPSDestBearingRef', '0010' GPSImgDirectionRef', '0009' GPSStatus', '0002' GPSLatitude', 001a GPSDestDistance'000D' GPSSpeed', '0018' GPSDestBearing', IntrTags '1001' RelatedImageWidth', 0001 InteroperabilityIndex0002 InteroperabilityVersion'1000' RelatedImageFileFormat', '0002' InteroperabilityVersion', '1002' RelatedImageLength', 1000 RelatedImageFileFormat1001 RelatedImageWidth1002 RelatedImageLength'0001' InteroperabilityIndex', card id 1002 @ cREVGeneral bookmarks handlerList tempScript prevHandler scriptSelection char 1 to 0script Info & Help Ep on mouseUp put the versionNumber of this stack into tVersion put the helpInfo of this stack into tHelp put "libEXIF Version " & tVersion & CR before tHelp set the htmlText of field "Field" to tHelp end mouseUp 6 R cREVGeneral scriptChecksum MBuL1Zk~>breakPoints handlerList mouseUpscriptSelection char 183 to 182 bookmarks revUniqueID 1101057048248prevHandler mouseUptempScript script aon mouseUp
put the versionNumber of this stack into tVersion
put the helpInfo of this stack into tHelp
put "libEXIF Version " & tVersion & CR before tHelp
set the htmlText of field "Field" to tHelp
end mouseUp
Test EpCon mouseUp set the cursor to watch put empty into field "Field" answer file "Input file:" titled "Test file input" -- with filter "TIFFs,*.tif" if it is empty then exit mouseUp put it into tN put the millisecs into tStartTime -- open file tN for binary read put URL ("binfile:" & tN) into theData put exifProcessFile(theData, true) into allTags put "took " & the millisecs - tStartTime & cr after field "Field" -- and now we have them all -- note - we sepcified we want all Tags - including undefined ones - so we must not -- simply print them all out repeat for each line K in allTags if K contains "Tag " or K contains "Undefined" then put "Skipping " & item 1 to 2 of K & cr after field "Field" else put K & cr after field "Field" end if end repeat end mouseUp $ R cREVGeneral scriptChecksum 5;%ޒIbreakPoints handlerList mouseUpscriptSelection char 831 to 830 bookmarks revUniqueID 1101069744540prevHandler mouseUptempScript scripton mouseUp
set the cursor to watch
put empty into field "Field"
answer file "Input file:" titled "Test file input" -- with filter "TIFFs,*.tif"
if it is empty then exit mouseUp
put it into tN
put the millisecs into tStartTime
-- open file tN for binary read
put URL ("binfile:" & tN) into theData
put exifProcessFile(theData, true) into allTags
put "took " & the millisecs - tStartTime & cr after field "Field"
-- and now we have them all
-- note - we sepcified we want all Tags - including undefined ones - so we must not
-- simply print them all out
repeat for each line K in allTags
if K contains "Tag " or K contains "Undefined" then
put "Skipping " & item 1 to 2 of K & cr after field "Field"
else
put K & cr after field "Field"
end if
end repeat
end mouseUp
Field )` B<