Page 1 of 2
tiny userlib: Exif date/time information (UTC)
Posted: Fri Feb 11, 2005 10:37 pm
by sverson
Hi!
This is a tiny "one command userlib" to get Exif date/time information (UTC) of jpeg images:
ExifDate()
Download:
ExifDate.zip
ExifDate -> PureLibraries/UserLibraries
ExifDate.chm -> Help
Have fun - and please tell me if you like it.

sverson
Bugfix: tiny userlib: Exif date/time information (UTC)
Posted: Sat Feb 19, 2005 7:05 am
by sverson
BUGFIX
Download v1.1:
ExifDateV11.zip
- ExifDate -> PureLibraries/UserLibraries
ExifDate.chm -> Help

sverson
Posted: Sat Jun 04, 2005 1:28 pm
by GeoTrail
Does anyone know how to write Exif info to a jpg file?
Posted: Sat Jun 04, 2005 4:46 pm
by Bonne_den_kule
Here is a reference to the meta data (exif) in jpg pictures :
http://www.kodak.com/global/plugins/acr ... ndard2.pdf
Posted: Sat Jun 04, 2005 10:01 pm
by GeoTrail
Thanks for the link Bonne, but I didn't help me much.
Reference to the format is one thing, but being able to write the tags into an image without corrupting it is one thing

Posted: Sat Jun 04, 2005 10:13 pm
by Bonne_den_kule
GeoTrail wrote:Thanks for the link Bonne, but I didn't help me much.
Reference to the format is one thing, but being able to write the tags into an image without corrupting it is one thing

To change the tag you need to rebuild the image, since the header (meta-data) has a varibale size
Posted: Sat Jun 04, 2005 11:14 pm
by PB
> To change the tag you need to rebuild the image
Maybe not -- if the tag can be read at offsets, then perhaps (haven't tried) it
can be changed by writing new bytes to the image file... I'll have a look later.
Posted: Sun Jun 05, 2005 1:57 am
by GeoTrail
Kewl, thanks

Posted: Sun Jun 05, 2005 6:49 am
by PB
Okay, I had a look, but I'm no expert on digital photos.
This information might
apply only to my digital camera (Pentax Optio S). When I load a photo into a
hex editor, there are 3 areas that the time/date are visible, and they are all
in the string format of :
YYYY:MM:DD HH:MM:SS (24-hour time is used).
The three offsets in the file are at bytes 228, 694 and 714. So, for my photos,
I can change the stored date using this code (try it at your own risk, and use
backups of your photos!):
Code: Select all
; Modify Exif Date example by PB. Feel free to use in any way. :)
; Works fine with photos taken with a Pentax Optio S digital camera.
; May work with photos by other cameras, but no guarantee is given!
;
; *** Any use of this procedure is entirely at your own risk! ***
Procedure ModifyExifDate(file$,ye,mo,da,ho,mi,se)
If OpenFile(0,file$)=0
ProcedureReturn 0 ; Couldn't open file, or it doesn't exist.
Else
a$=FormatDate("%yyyy:%mm:%dd %hh:%ii:%ss",Date(ye,mo,da,ho,mi,se)) ; Prepare new date to write.
; Next line writes new date into the 3 date offsets in the photo's Exif Data (228, 694 and 714).
FileSeek(228) : WriteString(a$) : FileSeek(694) : WriteString(a$) : FileSeek(714) : WriteString(a$)
CloseFile(0) : ProcedureReturn 1 ; Successful! :)
EndIf
EndProcedure
Debug ModifyExifDate("C:\IMGP0695.JPG",2005,12,25,0,0,0) ; Modify date to Christmas Day for this example.
Posted: Sun Jun 05, 2005 5:47 pm
by GeoTrail
Thanks for trying to help PB.
I tried that procedure with pictures I took with my S700i and PowerShot A60, but when I checked the file afterwards the time and date field was gone.
But when I check the files with a hex editor I can see that it is written.
Here I've taken screenshots of the hex source of the images.
This image is the one that I modified the date in using the procedure.
and this image is the unmodified image:

Posted: Wed Jun 08, 2005 1:53 pm
by Sparkie
@GeoTrail: Try this one.
Please make sure you work with a copy of the original image. This works with my Canon A75 but no guarantee it will work for you.
Code: Select all
UseJPEGImageDecoder()
#Exif_DateTime = 306
#Header = 12
Global date_time
Procedure.s GetExifDateTime(jpg$, writeIt, newDateTime$)
OpenFile(0, jpg$)
; --> Byte 0 of EXIF begins after JPEG header
FileSeek(#Header)
; --> Bytes 0-1 is word order 18761 ($4949) is Intel and 19789 ($4D4D) is Motorola
wordOrder = ReadWord()
If wordOrder = $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()
If currentTag = #Exif_DateTime
; --> 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
date_time$ = ReadString()
EndIf
date_time = #True
Break
Else
; --> Move to next field. Each field is 12 bytes.
; --> currentTag (2 bytes) is current Loc() so we add 10
FileSeek(Loc()+10)
EndIf
Next
If date_time <> #True
MessageRequester("Sorry", "Date Time field was not found.")
EndIf
Else
MessageRequester("Error", "Invalid file format!")
EndIf
Else
MessageRequester("Sorry", "Invalid file format!")
EndIf
CloseFile(0)
ProcedureReturn date_time$
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")
TextGadget(1, 10, 40, 280, 60, "", #PB_Text_Center)
TextGadget(2, 10, 80, 280, 20, "", #PB_Text_Center)
ButtonGadget(3, 10, 110, 280, 20, "Change Date")
DisableGadget(3, 1)
DateGadget(4, 10, 140, 280, 20, "%yyyy:%mm:%dd %hh:%ii")
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, "")
If date_time
SetGadgetText(1, fileOpen$)
SetGadgetText(2, "Original Date/Time is " + dt$)
DisableGadget(3, 0)
EndIf
EndIf
Case 3
; --> DateGadget has no support for seconds so add your own below
newDT$ = GetGadgetText(4) + ":00"
dt$ = GetExifDateTime(fileOpen$, 1, newDT$)
EndSelect
EndIf
Until event = #PB_Event_CloseWindow
EndIf
End
Posted: Wed Jun 08, 2005 3:35 pm
by GeoTrail
Nope, didn't work
Appriciate your efforts Sparkie

After I tried changing the date and checked the image file, the date was gone, along with all the other camera info like ISO format, flash etc.
Posted: Wed Jun 08, 2005 4:07 pm
by Sparkie
I'm at work right now, but when I get home I'll see what else we can try.
I looked at your hex code ^up there^ and it looks very similar to my A75 jpg output.

Posted: Thu Jun 09, 2005 2:42 am
by Sparkie
Doh! We were working with the wrong timestamp. That's the one that specifies the timestamp of last file modification. I asume you are looking for the timestamp of when the pic was taken/digitized.
I'll have to do some reading to figure this one out.

Posted: Thu Jun 09, 2005 2:17 pm
by Sparkie
@GeoTrail: I'm almost done with Exif date change, but before proceeding I'd like to see what results you get with the code below. Since you're using a Canon A60, this should show 3 timestamps:
Date last modified
Date picture was taken
Date picture was digitized
This is just a modified section of the code I have so far. If it doesn't work, don't worry. It just means the your A60 and my A75 do things a little differently and I'll have to adjust the code a little.
Code: Select all
UseJPEGImageDecoder()
jpg$ = OpenFileRequester("Select JPEG", "C:\Documents and Settings\Owner\My Documents\My Pictures\", "JPG files (JPG)|*.jpg;*.jpeg", 0)
If jpg$
OpenFile(0, jpg$)
FileSeek(188)
dateInfo$ = "Modified: " + Chr(9)
dateInfo$ + ReadString() + #CRLF$
FileSeek(586)
dateInfo$ + "Taken: " + Chr(9)
dateInfo$ + ReadString() + #CRLF$
FileSeek(606)
dateInfo$ + "Digitized: " + Chr(9)
dateInfo$ + ReadString()
CloseFile(0)
MessageRequester("Exif Date Info", dateInfo$)
EndIf
End