Open djjudas21 opened 2 years ago
I get the same error on Python 3.8.10 with piexif 1.1.3 using code taken directly from the repository example exif.py
gps_ifd = { piexif.GPSIFD.GPSVersionID: (2, 0, 0, 0), piexif.GPSIFD.GPSAltitudeRef: 0, piexif.GPSIFD.GPSAltitude: ele, piexif.GPSIFD.GPSLatitudeRef: lat_ref, piexif.GPSIFD.GPSLatitude: (lat_deg, lat_min, lat_sec), piexif.GPSIFD.GPSLongitudeRef: lon_ref, piexif.GPSIFD.GPSLongitude: (lon_deg, lon_min, lon_sec), }
exif_dict = {"GPS": gps_ifd} exif_bytes = piexif.dump(exif_dict) piexif.insert(exif_bytes, fpath)
Traceback (most recent call last):
File "/home/wplaird/Documents/Middle Creek/Maps/GIS/GoogleMaps/Flyover/src/app/make_layer_files.py", line 291, in
I think I figured this out. The root problem is piexif has terrible error checking.
This error means a value you passed, likely an integer or float, needs to be expressed as a Rational (or SRational).
For instance, ExposureTime is a rational and must be passed like (1, 300)
which translates to 1/300s.
In the case of GPS, piexif.GPSIFD.GPSLatitude and piexif.GPSIFD.GPSLongitude values need to be passed as 3 rational numbers... ((84, 1), (30, 1), (1, 2))
Nice one @aaronwmorris. I gave up on piexif ages ago because of this (and other) issues, but this week I started using pyexiv2 and found that it too handles rationals in this way. I've already got functions in my code for converting decimal GPS to degrees/minutes/seconds GPS, so I'm going to tweak that to return rationals instead. Thanks for the tip.
Here's what I've come up with. Note that it returns the 3 rationals as a single formatted string, as required for pyexiv2, e.g. 'Exif.GPSInfo.GPSLatitude': '51/1 27/1 3148/100'
def deg_to_dms(decdegrees):
"""
Convert from decimal degrees to degrees, minutes, seconds.
"""
decdegrees = Decimal(decdegrees)
# Multiply degrees up 3600 to get integer second resolution, divide by 60 to get mins and secs
mins, secs = divmod(abs(decdegrees)*3600, 60)
# Further divide by 60 to get degrees and mins
degs, mins = divmod(mins, 60)
# round down degs and mins. Secs remains a float
degs, mins = int(degs), int(mins)
return degs, mins, secs
def deg_to_dms_rational(decdegrees):
"""
Convert from decimal degrees to degrees, minutes, seconds expressed as rationals
This returns 3 rationals formatted as a string suitable for pyexiv2, e.g.
'Exif.GPSInfo.GPSLatitude': '51/1 27/1 3148/100'
"""
(degs, mins, secs) = deg_to_dms(decdegrees)
# As secs is a float, we multiply by 100 for increased precision in the rational
roundedsecs = round(secs * 100)
return f"{degs}/1 {mins}/1 {roundedsecs}/100"
I've got the following code:
It outputs this:
Is this a bug in piexif or am I using it wrong? Piexif 1.1.3 on Python 3.10.2.