[Python] Reading and writing photo location information tags (JPG file GPS Exif)

Introduction

This is also my own memo. You can do it easily with python. As a caveat

--Latitude and longitude are degrees, minutes and seconds, so 60-ary --Values are fractions, not real numbers. (Is it a rational number?)

There are several related libraries. It is better to unify it to one of them, but it is a memo that worked for the time being. (Hey)

Specification?

I found the following documents.

-Image file format standard for digital still cameras Exif 2.3

According to this, GPS Info IFD seems to be defined as follows.

image.png

There are many, but the files I dealt with were only tags 0-6. I was able to read and write the latitude, longitude, and height of GPS, so it was enough for the time being. Here, GPS Latitude Ref uses a single letter'N'or'S' to indicate north latitude or south latitude. GPS Latitude is expressed as a fraction.

Read and write with python

Read latitude and longitude with Pillow

I used [Pillow](9 https://pypi.org/project/Pillow/). I don't remember if I had a hard time preparing.

pip3 install pillow

I could read the latitude and longitude below.

read_gpsexif.py


from PIL import Image
infile = "test.JPG"
img = Image.open( infile )
exif = img._getexif()
for k, v in exif.items():
    if k==34853:
        print(v)

with this

{0: b'\x02\x00\x00\x00',
 1: 'N',
 2: (35.0, 20.0, 53.51123),
 3: 'E',
 4: (137.0, 9.0, 17.83123),
 5: b'\x00', 6: 256.123}

You will get results like You can see the meaning by comparing it with the definition of GPS INfo IFD in the previous specification. Since it is degrees, minutes, and seconds, conversion is required to convert it to decimal. For example


deg,minu,sec = 35.0, 20.0, 53.51366
deg + minu/60.0 + sec/3600.0

To get `` `35.34819823888889```.

Rewrite GPS Exif latitude / longitude with piexif

I used piexif. It is a strategy to read and rewrite Gps exif with conversion to degrees, minutes, seconds and fractions as a function.

def _to_deg(value, loc):                                                                                                                                               
    if value < 0:                                                                                                                                                    
       loc_value = loc[0]                                                                                                                                       
    elif value > 0:                                                                                                                                                  
       loc_value = loc[1]
    else:                                                                                                                                                            
       loc_value = ""                                                                                                                                           
    abs_value = abs(value)
    deg =  int(abs_value)                                                                                                                                        
    t1 = (abs_value-deg)*60                                                                                                                                      
    minu = int(t1)                                                                                                                                                
    sec = round((t1 - minu)* 60, 5)
    return (deg, min, sec, loc_value)                                                                                                                                                                                                                                                                                     

import Fraction
def _change_to_rational(number):
    f = Fraction(str(number))                                                                                                                                    
    return (f.numerator, f.denominator)     

To do the following:

write_gpsexif.py


import piexif
lat, lng, altitude = 39.123, 139.123, 50.123
jpg_filepath = "test.JPG"

lat_deg = to_deg(lat, ["S", "N"])
lng_deg = to_deg(lng, ["W", "E"])
                                                                                                                            exif_lat = (change_to_rational(lat_deg[0]), change_to_rational(lat_deg[1]), change_to_rational(lat_deg[2]))
exif_lng = (change_to_rational(lng_deg[0]), change_to_rational(lng_deg[1]), change_to_rational(lng_deg[2]))
gps_ifd = {
    piexif.GPSIFD.GPSVersionID: (2, 0, 0, 0),
    piexif.GPSIFD.GPSAltitudeRef: 0,
    piexif.GPSIFD.GPSAltitude: change_to_rational(round(altitude, 3)),
    piexif.GPSIFD.GPSLatitudeRef: lat_deg[3],
    piexif.GPSIFD.GPSLatitude: exif_lat,
    piexif.GPSIFD.GPSLongitudeRef: lng_deg[3],
    piexif.GPSIFD.GPSLongitude: exif_lng,
}

gps_exif = {"GPS": gps_ifd}
exif_data = piexif.load(jpg_filepath)
exif_data.update(gps_exif)
exif_bytes = piexif.dump(exif_data)
piexif.insert(exif_bytes, file_name)

I think I referred to StackOverflow for this, but I lost the link. If you find it, add it.

Summary / Miscellaneous feelings

This is a memo when I read and write GPSExif in the photo as needed.

--I used Pillow and piexif, but somehow it seems better to unify them and use them correctly.

It was a post saying that it is a work memo of Eiya, so I would like to expand it. It's been messy lately. .. ^^; (2020/08/08)

Recommended Posts

[Python] Reading and writing photo location information tags (JPG file GPS Exif)
Python CSV file reading and writing
Reading and writing NetCDF with Python
Reading and writing CSV with Python
Reading and writing text in Python
Reading and writing JSON files with Python
See file and folder information on python
Study from Python Reading and writing Hour9 files
Reading and writing CSV and JSON files in Python
Reading and writing fits files with Python (memo)
Example of reading and writing CSV with Python
[Introduction for beginners] Reading and writing Python CSV files
[Note] File reading ~ Python ~
Reading pyc file (Python 3.5.2)
python external file reading
Notes on reading and writing float32 TIFF images in python
Reading and writing csv files
uproot: Python / Numpy based library for reading and writing ROOT files