Exemple #1
0
 def __init__(self, photo, container, export_directory, base_name, options):
     """Creates a new ExportFile object."""
     self.photo = photo
     self.container = container
     # We cannot resize movie files.
     if options.size and not imageutils.is_movie_file(photo.image_path):
         self.size = options.size
         extension = 'jpg'
     else:
         self.size = None
         extension = su.getfileextension(photo.image_path)
     self.export_file = os.path.join(
         export_directory, base_name + '.' + extension)
     # Location of "Original" file, if any.
     originals_folder = u"Originals"
     if options.picasa:
         if (os.path.exists(os.path.join(export_directory,
                                         u".picasaoriginals")) or
             not os.path.exists(os.path.join(export_directory,
                                             u"Originals"))):
             originals_folder = u".picasaoriginals"
     if photo.originalpath:
         self.original_export_file = os.path.join(
             export_directory, originals_folder, base_name + "." +
             su.getfileextension(photo.originalpath))
     else:
         self.original_export_file = None
 def __init__(self, photo, container, export_directory, base_name, options):
     """Creates a new ExportFile object."""
     self.photo = photo
     self.container = container
     # We cannot resize movie files.
     if options.size and not imageutils.is_movie_file(photo.image_path):
         self.size = options.size
         extension = 'jpg'
     else:
         self.size = None
         extension = su.getfileextension(photo.image_path)
     self.export_file = os.path.join(
         export_directory, base_name + '.' + extension)
     # Location of "Original" file, if any.
     originals_folder = u"Originals"
     if options.picasa:
         if (os.path.exists(os.path.join(export_directory,
                                         u".picasaoriginals")) or
             not os.path.exists(os.path.join(export_directory,
                                             u"Originals"))):
             originals_folder = u".picasaoriginals"
     if photo.originalpath:
         self.original_export_file = os.path.join(
             export_directory, originals_folder, base_name + "." +
             su.getfileextension(photo.originalpath))
     else:
         self.original_export_file = None
Exemple #3
0
 def __init__(self, photo, album_name, base_name, options):
     """Creates a new PicasaFile object."""
     self.photo = photo
     self.title = base_name
     if options.size:
         extension = "jpg"
     else:
         extension = su.getfileextension(photo.image_path)
     self.export_file = os.path.join(album_name, base_name + "." + extension)
     self.picasa_photo = None
Exemple #4
0
 def __init__(self, photo, album_name, base_name, options):
     """Creates a new PicasaFile object."""
     self.photo = photo
     self.title = base_name
     if options.size:
         extension = "jpg"
     else:
         extension = su.getfileextension(photo.image_path)
     self.export_file = os.path.join(album_name,
                                     base_name + '.' + extension)
     self.picasa_photo = None
Exemple #5
0
 def __init__(self, photo, export_directory, base_name, options):
     """Creates a new ExportFile object."""
     self.photo = photo
     if options.size:
         extension = "jpg"
     else:
         extension = su.getfileextension(photo.image_path)
     self.export_file = os.path.join(
         export_directory, base_name + '.' + extension)
     # Location of "Original" file, if any.
     originals_folder = u"Originals"
     if options.picasa:
         if (os.path.exists(os.path.join(export_directory,
                                         u".picasaoriginals")) or
             not os.path.exists(os.path.join(export_directory,
                                             u"Originals"))):
             originals_folder = u".picasaoriginals"
     if photo.originalpath:
         self.original_export_file = os.path.join(
             export_directory, originals_folder, base_name + "." +
             su.getfileextension(photo.originalpath))
     else:
         self.original_export_file = None
Exemple #6
0
 def __init__(self, photo, export_directory, base_name, options):
     """Creates a new ExportFile object."""
     self.photo = photo
     if options.size:
         extension = "jpg"
     else:
         extension = su.getfileextension(photo.image_path)
     self.export_file = os.path.join(export_directory,
                                     base_name + '.' + extension)
     # Location of "Original" file, if any.
     originals_folder = u"Originals"
     if options.picasa:
         if (os.path.exists(
                 os.path.join(export_directory, u".picasaoriginals"))
                 or not os.path.exists(
                     os.path.join(export_directory, u"Originals"))):
             originals_folder = u".picasaoriginals"
     if photo.originalpath:
         self.original_export_file = os.path.join(
             export_directory, originals_folder,
             base_name + "." + su.getfileextension(photo.originalpath))
     else:
         self.original_export_file = None
Exemple #7
0
def get_content_type(image_path):
    """Returns the appropriate content type for a media file, based on the
    extension.

    Args:
        image_path: path to the media file.

    Returns:
        Content type string, like "image/jpeg".
    """
    extension = su.getfileextension(image_path)
    if extension == "jpg":
        return "image/jpeg"
    if extension == "mov":
        return "video/quicktime"
    if extension == "m4v":
        return "video/mp4"
    if extension == "avi":
        return "video/avi"
    print >> sys.stderr, ('Uploading of media files with extension %s'
                          ' not supported. Defaulting to image/jpeg: %s') % (
                              extension, image_path)
    return "image/jpeg"
Exemple #8
0
def get_content_type(image_path):
    """Returns the appropriate content type for a media file, based on the
    extension.

    Args:
        image_path: path to the media file.

    Returns:
        Content type string, like "image/jpeg".
    """
    extension = su.getfileextension(image_path)
    if extension == "jpg":
        return "image/jpeg"
    if extension == "mov":
        return "video/quicktime"
    if extension == "m4v":
        return "video/mp4"
    if extension == "avi":
        return "video/avi"
    print >> sys.stderr, (
        "Uploading of media files with extension %s" " not supported. Defaulting to image/jpeg: %s"
    ) % (extension, image_path)
    return "image/jpeg"
Exemple #9
0
    def __init__(self, key, data, keyword_map, face_map, aperture_data):
        self.id = key
        self.data = data
        self._caption = su.nn_string(data.get("Caption")).strip()
        self.comment = su.nn_string(data.get("Comment")).strip()
        version = None
        if aperture_data:
            version = aperture_data.versions.get(key)
        if data.has_key("DateAsTimerInterval"):
            self.date = applexml.getappletime(data.get("DateAsTimerInterval"))
        elif version:
            self.date = version.image_date
        else:
            # Try to get the date from a the caption in "YYYYMMDD ..." format
            m = re.match(_CAPTION_PATTERN, self._caption)
            if m:
                year = int(m.group(1))
                month = int(m.group(2))
                if not month:
                    month = 1
                date = int(m.group(3))
                if not date:
                    date = 1
                self.date = datetime.datetime(year, month, date)
            else:
                self.date = None
        self.mod_date = applexml.getappletime(
            data.get("ModDateAsTimerInterval"))
        self.image_path = data.get("ImagePath")
        if data.has_key("Rating"):
            self.rating = int(data.get("Rating"))
        elif version:
            self.rating = version.mainRating
        else:
            self.rating = None
        if data.get("longitude"):
            latitude = float(data.get("latitude"))
            longitude = float(data.get("longitude"))
            self.gps = imageutils.GpsLocation(latitude, longitude)
        elif version:
            self.gps = version.location
        else:
            self.gps = None

        self.keywords = []
        keyword_list = data.get("Keywords")
        if keyword_list is not None:
            for i in keyword_list:
                self.keywords.append(keyword_map.get(i))
        elif version:
            self.keywords = version.keywords

        if version:
            self.originalpath = None # This is just a placeholder...
            # Use the preview if there are adjustments.
            if (version.rotation or version.hasAdjustments or
                not su.getfileextension(version.master_image_path) in _JPG_EXTENSIONS):
                #if version.rotation:
                #    su.pout(u"Rotated: %s (%d)" % (self._caption, version.rotation))
                #if version.hasAdjustments:
                #    su.pout(u"Adjustments: %s" % (self._caption))
                #if not su.getfileextension(version.master_image_path) in _JPG_EXTENSIONS:
                #    su.pout(u"Not JPEG: %s" % (self._caption))
                self.originalpath = version.master_image_path
                if not version.imageProxy.fullSizePreviewPath:
                    su.pout(u"No preview path for %s." % (self.caption))
                else:
                    self.image_path = version.imageProxy.fullSizePreviewPath
            else:
                self.image_path = version.master_image_path
                self.originalpath = None
            if not version.imageProxy.fullSizePreviewUpToDate:
                su.pout(u"%s: full size preview not up to date." % (self.caption))
        else:
            self.originalpath = data.get("OriginalPath")
        self.roll = data.get("Roll") 

        self.albums = []  # list of albums that this image belongs to
        self.faces = []
        self.face_rectangles = []
        self.event_name = '' # name of event (roll) that this image belongs to
        self.event_index = '' # index within event
        self.event_index0 = '' # index with event, left padded with 0

        face_list = data.get("Faces")
        if face_list:
            for face_entry in face_list:
                face_key = face_entry.get("face key")
                face_name = face_map.get(face_key)
                if face_name:
                    self.faces.append(face_name)
                    # Rectangle is '{{x, y}, {width, height}}' as ratios,
                    # referencing the lower left corner of the face rectangle,
                    # with lower left corner of image as (0,0)
                    rectangle = parse_face_rectangle(face_entry.get("rectangle"))
                    # Convert to using center of area, relative to upper left corner of image
                    rectangle[0] += rectangle[2] / 2.0
                    rectangle[1] = max(0.0, 1.0 - rectangle[1] - rectangle[3] / 2.0)
                    self.face_rectangles.append(rectangle)
                # Other keys in face_entry: face index

                # Now sort the faces left to right.
                sorted_names = {}
                sorted_rectangles = {}
                for i in xrange(len(self.faces)):
                    x = self.face_rectangles[i][0]
                    while sorted_names.has_key(x):
                        x += 0.00001
                    sorted_names[x] = self.faces[i]
                    sorted_rectangles[x] = self.face_rectangles[i]
                self.faces = [sorted_names[x] for x in sorted(sorted_names.keys())]
                self.face_rectangles = [
                    sorted_rectangles[x] for x in sorted(sorted_rectangles.keys())]
Exemple #10
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
Exemple #11
0
def is_movie_file(file_name):
    """Tests if the file (name or full path) is a movie file."""
    return su.getfileextension(file_name) in ("mov", "avi", "m4v", "mpg")
Exemple #12
0
def is_image_file(file_name):
    """Tests if the file (name or full path) is an image file."""
    return su.getfileextension(file_name) in ("jpg", "jpeg", "tif", "png",
                                              "nef")
Exemple #13
0
def is_sharable_image_file(file_name):
    """Tests if the file (name or full path) is an image file in a format suitable for sharing."""
    return su.getfileextension(file_name) in ("jpg", "jpeg", "tif", "png")
    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_need_to_export(self, source_file, options):
        """Returns true if the image file needs to be exported.

        Args:
          source_file: path to image file, with aliases resolved.
          options: processing options.
        """
        if not os.path.exists(self.export_file):
            return True
        # In link mode, check the inode.
        if options.link:
            export_stat = os.stat(self.export_file)
            source_stat = os.stat(source_file)
            if export_stat.st_ino != source_stat.st_ino:
                su.pout('Changed:  %s: inodes don\'t match: %d vs. %d' %
                    (self.export_file, export_stat.st_ino, source_stat.st_ino))
                return True
        if (not options.reverse
            and os.path.getmtime(self.export_file) + _MTIME_FUDGE <
            os.path.getmtime(source_file)):
            su.pout('Changed:  %s: newer version is available: %s vs. %s' %
                    (self.export_file,
                     time.ctime(os.path.getmtime(self.export_file)),
                     time.ctime(os.path.getmtime(source_file))))
            return True

        if (options.reverse
            and os.path.getmtime(source_file) + _MTIME_FUDGE <
            os.path.getmtime(self.export_file)):
            su.pout('Changed:  %s: newer version is available: %s vs. %s' %
                    (self.export_file,
                     time.ctime(os.path.getmtime(source_file)),
                     time.ctime(os.path.getmtime(self.export_file))))
            return True
        
        if not self.size and not options.reverse:
            # With creative renaming in iPhoto it is possible to get
            # stale files if titles get swapped between images. Double
            # check the size, allowing for some difference for meta data
            # changes made in the exported copy
            source_size = os.path.getsize(source_file)
            export_size = os.path.getsize(self.export_file)
            diff = abs(source_size - export_size)
            if diff > _MAX_FILE_DIFF or (diff > 32 and options.link):
                su.pout('Changed:  %s: file size: %d vs. %d' %
                        (self.export_file, export_size, source_size))
                return True

        # In reverse mode, we don't check the file size (might have changed because
        # of Preview regeneration), so we look at the image dimensions instead to catch
        # some out-of-sync images.
        if options.reverse and su.getfileextension(self.export_file) in _EXIF_EXTENSIONS:
            (source_width, source_height) = imageutils.get_image_width_height(source_file)
            (export_width, export_height) = imageutils.get_image_width_height(self.export_file)
            if ((source_width and export_width and source_width != export_width) or
                (source_height and export_height and source_height != export_height)):
                su.pout('Changed:  %s: dimensions: %dx%d vs. %dx%d' % (
                    self.export_file, source_width, source_height, export_width, export_height))
                return True

        # In link mode, we don't need to check the modification date in the
        # database because we catch the changes by the size check above.
        #if (not options.link and
        #    datetime.datetime.fromtimestamp(os.path.getmtime(
        #       self.export_file)) < self.photo.mod_date):
        #    su.pout('Changed:  %s: modified in iPhoto: %s vs. %s ' % (
        #        self.export_file,
        #        time.ctime(os.path.getmtime(self.export_file)),
        #        self.photo.mod_date))
        #    return True
        return False
Exemple #16
0
    def _check_need_to_export(self, source_file, options):
        """Returns true if the image file needs to be exported.

        Args:
          source_file: path to image file, with aliases resolved.
          options: processing options.
        """
        if not os.path.exists(self.export_file):
            return True
        # In link mode, check the inode.
        if options.link:
            export_stat = os.stat(self.export_file)
            source_stat = os.stat(source_file)
            if export_stat.st_ino != source_stat.st_ino:
                su.pout('Changed:  %s: inodes don\'t match: %d vs. %d' %
                    (self.export_file, export_stat.st_ino, source_stat.st_ino))
                return True
        if (not options.reverse
            and os.path.getmtime(self.export_file) + _MTIME_FUDGE <
            os.path.getmtime(source_file)):
            su.pout('Changed:  %s: newer version is available: %s vs. %s' %
                    (self.export_file,
                     time.ctime(os.path.getmtime(self.export_file)),
                     time.ctime(os.path.getmtime(source_file))))
            return True

        if (options.reverse
            and os.path.getmtime(source_file) + _MTIME_FUDGE <
            os.path.getmtime(self.export_file)):
            su.pout('Changed:  %s: newer version is available: %s vs. %s' %
                    (self.export_file,
                     time.ctime(os.path.getmtime(source_file)),
                     time.ctime(os.path.getmtime(self.export_file))))
            return True
        
        if not self.size and not options.reverse:
            # With creative renaming in iPhoto it is possible to get
            # stale files if titles get swapped between images. Double
            # check the size, allowing for some difference for meta data
            # changes made in the exported copy
            source_size = os.path.getsize(source_file)
            export_size = os.path.getsize(self.export_file)
            diff = abs(source_size - export_size)
            if diff > _MAX_FILE_DIFF or (diff > 32 and options.link):
                su.pout('Changed:  %s: file size: %d vs. %d' %
                        (self.export_file, export_size, source_size))
                return True

        # In reverse mode, we don't check the file size (might have changed because
        # of Preview regeneration), so we look at the image dimensions instead to catch
        # some out-of-sync images.
        if options.reverse and su.getfileextension(self.export_file) in _EXIF_EXTENSIONS:
            (source_width, source_height) = imageutils.get_image_width_height(source_file)
            (export_width, export_height) = imageutils.get_image_width_height(self.export_file)
            if ((source_width and export_width and source_width != export_width) or
                (source_height and export_height and source_height != export_height)):
                su.pout('Changed:  %s: dimensions: %dx%d vs. %dx%d' % (
                    self.export_file, source_width, source_height, export_width, export_height))
                return True

        # In link mode, we don't need to check the modification date in the
        # database because we catch the changes by the size check above.
        #if (not options.link and
        #    datetime.datetime.fromtimestamp(os.path.getmtime(
        #       self.export_file)) < self.photo.mod_date):
        #    su.pout('Changed:  %s: modified in iPhoto: %s vs. %s ' % (
        #        self.export_file,
        #        time.ctime(os.path.getmtime(self.export_file)),
        #        self.photo.mod_date))
        #    return True
        return False
Exemple #17
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
Exemple #18
0
    def __init__(self, key, data, keyword_map, face_map, aperture_data):
        self.id = key
        self.data = data
        self._caption = su.nn_string(data.get("Caption")).strip()
        self.comment = su.nn_string(data.get("Comment")).strip()
        version = None
        if aperture_data:
            version = aperture_data.versions.get(key)
        if data.has_key("DateAsTimerInterval"):
            self.date = applexml.getappletime(data.get("DateAsTimerInterval"))
        elif version:
            self.date = version.image_date
        else:
            # Try to get the date from a the caption in "YYYYMMDD ..." format
            m = re.match(_CAPTION_PATTERN, self._caption)
            if m:
                year = int(m.group(1))
                month = int(m.group(2))
                if not month:
                    month = 1
                date = int(m.group(3))
                if not date:
                    date = 1
                self.date = datetime.datetime(year, month, date)
            else:
                self.date = None
        self.mod_date = applexml.getappletime(
            data.get("ModDateAsTimerInterval"))
        self.image_path = data.get("ImagePath")
        if data.has_key("Rating"):
            self.rating = int(data.get("Rating"))
        elif version:
            self.rating = version.mainRating
        else:
            self.rating = None
        if data.get("longitude"):
            latitude = float(data.get("latitude"))
            longitude = float(data.get("longitude"))
            self.gps = imageutils.GpsLocation(latitude, longitude)
        elif version:
            self.gps = version.location
        else:
            self.gps = None

        self.keywords = []
        keyword_list = data.get("Keywords")
        if keyword_list is not None:
            for i in keyword_list:
                self.keywords.append(keyword_map.get(i))
        elif version:
            self.keywords = version.keywords

        if version:
            self.originalpath = None  # This is just a placeholder...
            # Use the preview if there are adjustments.
            if (version.rotation or version.hasAdjustments
                    or not su.getfileextension(
                        version.master_image_path) in _JPG_EXTENSIONS):
                #if version.rotation:
                #    su.pout(u"Rotated: %s (%d)" % (self._caption, version.rotation))
                #if version.hasAdjustments:
                #    su.pout(u"Adjustments: %s" % (self._caption))
                #if not su.getfileextension(version.master_image_path) in _JPG_EXTENSIONS:
                #    su.pout(u"Not JPEG: %s" % (self._caption))
                self.originalpath = version.master_image_path
                if not version.imageProxy.fullSizePreviewPath:
                    su.pout(u"No preview path for %s." % (self.caption))
                else:
                    self.image_path = version.imageProxy.fullSizePreviewPath
            else:
                self.image_path = version.master_image_path
                self.originalpath = None
            if not version.imageProxy.fullSizePreviewUpToDate:
                su.pout(u"%s: full size preview not up to date." %
                        (self.caption))
        else:
            self.originalpath = data.get("OriginalPath")
        self.roll = data.get("Roll")

        self.albums = []  # list of albums that this image belongs to
        self.faces = []
        self.face_rectangles = []
        self.event_name = ''  # name of event (roll) that this image belongs to
        self.event_index = ''  # index within event
        self.event_index0 = ''  # index with event, left padded with 0

        face_list = data.get("Faces")
        if face_list:
            for face_entry in face_list:
                face_key = face_entry.get("face key")
                face_name = face_map.get(face_key)
                if face_name:
                    self.faces.append(face_name)
                    # Rectangle is '{{x, y}, {width, height}}' as ratios,
                    # referencing the lower left corner of the face rectangle,
                    # with lower left corner of image as (0,0)
                    rectangle = parse_face_rectangle(
                        face_entry.get("rectangle"))
                    # Convert to using center of area, relative to upper left corner of image
                    rectangle[0] += rectangle[2] / 2.0
                    rectangle[1] = max(0.0,
                                       1.0 - rectangle[1] - rectangle[3] / 2.0)
                    self.face_rectangles.append(rectangle)
                # Other keys in face_entry: face index

                # Now sort the faces left to right.
                sorted_names = {}
                sorted_rectangles = {}
                for i in xrange(len(self.faces)):
                    x = self.face_rectangles[i][0]
                    while sorted_names.has_key(x):
                        x += 0.00001
                    sorted_names[x] = self.faces[i]
                    sorted_rectangles[x] = self.face_rectangles[i]
                self.faces = [
                    sorted_names[x] for x in sorted(sorted_names.keys())
                ]
                self.face_rectangles = [
                    sorted_rectangles[x]
                    for x in sorted(sorted_rectangles.keys())
                ]
Exemple #19
0
def is_image_file(file_name):
    """Tests if the file (name or full path) is an image file."""
    return su.getfileextension(file_name) in ("jpg", "jpeg", "tif", "png",
                                              "nef")
Exemple #20
0
def is_movie_file(file_name):
    """Tests if the file (name or full path) is a movie file."""
    return su.getfileextension(file_name) in ("mov", "avi", "m4v", "mpg")
Exemple #21
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
Exemple #22
0
def is_sharable_image_file(file_name):
    """Tests if the file (name or full path) is an image file in a format suitable for sharing."""
    return su.getfileextension(file_name) in ("jpg", "jpeg", "tif", "png")