Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os
- import re
- import shutil
- from datetime import datetime
- from PIL import Image
- import piexif
- def set_image_date_taken(image_path, target_date=None):
- """
- Sets the 'DateTimeOriginal' EXIF attribute of a JPG image.
- If target_date is provided, uses that date. Otherwise, uses the file's modified date.
- """
- try:
- if target_date is None:
- # Get the file's modified date
- mtime = os.path.getmtime(image_path)
- target_date = datetime.fromtimestamp(mtime)
- with Image.open(image_path) as img:
- # Create a new exif dictionary
- exif_dict = {"0th": {}, "Exif": {}, "GPS": {}, "Interop": {}, "1st": {}, "thumbnail": None}
- # Convert datetime object to EXIF format: YYYY:MM:DD HH:MM:SS
- exif_datetime_str = target_date.strftime("%Y:%m:%d %H:%M:%S")
- # Set the EXIF tags that Windows Explorer expects for "Date taken"
- # Using direct tag IDs:
- # 36867 = DateTimeOriginal
- # 36868 = DateTimeDigitized
- # 306 = DateTime
- exif_dict["Exif"][36867] = exif_datetime_str.encode("utf-8")
- exif_dict["Exif"][36868] = exif_datetime_str.encode("utf-8")
- exif_dict["0th"][306] = exif_datetime_str.encode("utf-8")
- # Dump the exif_dict to bytes
- exif_bytes = piexif.dump(exif_dict)
- # Save the image with the new EXIF data
- img.save(image_path, exif=exif_bytes)
- return True
- except Exception as e:
- print(f"Error processing {image_path}: {str(e)}")
- # Try alternative method if the first one fails
- try:
- with Image.open(image_path) as img:
- # Create a new exif dictionary with minimal required fields
- exif_dict = {"0th": {}, "Exif": {}, "GPS": {}, "Interop": {}, "1st": {}, "thumbnail": None}
- exif_datetime_str = target_date.strftime("%Y:%m:%d %H:%M:%S")
- # Set only the essential DateTimeOriginal tag using direct ID
- exif_dict["Exif"][36867] = exif_datetime_str.encode("utf-8")
- exif_bytes = piexif.dump(exif_dict)
- img.save(image_path, exif=exif_bytes)
- return True
- except Exception as e2:
- print(f"Failed to process {image_path} with alternative method: {str(e2)}")
- return False
- def process_image_file(image_path, script_dir):
- """
- Process a single image file: copy to fixed folder with date-based naming and set EXIF data.
- """
- filename = os.path.basename(image_path)
- original_folder = os.path.basename(os.path.dirname(image_path))
- # Get the file's modified date
- mtime = os.path.getmtime(image_path)
- file_date = datetime.fromtimestamp(mtime)
- # Correct the year if it's 2026 (wrong camera configuration)
- if file_date.year == 2026:
- file_date = file_date.replace(year=2025)
- # Create the date-based filename: yyyy.mm.dd hh:mm.[extension]
- date_filename = file_date.strftime("%Y.%m.%d %H.%M")
- # Get the file extension
- _, extension = os.path.splitext(filename)
- # Create the fixed directory
- fixed_dir = os.path.join(script_dir, "fixed")
- os.makedirs(fixed_dir, exist_ok=True)
- # Handle duplicate filenames by adding a counter
- counter = 1
- new_file_path = os.path.join(fixed_dir, f"{date_filename}_{counter}_{original_folder}{extension}")
- while os.path.exists(new_file_path):
- counter += 1
- new_file_path = os.path.join(fixed_dir, f"{date_filename}_{counter}_{original_folder}{extension}")
- try:
- # Copy the file to the new location
- shutil.copy2(image_path, new_file_path)
- # Set the EXIF date using the corrected file date
- if set_image_date_taken(new_file_path, file_date):
- print(f"Successfully processed: {filename} -> {os.path.basename(new_file_path)}")
- else:
- print(f"Failed to set EXIF data for: {filename}")
- # Move to error folder if EXIF setting fails
- error_dir = os.path.join(script_dir, "fixed", "error")
- os.makedirs(error_dir, exist_ok=True)
- error_path = os.path.join(error_dir, filename)
- shutil.move(new_file_path, error_path)
- print(f"Moved {filename} to error folder due to EXIF failure")
- except Exception as e:
- print(f"Error processing {filename}: {str(e)}")
- # Move to error folder if any error occurs
- try:
- error_dir = os.path.join(script_dir, "fixed", "error")
- os.makedirs(error_dir, exist_ok=True)
- error_path = os.path.join(error_dir, filename)
- shutil.copy2(image_path, error_path)
- print(f"Copied {filename} to error folder due to processing error")
- except Exception as copy_error:
- print(f"Failed to copy {filename} to error folder: {str(copy_error)}")
- def main():
- script_dir = os.path.dirname(os.path.abspath(__file__))
- print(f"Searching for JPG files in subfolders of: {script_dir}")
- # Walk through all subdirectories
- for root, dirs, files in os.walk(script_dir):
- # Skip the 'fixed' directory to avoid processing already processed files
- if 'fixed' in root:
- continue
- if 'good' in root:
- continue
- for filename in files:
- if filename.lower().endswith(".jpg"):
- image_path = os.path.join(root, filename)
- process_image_file(image_path, script_dir)
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement