Esempio n. 1
0
def getMeta(path, args):
    m = Metadata(path)

    if args.print:
        print(
            'getMeta: {} exif_tags, {} iptc_tags, {} xmp_tags, path {}, dateFromDirname {}'
            .format(
                len(m.get_exif_tags()), len(m.get_iptc_tags()),
                len(m.get_xmp_tags()), path,
                dateFromDirname.strftime(DATE_FORMAT)
                if dateFromDirname else None))

        for t in m.get_tags():
            # if t != 'Exif.Photo.MakerNote': # avoid big binary? item
            if any(x in t for x in [
                    'Date', 'Image.Make', 'Model', 'Categories', 'GPS',
                    'Latitude', 'Longitude'
            ]):
                print('getMeta: {} -> {}'.format(t, m.get(t)))
            if any(x in t for x in [
                    'Tags', 'LastKeywordXMP', 'HierarchicalSubject',
                    'CatalogSets', 'Subject', 'Keywords'
            ]):
                print('getMeta: {} => [ {} ]'.format(
                    t, ', '.join(m.get_tag_multiple(t))))

    return m
Esempio n. 2
0
    def get_property_pages(self, files):

        # test file type
        if len(files) != 1: return
        file = files[0]
        if file.get_uri_scheme() != 'file': return

        # if mimetype corresponds to an image, read exif tags
        #if file.get_mime_type() in ('image/jpeg' 'image/png'):
        mimetype = file.get_mime_type().split('/')
        if mimetype[0] == "image":

            # create label and grid
            self.property_label = Gtk.Label('EXIF')
            self.property_label.show()
            self.grid = Gtk.Grid()
            self.grid.set_margin_start(10)
            self.grid.set_margin_end(10)
            self.grid.set_margin_top(5)
            self.grid.set_margin_bottom(5)
            self.grid.show()

            # display title
            self.dislayTag("<b>Tag</b>", "<b>Readable value</b>",
                           "<b>Raw value</b>", 0, 0)
            gtk_separator = Gtk.Separator(
                orientation=Gtk.Orientation.HORIZONTAL)
            self.grid.attach(gtk_separator, 0, 1, 3, 1)

            # read metadata from file
            filename = unquote(file.get_uri()[7:])
            self.tags = Metadata()
            self.tags.open_path(filename)

            # loop thru the tags
            index = 0
            for name in self.tags:
                interpreted = self.tags.get_tag_interpreted_string(name)[0:64]
                string_raw = self.tags.get_tag_string(name)[0:64]
                if interpreted == string_raw: string_raw = ""
                else: string_raw = "<i>" + string_raw + "</i>"
                name = "<b>" + name + "</b>"
                self.dislayTag(name, interpreted, string_raw, 0, index + 2)
                index = index + 1

            # declare main scrolled window
            self.window = Gtk.ScrolledWindow()
            self.window.add_with_viewport(self.grid)
            self.window.show_all()

            # return label and tab content
            return Nautilus.PropertyPage(name="NautilusPython::tags_info",
                                         label=self.property_label,
                                         page=self.window),
Esempio n. 3
0
def metadata_comp_table(files):
    # Extract tags for each file
    tags = {}
    for f in files:
        exif = Metadata()
        exif.open_path(f)
        tags[f] = {(x, exif[x]) for x in exif.get_tags()}
    # Compute common tags intersecting all sets
    commontags = tags[files[0]]
    for f in tags:
        commontags = commontags.intersection(tags[f])
    # Delete common tags for each entry
    for f in tags:
        tags[f] = tags[f] - commontags
    # Print results
    head = ["Tag"] + [os.path.basename(x) for x in files]
    tab = []
    alluniquetags = set()
    for f in tags:
        alluniquetags |= ({x[0] for x in tags[f]})
    for t in alluniquetags:
        aux = [t]
        for f in files:
            if t in [x[0] for x in tags[f]]:
                aux.append(dict(tags[f])[t][:200])
            else:
                aux.append("-")
        tab.append(aux)
    t = tt.Texttable()
    t.header(head)
    t.add_rows(tab, header=False)
    t.set_deco(t.HEADER)
    t.set_chars(['-', '|', '+', '-'])
    maxw = len(max(alluniquetags, key=len)) if alluniquetags else 5
    arrw = [maxw] + [25] * len(files)
    t.set_cols_width(arrw)
    print()
    print(t.draw())
    print("\n(Unique fields only. Common EXIF tags have been omitted)")
    print()
Esempio n. 4
0
    def update_file_info(self, file):
        # test file type
        if file.get_uri_scheme() != 'file': return

        # read data only if image file
        mimetype = file.get_mime_type().split('/')
        if mimetype[0] == "image":

            # format filename
            filename = unquote(file.get_uri()[7:])

            # get metadata
            self.tags = Metadata()
            self.tags.open_path(filename)

            # image width
            tag_value = ""
            if self.tags.has_tag('Exif.Photo.PixelXDimension'):
                tag_value = self.tags.get_tag_string(
                    'Exif.Photo.PixelXDimension')
            if tag_value == "" and self.tags.has_tag('Exif.Image.ImageWidth'):
                tag_value = self.tags.get_tag_string('Exif.Image.ImageWidth')
            file.add_string_attribute('exif_width', tag_value)

            # image height
            tag_value = ""
            if self.tags.has_tag('Exif.Photo.PixelYDimension'):
                tag_value = self.tags.get_tag_string(
                    'Exif.Photo.PixelYDimension')
            if tag_value == "" and self.tags.has_tag('Exif.Image.ImageLength'):
                tag_value = self.tags.get_tag_string('Exif.Image.ImageLength')
            file.add_string_attribute('exif_height', tag_value)

            # camera manufacturer
            tag_value = ""
            if self.tags.has_tag('Xmp.VendorInfo.Manufacturer'):
                tag_value = self.tags.get_tag_interpreted_string(
                    'Xmp.VendorInfo.Manufacturer')
            if tag_value == "" and self.tags.has_tag('Exif.Image.Make'):
                tag_value = self.tags.get_tag_interpreted_string(
                    'Exif.Image.Make')
            file.add_string_attribute('exif_maker', tag_value)

            # camera model
            tag_value = ""
            if self.tags.has_tag('Xmp.VendorInfo.Model'):
                tag_value = self.tags.get_tag_interpreted_string(
                    'Xmp.VendorInfo.Model')
            if tag_value == "" and self.tags.has_tag('Exif.Image.Model'):
                tag_value = self.tags.get_tag_interpreted_string(
                    'Exif.Image.Model')
            file.add_string_attribute('exif_model', tag_value)

            # camera focal length
            tag_value = ""
            if self.tags.has_tag('Xmp.Exif.FocalLengthIn35mmFormat'):
                tag_value = self.tags.get_tag_interpreted_string(
                    'Xmp.Exif.FocalLengthIn35mmFormat')
            if tag_value == "" and self.tags.has_tag(
                    'Exif.Photo.FocalLengthIn35mmFilm'):
                tag_value = self.tags.get_tag_interpreted_string(
                    'Exif.Photo.FocalLengthIn35mmFilm')
            if tag_value == "" and self.tags.has_tag('Exif.Photo.FocalLength'):
                tag_value = self.tags.get_tag_interpreted_string(
                    'Exif.Photo.FocalLength')
            file.add_string_attribute('exif_focal', tag_value)

            # camera aperture
            tag_value = ""
            if self.tags.has_tag('Xmp.Exif.ApertureValue'):
                tag_value = self.tags.get_tag_interpreted_string(
                    'Xmp.Exif.ApertureValue')
            if tag_value == "" and self.tags.has_tag(
                    'Exif.Photo.ApertureValue'):
                tag_value = self.tags.get_tag_interpreted_string(
                    'Exif.Photo.ApertureValue')
            if tag_value == "" and self.tags.has_tag('Exif.Photo.FNumber'):
                tag_value = self.tags.get_tag_interpreted_string(
                    'Exif.Photo.FNumber')
            file.add_string_attribute('exif_apert', tag_value)

            # city tag
            tag_value = ""
            if self.tags.has_tag('Xmp.City'):
                tag_value = self.tags.get_tag_interpreted_string('Xmp.City')
            if tag_value == "" and self.tags.has_tag('Xmp.photoshop.City'):
                tag_value = self.tags.get_tag_interpreted_string(
                    'Xmp.photoshop.City')
            if tag_value == "" and self.tags.has_tag('Iptc.City'):
                tag_value = self.tags.get_tag_interpreted_string('Iptc.City')
            file.add_string_attribute('exif_city', tag_value)

            # country tag
            tag_value = ""
            if self.tags.has_tag('Xmp.CountryName'):
                tag_value = self.tags.get_tag_interpreted_string(
                    'Xmp.CountryName')
            if tag_value == "" and self.tags.has_tag('Xmp.photoshop.Country'):
                tag_value = self.tags.get_tag_interpreted_string(
                    'Xmp.photoshop.Country')
            file.add_string_attribute('exif_country', tag_value)

            # GPS tag
            tag_value = "no"
            if self.tags.has_tag('Xmp.Exif.GPSLatitude'): tag_value = "yes"
            if tag_value == "no" and self.tags.has_tag(
                    'Xmp.LocationDetails.GPSLatitude'):
                tag_value = "yes"
            if tag_value == "no" and self.tags.has_tag(
                    'Exif.GPSInfo.GPSLatitude'):
                tag_value = "yes"
            file.add_string_attribute('exif_gps', tag_value)

        # else, file is not an image
        else:
            file.add_string_attribute('exif_maker', "")
            file.add_string_attribute('exif_model', "")
            file.add_string_attribute('exif_focal', "")
            file.add_string_attribute('exif_city', "")
            file.add_string_attribute('exif_country', "")
            file.add_string_attribute('exif_gps', "")
Esempio n. 5
0
  def get_property_pages(self, files):
    # default map size and zoom factor
    sizeMap = "512x512"
    zoomMap = "7"
  
    # test file type
    file = files[0]
    if len(files) != 1: return
    if file.get_uri_scheme() != 'file': return

    # if mimetype corresponds to JPG image, read data and populate tab
    mimetype = file.get_mime_type().split('/')
    if mimetype[0] in ('image'):
    
      # create tab
      self.tab = Gtk.Label('GPS')
      self.tab.show()

      # create grid
      self.grid = Gtk.Grid()
      self.grid.set_margin_start(10)
      self.grid.set_margin_end(10)
      self.grid.set_margin_top(5)
      self.grid.set_margin_bottom(5)
      self.grid.show()

      # create main scrolled window
      self.window = Gtk.ScrolledWindow()
      self.window.add_with_viewport(self.grid)
      self.window.show_all()

      # read metadata from file
      filename = unquote(file.get_uri()[7:])
      self.tags = Metadata()
      self.tags.open_path(filename)

      # get signed GPS position
      latitude  = self.tags.get_gps_latitude()
      longitude = self.tags.get_gps_longitude()
      altitude  = self.tags.get_gps_altitude()

      # if no GPS data, return
      if latitude == 0 and longitude == 0 and altitude == 0: return

      # trunk GPS data to 6 digits
      parts = str(latitude).split(".")
      strLatitude = parts[0] + "." + parts[1][:6]
      parts = str(longitude).split(".")
      strLongitude = parts[0] + "." + parts[1][:6]
      strAltitude = str(altitude)

      # generate GPS position
      strPosition = strLatitude + ',' + strLongitude

      # generate Google Maps links
      urlMaps = 'https://www.google.com/maps/place/' + strPosition + '/@' + strPosition + ',' + zoomMap + 'z/'
      urlJpeg = 'https://maps.googleapis.com/maps/api/staticmap?maptype=hybrid&zoom=' + zoomMap + '&size=' + sizeMap
      urlJpeg += '&center=' + strPosition + '&markers=' + strPosition + '&key=' + apikey
      
      # generate cache folder, and create if needed
      dirHomeCache = os.environ['HOME'] + '/.cache'
      dirGeotagCache = os.getenv('XDG_CACHE_HOME', dirHomeCache) + '/geotag'
      if not os.path.exists(dirGeotagCache): os.makedirs(dirGeotagCache)

      # generate cache file names
      fileMap = dirGeotagCache + '/map_' + strLatitude + '_' + strLongitude + '_' + sizeMap + '_' + zoomMap + '.png'
      fileDesc = dirGeotagCache + '/map_' + strLatitude + '_' + strLongitude + '.txt'

      # if description is not in the cache, retrieve it from Nominatim
      if not os.path.exists(fileDesc):
        # retrieve place description
        geolocator = Nominatim(user_agent="nautilus-exif-geotag")
        location = geolocator.reverse(strPosition)
        strDescription = location.address

        # write description to cache
        file = codecs.open(fileDesc, "w", "utf-8")
        file.write(strDescription)
        file.close()

      # if map is not in the cache, retrieve it from Google Maps
      if not os.path.exists(fileMap): urllib.request.urlretrieve(urlJpeg, fileMap)

      # retrieve description from cache
      file = codecs.open(fileDesc, "r", "utf-8")
      strDescription = file.read()
      file.close()

      # dislay GPS data
      self.DisplayText("<b>latitude</b>", 0, 0, 1, 1, "right")
      self.DisplayText(strLatitude, 1, 0, 1, 1, "left")
      self.DisplayText("<b>longitude</b>", 0, 1, 1, 1, "right")
      self.DisplayText(strLongitude, 1, 1, 1, 1, "left")
      self.DisplayText("<b>altitude</b>", 0, 2, 1, 1, "right")
      self.DisplayText(strAltitude, 1, 2, 1, 1, "left")

      # dislay address
      value = re.compile(',').sub('\n', strDescription)
      self.DisplayText("<b>address</b>", 2, 0, 1, 3, "right")
      self.DisplayText("<a href='" + urlMaps + "'>" + value + "</a>", 3, 0, 1, 5, "left")

      # dislay gmaps image
      self.DisplayImage(fileMap, 0, 5, 4, 1)

      # return label and tab content
      return Nautilus.PropertyPage( name="NautilusPython::geotag_info", label=self.tab, page=self.window ),
Esempio n. 6
0
def metadata_summary(path):
    exif = Metadata()
    exif.open_path(path)
    taglist = exif.get_tags()

    # Date
    date = []
    if 'Exif.Photo.DateTimeOriginal' in taglist:
        date.append(exif['Exif.Photo.DateTimeOriginal'])
    if 'Xmp.exif.DateTimeOriginal' in taglist:
        date.append(exif['Xmp.exif.DateTimeOriginal'])
    #date.append(time.ctime(os.path.getmtime(path)))
    if len(date) > 0:
        date = time.strftime("%d/%m/%Y %H:%M:%S",
                             time.strptime(date[0], "%Y:%m:%d %H:%M:%S"))
    else:
        date = ""

    # Orientation
    ori = exif.get('Exif.Image.Orientation', "?")

    # Tags
    tags = []
    if 'Iptc.Application2.Keywords' in taglist:
        tags.append(exif['Iptc.Application2.Keywords'])
    if 'Xmp.dc.subject' in taglist:
        tags += exif['Xmp.dc.subject'].split(",")
    if 'Xmp.digiKam.TagsList' in taglist:
        tags += exif['Xmp.digiKam.TagsList'].split(",")
    if 'Xmp.MicrosoftPhoto.LastKeywordXMP' in taglist:
        tags += exif['Xmp.MicrosoftPhoto.LastKeywordXMP'].split(",")
    tags = [x.strip() for x in tags]
    tags = list(set(tags))
    tags.sort()

    # Title
    aux = []
    title = ""
    if 'Iptc.Application2.Caption' in taglist:
        aux.append(exif['Iptc.Application2.Caption'])
    if 'Xmp.dc.title' in taglist:
        aux.append(exif['Xmp.dc.title'])
    if 'Iptc.Application2.Headline' in taglist:
        aux.append(exif['Iptc.Application2.Headline'])
    if len(aux) > 0:
        title = aux[0]

    # Software
    aux = []
    soft = ""
    if 'Exif.Image.Software' in taglist:
        aux.append(exif['Exif.Image.Software'])
    if 'Iptc.Application2.Program' in taglist:
        aux.append(exif['Iptc.Application2.Program'])
    if len(aux) > 0:
        soft = list(set(aux))[0]

    # Shorten title and soft
    if len(title) > 13:
        title = title[:10] + "..."
    if len(soft) > 15:
        soft = soft[:12] + "..."

    dinfo = {
        "date": date,
        "orientation": ori,
        "tags": tags,
        "title": title,
        "software": soft
    }

    return dinfo