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