Пример #1
0
def get_metadata(path):
    try:
        exif = GExiv2.Metadata(path=path)
    except TypeError:
        exif = GExiv2.Metadata()
        exif.open_path(path)
    return exif
Пример #2
0
def build_calibration_matrices(i, prev_sensor, K_matrices, filename1,
                               filename2):
    '''Extract exif metadata from image files, and use them to build the 2 calibration matrices.'''
    def get_sensor_sizes(i, prev_sensor, metadata1, metadata2):
        '''Looks up sensor width from the database based on the camera model.'''
        #focal length in pixels = (image width in pixels) * (focal length in mm) / (CCD width in mm)
        if i == 0:
            sensor_1 = cam_db.get_sensor_size(
                metadata1['Exif.Image.Model'].strip().upper())
            sensor_2 = cam_db.get_sensor_size(
                metadata2['Exif.Image.Model'].strip().upper())
        elif i >= 1:
            sensor_1 = prev_sensor
            sensor_2 = cam_db.get_sensor_size(metadata2['Exif.Image.Model'])

    metadata1 = GExiv2.Metadata(filename1)
    metadata2 = GExiv2.Metadata(filename2)

    # if False and metadata1.get_supports_exif() and metadata2.get_supports_exif():
    #         sensor_1, sensor_2 = get_sensor_sizes(i, prev_sensor, metadata1, metadata2)
    # else:
    #     if metadata1.get_supports_exif() == False:
    #             print "Exif data not available for ", filename1
    #     if metadata2.get_supports_exif() == False:
    #             print "Exif data not available for ", filename2
    #     sys.exit("Please try again.")

    # CDANCETTE : Fix sensor size at 30mm
    sensor_1, sensor_2 = 6.35, 6.35
    focal = 50  #3.8 # 50mm
    # CDANCETTE

    # Calibration matrix for camera 1 (K1)
    # f1_mm = metadata1.get_focal_length()
    f1_mm = focal
    w1 = metadata1.get_pixel_width()
    h1 = metadata1.get_pixel_height()
    f1_px = (w1 * f1_mm) / sensor_1
    K1 = np.array([[f1_px, 0, w1 / 2], [0, f1_px, h1 / 2], [0, 0, 1]])

    # Calibration matrix for camera 2 (K2)
    # f2_mm = metadata2.get_focal_length()
    f2_mm = focal
    w2 = metadata2.get_pixel_width()
    h2 = metadata2.get_pixel_height()
    f2_px = (w2 * f2_mm) / sensor_2
    K2 = np.array([[f2_px, 0, w2 / 2], [0, f2_px, h2 / 2], [0, 0, 1]])

    if i == 0:
        K_matrices.append(K1)
        K_matrices.append(K2)
    elif i >= 1:
        K_matrices.append(K2)

    return sensor_2, K_matrices
Пример #3
0
    def resize(self, src, dst):
        src_meta = GExiv2.Metadata(src)
        src_p = QPixmap(src)
        dst_p = src_p.scaled(4500, 3000, Qt.KeepAspectRatio,
                             Qt.SmoothTransformation)

        dst_p.save(src)
        shutil.move(src, dst)

        # copy all the metadata
        dst_meta = GExiv2.Metadata(dst)
        for tag in src_meta.get_tags():
            dst_meta[tag] = src_meta[tag]
        dst_meta.save_file()
Пример #4
0
 def comparePicturesByExifDate(self, curOrigFullFileName):
     try:
         src_exif = GExiv2.Metadata(self.absCopiesOrigDateiName)
         src_ExifDate = src_exif.get_date_time().strftime('%Y%m%d%H%M%S')
         #logging.DEBUG("src-exifTimeStamp for " + self.fileBaseName + " is " + src_ExifDate)
         tgt_exif = GExiv2.Metadata(curOrigFullFileName)
         tgt_ExifDate = tgt_exif.get_date_time().strftime('%Y%m%d%H%M%S')
         #logging.DEBUG("tgt-exifTimeStamp for " + os.path.basename(curOrigFullFileName) + " is " +tgt_ExifDate) )
         if src_ExifDate == tgt_ExifDate:
             return True
         else:
             return False
     except:
         logging.debug("Image does not have exiv date time")
         return False
Пример #5
0
    def write_metadata(self, filepath, info):

        metadata = GExiv2.Metadata()
        metadata.open_path(filepath)

        compressor_name = "compressor v[{}]".format(info["version"])

        # Exif.Image.ProcessingSoftware is overwritten by Lightroom when the final export is done
        key = "Exif.Image.ProcessingSoftware";  metadata.set_tag_string(key, compressor_name)
        key = "Exif.Image.Software";            metadata.set_tag_string(key, compressor_name)

        try:
            key = "Exif.Image.ExposureTime";    metadata.set_exif_tag_rational(key, info["exposure_time"], 1)
        except Exception as e:
            key = "Exif.Image.ExposureTime";    metadata.set_exif_tag_rational(key, info["exposure_time"])
        key = "Exif.Image.ImageNumber";         metadata.set_tag_long(key, info["exposure_count"])
        key = "Exif.Image.DateTimeOriginal";    metadata.set_tag_string(key, info["capture_date"].strftime(self.EXIF_DATE_FORMAT))
        key = "Exif.Image.DateTime";            metadata.set_tag_string(key, info["compressing_date"].strftime(self.EXIF_DATE_FORMAT))

        if info["focal_length"] is not None:
            try:
                key = "Exif.Image.FocalLength"; metadata.set_exif_tag_rational(key, info["focal_length"])
            except Exception as e:
                key = "Exif.Image.FocalLength"; metadata.set_exif_tag_rational(key, info["focal_length"], 1)
        # TODO GPS Location

        metadata.save_file(filepath)
        self.log.debug("metadata written to {}".format(filepath))
Пример #6
0
    def add_meta_data(self, img_path, comment="", rotation="landscape"):
        # Comment tags used by various programs: http://redmine.yorba.org/projects/shotwell/wiki/PhotoTags
        # All the supported tags: http://www.exiv2.org/metadata.html
        metadata = GExiv2.Metadata(img_path)

        metadata['Iptc.Application2.DateCreated'] = self.developed.date(
        ).strftime('%Y-%m-%d')
        metadata[
            'Iptc.Application2.DigitizationDate'] = self.last_digitized.date(
            ).strftime('%Y-%m-%d')
        metadata[
            'Iptc.Application2.DigitizationTime'] = self.last_digitized.time(
            ).strftime('%H:%M:%S%z')
        metadata['Exif.Photo.DateTimeOriginal'] = self.developed.date(
        ).strftime('%Y-%m-%d')
        metadata[
            'Exif.Photo.DateTimeDigitized'] = self.last_digitized.strftime(
                '%Y-%m-%d %H:%M:%S')

        metadata['Iptc.Application2.Caption'] = comment
        metadata['Exif.Image.ImageDescription'] = comment

        # We already rotated correctly, so specify that there are no further
        # rotations.
        #See: http://sylvana.net/jpegcrop/exif_orientation.html
        metadata['Exif.Image.Orientation'] = '1'

        metadata.save_file()
Пример #7
0
 def initialise(cls, config_store, verbosity):
     if not GExiv2.initialize():
         raise RuntimeError('Failed to initialise GExiv2')
     GExiv2.log_set_level(
         max(GExiv2.LogLevel.DEBUG, min(GExiv2.LogLevel.ERROR,
                                        4 - verbosity)))
     GExiv2.log_use_glib_logging()
     # Recent versions of Exiv2 have these namespaces defined, but
     # older versions may not recognise them. The xapGImg URL is
     # invalid, but Photini doesn't write xapGImg so it doesn't
     # matter.
     for prefix, name in (('exifEX', 'http://cipa.jp/exif/1.0/'),
                          ('xapGImg', 'http://ns.adobe.com/xxx/'),
                          ('xmpGImg', 'http://ns.adobe.com/xap/1.0/g/img/'),
                          ('xmpRights',
                           'http://ns.adobe.com/xap/1.0/rights/')):
         GExiv2.Metadata.register_xmp_namespace(name, prefix)
     # Gexiv2 won't register the 'Iptc4xmpExt' namespace as its
     # abbreviated version 'iptcExt' is already defined. This kludge
     # registers it by reading some data with the full namespace
     data = XMP_WRAPPER.format(
         'xmlns:Iptc4xmpExt="http://iptc.org/std/Iptc4xmpExt/2008-02-29/"')
     # open the data to register the namespace
     GExiv2.Metadata().open_buf(data.encode('utf-8'))
     # make list of possible character encodings
     cls.encodings = ['utf-8', 'iso8859-1', 'ascii']
     char_set = locale.getdefaultlocale()[1]
     if char_set:
         try:
             name = codecs.lookup(char_set).name
             if name not in cls.encodings:
                 cls.encodings.append(name)
         except LookupError:
             pass
Пример #8
0
 def merge_sc(self, other):
     # merge sidecar data into image file data, ignoring thumbnails
     raw_sc = GExiv2.Metadata()
     raw_sc.open_path(other._path)
     # allow exiv2 to infer Exif tags from XMP
     for tag in raw_sc.get_exif_tags():
         if tag.startswith('Exif.Thumbnail'):
             continue
         # ignore inferred datetime values the exiv2 gets wrong
         # (I think it's adding the local timezone offset)
         if tag in ('Exif.Image.DateTime', 'Exif.Photo.DateTimeOriginal',
                    'Exif.Photo.DateTimeDigitized'):
             self.clear_tag(tag)
         else:
             value = raw_sc.get_tag_string(tag)
             if value:
                 self.set_tag_string(tag, value)
     # copy all XMP tags except inferred Exif tags
     for tag in raw_sc.get_xmp_tags():
         if tag.startswith('Xmp.xmp.Thumbnails'):
             continue
         ns = tag.split('.')[1]
         if ns in ('exif', 'exifEX', 'tiff', 'aux'):
             # exiv2 will already have supplied the equivalent Exif tag
             pass
         elif self.get_tag_type(tag) == 'XmpText':
             value = raw_sc.get_tag_string(tag)
             if value:
                 self.set_tag_string(tag, value)
         else:
             value = raw_sc.get_tag_multiple(tag)
             if value:
                 self.set_tag_multiple(tag, value)
def UpdateFileMetadata(filename, datetime):
    exif = GExiv2.Metadata(filename)
    if exif is not None:
        fileDate = GetDateFromExif(exif)
        if fileDate is not None:
            fileDate = datetime.strptime(fileDate, DATE_FORMAT)
            # date within acceptable limit. don't update
            if abs((fileDate - datetime).days) <= FILE_METADATA_DATE_TOLERANCE:
                return

    log('Updating exif: %s to date: %s', \
        filename, datetime.strftime(DATE_FORMAT))

    if DRY_RUN == False:
        if exif is not None:
            exif['Exif.Photo.DateTimeOriginal'] = datetime.strftime(
                DATE_FORMAT)
            exif['Exif.Photo.DateTimeDigitized'] = datetime.strftime(
                DATE_FORMAT)
            exif['Exif.Image.DateTime'] = datetime.strftime(DATE_FORMAT)
            exif['Exif.Image.DateTimeOriginal'] = datetime.strftime(
                DATE_FORMAT)
            exif.save_file()

        xmpfile = XMPFiles(file_path=filename, open_forupdate=True)
        xmp = xmpfile.get_xmp()
        if xmp is not None:
            for xmpConst in XMP_CONSTANTS:
                for dateConst in DATE_CONSTANTS:
                    if xmp.does_property_exist(xmpConst, dateConst):
                        xmp.set_property( \
                            xmpConst, dateConst, datetime.strftime(DATE_FORMAT_XMP))
            if (xmpfile.can_put_xmp(xmp)):
                xmpfile.put_xmp(xmp)
                xmpfile.close_file()
Пример #10
0
    def resize_image_to_1024(parent_file_path, file_path):
        """Resizes the image to 1024 if it is larger in width.

        Parameters
        ==========
        parent_file_path : string
            The path to the original image file with all the metadata.
        file_path : string
            The path to the temporary image file that should be resized.

        Notes
        =====
        Do this before rotating the image because it is only based on width.

        """
        img = Image.open(file_path)
        width, height = img.size
        aspect_ratio = float(width) / float(height)
        max_width = 1024
        if width > max_width:

            reduced_size = max_width, int(max_width / aspect_ratio)
            img.thumbnail(reduced_size, Image.ANTIALIAS)
            img.save(file_path, img.format)

            # Copy all metadata from parent file to the resized file
            os.system('jhead -q -te {} {}'.format(parent_file_path, file_path))

            metadata = GExiv2.Metadata(file_path)
            if (metadata.get_pixel_width() != reduced_size[0]
                    or metadata.get_pixel_height() != reduced_size[1]):

                metadata.set_pixel_width(reduced_size[0])
                metadata.set_pixel_height(reduced_size[1])
                metadata.save_file()
Пример #11
0
    def get_data(self, filename):
        tag_camera = ""
        tag_focal = ""
        tag_city = ""
        tag_country = ""

        # get EXIF metadata
        self.tags = GExiv2.Metadata(filename)

        # read tags from metadata
        if 'Exif.Image.Model' in self.tags:
            tag_camera = self.tags['Exif.Image.Model']
        if 'Exif.Photo.FocalLengthIn35mmFilm' in self.tags:
            tag_focal = self.tags['Exif.Photo.FocalLengthIn35mmFilm']
        if 'Xmp.photoshop.City' in self.tags:
            tag_city = self.tags['Xmp.photoshop.City']
        if 'Xmp.photoshop.Country' in self.tags:
            tag_country = self.tags['Xmp.photoshop.Country']

        # check if GPS info available
        posGPS = self.tags.get_gps_info()
        if posGPS[0] <> 0 or posGPS[1] <> 0: tag_gps = "yes"
        else: tag_gps = "no"

        return tag_camera, tag_focal, tag_gps, tag_city, tag_country
Пример #12
0
    def read(self):
        if self.pixmap is None:
            self.pixmap = QPixmap(self.path)
            self.metadata = GExiv2.Metadata(self.path)

            # the view will need three parameters:
            # rotation
            # size
            # zoom
            # the first is needed to properly orient the view over the scene
            # the other two are needed for zoom, mostly
            # but the rotation defines the images size, so they're linked
            self.size = self.pixmap.size()

            try:
                # try directly to get the tag, because sometimes get_tags() returns
                # tags that don't actually are in the file

                # this implicitly loads the metadata
                rot = self.metadata['Exif.Image.Orientation']
            except KeyError:
                # guess :-/
                logger.info("rotation 'guessed'")
                rot = '1'

            self.rotation = self.rotation_to_degrees[rot]
            if self.rotation in (90, 270):
                self.size = QSize(self.size.height(), self.size.width())

            self.zoom
Пример #13
0
def fetch_thumbnail(filename, size=Gst.get_int('thumbnail-size'), orient=1):
    """Load a photo's thumbnail from disk

    >>> fetch_thumbnail('gg/widgets.py')
    Traceback (most recent call last):
    OSError: gg/widgets.py: No thumbnail found.
    >>> type(fetch_thumbnail('demo/IMG_2411.JPG'))
    <class 'gi.repository.GdkPixbuf.Pixbuf'>
    """
    try:
        exif = GExiv2.Metadata(filename)
    except GObject.GError:
        raise OSError('{}: No thumbnail found.'.format(filename))

    with ignored(KeyError, ValueError):
        orient = int(exif['Exif.Image.Orientation'])

    try:
        thumb = GdkPixbuf.Pixbuf.new_from_file_at_size(filename, size, size)
    except GObject.GError:
        try:
            preview = exif.get_preview_properties()
            data = exif.get_preview_image(preview[0]).get_data()
        except (IndexError, GObject.GError):
            raise OSError('{}: No thumbnail found.'.format(filename))

        return GdkPixbuf.Pixbuf.new_from_stream_at_scale(
            Gio.MemoryInputStream.new_from_data(data, None), size, size, True,
            None)

    return ROTATIONS.get(orient, lambda x: x)(thumb)
Пример #14
0
 def save_img(self, rating=None):
     exif = GExiv2.Metadata(self.fname)
     self.pixmap.save(self.fname, None, self.quality)
     if rating is not None:
         exif["Exif.Image.Rating"] = str(rating)
     if exif:
         exif.save_file()
Пример #15
0
    def to_file(self, path):
        """Write metadata to an XMP sidecar file.

        :param str path: The image/video file path name.

        """
        xmp_path = path + '.xmp'
        # create empty XMP
        with open(xmp_path, 'w') as of:
            of.write('<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" ')
            of.write('xmlns:x="adobe:ns:meta/">\n</x:xmpmeta>')
        # open empty XMP
        md = GExiv2.Metadata()
        md.open_path(xmp_path)
        # add our namespace
        md.register_xmp_namespace(
            'https://github.com/jim-easterbrook/pyctools', 'pyctools')
        # copy metadata
        for tag, value in self.data.items():
            if md.get_tag_type(tag) in ('XmpBag', 'XmpSeq'):
                md.set_tag_multiple(tag, value)
            else:
                md.set_tag_string(tag, value)
        if self.comment is not None:
            md.set_comment(self.comment)
        # save file
        md.save_file(xmp_path)
Пример #16
0
def fix_exif_dates(img_path, timedelta, dry_run=True):
    """
    Fix EXIF timestamps if date & time were set incorrectly
    on the camera when capturing the image.
    The file's access and modified times are preserved (restored).

    timedelta : datetime.timedelta applied to the original timestamp.
    """

    # Uses GExiv2
    # A GObject-based wrapper around the Exiv2 library.
    # Ubuntu/Debian: apt-get install gir1.2-gexiv2-0.10 libgexiv2-2
    # Mac OS X: brew install pygobject3 gtk+3 gexiv2
    # Arch Linux: pacman -S libgexiv2
    import gi
    gi.require_version('GExiv2', '0.10')
    from gi.repository import GExiv2
    import os
    from datetime import datetime as dt

    stat_result = os.stat(img_path)
    exif = GExiv2.Metadata()
    exif.open_path(img_path)
    orig_ts = exif.get_tag_string('Exif.Image.DateTime')
    orig_dt = dt.strptime(orig_ts, '%Y:%m:%d %H:%M:%S')
    fixed_dt = orig_dt + timedelta
    fixed_ts = fixed_dt.strftime('%Y:%m:%d %H:%M:%S')
    if not dry_run:
        exif.set_tag_string('Exif.Image.DateTime', fixed_ts)
        exif.set_tag_string('Exif.Photo.DateTimeDigitized', fixed_ts)
        exif.set_tag_string('Exif.Photo.DateTimeOriginal', fixed_ts)
        exif.save_file(img_path)
        os.utime(img_path, (stat_result.st_atime_ns, stat_result.st_mtime_ns))
    return (orig_dt, fixed_dt)
Пример #17
0
    def from_file(self, path):
        """Read metadata from an XMP sidecar file or, if there is no
        sidecar, from the image/video file (if it has metadata).

        Returns the :py:class:`Metadata` object, allowing convenient
        code like this::

            md = Metadata().from_file(path)

        :param str path: The image/video file path name.

        :rtype: :py:class:`Metadata`

        """
        for xmp_path in (path + '.xmp', path):
            md = GExiv2.Metadata()
            try:
                md.open_path(xmp_path)
            except GObject.GError:
                continue
            for tag in (md.get_exif_tags() + md.get_iptc_tags() +
                        md.get_xmp_tags()):
                if md.get_tag_type(tag) in ('XmpBag', 'XmpSeq'):
                    self.data[tag] = md.get_tag_multiple(tag)
                else:
                    self.data[tag] = md.get_tag_string(tag)
            self.comment = md.get_comment()
            break
        return self
Пример #18
0
    def exif_extract(self, temp_file, tweet):
        """
        Attempt to extract exif information from the provided tweet.
        If gexiv2 dependency is not installed, this will not work and will
        merely return an empty list
        """
        if not GExiv2:
            return []

        try:
            exif_data = GExiv2.Metadata(temp_file)
            longitude, latitude, altitude = exif_data.get_gps_info()
            if longitude == 0 and latitude == 0:
                return []

            coordinates = {}
            coordinates['from'] = 'exif'
            coordinates['context'] = (
                'https://twitter.com/%s/status/%s' %
                (tweet.user.screen_name, tweet.id),
                'Location retrieved from image exif metadata.\n Tweet was %s\n'
                % (tweet.text))
            coordinates['time'] = exif_data.get_date_time()
            coordinates['latitude'] = latitude
            coordinates['realname'] = tweet.user.name
            coordinates['longitude'] = longitude
            return coordinates
        except Exception:
            err = 'Error extracting gps coordinates from exif metadata'
            self.errors.append({
                'from': 'exif',
                'tweetid': 0,
                'url': '',
                'error': err
            })
Пример #19
0
def read_photo_metadata(filepath):
    '''Parses image metadata using GExiv2.'''
    metadata = GExiv2.Metadata(filepath)
    if not metadata.get_tags():
        return None
    else:
        return metadata
Пример #20
0
    def run(self, task):
        # Save task id for logging.
        self.task_id = task.id

        # Read metadata from a temp file.
        try:
            self.metadata = GExiv2.Metadata()
            self.metadata.open_buf(bytes(task.get_file_data))
        except Exception as e:
            logger.warning(
                "[Task {0}]: Unable to read image metadata: {1}".format(
                    task.id, e))
            self.metadata = None

        # Run all analysis.
        if self.metadata:
            self._get_comment()
            self._get_dimensions()
            self._get_exif()
            self._get_iptc()
            self._get_xmp()
            self._get_previews()
            self._get_gps_data()

        return self.results
Пример #21
0
def save_pixbuf(pixbuf, filename, update_orientation_tag=False):
    """Save the image with all the exif keys that exist if we have exif support.

    NOTE: This is used to override edited images, not to save images to new
        paths. The filename must exist as it is used to retrieve the image
        format and exif data.

    Args:
        pixbuf: GdkPixbuf.Pixbuf image to act on.
        filename: Name of the image to save.
        update_orientation_tag: If True, set orientation tag to NORMAL.
    """
    if not os.path.isfile(filename):
        raise FileNotFoundError(
            "Original file to retrieve data from not found")
    # Get needed information
    info = GdkPixbuf.Pixbuf.get_file_info(filename)[0]
    extension = info.get_extensions()[0]
    if _has_exif:
        exif = GExiv2.Metadata(filename)
    # Save
    pixbuf.savev(filename, extension, [], [])
    if _has_exif and exif.get_supports_exif():
        if update_orientation_tag:
            exif.set_orientation(GExiv2.Orientation.NORMAL)
        exif.save_file()
Пример #22
0
def remove_rotation(image_path):
    '''
    Fix a picture taken from an Apple device

    :param image: Image path
    '''

    # Get Metadata
    exif = GExiv2.Metadata(image_path)

    # Get current orientation
    orientation = exif.get_orientation()
    degrees = None
    if orientation == GExiv2.Orientation.ROT_90:
        degrees = 90
    elif orientation == GExiv2.Orientation.ROT_180:
        degrees = 180
    elif orientation == GExiv2.Orientation.ROT_270:
        degrees = 270

    if degrees is not None:
        # Remove orientation tag
        exif.set_orientation(GExiv2.Orientation.NORMAL)
        exif.save_file()

        # Rotate image
        image = Image.open(image_path)
        rotated_image = image.rotate(360 - degrees)
        rotated_image.save()
Пример #23
0
 def reload_auto(self):
     """Load a new image with auto-orientation."""
     self.get_img()
     try:
         orient = GExiv2.Metadata(self.fname)['Exif.Image.Orientation']
         self.orient_dict[orient]()
     except:
         self.load_img()
Пример #24
0
 def _read_data(self, data):
     fp = temporary.file(suffix='.xmp')
     try:
         fp.write(data)
         fp.flush()
         self._meta = GExiv2.Metadata(fp.name)
     finally:
         fp.close()
Пример #25
0
    def __init__(self, file_path):
        try:
            self.metadata = GExiv2.Metadata(file_path)
        except Exception as e:
            logger.warning("Unable to read image metadata: {0}".format(e))
            self.metadata = None

        self.results = AutoVivification()
    def update_images_info(self, folder, output_folder):
        """
        1) Retrieves all the images available in the input folder
        2) For each image, retrieves the timestamp
        3) From the list of available locations, searches for the closest location in time.
        4) EXIF is modified and image is stored in the output folder.

        :param folder: Name of the input folder
        :param output_folder: Name of the output folder.
        :return: None
        """
        extensions = ["jpg"]

        if not os.path.exists(output_folder):
            mkpath(output_folder)

        files = []
        for extension in extensions:
            files += glob.glob('%s/*.%s' % (folder, extension.lower()))
            files += glob.glob('%s/*.%s' % (folder, extension.upper()))

        timestamps = sorted(self.locations.keys())

        take_closest = lambda num, collection: min(collection,
                                                   key=lambda x: abs(x - num))

        # http://coreygoldberg.blogspot.com.es/2014/01/python-fixing-my-photo-library-dates.html
        # https://git.gnome.org/browse/gexiv2/tree/GExiv2.py
        for filename in files:
            output_file = os.path.join(output_folder,
                                       os.path.basename(filename))
            print filename, "-->", output_file

            copyfile(filename, output_file)

            exif = GExiv2.Metadata(filename)

            curr_timestamp = datetime.strptime(exif['Exif.Image.DateTime'],
                                               "%Y:%m:%d %H:%M:%S")
            curr_timestamp = (curr_timestamp -
                              datetime(1970, 1, 1)).total_seconds()

            closest_timestamp = take_closest(curr_timestamp, timestamps)

            gps_coords = self.locations[closest_timestamp]

            exif.set_gps_info(gps_coords[1], gps_coords[0], 0.0)
            if gps_coords[0] >= 0.0:
                exif.set_tag_string("Exif.GPSInfo.GPSLatitudeRef", "N")
            else:
                exif.set_tag_string("Exif.GPSInfo.GPSLatitudeRef", "S")

            if gps_coords[1] >= 0.0:
                exif.set_tag_string("Exif.GPSInfo.GPSLongitudeRef", "E")
            else:
                exif.set_tag_string("Exif.GPSInfo.GPSLongitudeRef", "W")

            exif.save_file(output_file)
def strip_metadata(path):

    from gi.repository import GExiv2
    import os
    for infile in os.listdir(path):
        exif = GExiv2.Metadata(infile)
        exif.clear_exif()
        exif.clear_xmp()
        exif.save_file()
Пример #28
0
def fix_image_dates(img_path):
    t = os.path.getctime(img_path)
    ctime = time.strftime('%Y:%m:%d %H:%M:%S', time.localtime(t))
    exif = GExiv2.Metadata(img_path)
    exif['Exif.Image.DateTime'] = ctime
    exif['Exif.Photo.DateTimeDigitized'] = ctime
    exif['Exif.Photo.DateTimeOriginal'] = ctime
    exif.save_file()
    os.utime(img_path, (t, t))
Пример #29
0
def main(camera, date, film, iso, files):
    """Tag scanned images with film-specific EXIF metadata."""

    if date:
        exif_datetime = date.strftime('%Y:%m:%d %H:%M:%S')
        click.echo('Set dates to:  {}'.format(date))
    if camera:
        click.echo('Set camera to: {}'.format(camera))
    if film:
        click.echo('Set film to:   {}'.format(film))
    if iso:
        click.echo('Set ISO to:    {}'.format(iso))

    click.confirm('Does this look OK?', abort=True)

    workqueue = []
    for f in files:
        p = Path(f)
        if p.exists() and p.is_dir():
            workqueue.extend([x for x in p.glob("*.[jJ][pP][gG]")])
        elif p.exists() and p.is_file():
            workqueue.append(p)

    with click.progressbar(workqueue, label='Tagging images...',
                           show_pos=True) as bar:
        for image in bar:
            # Write new metadata to image.
            m = GExiv2.Metadata()
            m.register_xmp_namespace("http://analogexif.sourceforge.net/ns",
                                     "AnalogExif")
            m.open_path(str(image))
            if date:
                m.set_tag_string('Exif.Image.DateTime', exif_datetime)
                m.set_tag_string('Exif.Photo.DateTimeOriginal', exif_datetime)
                m.set_tag_string('Exif.Photo.DateTimeDigitized', exif_datetime)
            if camera:
                if not camera in m.get_tag_multiple('Xmp.dc.subject'):
                    m.set_tag_string('Xmp.dc.subject',
                                     camera)  # set a keyword!
                for k, v in cameras[camera].items():
                    if isinstance(v, int):
                        m.set_tag_long(k, v)
                    else:
                        m.set_tag_string(k, v)
            if film:
                if not film in m.get_tag_multiple('Xmp.dc.subject'):
                    m.set_tag_string('Xmp.dc.subject', film)  # set a keyword!
                m.set_tag_string('Xmp.AnalogExif.Film', film)
                for k, v in films[film].items():
                    if isinstance(v, int):
                        m.set_tag_long(k, v)
                    else:
                        m.set_tag_string(k, v)
            if iso:
                m.set_tag_long("Exif.Photo.ISOSpeedRatings", iso)
            m.save_file(str(image))
    click.echo("Done.")
    def test_rotate_image(self):

        tmp_image_path = 'tmp_rotation_test_image.jpg'
        shutil.copyfile('rotation_test_image.jpg', tmp_image_path)

        metadata_before = GExiv2.Metadata(tmp_image_path)

        self.uploader.rotate_image(tmp_image_path)

        metadata_after = GExiv2.Metadata(tmp_image_path)

        assert metadata_after['Exif.Image.Orientation'] == '1'
        assert metadata_after.get_pixel_height() == \
            metadata_before.get_pixel_width()
        assert metadata_after.get_pixel_width() == \
            metadata_before.get_pixel_height()

        os.remove('tmp_rotation_test_image.jpg')