Example #1
0
    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
Example #2
0
    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)
Example #3
0
    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
Example #4
0
    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
Example #5
0
    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)
Example #6
0
    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