def trigger_capture(camera, shutter, start_time=(monotonic_time() + 0.05), meta=[], download_timeout=5.0): monotonic_alarm(start_time) o = gph_cmd('capture-image-and-download', timeout=shutter + download_timeout) s = filter(lambda x: x.startswith(_saving_file_response), o) if len(s) != 1: print("Couldn't retrieve file at the end of capture.") raise IOError filename = s[0][len(_saving_file_response):] exifd = ImageMetadata(filename) exifd.read() # Add a piece of debug info to exif header meta.append(('TriggerStartTime', start_time)) for (name, value) in meta: tag = 'Xmp.xmp.GPhotolapser.' + name exifd[tag] = XmpTag(tag, value=str(value)) exifd.write() return filename
def trigger_expose_bulb(camera, bulb, start_time=(monotonic_time() + 0.05), meta=[], download_timeout=3.5): end_time = start_time + bulb monotonic_alarm(start_time) gph_cmd(camera.bulb_begin) monotonic_alarm(end_time) gph_cmd(camera.bulb_end) o = gph_cmd('wait-event-and-download %is' % int(floor(download_timeout)), timeout=download_timeout) # Should download the image s = filter(lambda x: x.startswith(_saving_file_response), o) if len(s) != 1: print("Couldn't retrieve file at the end of bulb exposure.") raise IOError filename = s[0][len(_saving_file_response):] exifd = ImageMetadata(filename) exifd.read() # Add a piece of debug info to exif header meta.append(('BulbHoldTime', bulb)) meta.append(('TriggerStartTime', start_time)) for (name, value) in meta: tag = 'Xmp.xmp.GPhotolapser.' + name exifd[tag] = XmpTag(tag, value=str(value)) exifd.write() return filename
def _pyexiv2_new(self, fn): from pyexiv2 import ImageMetadata exif = ImageMetadata(fn) exif.read() self._exif = exif self._getitem = self._new_getitem self._contains = exif.__contains__
def correctRotaion(fl_input): print("imageProcessing::correctRotaion(fl_input)") try: # save the result metadata = ImageMetadata(fl_input) metadata.read() # Get the thumbnail of the image from EXIF. thumb = metadata.exif_thumbnail thumb.set_from_file(fl_input) thumb.write_to_file('512_' + "a") thumb.erase() # Rewrite the thumbnail with corrected image. metadata.write() # Return the output file name. return (True) except Exception as e: print("Error occurs in imageProcessing::correctRotaion(in_file)") print(str(e)) error.ErrorMessageImageProcessing(details=str(e), show=True, language="en") return (None)
def get_exif_metadata3(image_path): metadata = ImageMetadata(image_path) metadata.read() for item in metadata.exif_keys: tag = metadata[item] print(tag) f = open("Exifinfo.txt","w") f.write(str(tag) + "\n")
def get_exif_metadata3(image_path): metadata = ImageMetadata(image_path) metadata.read() for item in metadata.exif_keys: tag = metadata[item] print(tag) f = open("Exifinfo.txt", "w") f.write(str(tag) + "\n")
def getComment(self, filePath): """Function to retrieve comment from JPEG file""" """ Get comment info from the image specified filePath: full path of the image file """ metadata = ImageMetadata(filePath) metadata.read() return metadata.comment
def Extract(foto): metadata = ImageMetadata(foto) metadata.read() for item in metadata.exif_keys: tag = metadata[item] print tag f = open("Exifinfo.txt","a") f.write(str(tag) + "\n")
def exif3meta(image_path): print(GR+' [*] Reading METADATA info...') metadata = ImageMetadata(image_path) metadata.read() print(O+' [!] Found '+GR+str(len(metadata.exif_keys))+O+' keys...') for item in metadata.exif_keys: tag = metadata[item] print(C+' [+] '+str(tag).split('[')[0]+B+' ['+str(tag).split('[')[1].split(']')[0]+'] = '+GR+str(tag).split('=')[1].strip()) time.sleep(0.2)
def read_meta(src, dest): try: s = ImageMetadata(src) s.read() d = ImageMetadata(dest) d.read() except: print 'Unable to read the metadata for source or dest image.' raise return s, d
def write_metadata(src_image, dest_image): meta_source = ImageMetadata(src_image) meta_dest = ImageMetadata(dest_image) meta_dest.read() meta_source.read() for k in meta_source.exif_keys[:]: try: meta_dest[k] = ExifTag(k, meta_source[k].value) except Exception as e: continue meta_dest.write(preserve_timestamps=True)
def getExif(self, filename): """Return a dictionary of the metadata. """ ret = {} image = ImageMetadata(filename) try: image.read() except IOError: return ret for tag in image.values(): ret[tag.key] = tag.value return ret
def fetch_exif(filename): """Load EXIF data from disk. >>> fetch_exif('demo/2010 10 16.gpx') Traceback (most recent call last): IOError: demo/2010 10 16.gpx: The file contains data of an unknown image type >>> type(fetch_exif('demo/IMG_2411.JPG')) <class 'pyexiv2.metadata.ImageMetadata'> """ exif = ImageMetadata(filename) exif.read() return exif
def setComment(self, filePath, comment): """ Set comment info to the image specified filePath: full path of the image file comment: contains comment tag info """ metadata = ImageMetadata(filePath) metadata.read() try: metadata.comment = comment metadata.write() return True except Exception as e: return False
def add_tag_to_picture(filename: str, tag: str): metadata = ImageMetadata(filename) metadata.read() current_tags = [] if 'Exif.Photo.UserComment' in metadata: userdata = json.loads(metadata['Exif.Photo.UserComment'].value) if userdata["tags"] is not None: current_tags = list(userdata["tags"]) tags = [tag] + current_tags metadata = ImageMetadata(filename) metadata.read() userdata = {'tags': tags} metadata['Exif.Photo.UserComment'] = json.dumps(userdata) metadata.write() return True
def remove_tag_from_picture(filename: str, tag: str): metadata = ImageMetadata(filename) metadata.read() if 'Exif.Photo.UserComment' not in metadata: print("Exif.Photo.UserComment does not exist in metadata") return False userdata = json.loads(metadata['Exif.Photo.UserComment'].value) current_tags = [] if userdata["tags"] is not None else list( userdata["tags"]) if len(current_tags) > 0: current_tags.remove(tag) metadata = ImageMetadata(filename) metadata.read() userdata = {'tags': current_tags} metadata['Exif.Photo.UserComment'] = json.dumps(userdata) metadata.write() return True
def write(self, fname, instr, date, time, xaxis, yaxis, xunits, yunits, filter): metadata = ImageMetadata(fname) metadata.read() userdata = { 'File name': fname, 'Instrument': instr, 'Date': date, 'Time': time, 'X-Axis': xaxis, 'X-units': xunits, 'Y-units': yunits, 'Y-Axis': yaxis, 'Filter': filter, } metadata['Exif.Photo.UserComment'] = json.dumps(userdata) metadata.write()
def parsePhoto(self, photoPwd): chdir(photoPwd) for photo in listdir(photoPwd): if path.isfile(photo): metadata = ImageMetadata(photo) metadata.read() dt = metadata['Exif.Photo.DateTimeOriginal'].value _datetime, coord = self.getCoord(dt) #metadata['GPS.GPSVersionID'] = '2.2.0.0' #metadata['GPS.GPSLatitude'] = 0 #metadata['GPS.GPSLongitude'] = 2 #metadata[''] = 3 #metadata.write() print '%s %s %s %s' % (photo, dt, _datetime, coord)
def all_photos_in_dir(photo_dir: str, year: str, date: str) -> dict: today_photos = {} if os.path.isdir(photo_dir): for file in os.listdir(photo_dir): if file.lower().endswith( ('.png', '.jpg', '.jpeg', '.tiff', '.bmp', '.gif')): tags = [] try: file_name = "./static/photos/" + year + "/" + date + "/" + file metadata = ImageMetadata(file_name) metadata.read() if 'Exif.Photo.UserComment' in metadata: userdata = json.loads( metadata['Exif.Photo.UserComment'].value) if userdata["tags"] is not None: tags = list(userdata["tags"]) except Exception as e: logger.error(e) today_photos[year + "/" + date + "/" + file] = tags if file.lower().endswith('.mp4'): today_photos[year + "/" + date + "/" + file] = [] return today_photos
def index(source, destination_dir): """ @param source Source filename to copy. @param destinationDir Destination base directory to copy source to. Final directory name is determined from file. """ try: # Load EXIF information metadata = ImageMetadata(source) metadata.read() # Read the date/time at which the picture was taken tag = metadata['Exif.Image.DateTime'] mtime = tag.value.timetuple() log.debug('Successfully read EXIF from "{s}"'.format(s=source)) except Exception as e: log.debug(e) # Get the last modification time mtime = gmtime(getmtime(source)) # Destination filename destination = join(destination_dir, strftime('%Y', mtime), strftime('%Y-%m-%d', mtime)) # Directory must exist if not isdir(destination): log.debug(f'Create directory: "{destination}"') makedirs(destination, 0o755) # Append filename from source destination = join(destination, basename(source)) log.debug(f'Destination: "{destination}"') # Check if file already exists, skip if it does if exists(destination): log.info('Skipping "{d}", file already exists'.format(d=destination)) return log.info('Copying file "{s}" to directory "{d}"'.format(s=source, d=destination)) # Copy file copy(source, destination)
sys.exit(0) if (ver_libexiv2 < ver_libexiv2_min): print 'Newer version of libexiv2 required.' sys.exit(1) if (ver_pyexiv2 < ver_pyexiv2_min): print 'Newer version of pyexiv2 required.' sys.exit(1) if (len(sys.argv) != 3): print 'Usage: ' + sys.argv[0] + ' <sourcefile> <targetfile>' sys.exit(1) # Load the image, read the metadata and extract the thumbnail data src_metadata = ImageMetadata(sys.argv[1]) src_metadata.read() tgt_metadata = ImageMetadata(sys.argv[2]) tgt_metadata.read() for groupName, tagList in copy_tags.iteritems(): # print groupName # print tagList for i, tagName in enumerate(tagList): fullkey = 'Exif.' + groupName + '.' + tagName try: tag = src_metadata[fullkey] print fullkey + ': ' + tag.raw_value except KeyError: print "WARNING: can't find EXIF key '" + fullkey + "'" tgt_metadata[fullkey] = tag
from pyexiv2 import ImageMetadata if __name__ == '__main__': metadata1 = ImageMetadata('IMG_TEST_001.jpg') metadata1.read() info1 = metadata1._get_comment() print 'EXIF keys:', metadata1.exif_keys #img.close()
def __init__(self, path): self.path = path md = ImageMetadata(self.path) md.read() self.date = md['Exif.Image.DateTime'].value self.shutter = md['Exif.Nikon3.ShutterCount'].value
def load_exif_data(file): """ Load EXIF data from source file """ metadata = ImageMetadata(file) metadata.read() return metadata
class Photograph(Coordinates): """Represents a single photograph and it's location in space and time.""" def __init__(self, filename, callback, thumb_size=200): """Initialize new Photograph object's attributes with default values.""" self.filename = filename self.callback = callback self.thm_size = thumb_size self.label = None self.iter = None self.exif = None self.thumb = None self.manual = None def read(self): """Load exif data from disk.""" self.exif = ImageMetadata(self.filename) self.timestamp = None self.altitude = None self.latitude = None self.longitude = None self.timezone = None self.manual = False try: self.exif.read() except TypeError: raise IOError Camera(self.exif) # Try to get a thumbnail. try: self.thumb = GdkPixbuf.Pixbuf.new_from_file_at_size( self.filename, self.thm_size, self.thm_size) except GObject.GError: if len(self.exif.previews) > 0: data = self.exif.previews[-1].data elif len(self.exif.exif_thumbnail.data) > 0: data = self.exif.exif_thumbnail.data else: raise IOError self.thumb = GdkPixbuf.Pixbuf.new_from_stream_at_scale( Gio.MemoryInputStream.new_from_data(data, None), self.thm_size, self.thm_size, True, None) self.calculate_timestamp() try: self.latitude = dms_to_decimal( *self.exif[GPS + 'Latitude'].value + [self.exif[GPS + 'LatitudeRef'].value]) self.longitude = dms_to_decimal( *self.exif[GPS + 'Longitude'].value + [self.exif[GPS + 'LongitudeRef'].value]) except KeyError: pass try: self.altitude = float(self.exif[GPS + 'Altitude'].value) if int(self.exif[GPS + 'AltitudeRef'].value) > 0: self.altitude *= -1 except KeyError: pass def calculate_timestamp(self): """Determine the timestamp based on the currently selected timezone. This method relies on the TZ environment variable to be set before it is called. If you don't set TZ before calling this method, then it implicitely assumes that the camera and the computer are set to the same timezone. """ try: self.timestamp = int( mktime(self.exif['Exif.Photo.DateTimeOriginal'].value. timetuple())) except KeyError: self.timestamp = int(stat(self.filename).st_mtime) def write(self): """Save exif data to photo file on disk.""" if self.altitude is not None: self.exif[GPS + 'Altitude'] = float_to_rational(self.altitude) self.exif[GPS + 'AltitudeRef'] = '0' if self.altitude >= 0 else '1' self.exif[GPS + 'Latitude'] = decimal_to_dms(self.latitude) self.exif[GPS + 'LatitudeRef'] = 'N' if self.latitude >= 0 else 'S' self.exif[GPS + 'Longitude'] = decimal_to_dms(self.longitude) self.exif[GPS + 'LongitudeRef'] = 'E' if self.longitude >= 0 else 'W' self.exif[GPS + 'MapDatum'] = 'WGS-84' self.exif.write() def set_location(self, lat, lon, ele=None): """Alter the coordinates of this photo.""" if ele is not None: self.altitude = ele self.latitude = lat self.longitude = lon self.position_label() self.lookup_geoname() self.callback(self) def position_label(self): """Maintain correct position and visibility of ChamplainLabel.""" if self.valid_coords(): self.label.set_location(self.latitude, self.longitude) self.label.show() if self.label.get_selected(): self.label.raise_top() else: self.label.hide() def set_label_highlight(self, highlight, transparent): """Set the highlightedness of the given photo's ChamplainLabel.""" if self.label.get_property('visible'): self.label.set_scale(*[1.1 if highlight else 1] * 2) self.label.set_selected(highlight) self.label.set_opacity( 64 if transparent and not highlight else 255) if highlight: self.label.raise_top() def set_geodata(self, data): """Override Coordinates.set_geodata to apply directly into IPTC.""" city, state, country, tz = data self.exif[IPTC + 'City'] = [city or ''] self.exif[IPTC + 'ProvinceState'] = [get_state(country, state) or ''] self.exif[IPTC + 'CountryName'] = [get_country(country) or ''] self.exif[IPTC + 'CountryCode'] = [country or ''] self.timezone = tz.strip() def pretty_geoname(self): """Override Coordinates.pretty_geoname to read from IPTC.""" names = [] for key in ['City', 'ProvinceState', 'CountryName']: try: names.extend(self.exif[IPTC + key].values) except KeyError: pass length = sum(map(len, names)) return format_list(names, ',\n' if length > 35 else ', ')
def get_datetime_of_image(img_path: Path) -> datetime: meta = ImageMetadata(str(img_path)) meta.read() return meta.get("Exif.Image.DateTime").value
data extracted from an image. The path to the image file from which the thumbnail data should be extracted should be passed as the only argument of the script. It is of course assumed that you have pygtk installed. """ if (len(sys.argv) != 2): print 'Usage: ' + sys.argv[0] + ' path/to/picture/file/containing/jpeg/thumbnail' sys.exit(1) app = gtk.Window(gtk.WINDOW_TOPLEVEL) app.connect('destroy', lambda app: gtk.main_quit()) # Load the image, read the metadata and extract the thumbnail data metadata = ImageMetadata(sys.argv[1]) metadata.read() previews = metadata.previews if not previews: print "This image doesn't contain any thumbnail." sys.exit(1) # Get the largest preview available preview = previews[-1] # Create a pixbuf loader to read the thumbnail data pbloader = gtk.gdk.PixbufLoader() pbloader.write(preview.data) # Get the resulting pixbuf and build an image to be displayed pixbuf = pbloader.get_pixbuf() pbloader.close() imgwidget = gtk.Image()
class Photograph(Coordinates): """Represents a single photograph and it's location in space and time.""" liststore = get_obj('loaded_photos') def __init__(self, filename, thumb_size=200): """Initialize new Photograph object's attributes with default values.""" self.filename = filename self.thm_size = thumb_size self.label = None self.exif = None self.thumb = None self.manual = None self.camera = None self.iter = None def read(self): """Load exif data from disk.""" self.exif = ImageMetadata(self.filename) self.timestamp = None self.altitude = None self.latitude = None self.longitude = None self.timezone = None self.manual = False try: self.exif.read() except TypeError: raise IOError self.camera = get_camera(self) # Try to get a thumbnail. try: self.thumb = GdkPixbuf.Pixbuf.new_from_file_at_size( self.filename, self.thm_size, self.thm_size) except GObject.GError: if len(self.exif.previews) > 0: data = self.exif.previews[-1].data elif len(self.exif.exif_thumbnail.data) > 0: data = self.exif.exif_thumbnail.data else: raise IOError self.thumb = GdkPixbuf.Pixbuf.new_from_stream_at_scale( Gio.MemoryInputStream.new_from_data(data, None), self.thm_size, self.thm_size, True, None) # If we're reloading, then hide the label and clear the ListStore, # but if we're loading afresh then we'll need a new iter... if self.label is not None: self.label.hide() if self.thm_size < 250: if self.iter is None: self.iter = self.liststore.append() self.liststore.set_row(self.iter, [self.filename, self.long_summary(), self.thumb, self.timestamp]) self.calculate_timestamp() try: self.latitude = dms_to_decimal( *self.exif[GPS + 'Latitude'].value + [self.exif[GPS + 'LatitudeRef'].value] ) self.longitude = dms_to_decimal( *self.exif[GPS + 'Longitude'].value + [self.exif[GPS + 'LongitudeRef'].value] ) except KeyError: pass try: self.altitude = float(self.exif[GPS + 'Altitude'].value) if int(self.exif[GPS + 'AltitudeRef'].value) > 0: self.altitude *= -1 except KeyError: pass def calculate_timestamp(self): """Determine the timestamp based on the currently selected timezone. This method relies on the TZ environment variable to be set before it is called. If you don't set TZ before calling this method, then it implicitely assumes that the camera and the computer are set to the same timezone. """ try: self.timestamp = int(mktime( self.exif['Exif.Photo.DateTimeOriginal'].value.timetuple())) except KeyError: self.timestamp = int(stat(self.filename).st_mtime) self.timestamp += self.camera.get_offset() if self.label is not None: auto_timestamp_comparison(self) def write(self): """Save exif data to photo file on disk.""" if self.altitude is not None: self.exif[GPS + 'Altitude'] = float_to_rational(self.altitude) self.exif[GPS + 'AltitudeRef'] = '0' if self.altitude >= 0 else '1' self.exif[GPS + 'Latitude'] = decimal_to_dms(self.latitude) self.exif[GPS + 'LatitudeRef'] = 'N' if self.latitude >= 0 else 'S' self.exif[GPS + 'Longitude'] = decimal_to_dms(self.longitude) self.exif[GPS + 'LongitudeRef'] = 'E' if self.longitude >= 0 else 'W' self.exif[GPS + 'MapDatum'] = 'WGS-84' self.exif.write() modified.discard(self) self.liststore.set_value(self.iter, 1, self.long_summary()) def set_location(self, lat, lon, ele=None): """Alter the coordinates of this photo.""" if ele is not None: self.altitude = ele self.latitude = lat self.longitude = lon self.position_label() self.lookup_geoname() self.modify_summary() def modify_summary(self): """Update the text displayed in the GtkListStore.""" modified.add(self) self.liststore.set_value(self.iter, 1, ('<b>%s</b>' % self.long_summary())) def position_label(self): """Maintain correct position and visibility of ChamplainLabel.""" if self.label.get_parent() is None: return if self.valid_coords(): self.label.set_location(self.latitude, self.longitude) self.label.show() if self.label.get_selected(): self.label.raise_top() else: self.label.hide() def set_label_highlight(self, highlight, transparent): """Set the highlightedness of the given photo's ChamplainLabel.""" if self.label.get_property('visible'): self.label.set_scale(*[1.1 if highlight else 1] * 2) self.label.set_selected(highlight) self.label.set_opacity(64 if transparent and not highlight else 255) if highlight: self.label.raise_top() def set_geodata(self, data): """Override Coordinates.set_geodata to apply directly into IPTC.""" city, state, country, tz = data self.exif[IPTC + 'City'] = [city or ''] self.exif[IPTC + 'ProvinceState'] = [get_state(country, state) or ''] self.exif[IPTC + 'CountryName'] = [get_country(country) or ''] self.exif[IPTC + 'CountryCode'] = [country or ''] self.timezone = tz.strip() self.camera.set_found_timezone(self.timezone) def pretty_geoname(self): """Override Coordinates.pretty_geoname to read from IPTC.""" names = [] for key in [ 'City', 'ProvinceState', 'CountryName' ]: try: names.extend(self.exif[IPTC + key].values) except KeyError: pass return ', '.join([name for name in names if name]) def destroy(self): """Agony!""" self.label.unmap() self.label.destroy() self.camera.photos.discard(self) del photos[self.filename] modified.discard(self) self.liststore.remove(self.iter)
class GPSImage: def __init__(self, dirname, filename): self.path = dirname + '/' + filename #improve this using os.utils and concatenate locations self.filename = filename self.dirname = dirname self.id = str(uuid.uuid4()) self.thumb = self.generate_thumbnail() try: self.metadata = Metadata(self.path) self.metadata.read() except IOError: print "File " + self.path + " is not a valid image file" try: self.lng_tuple = self.metadata['Exif.GPSInfo.GPSLongitude'] self.lat_tuple = self.metadata['Exif.GPSInfo.GPSLatitude'] self.lng = self.coord_to_decimal(self.lng_tuple) self.lat = self.coord_to_decimal(self.lat_tuple) self.lng_ref = self.metadata['Exif.GPSInfo.GPSLongitudeRef'].value self.lat_ref = self.metadata['Exif.GPSInfo.GPSLatitudeRef'].value if(self.lng_ref == 'W'): self.lng = - self.lng if(self.lat_ref == 'S'): self.lat = - self.lat except KeyError: self.lng = 0 self.lat = 0 print "GPS tags not available for " + self.filename #The EXIF data may optionally embed a thumbnail in the JPEG or TIFF format. The thumbnail can be accessed, set from a JPEG file or buffer, saved to disk and erased: #thumb = metadata.exif_thumbnail #thumb.set_from_file('/tmp/thumbnail.jpg') #thumb.write_to_file('/tmp/copy') #thumb.erase() #metadata.write() def generate_thumbnail(self): ext = ".jpg" thumbs_dir = self.create_thumbs_dir() thumb_img = thumbs_dir + self.filename.split(".")[0] + "_thumb" + ext if os.path.exists(thumb_img): print "Thumb for " + self.filename + " found & skipped." return thumb_img image = Image.open(self.path) image = image.resize((128, 128), Image.ANTIALIAS) image.save(thumb_img) return thumb_img def create_thumbs_dir(self): dir_path = self.dirname + "/.thumbs/" if not os.path.exists(dir_path): os.makedirs(dir_path) return dir_path def print_gps_data(self): keys = [ 'Exif.GPSInfo.GPSMeasureMode', 'Exif.GPSInfo.GPSVersionID', 'Exif.GPSInfo.GPSLatitudeRef', 'Exif.GPSInfo.GPSLatitude', 'Exif.GPSInfo.GPSLongitudeRef', 'Exif.GPSInfo.GPSLongitude', 'Exif.GPSInfo.GPSTimeStamp', 'Exif.GPSInfo.GPSSatellites' ] for key in keys: print self.metadata[key].raw_value def print_coords(self): print 'Longitude: ' + str(self.lng) print 'Latitude: ' + str(self.lat) print '' def coord_to_decimal(self, coord): (degree, minute, second) = coord.value return (float(degree.numerator)/degree.denominator + float(minute.numerator)/minute.denominator/60 + float(second.numerator)/second.denominator/3600)
class Photograph(Coordinates): """Represents a single photograph and it's location in space and time.""" def __init__(self, filename, callback, thumb_size=200): """Initialize new Photograph object's attributes with default values.""" self.filename = filename self.callback = callback self.thm_size = thumb_size self.label = None self.iter = None self.exif = None self.thumb = None self.manual = None def read(self): """Load exif data from disk.""" self.exif = ImageMetadata(self.filename) self.timestamp = None self.altitude = None self.latitude = None self.longitude = None self.timezone = None self.manual = False try: self.exif.read() except TypeError: raise IOError Camera(self.exif) # Try to get a thumbnail. try: self.thumb = GdkPixbuf.Pixbuf.new_from_file_at_size( self.filename, self.thm_size, self.thm_size) except GObject.GError: if len(self.exif.previews) > 0: data = self.exif.previews[-1].data elif len(self.exif.exif_thumbnail.data) > 0: data = self.exif.exif_thumbnail.data else: raise IOError self.thumb = GdkPixbuf.Pixbuf.new_from_stream_at_scale( Gio.MemoryInputStream.new_from_data(data, None), self.thm_size, self.thm_size, True, None) self.calculate_timestamp() try: self.latitude = dms_to_decimal( *self.exif[GPS + 'Latitude'].value + [self.exif[GPS + 'LatitudeRef'].value] ) self.longitude = dms_to_decimal( *self.exif[GPS + 'Longitude'].value + [self.exif[GPS + 'LongitudeRef'].value] ) except KeyError: pass try: self.altitude = float(self.exif[GPS + 'Altitude'].value) if int(self.exif[GPS + 'AltitudeRef'].value) > 0: self.altitude *= -1 except KeyError: pass def calculate_timestamp(self): """Determine the timestamp based on the currently selected timezone. This method relies on the TZ environment variable to be set before it is called. If you don't set TZ before calling this method, then it implicitely assumes that the camera and the computer are set to the same timezone. """ try: self.timestamp = int(mktime( self.exif['Exif.Photo.DateTimeOriginal'].value.timetuple())) except KeyError: self.timestamp = int(stat(self.filename).st_mtime) def write(self): """Save exif data to photo file on disk.""" if self.altitude is not None: self.exif[GPS + 'Altitude'] = float_to_rational(self.altitude) self.exif[GPS + 'AltitudeRef'] = '0' if self.altitude >= 0 else '1' self.exif[GPS + 'Latitude'] = decimal_to_dms(self.latitude) self.exif[GPS + 'LatitudeRef'] = 'N' if self.latitude >= 0 else 'S' self.exif[GPS + 'Longitude'] = decimal_to_dms(self.longitude) self.exif[GPS + 'LongitudeRef'] = 'E' if self.longitude >= 0 else 'W' self.exif[GPS + 'MapDatum'] = 'WGS-84' self.exif.write() def set_location(self, lat, lon, ele=None): """Alter the coordinates of this photo.""" if ele is not None: self.altitude = ele self.latitude = lat self.longitude = lon self.position_label() self.lookup_geoname() self.callback(self) def position_label(self): """Maintain correct position and visibility of ChamplainLabel.""" if self.valid_coords(): self.label.set_location(self.latitude, self.longitude) self.label.show() if self.label.get_selected(): self.label.raise_top() else: self.label.hide() def set_label_highlight(self, highlight, transparent): """Set the highlightedness of the given photo's ChamplainLabel.""" if self.label.get_property('visible'): self.label.set_scale(*[1.1 if highlight else 1] * 2) self.label.set_selected(highlight) self.label.set_opacity(64 if transparent and not highlight else 255) if highlight: self.label.raise_top() def set_geodata(self, data): """Override Coordinates.set_geodata to apply directly into IPTC.""" city, state, country, tz = data self.exif[IPTC + 'City'] = [city or ''] self.exif[IPTC + 'ProvinceState'] = [get_state(country, state) or ''] self.exif[IPTC + 'CountryName'] = [get_country(country) or ''] self.exif[IPTC + 'CountryCode'] = [country or ''] self.timezone = tz.strip() def pretty_geoname(self): """Override Coordinates.pretty_geoname to read from IPTC.""" names = [] for key in [ 'City', 'ProvinceState', 'CountryName' ]: try: names.extend(self.exif[IPTC + key].values) except KeyError: pass length = sum(map(len, names)) return format_list(names, ',\n' if length > 35 else ', ')
def read_exif(self, input_temp_file): fields = [ 'ImageSize', 'ProfileDescription', 'ColorType', 'FileType', 'Transparency' ] fields += self.context.config.EXIF_FIELDS_TO_KEEP command = [ '-s', '-s', ] command += ['-{0}'.format(i) for i in fields] # T172556 We read EXIF Orientation with pyexiv2 because exiftool is # unreliable for that field (overzealous in the way it interprets the field). # We can't replace all use of exiftool with pyexiv2 because ICC profile # support was only introduced in exiv2 0.26 (not available on Jessie yet) # and it can only extract the ICC profile, not get its name/description upfront. # Which would make the sRGB replacement more difficult (it's unclear how many # variations of the binary content for that family of profiles there are). metadata = ImageMetadata(input_temp_file.name) try: # T178072 pyexviv2 writes to stderr even if the exception is caught logging.disable(logging.ERROR) metadata.read() logging.disable(logging.NOTSET) if 'Exif.Image.Orientation' in metadata.exif_keys: # Distinctive key name to avoid colliding with EXIF_FIELDS_TO_KEEP self.exif['Pyexiv2Orientation'] = metadata.get('Exif.Image.Orientation').value except IOError: logging.disable(logging.NOTSET) self.debug('[IM] Could not read EXIF with pyexiv2') stdout = Engine.exiftool.command( context=self.context, pre=command, input_temp_file=input_temp_file ) for s in stdout.splitlines(): values = s.split(': ', 1) self.exif[values[0]] = values[1] self.debug('[IM] EXIF: %r' % self.exif) if 'ImageSize' in self.exif: self.internal_size = map(int, self.exif['ImageSize'].split('x')) else: # Have not been able to find a test file where that EXIF field comes up unpopulated self.internal_size = (1, 1) # pragma: no cover # If we encounter any non-sRGB ICC profile, we save it to re-apply # it to the result if 'ProfileDescription' not in self.exif: self.debug('[IM] File has no ICC profile') return expected_profile = self.context.config.EXIF_TINYRGB_ICC_REPLACE.lower() profile = self.exif['ProfileDescription'].lower() if profile == expected_profile: self.icc_profile_path = self.context.config.EXIF_TINYRGB_PATH self.debug('[IM] File has sRGB profile') return self.debug('[IM] File has non-sRGB profile') command = [ '-icc_profile', '-b', '-m', ] self.icc_profile_saved = Engine.exiftool.command( context=self.context, pre=command, input_temp_file=input_temp_file )
def test3(self, fname): metadata = ImageMetadata(fname) metadata.read() userdata = json.loads(metadata['Exif.Photo.UserComment'].value) pprint.pprint(userdata)
#!/usr/bin/python from pyexiv2 import ImageMetadata import os import time from gi.repository import GdkPixbuf dir = '/d/Pics/Wallpapers/Favorites' s = time.time() i = 0 for i, f in enumerate(os.listdir(dir)): try: file = os.path.join(dir, f) GdkPixbuf.Pixbuf.get_file_info(file) except Exception: pass print i, time.time() - s s = time.time() i = 0 for i, f in enumerate(os.listdir(dir)): try: file = os.path.join(dir, f) meta = ImageMetadata(file) meta.read() except Exception: pass print i, time.time() - s
The path to the image file from which the thumbnail data should be extracted should be passed as the only argument of the script. It is of course assumed that you have pygtk installed. """ if (len(sys.argv) != 2): print 'Usage: ' + sys.argv[ 0] + ' path/to/picture/file/containing/jpeg/thumbnail' sys.exit(1) app = gtk.Window(gtk.WINDOW_TOPLEVEL) app.connect('destroy', lambda app: gtk.main_quit()) # Load the image, read the metadata and extract the thumbnail data metadata = ImageMetadata(sys.argv[1]) metadata.read() previews = metadata.previews if not previews: print "This image doesn't contain any thumbnail." sys.exit(1) # Get the largest preview available preview = previews[-1] # Create a pixbuf loader to read the thumbnail data pbloader = gtk.gdk.PixbufLoader() pbloader.write(preview.data) # Get the resulting pixbuf and build an image to be displayed pixbuf = pbloader.get_pixbuf() pbloader.close() imgwidget = gtk.Image()