18

I have over 500 images (png /jpg) having wrong captured date (Date taken) because of wrong camera date settings. I moved photos to mobile and mobile gallery sorts photos on the basis of 'Date Taken'. I want all photos to be displayed in order.

So how can I change captured date (Date taken) using python script?

Gaurav Vichare
  • 1,143
  • 2
  • 11
  • 26

4 Answers4

22

This is quite easy to do using the piexif library:

from datetime import datetime
import piexif

filename = 'image.jpg'
exif_dict = piexif.load(filename)
new_date = datetime(2018, 1, 1, 0, 0, 0).strftime("%Y:%m:%d %H:%M:%S")
exif_dict['0th'][piexif.ImageIFD.DateTime] = new_date
exif_dict['Exif'][piexif.ExifIFD.DateTimeOriginal] = new_date
exif_dict['Exif'][piexif.ExifIFD.DateTimeDigitized] = new_date
exif_bytes = piexif.dump(exif_dict)
piexif.insert(exif_bytes, filename)

This script will insert the new date 2018:01:01 00:00:00 into the DateTime, DateTimeOriginal and DateTimeDigitized EXIF fields for image.jpg.

oulenz
  • 1,199
  • 1
  • 15
  • 24
Joachim
  • 567
  • 1
  • 7
  • 20
  • 9
    piexif.insert() adds a 2nd EXIF block if one already exists. A better way would be : exif_dict = piexif.load(filename); piexif.remove(filename); ... ; piexif.insert(exif_bytes, filename). Google Photos always reads the 1st EXIF block, other softwares display the last one. Better to have only one EXIF block in the JPEG. – Eric H. Nov 12 '20 at 11:15
6

I might be late to this party, but i wrote a python script for bulk changing taken time field for whatsapp photos based on filename format Eg: IMG-20160117-WA0001.jpg. Also this does not overwrite the existing properties. https://github.com/dsouzawilbur/Scripts/blob/master/Change_Photo_Taken_Time.py

from datetime import datetime
import os
import re
import piexif

def absoluteFilePaths(directory):
    for dirpath,_,filenames in os.walk(directory):
        for f in filenames:
            fullPath = os.path.abspath(os.path.join(dirpath, f))
            if re.match(r"^IMG-\d\d\d\d\d\d\d\d-WA\d\d\d\d.*", f) and not re.match(r"^IMG-\d\d\d\d\d\d\d\d-WA\d\d\d\d-ANIMATION.gif", f):
                print(f+" Matched")
                match = re.search("^IMG-(\d\d\d\d)(\d\d)(\d\d)-WA\d\d\d\d.*", f)
                year = match.group(1)
                month= match.group(2)
                day = match.group(3)
                exif_dict = piexif.load(fullPath)
                #Update DateTimeOriginal
                exif_dict['Exif'][piexif.ExifIFD.DateTimeOriginal] = datetime(int(year), int(month), int(day), 4, 0, 0).strftime("%Y:%m:%d %H:%M:%S")
                #Update DateTimeDigitized               
                exif_dict['Exif'][piexif.ExifIFD.DateTimeDigitized] = datetime(int(year), int(month), int(day), 4, 0, 0).strftime("%Y:%m:%d %H:%M:%S")
                #Update DateTime
                exif_dict['0th'][piexif.ImageIFD.DateTime] = datetime(int(year), int(month), int(day), 4, 0, 0).strftime("%Y:%m:%d %H:%M:%S")
                exif_bytes = piexif.dump(exif_dict)
                piexif.insert(exif_bytes, fullPath)
                print("############################")


absoluteFilePaths("__DIRECTORY_WITH_PHOTOS__")
Vikhyat Agarwal
  • 1,723
  • 1
  • 11
  • 29
Wilbur Dsouza
  • 127
  • 1
  • 10
4

No real need to write Python, you can do it in one line in the Terminal using jhead. For example, adjust all EXIF times forward by 1 hour

jhead -ta+1:00 *.jpg

Make a COPY of your files and test it out on that first!

Download from here.

E_net4
  • 27,810
  • 13
  • 101
  • 139
Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • 28
    This is a question how to do it in Python. – Peter Wood Oct 09 '15 at 08:26
  • 8
    @PeterWood Yes, I know. The OP may think some lengthy script is required and may only know Python and therefore have tagged it as such. I am merely pointing out a far simpler solution - if OP wishes to ignore it, he is welcome.... else he could spend 3 days writing Python and say *"If only someone had mentioned I could do it in 5 seconds with a one-liner"*. Just trying to help. – Mark Setchell Oct 09 '15 at 08:30
  • You could clarify that with a question in the comments. I appreciate you are very helpful. I also try to be helpful. – Peter Wood Oct 09 '15 at 08:42
  • 9
    Except I was searching for "python add date taken exif", this is one of the top results, and it's completely not helpful to me – autonomy Sep 13 '18 at 14:53
  • @MarkSetchell I'm trying to use your solution in this thread and could use your advice! [https://stackoverflow.com/questions/60514748/changing-jpg-date-taken-to-be-5-hours-before-existing-value] (https://stackoverflow.com/questions/60514748/changing-jpg-date-taken-to-be-5-hours-before-existing-value) – zemken12 Mar 03 '20 at 20:38
2

PNG does not support EXIF so I made this to fix the creation/modification time instead, based on Wilbur Dsouza's answer:

import datetime
import os
import re
import sys
import time

import piexif


def fix(directory):
    print(directory)
    for dirpath, _, filenames in os.walk(directory):
        for f in filenames:
            fullPath = os.path.abspath(os.path.join(dirpath, f))
            # Format: Screenshot_20170204-200801.png
            if re.match(r"^Screenshot_\d\d\d\d\d\d\d\d-\d\d\d\d\d\d.*", f):
                match = re.search("^Screenshot_(\d\d\d\d)(\d\d)(\d\d)-(\d\d)(\d\d)(\d\d).*", f)
                year = int(match.group(1))
                month = int(match.group(2))
                day = int(match.group(3))
                hour = int(match.group(4))
                minute = int(match.group(5))
                second = int(match.group(6))

                date = datetime.datetime(year=year, month=month, day=day, hour=hour, minute=minute, second=second)
                modTime = time.mktime(date.timetuple())

                print(f, date)

                os.utime(fullPath, (modTime, modTime))


if __name__ == "__main__":
    fix(sys.argv[1]) 
wjandrea
  • 28,235
  • 9
  • 60
  • 81
stan
  • 809
  • 9
  • 18