Here is my attempt to make UDF for retrieving EXIF info from JPEG's in "right way". Not sure it will work with edited images, and currently it don't work with EXIF's have straight byte order (for ex. all Casio cameras). But it work fine with all images I have from other cameras (7 different models). If you know how you are welcome to add other parameters (Shutter Speed, Aperture etc.) Example: $file = FileOpenDialog("Please select file", "", "JPEG files (*.jpg;*.jpeg)"); if @error then Exit $aExif = _GetEXIFData($file) if @error then Exit $aLabel = StringSplit("Date/Time: |Vendor: |Model: |Descr: |Copyright: |Orientation: |Width: |Height: _ |Original Date: |Digitized Date: |Comments: ", "|") Dim $out = "" for $i = 0 to UBound($aExif)-1 $out = $out & $aLabel[$i+1] & $aExif[$i] & @CR next MsgBox (0, "EXIF Data", $out) UDF: ;=============================================================================== ; ; Description: Reads EXIF info ; Parameter(s): File name ; Requirement(s): None ; Return Value(s): On Success - array with EXIF data: ; 0 - Date & Time ; 1 - Camera Vendor ; 2 - Camera Model ; 3 - Image Description ; 4 - Copyright ; 5 - Orientation ; 6 - Width ; 7 - Height ; 8 - Original Date & Time ; 9 - Digitized Date & Time ; 10 - User Comments ; On Failure empty string and sets @ERROR: ; 1 - File is not JPEG file ; 2 - EXIF info not found ; Author(s): YDY (Kot) <mpc@nm.ru> ; Version: 1.1.00 ; Date: 09.08.2004 ; Note(s): None ; ;=============================================================================== Func _GetEXIFData($file) Local $pos = 3 If not (_FileReadAtOffsetHEX ($file, 1, 2) = "FFD8") Then SetError(1); Not JPEG Return("") Endif $fs = FileGetSize($file) While $pos < $fs $data = _FileReadAtOffsetHEX ($file, $pos, 4) If StringLeft($data, 2) = "FF" then; Valid segment start $segtype = StringMid($data, 3, 2) if $segtype = "E1" then Return(ParseExif($pos)) $pos = $pos + Dec(StringRight($data, 4)) + 2 Else Exitloop Endif Wend SetError(2); Segment not found Return("") Endfunc Func ParseExif($exif_offset) Local $ByteOrder = 0 Local $ic, $idf_offset, $exif[11] Local $orient = StringSplit("Normal|Mirrored|180░|180░ and mirrored|90░ left and mirrored|_ 90░ right|90░ right and mirrored|90░ left", "|") If _FileReadAtOffsetHEX ($file, $exif_offset+10, 2) = "4D4D" then $ByteOrder = 1 $size = _FileReadAtOffsetHEX ($file, $exif_offset+2, 2) $exif_offset = $exif_offset + 11 + 9; 9 JFIF header size + 11 - IDF header size, For $ic = 0 To 11 $tag_full = _FileReadAtOffsetHEX($file, $exif_offset + $ic * 12, 12) $id = StringLeft($tag_full, 4) If $ByteOrder Then $id = StringRight($id, 2) & StringLeft($id, 2) Select Case $id = "6987"; Exif IDF offset $idf_offset = _GetNumValue(StringRight($tag_full, 8), $ByteOrder) Case $id = "3201"; DateTime 3201 $exif[0] = _ReadValue($file, $tag_full, $ByteOrder) Case $id = "0F01"; Vendor $exif[1] = _ReadValue($file, $tag_full, $ByteOrder) Case $id = "1001"; Model $exif[2] = _ReadValue($file, $tag_full, $ByteOrder) Case $id = "0E01"; ImageDescription $exif[3] = _ReadValue($file, $tag_full, $ByteOrder) Case $id = "9882"; Copyright $exif[4] = _ReadValue($file, $tag_full, $ByteOrder) Case $id = "1201"; Orientation $value = _GetNumValue(StringRight($tag_full, 8), $ByteOrder) If $ByteOrder Then $value = BitShift($value, 16) If ($value > 0) and ($value < 9) Then $exif[5] = $orient[$value] Else $exif[5] = "Undefined" Endif EndSelect Next If not ($idf_offset > 0) Then Return($exif) For $ic = 0 To 23 $tag_full = _FileReadAtOffsetHEX ($file, $idf_offset + 15 + $ic * 12, 12) $id = StringLeft($tag_full, 4) If $ByteOrder Then $id = StringRight($id, 2) & StringLeft($id, 2) Select Case $id = "02A0"; Width $exif[6] = _GetNumValue(StringRight($tag_full, 8), $ByteOrder) Case $id = "03A0"; Height $exif[7] = _GetNumValue(StringRight($tag_full, 8), $ByteOrder) Case $id = "0390"; DateTimeOriginal $exif[8] = _ReadValue($file, $tag_full, $ByteOrder) Case $id = "0490"; DateTimeDigitized $exif[9] = _ReadValue($file, $tag_full, $ByteOrder) Case $id = "8692"; UserComments $exif[10] = _ReadValue($file, $tag_full, $ByteOrder) EndSelect Next Return($exif) EndFunc Func _ReadValue($file, $tag, $ByteOrder) Local $count = _GetNumValue(StringMid($tag, 9, 8), $ByteOrder) Local $offset = _GetNumValue(StringMid($tag, 17, 8), $ByteOrder) Local $tStr = _FileReadAtOffsetHEX ($file, $offset+13, $count) Local $oStr = "" While StringLen($tStr) > 0 $oStr = $oStr & Chr(Dec(StringLeft($tStr, 2))) $tStr = StringTrimLeft($tStr, 2) WEnd Return($oStr) EndFunc Func _GetNumValue ($input, $ByteOrder) Local $tStr = "" If $ByteOrder then $tStr = $input Else While StringLen($input) > 0 $tStr = $tStr & StringRight($input, 2) $input = StringTrimRight($input, 2) WEnd Endif Return (Dec($tStr)) EndFunc Func _FileReadAtOffsetHEX ($file, $offset, $bytes) Local $tfile = FileOpen($file, 0) Local $tstr = "" FileRead($tfile, $offset-1) For $i = $offset To $offset + $bytes - 1 $tstr = $tstr & Hex(Asc(FileRead($tfile, 1)), 2) Next FileClose($tfile) Return ($tstr) Endfunc