PILL Image retrieve exif dict from base64 converted images for editing and save error, dict return is NULL, any ideas?

1.4k views Asked by At

I am new at asking questions here, i hope this information is all the things you require to properly understand the problem. Thank you in advance for your time answering this.

ENV: Python 2.7.6, Pillow 3.4.2, Piexif 1.0.8

I have a small script to convert an image from base_64 to image file; The image is correctly saved on the server while doing a for loop of an array;

 # write decoded image from base to jpg, works perfectly
 fh = open(image_name_location, "wb")
 fh.write(decodestring(image_src))
 fh.close() 

After this i want the same image to insert gps and date information inside the exif, so for this i use PIL and piexif; I use PIL to etract the current exif and piexif to insert new data into the exif of the image;

 im = Image.open(image_name_location)

 #load existing exif to use as carrier
 exif_dict = piexif.load(im.info["exif"])

 #insert new information for gps and date
 exif_dict['GPS']['Latitude']= float(image_gps.split(',')[0])
 exif_dict['GPS']['Longitude']= float(image_gps.split(',')[1])
 exif_dict['0th']['Date and time (digitized)']= datetime.datetime.strptime(image_date, '%d/%m/%Y %H:%M').strftime("%Y:%m:%d %H:%M:%S")

  #convert exif to bytes
  exif_bytes = piexif.dump(exif_dict)

  #add to the image
  piexif.insert(exif_bytes, image_name_location)

  #close the image from memory
  im.close()

The error is, whatever i do, and any way i try to get the EXIF current dict, it will return NULL;

Anyone has any idea? Need to mention, on existing images, after they have been loaded in an html, this script works fine, but for some reason, on making the images it does not.

i have changed and added this code to get the exif:

try:
    exif_dict = piexif.load(im.info["exif"])

    #insert new information for gps and date
    exif_dict['GPS']['Latitude']= str(image_gps.split(',')[0])
    exif_dict['GPS']['Longitude']= str(image_gps.split(',')[1])
    exif_dict['0th']['Date and time (digitized)']= datetime.datetime.strptime(image_date, '%d/%m/%Y %H:%M').strftime("%Y:%m:%d %H:%M:%S")

    #close the image from memory
    im.close()

except:
    #create clean exif info for new image if none detected
    zeroth_ifd = {piexif.ImageIFD.Make: "Image maker",
                  piexif.ImageIFD.Software: "software here"
                  }
    exif_ifd = {piexif.ExifIFD.DateTimeOriginal: datetime.datetime.strptime(image_date, '%d/%m/%Y %H:%M').strftime("%Y:%m:%d %H:%M:%S"),
               piexif.ExifIFD.DateTimeDigitized: datetime.datetime.now().strftime("%Y:%m:%d %H:%M:%S")
                }
    gps_ifd = {piexif.GPSIFD.GPSVersionID: (2, 0, 0, 0),
               piexif.GPSIFD.GPSAltitudeRef: 1,
               piexif.GPSIFD.GPSLatitude: float(Fraction(str(image_gps.split(',')[0]))),
               piexif.GPSIFD.GPSLongitude: float(Fraction(str(image_gps.split(',')[1])))
               }

    exif_dict = {"0th":zeroth_ifd, "Exif":exif_ifd, "GPS":gps_ifd}

That solves the error of NULL, because it has the exif clean if none, but now i get the piexif error on converting the gps data fro float to touple??

1

There are 1 answers

4
Thanatos11th On BEST ANSWER

Final Solution, so PILL Image has trouble retrieving anything regarding exif if none, but the piexif library works like a charm, and even creates an empty exif if none is found.

added this code to replace the exif computation:

            exif_dict = piexif.load(image_name_location)

            #convert GPS to degree, minutes, seconds for touple
            latitude_coo = Latitude(image_gps.split(',')[0]).to_string('d% %M% %S% %H').split()
            longitude_coo = Longitude(image_gps.split(',')[1]).to_string('d% %M% %S% %H').split()

            gps_ifd = {piexif.GPSIFD.GPSVersionID: (2, 0, 0, 0),
                       piexif.GPSIFD.GPSAltitudeRef: 1,
                       piexif.GPSIFD.GPSLatitude: ((int(latitude_coo[0]),1),(int(float(latitude_coo[1])*100),100),(int(float(latitude_coo[2])*100),100)),
                       piexif.GPSIFD.GPSLatitudeRef: latitude_coo[3],
                       piexif.GPSIFD.GPSLongitude: ((int(longitude_coo[0]),1),(int(float(longitude_coo[2])*100),100),(int(float(longitude_coo[2])*100),100)),
                       piexif.GPSIFD.GPSLongitudeRef: longitude_coo[3]
                       }

            #insert new information for gps and date
            exif_dict['Exif'][piexif.ExifIFD.DateTimeOriginal]= datetime.datetime.strptime(image_date, '%d/%m/%Y %H:%M').strftime("%Y:%m:%d %H:%M:%S")
            exif_dict['Exif'][piexif.ExifIFD.DateTimeDigitized]= datetime.datetime.now().strftime("%Y:%m:%d %H:%M:%S")
            exif_dict['0th'][piexif.ImageIFD.Make]= "Your test here"
            exif_dict['0th'][piexif.ImageIFD.Software]= "the software name"
            exif_dict['0th'][piexif.ImageIFD.DateTime]= datetime.datetime.strptime(image_date, '%d/%m/%Y %H:%M').strftime("%Y:%m:%d %H:%M:%S")
            exif_dict['GPS'] = gps_ifd

            #convert exif to bytes
            exif_bytes = piexif.dump(exif_dict)

            #add to the image
            piexif.insert(exif_bytes, image_name_location)

Also used this library https://pypi.python.org/pypi/LatLon/1.0.2 to get the coordonates from lat,lon google format to degree, minutes, seconds, reference, and applied accoring to this books instruction on GPS Touple format: http://www.cipa.jp/std/documents/e/DC-008-2012_E.pdf

It was worth it :P