@@ -62,13 +62,6 @@ def generate_log_filename(base_name, directory):
62
62
counter += 1
63
63
return os .path .join (directory , filename )
64
64
65
- # Function to get the date taken
66
- from pillow_heif import register_heif_opener
67
- from PIL import Image
68
-
69
- # Register HEIC support
70
- register_heif_opener ()
71
-
72
65
# Updated get_date_taken function
73
66
def get_date_taken (file_path ):
74
67
fallback_creation_time = datetime .datetime .fromtimestamp (os .path .getctime (file_path ))
@@ -82,34 +75,86 @@ def get_date_taken(file_path):
82
75
image = Image .open (file_path )
83
76
84
77
# Handle HEIC/HEIF formats using pillow-heif
78
+ # --------------------------------------------------------------------------------------------------
79
+ # --------------------------------------------------------------------------------------------------
80
+ # --------------------------------------------------------------------------------------------------
81
+
85
82
if mime_type in ("image/heic" , "image/heif" ):
86
83
try :
87
- register_heif_opener ()
88
- metadata = image .info .get ("Exif" )
89
-
90
- # Extract EXIF metadata if present
84
+ try :
85
+ import piexif
86
+ write_log ("[DEBUG] Successfully imported piexif in the bundled executable." )
87
+ except ImportError as e :
88
+ write_log (f"[ERROR] Failed to import piexif: { e } " )
89
+
90
+ metadata = image .info .get ("exif" ) # Note: Changed to lowercase 'exif' key
91
+ xmp_data = image .info .get ("xmp" )
92
+
93
+ # Debugging fetched metadata (show first 500 characters for clarity)
94
+ metadata_preview = str (image .info )[:500 ]
95
+ write_log (f"[DEBUG] Metadata preview for { file_path } : { metadata_preview } " )
96
+
97
+ # Attempt to parse EXIF metadata using piexif
91
98
if metadata :
92
- from exif import Image as ExifImage
93
- exif_image = ExifImage (metadata )
94
- if exif_image .has_exif and exif_image .datetime_original :
95
- naive_time = datetime .datetime .strptime (exif_image .datetime_original , '%Y:%m:%d %H:%M:%S' )
96
- date_taken = eastern .localize (naive_time ) if naive_time .tzinfo is None else naive_time .astimezone (eastern )
97
- is_fallback = False
98
-
99
- # Extract XMP metadata as a fallback
100
- if date_taken is None :
101
- xmp_data = image .info .get ("xmp" )
102
- if xmp_data :
99
+ write_log (f"[DEBUG] Found EXIF metadata for { file_path } . Attempting to parse with piexif..." )
100
+ try :
101
+ exif_dict = piexif .load (metadata )
102
+ write_log (f"[DEBUG] Parsed EXIF tags: { exif_dict .keys ()} " )
103
+
104
+ # Extract DateTimeOriginal
105
+ datetime_original = exif_dict .get ("Exif" , {}).get (piexif .ExifIFD .DateTimeOriginal )
106
+ if datetime_original :
107
+ datetime_original = datetime_original .decode ("utf-8" ) # Convert bytes to string
108
+ write_log (f"[DEBUG] Found DateTimeOriginal: { datetime_original } " )
109
+ naive_time = datetime .datetime .strptime (datetime_original , '%Y:%m:%d %H:%M:%S' )
110
+ date_taken = eastern .localize (naive_time ) if naive_time .tzinfo is None else naive_time .astimezone (eastern )
111
+ is_fallback = False
112
+ else :
113
+ write_log (f"[WARNING] No DateTimeOriginal found in EXIF metadata." )
114
+
115
+ # Fallback to DateTimeDigitized
116
+ if date_taken is None :
117
+ datetime_digitized = exif_dict .get ("Exif" , {}).get (piexif .ExifIFD .DateTimeDigitized )
118
+ if datetime_digitized :
119
+ datetime_digitized = datetime_digitized .decode ("utf-8" )
120
+ write_log (f"[DEBUG] Found DateTimeDigitized: { datetime_digitized } " )
121
+ naive_time = datetime .datetime .strptime (datetime_digitized , '%Y:%m:%d %H:%M:%S' )
122
+ date_taken = eastern .localize (naive_time ) if naive_time .tzinfo is None else naive_time .astimezone (eastern )
123
+ is_fallback = False
124
+ else :
125
+ write_log (f"[WARNING] No DateTimeDigitized found in EXIF metadata." )
126
+ except Exception as exif_error :
127
+ write_log (f"[ERROR] Failed to parse EXIF metadata using piexif for { file_path } : { exif_error } " )
128
+
129
+ # Extract XMP metadata as a further fallback
130
+ if date_taken is None and xmp_data :
131
+ write_log (f"[DEBUG] Found XMP metadata for { file_path } . Attempting to parse..." )
132
+ try :
103
133
import xml .etree .ElementTree as ET
104
134
root = ET .fromstring (xmp_data )
105
135
create_date = root .find (".//{http://ns.adobe.com/xap/1.0/}CreateDate" )
106
136
if create_date is not None :
137
+ write_log (f"[DEBUG] Found CreateDate in XMP metadata: { create_date .text } " )
107
138
naive_time = datetime .datetime .strptime (create_date .text , '%Y-%m-%dT%H:%M:%S' )
108
139
date_taken = eastern .localize (naive_time ) if naive_time .tzinfo is None else naive_time .astimezone (eastern )
109
140
is_fallback = False
141
+ else :
142
+ write_log (f"[WARNING] No CreateDate found in XMP metadata for { file_path } ." )
143
+ except Exception as xmp_error :
144
+ write_log (f"[ERROR] Failed to parse XMP metadata for { file_path } : { xmp_error } " )
145
+
146
+ # Final debugging message
147
+ if date_taken :
148
+ write_log (f"[INFO] Successfully determined date_taken for { file_path } : { date_taken } " )
149
+ else :
150
+ write_log (f"[ERROR] Unable to determine date_taken for { file_path } . All methods failed." )
110
151
111
152
except Exception as e :
112
- write_log (f"Error processing HEIC/HEIF metadata for { file_path } : { e } " )
153
+ write_log (f"[ERROR] Processing HEIC/HEIF metadata failed for { file_path } : { e } " )
154
+
155
+ # --------------------------------------------------------------------------------------------------
156
+ # --------------------------------------------------------------------------------------------------
157
+ # --------------------------------------------------------------------------------------------------
113
158
else :
114
159
# Standard image formats using Pillow
115
160
exif_data = image ._getexif ()
@@ -121,6 +166,11 @@ def get_date_taken(file_path):
121
166
date_taken = eastern .localize (naive_time ) if naive_time .tzinfo is None else naive_time .astimezone (eastern )
122
167
is_fallback = False
123
168
break
169
+ elif decoded == "DateTimeDigitized" :
170
+ naive_time = datetime .datetime .strptime (value , '%Y:%m:%d %H:%M:%S' )
171
+ date_taken = eastern .localize (naive_time ) if naive_time .tzinfo is None else naive_time .astimezone (eastern )
172
+ is_fallback = False
173
+ break
124
174
125
175
elif mime_type and mime_type .startswith ('video' ):
126
176
# Extract metadata from video formats using ffprobe
@@ -244,7 +294,8 @@ def rename_files_by_date(folder_path):
244
294
245
295
# GUI Implementation
246
296
def create_gui ():
247
- global log_widget , progress_bar , progress_bar_labels # Make log_widget accessible to other functions
297
+
298
+ global log_widget , progress_bar , progress_bar_labels
248
299
249
300
def pick_folder ():
250
301
folder = filedialog .askdirectory ()
0 commit comments