Closed CarlesLlobet closed 3 months ago
Hi This issue has been discussed recently, see: https://github.com/LeoHsiao1/pyexiv2/issues/133 The source code of exiv2 supports writing duplicate exif keys. But there is rarely a need for this, as ordinary software cannot read duplicate exif keys.
HI @LeoHsiao1,
Yes, I saw that issue but the implemented function only allows to copy all the tags from one image to the other as they are. I'd need to also modify some of the Date tags while copying.
Would that be possible with the copy function implemented in that issue to modify some of them during copy?
In addition to COPY, I offer another option: https://github.com/LeoHsiao1/pyexiv2/issues/133#issuecomment-1905995016
Write duplicate exif key by list type value:
>>> img.modify_exif({'Exif.Image.DateTime': ['2024:03:15 17:35:02', '2024:00:00 10:00:00']})
>>> img.read_exif()['Exif.Image.DateTime']
['2024:03:15 17:35:02', '2024:00:00 10:00:00']
But the order of the list may be reversed. Does this meet your needs?
That does not seem to do what I need, no.
Lets say we have this code example:
import pyexiv2
from datetime import datetime
def modify_exif_timestamps(image_path):
# Open the image file
image = pyexiv2.Image(image_path)
# Define the new timestamp
new_timestamp = datetime(1970, 1, 1, 0, 0, 0, 1)
image.modify_exif({'Exif.Image.DateTime': ['1970:01:01 00:00:00.001', '1970:01:01 00:00:00.001']})
image.close()
# Replace 'original_modified.jpg' with the path to your image file
modify_exif_timestamps('original_modified.jpg')
As you can see, my original image has several dates duplicated (Modify Date, Create Date, Date/Time Original). Whenever I execute the sample code, the modified tag (Modify Date) does get modified correctly but theres only 1 instance now:
I have a suspicion.The Modify Date
output by exiftool does not necessarily correspond to the Exif.Image.DateTime
of exiv2. May be affected by multiple keys of exiv2.
Could you please test writing few keys?
image.clear_exif()
image.modify_exif({'Exif.Image.DateTime': ['1970:01:01 00:00:00.001', '1971:01:01 00:00:00.001']})
image.read_exif()
And then view that image with exiftool?
Sure, here's the code:
import pyexiv2
from datetime import datetime
def modify_exif_timestamps(image_path):
# Open the image file
image = pyexiv2.Image(image_path)
# Define the new timestamp
new_timestamp = datetime(1970, 1, 1, 0, 0, 0, 1)
image.clear_exif()
image.modify_exif({'Exif.Image.DateTime': ['1970:01:01 00:00:00.001', '1970:01:01 00:00:00.001']})
image.read_exif()
image.close()
# Replace 'original_modified.jpg' with the path to your image file
modify_exif_timestamps('original_modified.jpg')
and results:
You also can have the original image if you want to do some tests:
Ok, the cause of the problem is still there: The Modify Date
output by exiftool does not necessarily correspond to the Exif.Image.DateTime
of exiv2.
After analyzing, I don't think your EXIF key is duplicated.
Use exiftool -v
to show the data structure of the metadata:
$ exiftool -v original.jpg
ExifToolVersion = 12.78
FileName = 1-raw.jpg
Directory = ..
FileSize = 2851929
FileModifyDate = 1710512547
FileAccessDate = 1710512636
FileInodeChangeDate = 1710513088
FilePermissions = 33279
FileType = JPEG
FileTypeExtension = JPG
MIMEType = image/jpeg
JPEG APP1 (65402 bytes):
ExifByteOrder = II
+ [IFD0 directory with 19 entries]
| 0) ImageWidth = 4000
| 1) ImageHeight = 3000
| 2) ImageDescription =
| 3) Make = samsung
| 4) Model = SM-A326U
| 5) Orientation = 6
| 6) XResolution = 72 (72/1)
| 7) YResolution = 72 (72/1)
| 8) ResolutionUnit = 2
| 9) Software = MediaTek Camera Application
| 10) ModifyDate = 2023:11:20 15:46:23
| 11) YCbCrPositioning = 2
| 12) Exif_0x0220 = 0
| 13) Exif_0x0221 = 0
| 14) Exif_0x0222 = 0
| 15) Exif_0x0223 = 0
| 16) Exif_0x0224 = 0
| 17) Exif_0x0225 =
| 18) ExifOffset (SubDirectory) -->
| + [ExifIFD directory with 32 entries]
| | 0) ExposureTime = 0.041662 (41662000/1000000000)
| | 1) FNumber = 1.8 (1800/1000)
| | 2) ExposureProgram = 2
| | 3) ISO = 500
| | 4) SensitivityType = 0
| | 5) RecommendedExposureIndex = 0
| | 6) ExifVersion = 0220
| | 7) DateTimeOriginal = 2023:11:20 15:46:23
| | 8) CreateDate = 2023:11:20 15:46:23
| | 9) ComponentsConfiguration = 1 2 3 0
| | 10) ShutterSpeedValue = 4.585 (4585/1000)
| | 11) ApertureValue = 1.8 (1800/1000)
| | 12) BrightnessValue = 3 (30/10)
| | 13) ExposureCompensation = 0 (0/10)
| | 14) MaxApertureValue = 1.69 (169/100)
| | 15) MeteringMode = 2
| | 16) LightSource = 255
| | 17) Flash = 9
| | 18) FocalLength = 4.6 (4600/1000)
| | 19) SubSecTime = 703
| | 20) SubSecTimeOriginal = 703
| | 21) SubSecTimeDigitized = 703
...
It can be seen that only ModifyDate = 2023:11:20 15:46:23
and SubSecTime = 703
are stored in the image.
Use exiftool -exif:*
to show only EXIF metadata:
$ exiftool -exif:* original.jpg | grep Date
Modify Date : 2023:11:20 15:46:23
Date/Time Original : 2023:11:20 15:46:23
Create Date : 2023:11:20 15:46:23
There are no two ModifyDate
here.
So why do you see two ModifyDates?
$ exiftool original.jpg | grep Date
File Modification Date/Time : 2024:03:15 22:22:27+08:00
File Access Date/Time : 2024:03:15 22:23:56+08:00
File Inode Change Date/Time : 2024:03:15 22:31:28+08:00
Modify Date : 2023:11:20 15:46:23
Date/Time Original : 2023:11:20 15:46:23
Create Date : 2023:11:20 15:46:23
Create Date : 2023:11:20 15:46:23.703
Date/Time Original : 2023:11:20 15:46:23.703
Modify Date : 2023:11:20 15:46:23.703
My guess is that exiftool shows two values with different precision when there is SubSecTime = 703
.
So, to follow the principles of exiftool, you need to change
img.modify_exif({'Exif.Image.DateTime': '1970:01:01 00:00:00.703'})
to
img.modify_exif({'Exif.Image.DateTime': '1970:01:01 00:00:00', "Exif.Photo.SubSecTime": "703"})
Then execute exiftool, it shows two Modify Date
:
$ exiftool 1.jpg | grep Modify
Modify Date : 1970:01:01 00:00:00
Modify Date : 1970:01:01 00:00:00.703
Wow thank you so much for digging into this and finding the root cause!
Thats weird from exiftool and it was driving me crazy!
Thanks again, I'll close the ticket 🙏
I have an image with the following exif information:
As you can see there are duplicate tags (ModifyDate, Create Date, DateTimeOriginal, ..).
The problem is that if I modify any of this (e.g:
image.modify_exif({'Exif.Image.DateTime': '1970:01:01 00:00:00.001'})
), It will override the metadata and just keep one of them, since dictionaries in python only keep the latest value.How could I modify all dates without smashing duplicate keys?