def check_iptc_data(self, export_file, options, is_original=False): """Tests if a file has the proper keywords and caption in the meta data.""" if not su.getfileextension(export_file) in ("jpg", "tif", "tiff", "png", "nef", "cr2"): return False (file_keywords, file_caption, date_time_original, rating, gps, region_rectangles, region_names) = exiftool.get_iptc_data(export_file) if options.aperture: # Aperture maintains all these metadata in the preview files, and # does not even save all the information into the .xml file. new_caption = None new_keywords = None new_date = None new_rating = -1 new_gps = None else: new_caption = imageutils.get_photo_caption(self.photo, options.captiontemplate) if not su.equalscontent(file_caption, new_caption): su.pout('Updating IPTC for %s because it has Caption "%s" ' 'instead of "%s".' % (export_file, file_caption, new_caption)) else: new_caption = None new_keywords = self.get_export_keywords(options.face_keywords) if not imageutils.compare_keywords(new_keywords, file_keywords): su.pout("Updating IPTC for %s because of keywords (%s instead " "of %s)" % (export_file, ",".join(file_keywords), ",".join(new_keywords))) else: new_keywords = None new_date = None if self.photo.date and date_time_original != self.photo.date: su.pout("Updating IPTC for %s because of date (%s instead of " "%s)" % (export_file, date_time_original, self.photo.date)) new_date = self.photo.date new_rating = -1 if self.photo.rating != None and rating != self.photo.rating: su.pout( "Updating IPTC for %s because of rating (%d instead of " "%d)" % (export_file, rating, self.photo.rating)) new_rating = self.photo.rating new_gps = None if options.gps and self.photo.gps: if (not gps or not self.photo.gps.is_same(gps)): if gps: old_gps = gps else: old_gps = imageutils.GpsLocation() su.pout("Updating IPTC for %s because of GPS %s vs %s" % (export_file, old_gps.to_string(), self.photo.gps.to_string())) new_gps = self.photo.gps # Don't export the faces into the original file (could have been # cropped). do_faces = options.faces and not is_original (new_rectangles, new_persons) = self._check_person_iptc_data(export_file, region_rectangles, region_names, do_faces) if (new_caption != None or new_keywords != None or new_date or new_gps or new_rating != -1 or new_rectangles or new_persons): if not options.dryrun: exiftool.update_iptcdata(export_file, new_caption, new_keywords, new_date, new_rating, new_gps, new_rectangles, new_persons) return True return False
def generate_update(self, client, options): """Attempts to update a photo. If the media file needs updating, deletes it first, then adds it back in. Args: client - the PicasaWeb client album_id - the id of the album for this photo """ # check albumFile self.picasa_photo = check_media_update(client, self.picasa_photo, self.photo, self.export_file, options) picasa_photo = self.picasa_photo # Now check if any of the meta data needs to be updated. needs_update = False picasa_title = su.unicode_string(picasa_photo.title.text) if self.title != picasa_title: print( 'Updating meta data for %s because it has Caption "%s" ' 'instead of "%s".') % (su.fsenc( self.export_file), su.fsenc(picasa_title), su.fsenc(self.title)) picasa_photo.title.text = self.title needs_update = True # Combine title and description because PicasaWeb does not show the # title anywhere. comment = imageutils.get_photo_caption(self.photo, options.captiontemplate) online_summary = su.unicode_string(picasa_photo.summary.text) if not su.equalscontent(comment, online_summary): print("Updating meta data for " + su.fsenc(self.export_file) + ' because it has description "' + su.fsenc(online_summary) + '" instead of "' + su.fsenc(comment) + '".') picasa_photo.summary.text = comment.strip() needs_update = True if self.photo.date: photo_time = get_picasaweb_date(self.photo.date) if photo_time != picasa_photo.timestamp.text: print( 'Updating meta data for %s because it has timestamp "' '%s" instead of "%s"') % (su.fsenc( self.export_file), picasa_photo.timestamp.datetime(), self.photo.date) picasa_photo.timestamp.text = photo_time needs_update = True export_keywords = self.get_export_keywords(options) picasa_keywords = [] if (picasa_photo.media and picasa_photo.media.keywords and picasa_photo.media.keywords.text): picasa_keywords = su.unicode_string( picasa_photo.media.keywords.text).split(', ') else: picasa_keywords = [] if not imageutils.compare_keywords(export_keywords, picasa_keywords): print("Updating meta data for " + su.fsenc(self.export_file) + " because of keywords (" + su.fsenc(",".join(picasa_keywords)) + ") instead of (" + su.fsenc(",".join(export_keywords)) + ").") if not picasa_photo.media: picasa_photo.media = gdata.media.Group() if not picasa_photo.media.keywords: picasa_photo.media.keywords = gdata.media.Keywords() picasa_photo.media.keywords.text = ', '.join(export_keywords) needs_update = True if options.gps and self.photo.gps: if picasa_photo.geo and picasa_photo.geo.Point: picasa_location = imageutils.GpsLocation().from_gdata_point( picasa_photo.geo.Point) else: picasa_location = imageutils.GpsLocation() if not picasa_location.is_same(self.photo.gps): print("Updating meta data for " + su.fsenc(self.export_file) + " because of GPS " + picasa_location.to_string() + " vs " + self.photo.gps.to_string()) set_picasa_photo_pos(picasa_photo, self.photo.gps) needs_update = True if not needs_update: return if not options.update: print "Needs update: " + su.fsenc(self.export_file) + "." print "Use the -u option to update this file." return print("Updating metadata: " + self.export_file) if options.dryrun: return retry = 0 wait_time = 1.0 while True: try: client.throttle() picasa_photo = client.gd_client.UpdatePhotoMetadata( picasa_photo) return except gdata.photos.service.GooglePhotosException, e: retry += 1 if retry == 10: raise e if str(e).find("17 REJECTED_USER_LIMIT") == -1: raise e wait_time = wait_time * 2 print("Retrying after " + wait_time + "s because of " + str(e)) time.sleep(wait_time)
def check_iptc_data(self, export_file, options, is_original=False, file_updated=False): """Tests if a file has the proper keywords and caption in the meta data.""" if not su.getfileextension(export_file) in _EXIF_EXTENSIONS: return False messages = [] iptc_data = exiftool.get_iptc_data(export_file) new_caption = imageutils.get_photo_caption(self.photo, self.container, options.captiontemplate) if not su.equalscontent(iptc_data.caption, new_caption): messages.append(u' File caption: %s' % (su.nn_string(iptc_data.caption).strip())) messages.append(u' iPhoto caption: %s' % (new_caption)) else: new_caption = None new_keywords = None new_date = None new_rating = -1 new_keywords = self.get_export_keywords(options.face_keywords) if not imageutils.compare_keywords(new_keywords, iptc_data.keywords): messages.append(u' File keywords: %s' % (u','.join(iptc_data.keywords))) if new_keywords == None: messages.append(u' iPhoto keywords: <None>') else: messages.append(u' iPhoto keywords: %s' % (u','.join(new_keywords))) else: new_keywords = None if not options.aperture: #if self.photo.date and date_time_original != self.photo.date: # messages.append(u' File date: %s' % (date_time_original)) # messages.append(u' iPhoto date: %s' % (self.photo.date)) # new_date = self.photo.date if self.photo.rating != None and iptc_data.rating != self.photo.rating: messages.append(u' File rating: %d' % (iptc_data.rating)) messages.append(u' iPhoto rating: %d' % (self.photo.rating)) new_rating = self.photo.rating else: if options.face_keywords: merged_keywords = iptc_data.keywords[:] for keyword in self.photo.getfaces(): if not keyword in merged_keywords: merged_keywords.append(keyword) new_keywords = merged_keywords if iptc_data.hierarchical_subject and not options.reverse: messages.append(u' File subjects: %s' % (u','.join(iptc_data.hierarchical_subject))) new_gps = None if options.gps and self.photo.gps: if (not iptc_data.gps or not self.photo.gps.is_same(iptc_data.gps)): if iptc_data.gps: old_gps = iptc_data.gps else: old_gps = imageutils.GpsLocation() messages.append(u' File GPS: %s' % (old_gps.to_string())) messages.append(u' iPhoto GPS: %s' % (self.photo.gps.to_string())) new_gps = self.photo.gps # Don't export the faces into the original file (could have been # cropped). do_faces = options.faces and not is_original (new_rectangles, new_persons) = self._check_person_iptc_data( export_file, iptc_data.region_rectangles, iptc_data.region_names, do_faces, messages) if (new_caption != None or new_keywords != None or new_date or (not options.reverse and iptc_data.hierarchical_subject) or new_gps or new_rating != -1 or new_rectangles != None or new_persons != None): su.pout(u'Updating IPTC for %s because of\n%s' % (export_file, u'\n'.join(messages))) if (file_updated or imageutils.should_update(options)) and not options.dryrun: exiftool.update_iptcdata(export_file, new_caption, new_keywords, new_date, new_rating, new_gps, new_rectangles, new_persons, iptc_data.image_width, iptc_data.image_height, hierarchical_subject=[]) return True return False
def check_iptc_data(self, export_file, options, is_original=False): """Tests if a file has the proper keywords and caption in the meta data.""" if not su.getfileextension(export_file) in ("jpg", "tif", "tiff", "png", "nef", "cr2"): return False (file_keywords, file_caption, date_time_original, rating, gps, region_rectangles, region_names) = exiftool.get_iptc_data( export_file) if options.aperture: # Aperture maintains all these metadata in the preview files, and # does not even save all the information into the .xml file. new_caption = None new_keywords = None new_date = None new_rating = -1 new_gps = None else: new_caption = imageutils.get_photo_caption(self.photo, options.captiontemplate) if not su.equalscontent(file_caption, new_caption): su.pout('Updating IPTC for %s because it has Caption "%s" ' 'instead of "%s".' % (export_file, file_caption, new_caption)) else: new_caption = None new_keywords = self.get_export_keywords(options.face_keywords) if not imageutils.compare_keywords(new_keywords, file_keywords): su.pout("Updating IPTC for %s because of keywords (%s instead " "of %s)" % (export_file, ",".join(file_keywords), ",".join(new_keywords))) else: new_keywords = None new_date = None if self.photo.date and date_time_original != self.photo.date: su.pout("Updating IPTC for %s because of date (%s instead of " "%s)" % (export_file, date_time_original, self.photo.date)) new_date = self.photo.date new_rating = -1 if self.photo.rating != None and rating != self.photo.rating: su.pout("Updating IPTC for %s because of rating (%d instead of " "%d)" % (export_file, rating, self.photo.rating)) new_rating = self.photo.rating new_gps = None if options.gps and self.photo.gps: if (not gps or not self.photo.gps.is_same(gps)): if gps: old_gps = gps else: old_gps = imageutils.GpsLocation() su.pout("Updating IPTC for %s because of GPS %s vs %s" % (export_file, old_gps.to_string(), self.photo.gps.to_string())) new_gps = self.photo.gps # Don't export the faces into the original file (could have been # cropped). do_faces = options.faces and not is_original (new_rectangles, new_persons) = self._check_person_iptc_data( export_file, region_rectangles, region_names, do_faces) if (new_caption != None or new_keywords != None or new_date or new_gps or new_rating != -1 or new_rectangles or new_persons): if not options.dryrun: exiftool.update_iptcdata(export_file, new_caption, new_keywords, new_date, new_rating, new_gps, new_rectangles, new_persons) return True return False
def generate_update(self, client, options): """Attempts to update a photo. If the media file needs updating, deletes it first, then adds it back in. Args: client - the PicasaWeb client album_id - the id of the album for this photo """ # check albumFile self.picasa_photo = check_media_update(client, self.picasa_photo, self.photo, self.export_file, options) picasa_photo = self.picasa_photo # Now check if any of the meta data needs to be updated. needs_update = False picasa_title = su.unicode_string(picasa_photo.title.text) if self.title != picasa_title: print ('Updating meta data for %s because it has Caption "%s" ' 'instead of "%s".') % ( su.fsenc(self.export_file), su.fsenc(picasa_title), su.fsenc(self.title), ) picasa_photo.title.text = self.title needs_update = True # Combine title and description because PicasaWeb does not show the # title anywhere. comment = imageutils.get_photo_caption(self.photo, options.captiontemplate) online_summary = su.unicode_string(picasa_photo.summary.text) if not su.equalscontent(comment, online_summary): print ( "Updating meta data for " + su.fsenc(self.export_file) + ' because it has description "' + su.fsenc(online_summary) + '" instead of "' + su.fsenc(comment) + '".' ) picasa_photo.summary.text = comment.strip() needs_update = True if self.photo.date: photo_time = get_picasaweb_date(self.photo.date) if photo_time != picasa_photo.timestamp.text: print ('Updating meta data for %s because it has timestamp "' '%s" instead of "%s"') % ( su.fsenc(self.export_file), picasa_photo.timestamp.datetime(), self.photo.date, ) picasa_photo.timestamp.text = photo_time needs_update = True export_keywords = self.get_export_keywords(options) picasa_keywords = [] if picasa_photo.media and picasa_photo.media.keywords and picasa_photo.media.keywords.text: picasa_keywords = su.unicode_string(picasa_photo.media.keywords.text).split(", ") else: picasa_keywords = [] if not imageutils.compare_keywords(export_keywords, picasa_keywords): print ( "Updating meta data for " + su.fsenc(self.export_file) + " because of keywords (" + su.fsenc(",".join(picasa_keywords)) + ") instead of (" + su.fsenc(",".join(export_keywords)) + ")." ) if not picasa_photo.media: picasa_photo.media = gdata.media.Group() if not picasa_photo.media.keywords: picasa_photo.media.keywords = gdata.media.Keywords() picasa_photo.media.keywords.text = ", ".join(export_keywords) needs_update = True if options.gps and self.photo.gps: if picasa_photo.geo and picasa_photo.geo.Point: picasa_location = imageutils.GpsLocation().from_gdata_point(picasa_photo.geo.Point) else: picasa_location = imageutils.GpsLocation() if not picasa_location.is_same(self.photo.gps): print ( "Updating meta data for " + su.fsenc(self.export_file) + " because of GPS " + picasa_location.to_string() + " vs " + self.photo.gps.to_string() ) set_picasa_photo_pos(picasa_photo, self.photo.gps) needs_update = True if not needs_update: return if not options.update: print "Needs update: " + su.fsenc(self.export_file) + "." print "Use the -u option to update this file." return print ("Updating metadata: " + self.export_file) if options.dryrun: return retry = 0 wait_time = 1.0 while True: try: client.throttle() picasa_photo = client.gd_client.UpdatePhotoMetadata(picasa_photo) return except gdata.photos.service.GooglePhotosException, e: retry += 1 if retry == 10: raise e if str(e).find("17 REJECTED_USER_LIMIT") == -1: raise e wait_time = wait_time * 2 print ("Retrying after " + wait_time + "s because of " + str(e)) time.sleep(wait_time)