Read/Write Exif dates
Posted: Tue Jun 14, 2005 3:04 am
This is in response to a request from GeoTrail in another thread.
@GeoTrail: Try this code and see if it returns the Exif dates form both your cameras. If it does, then I will add a procedure for changing the dates.
@GeoTrail: Try this code and see if it returns the Exif dates form both your cameras. If it does, then I will add a procedure for changing the dates.

Code: Select all
UseJPEGImageDecoder()
#Exif_DT_Modified = $132 ; 306
#Exif_Sub = $8769 ; 34665
#Exif_DT_Taken = $9003 ; 36867
#Exif_DT_Digitized = $9004 ; 36868
#Header = 12
#ModifiedDate = 0
#TakenDate = 1
#DigitizedDate = 2
Global date_time
Dim exifDate$(2)
Procedure.s GetExifDateTime(jpg$, writeIt, newDateTime$)
OpenFile(0, jpg$)
; --> Byte 0 of EXIF begins after JPEG header
FileSeek(#Header)
; --> Bytes 0-1 is byte order 18761 ($4949) is Intel and 19789 ($4D4D) is Motorola
byteOrder = ReadWord()
If byteOrder = $4949
; --> Bytes 2-3 is TIFF format, it's always 42 ($2A). If not, give up.
tifFormat = ReadWord()
If tifFormat = $2A
; --> Bytes 4-7 is starting offset for IFD (Image File Directory)
ifd1 = ReadLong()
; --> Move to start of IFD
FileSeek(ifd1 + #Header)
; --> First 2 bytes of IFD is number of field entries
nFields = ReadWord()
; --> Loop through all fields to find Date/Time stamp
date_time = #False
For i = 1 To nFields
; --> Bytes 0-1 contain the Tag for the field.
currentTag = ReadWord() &$FFFF
Select currentTag
Case #Exif_DT_Modified
; --> Bytes 2-3 contain the field Type.
; --> We know this will be 2 (ASCII) For Date/Time
fieldType = ReadWord()
; --> Bytes 4-7 contain the Length of the field.
fieldLength = ReadLong()
currentloc = Loc()
; --> Bytes 8-11 contain a pointer to ASCII Date/Time
fieldValue = ReadLong()
; --> Move to that pointer
FileSeek(fieldValue + #Header)
; --> This is the start point of Dat/Time ASCII string
If writeIt And newDateTime$
WriteString(newDateTime$)
date_time$ = newDateTime$
MessageRequester("Info", "Date and Time have been changed.")
Else
exifDate$(#ModifiedDate) = ReadString()
allDate$ = "Modified:" + #TAB$ + exifDate$(#ModifiedDate)
FileSeek(currentloc+4)
EndIf
Case #Exif_Sub
FileSeek(Loc() + 6)
ExifLoc = ReadLong()
FileSeek(ExifLoc + #Header + 2)
Repeat
tag = ReadWord() &$FFFF
If tag = #Exif_DT_Taken
currLoc = Loc()
FileSeek(Loc() + 6)
datLoc = ReadLong()
FileSeek(datLoc + #Header)
exifDate$(#TakenDate) = ReadString()
allDate$ + #CRLF$ + "Taken:" + #TAB$ + exifDate$(#TakenDate)
FileSeek(currLoc + 10)
EndIf
If tag = #Exif_DT_Digitized
currLoc = Loc()
FileSeek(Loc() + 6)
datLoc = ReadLong()
FileSeek(datLoc + #Header)
exifDate$(#DigitizedDate) = ReadString()
allDate$ + #CRLF$ + "Digitized:" + #TAB$ + exifDate$(#DigitizedDate)
FileSeek(currLoc + 10)
EndIf
If tag <> #Exif_DT_Taken And tag <> #Exif_DT_Digitized
FileSeek(Loc() + 10)
EndIf
Until tag = 0
Default
; --> Move to next field. Each field is 12 bytes.
; --> currentTag (2 bytes) is current Loc() so we add 10
FileSeek(Loc()+10)
EndSelect
Next i
Else
MessageRequester("Error", "Invalid file format!")
EndIf
Else
MessageRequester("Sorry", "Invalid file format!")
EndIf
CloseFile(0)
ProcedureReturn allDate$
EndProcedure
If OpenWindow(0, 10, 10, 300, 200, #PB_Window_SystemMenu, "Exif Date/Time") And CreateGadgetList(WindowID())
ButtonGadget(0, 10, 10, 280, 20, "Open JPG for Exif info")
Repeat
event = WaitWindowEvent()
If event = #PB_EventGadget
Select EventGadgetID()
Case 0
fileOpen$ = (OpenFileRequester("Select JPEG", "C:\Documents and Settings\Owner\My Documents\My Pictures\", "JPG files (JPG)|*.jpg;*.jpeg", 0))
If fileOpen$
dt$ = GetExifDateTime(fileOpen$, 0, "")
MessageRequester("Exif Info", dt$)
EndIf
EndSelect
EndIf
Until event = #PB_Event_CloseWindow
EndIf
End