def read_exif(self): """Reads relevant exif tags from an image provided as PIL.Image object""" image_handle = Image.open(self.image_path) exif = image_handle.info["parsed_exif"] iptc = IptcImagePlugin.getiptcinfo(image_handle) labeled_exifs = label_exifs(exif) image_handle = None # longitude, latitude geotags = get_geotagging(exif) self.lon, self.lat = get_coordinates(geotags) # date taken self._date_taken = datetime.strptime( labeled_exifs.get("DateTimeOriginal"), "%Y:%m:%d %H:%M:%S", ) # headline if not self.skip: headline = iptc.get(IPTC_KEYS["headline"]) if headline is not None: self.headline = headline.decode("UTF-8") else: self.headline = reverse_geocode(self) # description description = iptc.get(IPTC_KEYS["description"]) if description is not None: self.description = description.decode("UTF-8") else: self.description = "No description...yet"
def get_iptc_data(filename): """Return a dict with the raw IPTC data.""" logger = logging.getLogger(__name__) iptc_data = {} raw_iptc = {} # PILs IptcImagePlugin issues a SyntaxError in certain circumstances # with malformed metadata, see PIL/IptcImagePlugin.py", line 71. # ( https://github.com/python-pillow/Pillow/blob/9dd0348be2751beb2c617e32ff9985aa2f92ae5f/src/PIL/IptcImagePlugin.py#L71 ) try: img = _read_image(filename) raw_iptc = IptcImagePlugin.getiptcinfo(img) except SyntaxError: logger.info('IPTC Error in %s', filename) # IPTC fields are catalogued in: # https://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata # 2:05 is the IPTC title property if raw_iptc and (2, 5) in raw_iptc: iptc_data["title"] = raw_iptc[(2, 5)].decode('utf-8', errors='replace') # 2:120 is the IPTC description property if raw_iptc and (2, 120) in raw_iptc: iptc_data["description"] = raw_iptc[(2, 120)].decode('utf-8', errors='replace') # 2:105 is the IPTC headline property if raw_iptc and (2, 105) in raw_iptc: iptc_data["headline"] = raw_iptc[(2, 105)].decode('utf-8', errors='replace') return iptc_data
def get_meta_iptc(file_stream): """Returns the image IPTC metadata in a dictionary of tag:value pairs. @param file_stream: stream """ file_stream.seek(0) img = Image.open(file_stream) iptc_raw = IptcImagePlugin.getiptcinfo(img) metadata = {} if iptc_raw is None: return metadata for code, value in iptc_raw.items(): try: tag = iim_codes[code] except KeyError: continue if isinstance(value, list): try: value = [v.decode('utf-8') for v in value] except UnicodeDecodeError: pass elif isinstance(value, bytes): try: value = value.decode('utf-8') except UnicodeDecodeError: pass metadata[tag] = value return metadata
def read_metadata(self, filename): try: image = Image.open(filename) iptc = IptcImagePlugin.getiptcinfo(image) metadata = { k.strip(): v.strip() for (k, v) in [kv.decode("utf-8").split(':') for kv in iptc[(2, 25)]] } return metadata except Exception as ex: try: tags = None with open(filename, 'rb') as image_file: tags = exifread.process_file(image_file, debug=True) if tags and 'Image ApplicationNotes' in tags: xml = str(tags['Image ApplicationNotes']) xml = ET.fromstring(xml) items = xml.findall( './/{http://www.w3.org/1999/02/22-rdf-syntax-ns#}Bag/{http://www.w3.org/1999/02/22-rdf-syntax-ns#}li' ) items = [item.text.split(':') for item in items] items = [(a.strip(), b.strip()) for a, b in items] metadata = dict(items) return metadata except Exception as ex2: pass return None
def expand(self): self.fetch_data() # Get rating # cursor.execute("SELECT AVG(rating) AS average FROM " + tbl_image_rating + " WHERE image = %s GROUP BY image", [imageId]) # rating = cursor.fetchone() # if rating != None: # image['rating'] = rating # get author name if self.author: self.author_name = db.fetch("SELECT name FROM " + db.tbl_author + " WHERE id=%s", [self.author], one=True, as_list=True) # get labels labels = db.fetch( "SELECT id, name FROM " + db.tbl_label + " INNER JOIN " + db.tbl_image_label + " ON (label = id AND image = %s)", [self.id]) if labels: self.labels = labels # get meta data self.open() exif = {} iptc = {} exif_info = self.image._getexif() or {} for tag, value in exif_info.items(): decoded = ExifTags.TAGS.get(tag, str(tag)) exif[decoded] = value iptc_info = IptcImagePlugin.getiptcinfo(self.image) or {} for tag, value in iptc_info.items(): decoded = iptc_tags.get(tag, str(tag)) iptc[decoded] = value self.exif = exif self.iptc = iptc
def test_getiptcinfo_tiff_none(self): # Arrange im = Image.open("Tests/images/hopper.tif") # Act iptc = IptcImagePlugin.getiptcinfo(im) # Assert self.assertIsNone(iptc)
def test_getiptcinfo_jpg_none(self): # Arrange im = hopper() # Act iptc = IptcImagePlugin.getiptcinfo(im) # Assert self.assertIsNone(iptc)
def test_getiptcinfo_tiff_none(): # Arrange with Image.open("Tests/images/hopper.tif") as im: # Act iptc = IptcImagePlugin.getiptcinfo(im) # Assert assert iptc is None
def test_getiptcinfo_jpg_none(): # Arrange with hopper() as im: # Act iptc = IptcImagePlugin.getiptcinfo(im) # Assert assert iptc is None
def test_getiptcinfo_jpg_found(): # Arrange with Image.open(TEST_FILE) as im: # Act iptc = IptcImagePlugin.getiptcinfo(im) # Assert assert isinstance(iptc, dict) assert iptc[(2, 90)] == b"Budapest" assert iptc[(2, 101)] == b"Hungary"
def test_getiptcinfo_jpg_found(self): # Arrange im = Image.open(TEST_FILE) # Act iptc = IptcImagePlugin.getiptcinfo(im) # Assert self.assertIsInstance(iptc, dict) self.assertEqual(iptc[(2, 90)], b"Budapest") self.assertEqual(iptc[(2, 101)], b"Hungary")
def get_iptc_data(filename): """Return a dict with the raw IPTC data.""" img = _read_image(filename) raw_iptc = IptcImagePlugin.getiptcinfo(img) # IPTC fields are catalogued in: # https://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata iptc_data = {} # 2:05 is the IPTC title property if raw_iptc and (2, 5) in raw_iptc: iptc_data["title"] = raw_iptc[(2, 5)].decode('utf-8') # 2:120 is the IPTC description property if raw_iptc and (2, 120) in raw_iptc: iptc_data["description"] = raw_iptc[(2, 120)].decode('utf-8') return iptc_data
def extractIptc(self, image): iptc = {} iptc_tags = { (1, 90): 'CodedCharacterSet', (2, 0): 'Whatever', (2, 5): 'ObjectName', (2, 10): 'Urgency', (2, 15): 'Category', (2, 20): 'Subcategories', (2, 25): 'Keywords', (2, 40): 'SecialInstructions', (2, 55): 'CreationDate', (2, 60): 'CreationTime', (2, 62): 'DigitizationDate', (2, 80): 'AuthorByline', (2, 85): 'AuthorTitle', (2, 90): 'City', (2, 92): 'SubLocation', (2, 95): 'State', (2, 100): 'CountryCode', (2, 101): 'Country', (2, 103): 'OTR', (2, 105): 'Headline', (2, 110): 'Source', (2, 115): 'PhotoSource', (2, 116): 'Copyright', (2, 120): 'Caption', (2, 122): 'CaptionWriter', } iptc_info = IptcImagePlugin.getiptcinfo(image) or {} for tag, value in iptc_info.items(): decoded = iptc_tags.get(tag, str(tag)) if isinstance(value, (bytes, bytearray)): iptc[decoded] = value.decode('utf-8') elif isinstance(value, (list)): for k, v in enumerate(value): value[k] = v.decode('utf-8') iptc[decoded] = value else: iptc[decoded] = str(value) self.metaData[self.currentFile]['iptc'] = iptc
def get_image_metadata(path): metadata = {'Exif.Image.Rating': None, 'Iptc.Application2.Keywords': []} exif, iptc = None, None try: image = Image.open(path) exif = image._getexif() iptc = IptcImagePlugin.getiptcinfo(image) image = None except: log.error("Error loading metadata: %s" % path) if exif and exif.has_key(EXIF_IMAGE_RATING_RAW): metadata[RATING] = exif[EXIF_IMAGE_RATING_RAW] if iptc and iptc.has_key(IPTC_APPLICATION2_KEYWORDS_RAW): metadata[TAGS] = iptc[IPTC_APPLICATION2_KEYWORDS_RAW] if isinstance(metadata[TAGS], str): metadata[TAGS] = [metadata[TAGS]] metadata[TAGS] = set(metadata[TAGS]) return metadata
def get_iptc_metadata(self, image_file_path): """ Reads the IPTC metadata of an image given by 'image_file_path' and returns it. Returns empty array if IPTC metadata is not available. :param image_file_path: :return iptc: """ logger.debug('get_iptc_metadata()') try: im = PIL.Image.open(image_file_path) iptc = IptcImagePlugin.getiptcinfo(im) im.close() if not iptc is None: return iptc else: return [] except: e = sys.exc_info()[0] logger.debug('is_image_landscape() - {}'.format(e))
def get_meta_iptc(file_stream): """Returns the image IPTC metadata in a dictionary of tag:value pairs. @param file_stream: stream """ file_stream.seek(0) img = Image.open(file_stream) iptc_raw = IptcImagePlugin.getiptcinfo(img) metadata = {} if iptc_raw is None: return metadata for code, value in iptc_raw.items(): try: tag = iim_codes[code] except KeyError: continue if isinstance(value, list): value = [decode(v) for v in value] elif isinstance(value, bytes): value = decode(value) metadata[tag] = value return metadata
def get_caption(image): iptc = IptcImagePlugin.getiptcinfo(image) return iptc.get((2, 5)).decode()
@staticmethod def mdget(phile): try: im = Image.open(phile) except IOError, why: sys.stderr.write("Can't find metadata for %s (%s).\n" % (phile, why) ) return None out = {} exif_info = im._getexif() or {} for tag, value in exif_info.items(): decoded = ExifTags.TAGS.get(tag, "unknown") out["Exif." + decoded] = value iptc_info = IptcImagePlugin.getiptcinfo(im) or {} for tag, value in iptc_info.items(): decoded = PhotoWebber._iptc_tags.get(tag, "unknown") out["Iptc." + decoded] = value return out, im.size @staticmethod def error(msg): "Something has gone horribly wrong." sys.stderr.write("FATAL: %s\n" % msg) sys.exit(1) def photoweb_cli(): "Run command-line photoweb." usage = "Usage: %prog [options] <dir>"
def pil(file_path: str): from PIL import Image, IptcImagePlugin im = Image.open(file_path) meta = IptcImagePlugin.getiptcinfo(im) pprint(meta)
def update_metadata(self): self.open() iptc_info = IptcImagePlugin.getiptcinfo(self.image) or {} exif_info = self.image._getexif() or {} fields = [] values = [] if IPTC_OBJECT_NAME in iptc_info: title = iptc_info[IPTC_OBJECT_NAME].decode('utf-8') fields.append("description") values.append(title) timestamp = None if IPTC_DATE_CREATED in iptc_info and IPTC_TIME_CREATED in iptc_info: timestamp_str = iptc_info[IPTC_DATE_CREATED].decode('utf-8') + iptc_info[IPTC_TIME_CREATED].decode('utf-8') if len(timestamp_str) == 14: timestamp_str = timestamp_str + '+0000' timestamp = datetime.strptime(timestamp_str, '%Y%m%d%H%M%S%z') elif EXIF_DATE_TIME_ORIGINAL in exif_info: timestamp_str = exif_info[EXIF_DATE_TIME_ORIGINAL] if len(timestamp_str) == 19: timestamp_str = timestamp_str + '+0000' elif timestamp_str[-3] == ':': timestamp_str = kill_char(timestamp_str, len(timestamp_str)-3) timestamp = datetime.strptime(timestamp_str, '%Y:%m:%d %H:%M:%S%z') elif EXIF_DATE_TIME_DIGITIZED in exif_info: timestamp_str = exif_info[EXIF_DATE_TIME_DIGITIZED] timestamp = datetime.strptime(timestamp_str, '%Y:%m:%d %H:%M:%S') if timestamp: fields.append("stime") values.append(timestamp) if IPTC_BYLINE in iptc_info: author_name = iptc_info[IPTC_BYLINE].decode('utf-8') author_id = db.fetch("SELECT id FROM " + db.tbl_author + " WHERE name=%s", [author_name], one=True, as_list=True) if not author_id: author_id = db.execute("INSERT INTO " + db.tbl_author + "(name) VALUES (%s) RETURNING id", [author_name]) fields.append("author") values.append(author_id) if IPTC_KEYWORDS in iptc_info: labels = [] if isinstance(iptc_info[IPTC_KEYWORDS], list): for label in iptc_info[IPTC_KEYWORDS]: labels.append(label.decode('utf-8')) else: labels.append(iptc_info[IPTC_KEYWORDS].decode('utf-8')) self.set_labels(labels) fields.append("width") values.append(self.image.width) fields.append("height") values.append(self.image.height) if fields: values.append(self.id) fields_str = ", ".join(map(lambda x: "%s=%%s" % x, fields)) db.execute("UPDATE " + db.tbl_image + " SET " + fields_str + " WHERE id=%s", values) db.commit()