def test_save_as_saves_as_new_file_with_new_info(): if os.path.isfile('fixtures/deleteme.jpg'): # pragma: no cover os.unlink('fixtures/deleteme.jpg') new_headline = b'test headline %d' % random.randint(0, 100) info = IPTCInfo('fixtures/Lenna.jpg') info['headline'] = new_headline info.save_as('fixtures/deleteme.jpg') info2 = IPTCInfo('fixtures/deleteme.jpg') assert info2['headline'] == new_headline
def process_image(ifile:str, siteconfig, ofile:str=None): '''resize an image and return the output file name and the exif and iptc meta data''' try: size = siteconfig.get('resize') site_copyright_notice = siteconfig.get('copyright_notice') im = Image.open(ifile) im_xif = im.info.get('exif') im_iptc = retrieve_copyright_notice(ifile) dest = ofile if size and ofile else ifile #Target the input file if the output file is not provided # Image resizing with exif preservation if size: im2 = im.resize(size) params = dict(exif=im_xif) if im_xif else dict() im2.save(dest, **params) # IPTC data rewriting. IPTC are lost during the resize operation. We have to put them back manually # If the inputfile contains a copyright notice, then use it instead of the siteconfig value im_iptc['copyright notice'] = im_iptc.get('copyright notice', site_copyright_notice) if im_iptc or site_copyright_notice: iptc = IPTCInfo(dest) for key in im_iptc: iptc[key] = im_iptc[key] iptc.save() return (dest, im_xif, im_iptc) except Exception as e: printfailure('could not process image ', ifile, ' traceback ', str(e)) return (ifile, None, None)
def __init__(self, path): self.path = path self.exif = self.extract_exif(path) self.iptc = IPTCInfo(path) latitude, longitude = GPS(path).decimal_coordinates self.latitude = latitude self.longitude = longitude
def get_imageinfo(filepath: str) -> dict: """ Return EXIF and IPTC information found from image file in a dictionary. """ info = {} info["exif"] = exif = read_exif(filepath) info["gps"] = gps = parse_gps(exif) info.update(parse_datetime(exif, tag_name="EXIF DateTimeOriginal", gps=gps)) if "lat" in gps: # Backwards compatibility info["lat"], info["lon"] = gps["lat"], gps["lon"] info["iptc"] = iptc = IPTCInfo(filepath, force=True) try: if iptc.data["caption/abstract"]: info["caption"] = iptc.data["caption/abstract"] if iptc.data["object name"]: info["title"] = iptc.data["object name"] if iptc.data["keywords"]: kw_str = ",".join(iptc.data["keywords"]) info["keywords"] = kw_str info["tags"] = iptc.data["keywords"] for key in info: # Convert all str values to unicode if isinstance(info[key], str): info[key] = str(info[key], guess_encoding(info[key])) except AttributeError: pass with open(str(filepath), "rb") as f: im = Image.open(f) info["width"], info["height"] = im.size del im return info
def test_getitem_can_read_info(): info = IPTCInfo('fixtures/Lenna.jpg') assert len(info) >= 4 assert info['keywords'] == [b'lenna', b'test'] assert info['supplemental category'] == [b'supplemental category'] assert info['caption/abstract'] == b'I am a caption'
def retrieve_copyright_notice(fn:str) -> dict: '''Retrieves the copyright notice from the input file Returns ------- Tuple (copyright notice, description) ''' info = IPTCInfo(fn) return { key: info[key] for key in c_datasets.values() if info[key] }
def test_save_as_saves_as_new_file_with_info(): if os.path.isfile('fixtures/deleteme.jpg'): # pragma: no cover os.unlink('fixtures/deleteme.jpg') info = IPTCInfo('fixtures/Lenna.jpg') info.save_as('fixtures/deleteme.jpg') info2 = IPTCInfo('fixtures/deleteme.jpg') # The files won't be byte for byte exact, so filecmp won't work assert info._data == info2._data with open('fixtures/Lenna.jpg', 'rb') as fh, open('fixtures/deleteme.jpg', 'rb') as fh2: start, end, adobe = jpeg_collect_file_parts(fh) start2, end2, adobe2 = jpeg_collect_file_parts(fh2) # But we can compare each section assert start == start2 assert end == end2 assert adobe == adobe2
def process_file(filename): """ Want to return: [filename, caption, [tags]] """ info = IPTCInfo(filename) if len(info.data) < 4: raise Exception(info.error) keywords = [] for keyword in info.keywords: keywords.append(keyword.decode("utf-8")) return [filename, info.data["caption/abstract"], keywords]
def get_date(DATADIR_RAW, DATADIR_RAW_NEW): '''Function wich takes as input path of dirs. in those dirs the function will irreterate throug all jpg, extract a date from their meta date and it a IPTC protocol''' # get the image name from the dir DATADIR_RAW for img in os.listdir(DATADIR_RAW): image_path = os.path.join(DATADIR_RAW, img) info = IPTCInfo(image_path, force=True) print(img) # Open the image and access the metadate. Use regex to extract date: image = Image.open(image_path) txt = str(image.info['exif']) # exif are mostly JPEG r = '[\d]{4}:[\d]{2}:[\d]{2}' # format yyyy:mm:dd date = re.search(r, txt).group().replace(':', '') print(f'date of picture: {date}') # Force open the IPTC protocol to insert date info = IPTCInfo(image_path, force=True) print(f"info before: {info['date created']}" ) #Before. Shows wheter or not the entry was empty before info['date created'] = date print(f"info after: {info['date created']}" ) # after. Shows the date extracted from the meta data print('\n') # Create the new dir DATADIR_RAW_NEW if it does not already exist if not os.path.exists(DATADIR_RAW_NEW): os.makedirs(DATADIR_RAW_NEW) # Create the new path for the image new_path = os.path.join(DATADIR_RAW_NEW, 'new' + img) # If that image is already in the path, delete it. if os.path.exists(DATADIR_RAW_NEW): try: os.remove(new_path) except: pass # Save new image. info.save_as(new_path)
def make_big_groups(photo_filenames): """Group images by keyword """ grouped = {} for photo_filename in photo_filenames: info = IPTCInfo(photo_filename) for x in info["keywords"]: x = x.decode("utf-8") if x not in grouped: grouped[x] = [] grouped[x].append(photo_filename) return grouped
def update_index(filepath, filename): info = IPTCInfo(filepath + "/" + filename, force=True) keywords = [] master_index_trie = load_obj("master_index_trie") pp(master_index_trie) for item in info["keywords"]: keywords.append(item.decode("utf-8")) for item in keywords: associated_pics = trie.find_prefix(master_index_trie, item)[2] if type(associated_pics) == list and filename not in associated_pics: trie.add_value(master_index_trie, item, filename) save_obj(master_index_trie, "master_index_trie")
def get_img_data(sfile): try: info = IPTCInfo(sfile) except: logging.ERROR("Could not open file: %s" % sfile) data = dict() data["path"] = sfile data["filename"] = os.path.basename(sfile) title = info["object name"] or info["headline"] if title: data["title"] = title.decode(ENCODING) desc = info["caption/abstract"] if desc: data["description"] = desc.decode(ENCODING) date = info["date created"] if date: date_obj = datetime.datetime.strptime(date.decode(ENCODING), '%Y%m%d') data["date"] = date_obj data["keywords"] = [] if info["keywords"]: for key in info["keywords"]: data["keywords"].append(key.decode(ENCODING)) # exif exif = get_exif(sfile) for tag in exif.keys(): value = str(exif[tag]) if tag == "Image Model": data["model"] = value if tag == "EXIF ExposureTime": data["shutter"] = value if tag == "EXIF FocalLength": data["focal"] = value if tag == "EXIF FNumber": data["aperture"] = str(parse_fstop(value)) if tag == "EXIF ISOSpeedRatings": data["iso"] = value if tag == "EXIF LensModel": data["lens"] = value data["shortcode"] = get_shortcode(data) return data
def process_file(filepath, random_replace=False, verbose=False): img_type = imghdr.what(filepath) if img_type is None: if verbose: print("Skipping).") return if verbose: print(img_type, end='). ') info = IPTCInfo(filepath, force=True) special_instructions = info['special instructions'] if special_instructions is None: if verbose: print("FBMD not found") return fbmd_index = special_instructions.find(b'FBMD') if fbmd_index < 0: if verbose: print("FBMD not found") return length_hex = special_instructions[fbmd_index + 6:fbmd_index + 6 + 4] length = int(length_hex, 16) info['special instructions'] = update_instructions(special_instructions, fbmd_index, length, random=random_replace) if verbose: print(special_instructions[fbmd_index:fbmd_index + 6 + 4 + (length + 1) * 8]) info.save() os.remove(filepath + "~")