def test_piexif( input_file_name, output_file_name, args ): """ Tests Exif manipulation using Piexif performing JPEG I/O with buffered reads and writes. Takes 3 arguments: input_file_name - Path of input JPEG file. output_file_name - Path of output JPEG file. args - Dictionary of arguments provided to the test. This is unused. Returns nothing. """ import piexif jpeg_data = open( input_file_name, "rb" ).read() o = io.BytesIO() # use piexif to extract our Exif data and insert it back into the raw JPEG # byte stream. exif_dict = piexif.load( input_file_name ) exif_dict['GPS'][2] = ((1, 1), (2, 1), (3, 1)) exif_dict['GPS'][4] = ((4, 1), (5, 1), (6, 1)) exif_bytes = piexif.dump( exif_dict ) piexif.insert( exif_bytes, jpeg_data, o ) with open( output_file_name, "wb" ) as file: file.write( o.getvalue() ) munged_jpeg_data = open( output_file_name, "rb" ).read() munged_exif_dict = piexif.load( output_file_name ) munged_exif_bytes = piexif.dump( munged_exif_dict )
def test_dump_fail(self): with open(os.path.join("tests", "images", "large.jpg"), "rb") as f: thumb_data = f.read() exif_dict = {"0th":ZEROTH_IFD, "Exif":EXIF_IFD, "GPS":GPS_IFD, "Interop":INTEROP_IFD, "1st":FIRST_IFD, "thumbnail":thumb_data} with self.assertRaises(ValueError): piexif.dump(exif_dict)
def test_update_exif_orientation_without_orientation(self): """ Test the update_exif_orientation without orientation will not throw exception. """ requested_images = {10: "ten.jpg"} with make_image_file(extension='.jpg') as imfile: for _, image in self._create_mocked_profile_images(imfile, requested_images): self.check_exif_orientation(image, None) exif = image.info.get('exif', piexif.dump({})) self.assertEqual( _update_exif_orientation(exif, None), image.info.get('exif', piexif.dump({})) )
def test_dump_and_load2(self): thumbnail_io = io.BytesIO() thumb = Image.open(INPUT_FILE2) thumb.thumbnail((40, 40)) thumb.save(thumbnail_io, "JPEG") thumb.close() thumb_data = thumbnail_io.getvalue() exif_dict = {"0th":ZEROTH_IFD, "Exif":EXIF_IFD, "GPS":GPS_IFD, "Interop":INTEROP_IFD, "1st":FIRST_IFD, "thumbnail":thumb_data} exif_bytes = piexif.dump(exif_dict) im = Image.new("RGBA", (80, 80)) o = io.BytesIO() im.save(o, format="jpeg", exif=exif_bytes) im.close() o.seek(0) exif = piexif.load(o.getvalue()) exif["0th"].pop(ImageIFD.ExifTag) # pointer to exif IFD exif["0th"].pop(ImageIFD.GPSTag) # pointer to GPS IFD exif["Exif"].pop(ExifIFD.InteroperabilityTag) self.assertDictEqual(ZEROTH_IFD, exif["0th"]) self.assertDictEqual(EXIF_IFD, exif["Exif"]) self.assertDictEqual(GPS_IFD, exif["GPS"]) self.assertDictEqual(INTEROP_IFD, exif["Interop"]) exif["1st"].pop(513) # pointer to exif IFD exif["1st"].pop(514) # pointer to GPS IFD self.assertDictEqual(FIRST_IFD, exif["1st"]) Image.open(io.BytesIO(exif["thumbnail"])).close()
def dirwithfiles(tmpworkdir): img = PIL.Image.new('RGB', (100, 100)) draw = ImageDraw.Draw(img) draw.text((10, 10), "img", fill=(255, 0, 0)) del draw exifdata= piexif.dump({"0th":{}, "Exif":someexif, "GPS":{}, "Interop":{}, "1st":{}, "thumbnail":None}) img.save('img.jpg','jpeg',exif=exifdata) img.save('newimg.jpg','jpeg') with open('some.html','w') as f: f.write(""" <!DOCTYPE html> <html> <head> <title>Page Title</title> </head> <body> <img src="some_files/img.jpg"> </body> </html> """) shutil.copy2('some.html','sometxt.txt') os.mkdir('sub') [shutil.copy2(x,'sub') for x in glob('*.jpg')] os.mkdir('some_files') shutil.copy2('img.jpg','some_files') return str(tmpworkdir)
def download_album(account, password, main_folder_path): cookie_object = Cookie(account=account, password=password) for album_name, album_URL in Album(cookie_object=cookie_object).iterate_album_info(): print("Working on album {} ...".format(album_name)) album_folder_path = os.path.join(main_folder_path, album_name) os.makedirs(album_folder_path, exist_ok=True) for image_name, image_URL_tuple, image_time in Image(cookie_object=cookie_object, album_URL=album_URL).iterate_image_info(): image_file_path = os.path.join(album_folder_path, image_name) if os.path.isfile(image_file_path): continue print("Working on image {} ...".format(image_name)) for image_URL in image_URL_tuple: download_image(image_URL, image_file_path) if os.path.isfile(image_file_path): break if not os.path.isfile(image_file_path): print("Failed to download image {}!".format(image_name)) continue # Insert EXIF information datetime_object = datetime.strptime(image_time, "%a %b %d %H:%M:%S %Z %Y") exif_ifd = {piexif.ExifIFD.DateTimeOriginal: datetime_object.isoformat(" ")} exif_dict = {"Exif": exif_ifd} exif_bytes = piexif.dump(exif_dict) piexif.insert(exif_bytes, image_file_path)
def make_image_file(dimensions=(320, 240), extension=".jpeg", force_size=None, orientation=None): """ Yields a named temporary file created with the specified image type and options. Note the default dimensions are unequal (not a square) ensuring that center-square cropping logic will be exercised during tests. The temporary file will be closed and deleted automatically upon exiting the `with` block. """ image = Image.new('RGB', dimensions, "green") image_file = NamedTemporaryFile(suffix=extension) try: if orientation and orientation in xrange(1, 9): exif_bytes = piexif.dump({'0th': {piexif.ImageIFD.Orientation: orientation}}) image.save(image_file, exif=exif_bytes) else: image.save(image_file) if force_size is not None: image_file.seek(0, os.SEEK_END) bytes_to_pad = force_size - image_file.tell() # write in hunks of 256 bytes hunk, byte_ = bytearray([0] * 256), bytearray([0]) num_hunks, remainder = divmod(bytes_to_pad, 256) for _ in xrange(num_hunks): image_file.write(hunk) for _ in xrange(remainder): image_file.write(byte_) image_file.flush() image_file.seek(0) yield image_file finally: image_file.close()
def manipulate_exif(img, settings): try: exif = piexif.load(img.info['exif']) except Exception: logger.debug('EXIF information not found') exif = {} if settings['PHOTO_EXIF_AUTOROTATE']: img, exif = rotate_image(img, exif) if settings['PHOTO_EXIF_REMOVE_GPS']: exif.pop('GPS') if settings['PHOTO_EXIF_COPYRIGHT']: # We want to be minimally destructive to any preset exif author or copyright information. # If there is copyright or author information prefer that over everything else. if not exif['0th'].get(piexif.ImageIFD.Artist): exif['0th'][piexif.ImageIFD.Artist] = settings['PHOTO_EXIF_COPYRIGHT_AUTHOR'] author = settings['PHOTO_EXIF_COPYRIGHT_AUTHOR'] if not exif['0th'].get(piexif.ImageIFD.Copyright): license = build_license(settings['PHOTO_EXIF_COPYRIGHT'], author) exif['0th'][piexif.ImageIFD.Copyright] = license return (img, piexif.dump(exif))
def renameImageFile(key, oldFileName, newFileName, outputFolder, payloadFolder = None): """ Accepts an image path and copies while renaming it key = the key from the recordDict, which should correspond to the field number. Passing this to avoid addtl. work. oldFileName = the field-number-named file which needs to be renamed and moved newFileNAme = the desired new name after moving outputFolder = the folder to save the catalog-number-named file payloadFolder = the folder to congregate to be transfered files, if not passed presumes it is the same as outputFolder """ if payloadFolder == None: payloadFolder = outputFolder newFileNames = [] #start with an empty list.... for destFolder in set([outputFolder, payloadFolder]): newFileNames.append(str(destFolder + '/{}.jpg'.format(newFileName))) #Build a list of paths to copy the orig file to. # see this example for concerns about loss of metadata upon image copy: # https://stackoverflow.com/questions/6106303/how-to-rename-a-file-and-preserve-creation-date-in-python stat = os.stat(oldFileName) #Take note of creation and modification metadata from initial file for outputName in newFileNames: # for each filepath we're copying to os.makedirs(os.path.dirname(outputName), exist_ok=True) shutil.copy2(oldFileName, outputName) # copy the origional and rename it according to the outputName # insert metadata metaDataDict = {'otherCatalogNumber':key} #This dict can be altered to add ... everything? zeroth_ifd = {270: str(metaDataDict)} #converting dict to string to embed it into the same field exif_bytes = piexif.dump({"0th":zeroth_ifd}) os.utime(outputName, (stat.st_atime, stat.st_mtime)) #Write orig creation and modification metadata to the copied file #debugging creation time metadata loss # print(stat) # print(os.stat(outputName)) piexif.insert(exif_bytes,outputName)
def hide(input_image_file, img_enc, secret_message = None, secret_file = None): """ Hide a message (string) in an image. """ from zlib import compress from base64 import b64encode if secret_file != None: with open(secret_file, "r") as f: secret_message = f.read() try: text = compress(b64encode(bytes(secret_message, "utf-8"))) except: text = compress(b64encode(secret_message)) img = Image.open(input_image_file) if "exif" in img.info: exif_dict = piexif.load(img.info["exif"]) else: exif_dict = {} exif_dict["0th"] = {} exif_dict["0th"][piexif.ImageIFD.ImageDescription] = text exif_bytes = piexif.dump(exif_dict) img.save(img_enc, exif=exif_bytes) img.close() return img
def setgeoimage(data,lat,lon,imagedescription="",usercomment="",dt=None): exif_dict = piexif.load(data) #for ifd in ("0th", "Exif", "GPS", "1st"): # for tag in exif_dict[ifd]: # print tag # print(piexif.TAGS[ifd][tag]["name"], exif_dict[ifd][tag]) # #lat,lon=get_geo(exif_dict) #print "lat lon",lat,lon if dt is None: exif_dict["0th"][piexif.ImageIFD.DateTime]=datetime.utcnow().strftime("%Y:%m:%d %H:%M:%S") else: exif_dict["0th"][piexif.ImageIFD.DateTime]=dt.strftime("%Y:%m:%d %H:%M:%S") set_geo(exif_dict, lat, lon) exif_dict["Exif"][piexif.ExifIFD.UserComment]=chr(0x55)+chr(0x4E)+chr(0x49)+chr(0x43)+chr(0x4F)+chr(0x44)+chr(0x45)+chr(0x00)+usercomment exif_dict["0th"][piexif.ImageIFD.ImageDescription]=imagedescription exif_bytes = piexif.dump(exif_dict) new_data=io.BytesIO(data) piexif.insert(exif_bytes, data, new_data) return new_data.getvalue()
def normalize_image_orientation(img_file): """Reads orientation tag from the exif data attached to a JPEG image. Returns the image rotated to normal orientation and with corresponding normal exif orientation tag. Note: horizontal (normal) exif value = 1 """ ### Open image and read orientation tag im = Image.open(img_file) exif_dict = piexif.load(im.info["exif"]) orientation = exif_dict["0th"][piexif.ImageIFD.Orientation] print(orientation) ## Rotate image im = rotate_image_to_normal(im, orientation) ## Create new exif dict with base orientation value of 1 exif_dict["0th"][piexif.ImageIFD.Orientation] = 1 exif_bytes = piexif.dump(exif_dict) ## Return file in a buffer buf = BytesIO() im.save(buf, "jpeg", exif=exif_bytes) buf.seek(0) return(buf)
def add_gps_tags(path: str, gps_tags: {str: any}): """This method will add gps tags to the photo found at path""" exif_dict = piexif.load(path) for tag, tag_value in gps_tags.items(): exif_dict["GPS"][tag] = tag_value exif_bytes = piexif.dump(exif_dict) piexif.insert(exif_bytes, path)
def test_piexif_with_pil( input_file_name, output_file_name, args ): """ Tests Exif manipulation using Piexif performing JPEG I/O with PIL. Note that PIL performs image decompression and recompression which will likely alter the contents of image. Takes 3 arguments: input_file_name - Path of input JPEG file. output_file_name - Path of output JPEG file. args - Dictionary of arguments provided to the test. This may contain a "quality" key that specifies a quality parameter suitable for use when saving a JPEG with PIL. Returns nothing. """ import piexif from PIL import Image # use piexif to extract our Exif data. exif_dict = piexif.load( input_file_name ) exif_dict['GPS'][2] = ((1, 1), (2, 1), (3, 1)) exif_dict['GPS'][4] = ((4, 1), (5, 1), (6, 1)) exif_bytes = piexif.dump( exif_dict ) # use PIL to specify raw Exif data when saving. # # NOTE: this will reencode the file that has been opened which is likely # not what a user wants. im = Image.open( input_file_name ) im.save( output_file_name, exif=exif_bytes, **args )
def create_duplicateOLD(source, target, batch, frame): if config['overlay-text'] or config['resize']: img = Image.open(source) exif_bytes = None if config['resize']: img = img.resize( (config['resize_width'], config['resize_height']), Image.ANTIALIAS) if config['write_exif']: exif_dict = piexif.load(img.info['exif']) # from pprint import pprint # pprint(exif_dict) exif_dict["0th"][piexif.ImageIFD.Orientation] = 4 exif_bytes = piexif.dump(exif_dict) if config['overlay-text']: # text overlay if config['image_format'] == "XXXX_XX": text = "%04d-%02d" % (batch, frame) else: text = "%04d" % (batch) draw = ImageDraw.Draw(img) draw.text( (60, 60), text, (255, 14, 179), font=config['font'] ) if config['write_exif']: img.save(target, quality=config['image-quality'], exif=exif_bytes) else: img.save(target, quality=config['image-quality']) else: shutil.copy2(source, target) time.sleep(config['delay_between_frames'])
def optimize(image, filename): exif_dict = get_exif(image) exif_bytes = piexif.dump(exif_dict) if piexif.ImageIFD.Orientation in exif_dict["0th"]: orientation = exif_dict["0th"].pop(piexif.ImageIFD.Orientation) if orientation == 2: image = image.transpose(Image.FLIP_LEFT_RIGHT) elif orientation == 3: image = image.rotate(180) elif orientation == 4: image = image.rotate(180).transpose(Image.FLIP_LEFT_RIGHT) elif orientation == 5: image = image.rotate(-90).transpose(Image.FLIP_LEFT_RIGHT) elif orientation == 6: image = image.rotate(-90) elif orientation == 7: image = image.rotate(90).transpose(Image.FLIP_LEFT_RIGHT) elif orientation == 8: image = image.rotate(90) width, height = image.size if width > self.MAX_IMAGE_WIDTH: new_height = int(round(height / (width / self.MAX_IMAGE_WIDTH))) image = image.resize((self.MAX_IMAGE_WIDTH, new_height), Image.ANTIALIAS) image.save(filename, optimize=True, quality=90, exif=exif_bytes) return image
def resize_image(self, src, dst, max_size, bigger_panoramas=True, preserve_exif_data=False, exif_whitelist={}): """Make a copy of the image in the requested size.""" if not Image or os.path.splitext(src)[1] in ['.svg', '.svgz']: self.resize_svg(src, dst, max_size, bigger_panoramas) return im = Image.open(src) if hasattr(im, 'n_frames') and im.n_frames > 1: # Animated gif, leave as-is utils.copy_file(src, dst) return size = w, h = im.size if w > max_size or h > max_size: size = max_size, max_size # Panoramas get larger thumbnails because they look *awful* if bigger_panoramas and w > 2 * h: size = min(w, max_size * 4), min(w, max_size * 4) try: exif = piexif.load(im.info["exif"]) except KeyError: exif = None # Inside this if, we can manipulate exif as much as # we want/need and it will be preserved if required if exif is not None: # Rotate according to EXIF value = exif['0th'].get(piexif.ImageIFD.Orientation, 1) if value in (3, 4): im = im.transpose(Image.ROTATE_180) elif value in (5, 6): im = im.transpose(Image.ROTATE_270) elif value in (7, 8): im = im.transpose(Image.ROTATE_90) if value in (2, 4, 5, 7): im = im.transpose(Image.FLIP_LEFT_RIGHT) exif['0th'][piexif.ImageIFD.Orientation] = 1 try: im.thumbnail(size, Image.ANTIALIAS) if exif is not None and preserve_exif_data: # Put right size in EXIF data w, h = im.size if '0th' in exif: exif["0th"][piexif.ImageIFD.ImageWidth] = w exif["0th"][piexif.ImageIFD.ImageLength] = h if 'Exif' in exif: exif["Exif"][piexif.ExifIFD.PixelXDimension] = w exif["Exif"][piexif.ExifIFD.PixelYDimension] = h # Filter EXIF data as required exif = self.filter_exif(exif, exif_whitelist) im.save(dst, exif=piexif.dump(exif)) else: im.save(dst) except Exception as e: self.logger.warn("Can't process {0}, using original " "image! ({1})".format(src, e)) utils.copy_file(src, dst)
def save_seq_num(img,img_name,seq): key = get_config('tags')[2] value = str(seq) tags = get_meta_dict(img) tags[key] = value debug('new tag dict to insert',tags) exif_bytes = piexif.dump(tags) piexif.insert(exif_bytes, img_name)
def test_no_exif_dump(self): o = io.BytesIO() exif_bytes = piexif.dump({}) i = Image.new("RGBA", (8, 8)) i.save(o, format="jpeg", exif=exif_bytes) o.seek(0) exif_dict2 = load_exif_by_PIL(o) self.assertDictEqual({}, exif_dict2)
def add_metadata(im): """ Funkce add_metadata vrací exif vstupniho obrazku im obohaceného o textová a obrazová metadata v bytové podobě. Na uživatelském vstupu jsou očekávány text a cesta k obrázku k připojení. Pokud cesta neexistuje neboje obrazek příliš velký, je uživatel vyzván k opětovnému zadání. Textová data jsou ukládána do exifu pod klíčem 37510 a obrazová pod kódem 37500. """ meta_text = input('Zadejte textová metadata ' '(pokud nechcete pridavat, ponechte prazdne): ') if meta_text == "": print("Textova metadata nepripojena.") exif_dict = piexif.load(im.info["exif"]) exif_dict['Exif'][37510] = meta_text path = input('Zadejte cestu k obrazovym metadatum ' '(pokud nechcete pridavat, ponechte prazdne): ') while True: if path == "": print("Obrazova metadata nepripojena.") exif_bytes = piexif.dump(exif_dict) return exif_bytes try: with open(path, "rb") as imageFile: f = imageFile.read() except FileNotFoundError: print("Na zadane ceste:", path, "neexistuje obrazek. Zadejte novou cestu:") path = input() else: if os.stat(path).st_size > 56000: print("Obrazek na ceste:", path, "je prilis velky. Zadejte novou cestu:") path = input() else: break byte_image = bytearray(f) exif_dict['Exif'][37500] = byte_image exif_bytes = piexif.dump(exif_dict) return exif_bytes
def _update_exif_orientation(exif, orientation): """ Given an exif value and an integer value 1-8, reflecting a valid value for the exif orientation, return a new exif with the orientation set. """ exif_dict = piexif.load(exif) if orientation: exif_dict['0th'][piexif.ImageIFD.Orientation] = orientation return piexif.dump(exif_dict)
def test_insert_m(self): """'insert' on memory. """ exif_dict = {"0th":ZEROTH_IFD, "Exif":EXIF_IFD, "GPS":GPS_IFD} exif_bytes = piexif.dump(exif_dict) o = io.BytesIO() piexif.insert(exif_bytes, I1, o) self.assertEqual(o.getvalue()[0:2], b"\xff\xd8") exif = load_exif_by_PIL(o)
def insert_sample(): zeroth_ifd = {282: (96, 1), 283: (96, 1), 296: 2, 305: 'piexif'} exif_bytes = piexif.dump({"0th":zeroth_ifd}) piexif.insert(exif_bytes, "remove_sample.jpg", "insert_sample.jpg")
def test_load_from_pilImage_property(self): o = io.BytesIO() i = Image.open(INPUT_FILE1) exif = i.info["exif"] exif_dict = piexif.load(exif) exif_bytes = piexif.dump(exif_dict) i.save(o, "jpeg", exif=exif_bytes) i.close() o.seek(0) Image.open(o).close()
def test_insert_fail1(self): with open(INPUT_FILE1, "rb") as f: data = f.read() with open("insert.jpg", "wb+") as f: f.write(data) exif_dict = {"0th":ZEROTH_IFD, "Exif":EXIF_IFD, "GPS":GPS_IFD} exif_bytes = piexif.dump(exif_dict) with self.assertRaises(ValueError): piexif.insert(exif_bytes, INPUT_FILE_TIF) os.remove("insert.jpg")
def check_exif_orientation(self, image, expected_orientation): """ Check that the created object is a JPEG and that it has the expected """ self.assertEqual(image.format, 'JPEG') if expected_orientation is not None: self.assertIn('exif', image.info) self.assertEqual(_get_exif_orientation(image.info['exif']), expected_orientation) else: self.assertIsNone(_get_exif_orientation(image.info.get('exif', piexif.dump({}))))
def _get_corrected_exif(image, original): """ If the original image contains exif data, use that data to preserve image orientation in the new image. """ if 'exif' in original.info: image_exif = image.info.get('exif', piexif.dump({})) original_exif = original.info['exif'] image_exif = _update_exif_orientation(image_exif, _get_exif_orientation(original_exif)) return image_exif
def dump_sample(input_file, output_file): zeroth_ifd = {piexif.ImageIFD.Make: "foo", piexif.ImageIFD.XResolution: (96, 1), piexif.ImageIFD.YResolution: (96, 1), piexif.ImageIFD.Software: "pixief", } exif_bytes = piexif.dump({"0th":zeroth_ifd}) im = Image.open(input_file) im.thumbnail((100, 100), Image.ANTIALIAS) im.save(output_file, exif=exif_bytes)
def test_dump_and_load3(self): ascii_v = ["a", "ab", "abc", "abcd", "abcde"] undefined_v = [b"\x00", b"\x00\x01", b"\x00\x01\x02", b"\x00\x01\x02\x03", b"\x00\x01\x02\x03\x04"] byte_v = [255, (255, 254), (255, 254, 253), (255, 254, 253, 252), (255, 254, 253, 252, 251)] short_v = [65535, (65535, 65534), (65535, 65534, 65533), (65535, 65534, 65533, 65532), (65535, 65534, 65533, 65532, 65531)] long_v = [4294967295, (4294967295, 4294967294), (4294967295, 4294967294, 4294967293), (4294967295, 4294967294, 4294967293, 4294967292), (5, 4, 3, 2, 1)] rational_v = [(4294967295, 4294967294), ((4294967295, 4294967294), (4294967293, 4294967292)), ((1, 2), (3, 4), (5, 6)), ((1, 2), (3, 4), (5, 6), (7, 8)), ((1, 2), (3, 4), (5, 6), (7, 8), (9, 10))] srational_v = [(2147483647, -2147483648), ((2147483647, -2147483648), (2147483645, 2147483644)), ((1, 2), (3, 4), (5, 6)), ((1, 2), (3, 4), (5, 6), (7, 8)), ((1, 2), (3, 4), (5, 6), (7, 8), (9, 10))] for x in range(5): exif_dict = { "0th":{ImageIFD.ProcessingSoftware:ascii_v[x], ImageIFD.InterColorProfile:undefined_v[x], ImageIFD.SubfileType:short_v[x], ImageIFD.WhitePoint:rational_v[x], ImageIFD.BlackLevelDeltaH:srational_v[x]}, "Exif":{ExifIFD.ISOSpeed:long_v[x]}, "GPS":{GPSIFD.GPSVersionID:byte_v[x]},} exif_bytes = piexif.dump(exif_dict) e = piexif.load(exif_bytes) self.assertEqual( e["0th"][ImageIFD.ProcessingSoftware].decode("latin1"), ascii_v[x]) self.assertEqual( e["0th"][ImageIFD.InterColorProfile], undefined_v[x]) self.assertEqual(e["0th"][ImageIFD.SubfileType], short_v[x]) self.assertEqual(e["0th"][ImageIFD.WhitePoint], rational_v[x]) self.assertEqual( e["0th"][ImageIFD.BlackLevelDeltaH], srational_v[x]) self.assertEqual(e["Exif"][ExifIFD.ISOSpeed], long_v[x]) self.assertEqual(e["GPS"][GPSIFD.GPSVersionID], byte_v[x])
def update_exif(meta): updated_exif = get_updated_exif(meta) exif_bytes = piexif.dump(updated_exif) piexif.insert(exif_bytes, meta['uri'])
def test_dump_fail2(self): exif_ifd = {ExifIFD.DateTimeOriginal: 123} exif_dict = {"Exif": exif_ifd} with self.assertRaises(ValueError): piexif.dump(exif_dict)
if field in exif_section: print(exif_section[field]) dt = datetime.strptime(exif_section[field].decode(), EXIF_DT_FORMAT) if dt.strftime('%Y-%m-%d') == date and dt.hour == wrong_hour: dt = dt - timedelta(minutes=decreate_minutes) + timedelta( minutes=increate_minutes) exif_section[field] = dt.strftime(EXIF_DT_FORMAT).encode() print('Time changed to %s' % dt) exif_section = exif['Exif'] for field in [ piexif.ExifIFD.DateTimeOriginal, piexif.ExifIFD.DateTimeDigitized ]: if field in exif_section: print(exif_section[field]) dt = datetime.strptime(exif_section[field].decode(), EXIF_DT_FORMAT) if dt.strftime( '%Y-%m-%d') == date and dt.hour == wrong_hour: dt = dt - timedelta( minutes=decreate_minutes) + timedelta( minutes=increate_minutes) exif_section[field] = dt.strftime( EXIF_DT_FORMAT).encode() print('Time changed to %s' % dt) byte_exif = piexif.dump(exif) piexif.insert(byte_exif, fullname)
import json import sys import piexif import pydicom from PIL import Image try: src_path = sys.argv[-2] dst_path = sys.argv[-1] except Exception: print('Usage: python dcm2jpg.py <src> <dst>') exit() dcm = pydicom.dcmread(src_path) attr = { "StudyInstanceUID": dcm.StudyInstanceUID, "SeriesInstanceUID": dcm.SeriesInstanceUID, "SOPInstanceUID": dcm.SOPInstanceUID, "PatientSex": dcm.PatientSex, "PatientAge": int(dcm.PatientAge), "ViewPosition": dcm.ViewPosition, "PixelSpacing": [float(s) for s in dcm.PixelSpacing], } img = Image.fromarray(dcm.pixel_array) exif_ifd = {piexif.ExifIFD.MakerNote: json.dumps(attr).encode("ascii")} exif = {"Exif": exif_ifd} img.save(dst_path, format='jpeg', exif=piexif.dump(exif))
def write(self): """Writes EXIF tags in associated file""" if self.exif_dict != {}: exif_bytes = piexif.dump(self.exif_dict) piexif.insert(exif_bytes, self.filename)
from os.path import isfile, join from PIL import Image from datetime import datetime, timedelta import time import piexif import sys mypath = sys.argv[1] start_time = datetime(2017, 12, 30, 11, 0, 0) interval = timedelta(seconds=20) onlyfiles = [ join(mypath, f) for f in listdir(mypath) if isfile(join(mypath, f)) ] curr_time = start_time for f in sorted(onlyfiles): #change Exif using PIL and piexif im = Image.open(f) exif_dict = {"Exif": {}} if "exif" in im.info: exif_dict = piexif.load(im.info["exif"]) exif_dict["Exif"][piexif.ExifIFD.DateTimeOriginal] = curr_time.strftime( "%Y:%m:%d %H:%M:%S") exif_bytes = piexif.dump(exif_dict) im.save(f, exif=exif_bytes) #change accessed and modified in filesystem t = time.mktime(curr_time.timetuple()) utime(f, (t, t)) #increment time curr_time += interval
if factor >= 1: print_warn( "Image already smaller than the target, ignoring resize factor {}" .format(factor)) else: print_info("Resize factor: {}".format(factor)) new_size = [round(d * factor) for d in image.size] image = image.resize(new_size, resample=Image.LANCZOS) exif_dict["Exif"][EXIF_IMAGEWIDTH] = new_size[0] exif_dict["Exif"][EXIF_IMAGEHEIGHT] = new_size[1] # Equivalent : #exif_dict["Exif"][piexif.ExifIFD.PixelYDimension] = new_size[1] if not args.keep_gps: del exif_dict["GPS"] destination = os.path.join(args.destination, os.path.basename(filename)) image.save(destination, format="JPEG", quality=args.quality, exif=piexif.dump(exif_dict)) destination_filesize = os.path.getsize(destination) print_info( "Final dimensions {}, filesize {} kB (compression ratio {:.1f}%)". format(image.size, int(destination_filesize / 1024), destination_filesize * 100 / source_filesize)) if (destination_filesize > source_filesize): print_alarm("Resulting image is larger in filesize !")
def set_file_geo_data(file: Path, json): """ Reads the geoData from google and saves it to the EXIF. This works assuming that the geodata looks like -100.12093, 50.213143. Something like that. Written by DalenW. :param file: :param json: :return: """ # prevents crashes try: exif_dict = _piexif.load(str(file)) except: exif_dict = {'0th': {}, 'Exif': {}} # converts a string input into a float. If it fails, it returns 0.0 def _str_to_float(num): if type(num) == str: return 0.0 else: return float(num) # fallbacks to GeoData Exif if it wasn't set in the photos editor. # https://github.com/TheLastGimbus/GooglePhotosTakeoutHelper/pull/5#discussion_r531792314 longitude = _str_to_float(json['geoData']['longitude']) latitude = _str_to_float(json['geoData']['latitude']) altitude = _str_to_float(json['geoData']['altitude']) # Prioritise geoData set from GPhotos editor. If it's blank, fall back to geoDataExif if longitude == 0 and latitude == 0: longitude = _str_to_float(json['geoDataExif']['longitude']) latitude = _str_to_float(json['geoDataExif']['latitude']) altitude = _str_to_float(json['geoDataExif']['altitude']) # latitude >= 0: North latitude -> "N" # latitude < 0: South latitude -> "S" # longitude >= 0: East longitude -> "E" # longitude < 0: West longitude -> "W" if longitude >= 0: longitude_ref = 'E' else: longitude_ref = 'W' longitude = longitude * -1 if latitude >= 0: latitude_ref = 'N' else: latitude_ref = 'S' latitude = latitude * -1 # referenced from https://gist.github.com/c060604/8a51f8999be12fc2be498e9ca56adc72 gps_ifd = {_piexif.GPSIFD.GPSVersionID: (2, 0, 0, 0)} # skips it if it's empty if latitude != 0 or longitude != 0: gps_ifd.update({ _piexif.GPSIFD.GPSLatitudeRef: latitude_ref, _piexif.GPSIFD.GPSLatitude: degToDmsRational(latitude), _piexif.GPSIFD.GPSLongitudeRef: longitude_ref, _piexif.GPSIFD.GPSLongitude: degToDmsRational(longitude) }) if altitude != 0: gps_ifd.update({ _piexif.GPSIFD.GPSAltitudeRef: 1, _piexif.GPSIFD.GPSAltitude: change_to_rational(round(altitude)) }) gps_exif = {"GPS": gps_ifd} exif_dict.update(gps_exif) try: _piexif.insert(_piexif.dump(exif_dict), str(file)) except Exception as e: logger.debug("Couldn't insert geo exif!") # local variable 'new_value' referenced before assignment means that one of the GPS values is incorrect logger.debug(e)
print("no file at row" + str(i)) continue # piexif.transplant(template_fn,target_fn) exif = piexif.load(template_fn) # print(exif['GPS']) longitude = row.lon latitude = row.lat altitude = row.alt ori, res = lon_lat_to_degree_min_sec(latitude, 'lat') exif['GPS'][1] = ori exif['GPS'][2] = res ori, res = lon_lat_to_degree_min_sec(longitude, 'lon') exif['GPS'][3] = ori exif['GPS'][4] = res exif['GPS'][5] = 0 exif['GPS'][6] = (int(altitude * 1000000), 1000000) # print(exif['GPS']) # print(exif) new_exif_byte = piexif.dump(exif) piexif.insert(new_exif_byte, target_fn) os.system("pause")
def post(self): data = {"success": False} options = request.args.get('options', '[]') # reads file streams and inputs them in correct array structure files = request.files.to_dict() if files.get("image") and files.get("mask"): im = io.BytesIO(files['image'].read()) # img = imread(im) mask_img = imread(io.BytesIO(files['mask'].read())) # need Pillow to get exif data from image im = Image.open(im) if im.mode != "RGB": im = im.convert("RGB") exif = im.info["exif"] if "exif" in im.info else piexif.dump({ "0th": {}, "Exif": {}, "GPS": {}, "1st": {}, "thumbnail": None }) tags = request.args.get('metadata', '[]') tags = tags.strip('][').split(',') k = str(uuid.uuid4()) img = np.array(im) image_shape = img.shape # swap axes in case axes do not correspond correctly if (image_shape[0] == mask_img.shape[1] and image_shape[1] == mask_img.shape[0]): mask_img = np.swapaxes(mask_img, 0, 1) # resize mask in case it isn't the same size if (image_shape[0] != mask_img.shape[0] and image_shape[1] != mask_img.shape[1]): mask_img = resize(mask_img, (image_shape[0], image_shape[1]), mode='constant', preserve_range=True) img = get_response_image(img) mask_img = get_response_image(mask_img) d = { "id": k, "image": img, "mask": mask_img, "shape": image_shape, "options": options, "exif": exif, "tags": tags } db.rpush(settings.CENSOR_IMAGE_QUEUE, bson.dumps(d)) timeDelta = datetime.datetime.now() + datetime.timedelta(minutes=3) while True: output = db.get(k) if output is not None: output = output.decode("utf-8") data["ImageBytes"] = json.loads(output) db.delete(k) break time.sleep(settings.CLIENT_SLEEP) if datetime.datetime.now() > timeDelta: print('timeout') break if "ImageBytes" in data: data["success"] = True else: db.delete(k) return "System error", 500 return jsonify(data)
def change_title(file, title): exif_dict = {"0th": {piexif.ImageIFD.ImageDescription: title}} exif_bytes = piexif.dump(exif_dict) piexif.insert(exif_bytes, file)
def save_spotlight_image(sess, params, outdir, mode="landscape"): spotlight_api = 'https://arc.msn.com/v3/Delivery/Cache' result = sess.get(spotlight_api, params=params) result.raise_for_status() js = json.loads(result.text) items = js.get('batchrsp').get('items') for item in items: item_js = json.loads(item.get('item')) ad = item_js.get('ad') title = ad.get('title_text').get('tx') for i in [1]: # do not change key = "image_fullscreen_%03d_%s" % (i, mode) image_info = ad.get(key) if not image_info: break url = image_info.get('u') sha256 = image_info.get('sha256') fileSize = image_info.get('fileSize') m = url_pat.search(url) fn = m.group(1) save_path_tentative = title + '_' + fn + '.jpg' save_path = os.path.join(outdir, save_path_tentative.replace('?', '_')) sys.stderr.write('[Info] downloading %s\n' % save_path) img_result = sess.get(url) jpeg_data = img_result.content sys.stderr.write('[Info] sanity check\n') if len(jpeg_data) != fileSize: Exception("fileSize is not consistent!") if hashlib.sha256(jpeg_data).hexdigest() != sha256: Exception("sha256 is not consistent!") # 0x010e: b'title' # 0x013b: b'creator' # 0x8298: b'copyright' # 0x9c9b: kenmei # 0x9c9c: comment # 0x9c9d: author # 0x9c9f: subject exif_0th = {} exif_0th[0x010e] = title.encode('utf-8') # exif_0th[0x013b] = "creator" exif_0th[0x8298] = ad.get('copyright_text').get('tx').encode( 'utf-8') exif_0th[0x9c9c] = "\n\n".join([ ad.get('title_text').get('tx'), edge_pat.sub("", ad.get('title_destination_url').get('u')), ad.get('hs1_title_text').get('tx'), ad.get('hs1_cta_text').get('tx'), edge_pat.sub("", ad.get('hs1_destination_url').get('u')), ad.get('hs2_title_text').get('tx'), ad.get('hs2_cta_text').get('tx'), edge_pat.sub("", ad.get('hs2_destination_url').get('u')) ]).encode('utf-16') exif = {'0th': exif_0th} exif_bytes = piexif.dump(exif) piexif.insert(exif_bytes, jpeg_data, save_path)
def insert_user_comment(comment, file_name): exif_dict = piexif.load(file_name) user_comment = piexif.helper.UserComment.dump(u"{\"comment\":\"this is test!\"}") exif_dict["Exif"][piexif.ExifIFD.UserComment] = comment exif_raw = piexif.dump(exif_dict) piexif.insert(exif_raw, file_name)
def test_insert_fail2(self): exif_dict = {"0th": ZEROTH_IFD, "Exif": EXIF_IFD, "GPS": GPS_IFD} exif_bytes = piexif.dump(exif_dict) with self.assertRaises(ValueError): piexif.insert(exif_bytes, I1, False)
def addCoordFromGPX(self): secInterpol = self.ui.spinBoxInterpol.value() utc = self.ui.currentUTC secDecalage = self.ui.spinBoxDecalage.value() path_gpx = self.gpxPath + "|layername=track_points" vLayer = QgsVectorLayer(path_gpx, "ogr") currentPBarValue = 0 nbObj = len(self.listPictureObj) self.ui.progressBar.setMaximum(nbObj) self.newListPictureObj = [] for obj in self.listPictureObj: if obj.isCoordonate and self.ui.checkBoxKeep.isChecked(): pass elif obj.time and obj.isEXIF: #time = b'YYYY:MM:DD HH:MM:SS' strTime = obj.time.decode() objDate = QtCore.QDate(int(strTime[0:4]), int(strTime[5:7]), int(strTime[8:10])) timeofDay = int(strTime[11:13]) * 3600 + int( strTime[14:16]) * 60 + int(strTime[17:19]) timeUp = timeofDay + secInterpol timeDown = timeofDay - secInterpol geoUp = None geoDown = None timeDiffUp = secInterpol timeDiffDown = secInterpol for feature in vLayer.getFeatures(): try: featTimeAttr = feature.attribute('time') except: pass else: if featTimeAttr.date() == objDate: fTime = featTimeAttr.time() timeofFeat = (fTime.hour() + utc) * 3600 + fTime.minute( ) * 60 + fTime.second() + secDecalage if timeofFeat < timeofDay: currentDiff = timeofFeat - timeDown if currentDiff <= timeDiffDown: timeDiffDown = timeofFeat geoDown = feature.geometry() elif timeofFeat > timeofDay: currentDiff = timeUp - timeofFeat if currentDiff <= timeDiffUp: timeDiffUp = timeofFeat geoUp = feature.geometry() #listGeometry.append(feature.geometry()) #Très important de vérifié la compatibilité, fonctionne pour mon GPX, en général toujours le cas delta = timeDiffUp - timeDiffDown if geoDown and geoUp and delta <= secInterpol: prop = (timeofDay - timeDiffDown) / delta invProp = 1 - prop upX = geoUp.get().x() upY = geoUp.get().y() upZ = geoUp.get().z() downX = geoDown.get().x() downY = geoDown.get().y() downZ = geoDown.get().z() xCoord = upX * prop + downX * invProp yCoord = upY * prop + downY * invProp zCoord = upZ * prop + downZ * invProp pictureExif = piexif.load(obj.path) d = int(xCoord) m = int((abs(xCoord) - abs(d)) * 60) s = (abs(xCoord) - abs(d) - (m / 60)) * 3600 xDMS = [d, m, s] if d > 0: refLong = 'E' else: refLong = 'W' deg = (abs(d), 1) minute = (m, 1) fractSec = Fraction(s).limit_denominator() sec = (fractSec.numerator, fractSec.denominator) longitude = (deg, minute, sec) pictureExif['GPS'][piexif.GPSIFD.GPSLongitudeRef] = refLong pictureExif['GPS'][piexif.GPSIFD.GPSLongitude] = longitude d = int(yCoord) m = int((abs(yCoord) - abs(d)) * 60) s = (abs(yCoord) - abs(d) - (m / 60)) * 3600 yDMS = [d, m, s] if d > 0: refLat = 'N' else: refLat = 'S' deg = (abs(d), 1) minute = (m, 1) fractSec = Fraction(s).limit_denominator() sec = (fractSec.numerator, fractSec.denominator) latitude = (deg, minute, sec) pictureExif['GPS'][piexif.GPSIFD.GPSLatitudeRef] = refLat pictureExif['GPS'][piexif.GPSIFD.GPSLatitude] = latitude fractAlt = Fraction(zCoord).limit_denominator() altitude = (fractAlt.numerator, fractAlt.denominator) pictureExif['GPS'][piexif.GPSIFD.GPSAltitude] = altitude obj.isCoordonate = True obj.xStandCoord = xCoord obj.xDMS = xDMS obj.yStandCoord = yCoord obj.yDMS = yDMS obj.isAltitude = True obj.altitude = zCoord exif_bytes = piexif.dump(pictureExif) piexif.insert(exif_bytes, obj.path) currentPBarValue += 1 self.ui.progressBar.setValue(currentPBarValue) self.ui.progressBar.update() self.newListPictureObj.append(obj) self.applyGPXDone.emit(self.newListPictureObj)
def set_desc(imgPath, message): exif_dict = piexif.load(imgPath) exif_dict['0th'][40092] = string_to_array(message) exif_bytes = piexif.dump(exif_dict) piexif.insert(exif_bytes, imgPath) return 1
def resize_image(self, src, dst=None, max_size=None, bigger_panoramas=True, preserve_exif_data=False, exif_whitelist={}, preserve_icc_profiles=False, dst_paths=None, max_sizes=None): """Make a copy of the image in the requested size(s). max_sizes should be a list of sizes, and the image would be resized to fit in a square of each size (preserving aspect ratio). dst_paths is a list of the destination paths, and should be the same length as max_sizes. Backwards compatibility: * If max_sizes is None, it's set to [max_size] * If dst_paths is None, it's set to [dst] * Either max_size or max_sizes should be set * Either dst or dst_paths should be set """ if dst_paths is None: dst_paths = [dst] if max_sizes is None: max_sizes = [max_size] if len(max_sizes) != len(dst_paths): raise ValueError('resize_image called with incompatible arguments: {} / {}'.format(dst_paths, max_sizes)) extension = os.path.splitext(src)[1].lower() if extension in {'.svg', '.svgz'}: self.resize_svg(src, dst_paths, max_sizes, bigger_panoramas) return _im = Image.open(src) # The jpg exclusion is Issue #3332 is_animated = hasattr(_im, 'n_frames') and _im.n_frames > 1 and extension not in {'.jpg', '.jpeg'} exif = None if "exif" in _im.info: exif = piexif.load(_im.info["exif"]) # Rotate according to EXIF if "0th" in exif: value = exif['0th'].get(piexif.ImageIFD.Orientation, 1) if value in (3, 4): _im = _im.transpose(Image.ROTATE_180) elif value in (5, 6): _im = _im.transpose(Image.ROTATE_270) elif value in (7, 8): _im = _im.transpose(Image.ROTATE_90) if value in (2, 4, 5, 7): _im = _im.transpose(Image.FLIP_LEFT_RIGHT) exif['0th'][piexif.ImageIFD.Orientation] = 1 exif = self.filter_exif(exif, exif_whitelist) icc_profile = _im.info.get('icc_profile') if preserve_icc_profiles else None for dst, max_size in zip(dst_paths, max_sizes): if is_animated: # Animated gif, leave as-is utils.copy_file(src, dst) continue im = _im.copy() size = w, h = im.size if w > max_size or h > max_size: size = max_size, max_size # Panoramas get larger thumbnails because they look *awful* if bigger_panoramas and w > 2 * h: size = min(w, max_size * 4), min(w, max_size * 4) try: im.thumbnail(size, Image.ANTIALIAS) save_args = {} if icc_profile: save_args['icc_profile'] = icc_profile if exif is not None and preserve_exif_data: # Put right size in EXIF data w, h = im.size if '0th' in exif: exif["0th"][piexif.ImageIFD.ImageWidth] = w exif["0th"][piexif.ImageIFD.ImageLength] = h if 'Exif' in exif: exif["Exif"][piexif.ExifIFD.PixelXDimension] = w exif["Exif"][piexif.ExifIFD.PixelYDimension] = h # Filter EXIF data as required save_args['exif'] = piexif.dump(exif) im.save(dst, **save_args) except Exception as e: self.logger.warning("Can't process {0}, using original " "image! ({1})".format(src, e)) utils.copy_file(src, dst)
def getOn(filename, new_file): im = Image.open(filename) exif_dict = piexif.load(im.info["exif"]) exif_bytes = piexif.dump(exif_dict) im.save(new_file, "jpeg", exif=exif_bytes)
def show_spotlight_url(sess, params): spotlight_api = 'https://arc.msn.com/v3/Delivery/Cache' result = sess.get(spotlight_api, params=params) # sys.stdout.write(result.content) if requests.codes.get("ok") != result.status_code: sys.stderr.write("[info] status_code = %s\n" % result.status_code) exit() js = json.loads(result.text) items = js.get('batchrsp').get('items') # print "len:%s" % len(items) for item in items: # print item # print type(item.get('item')) item_js = json.loads(item.get('item')) # print item_js ad = item_js.get('ad') # print ad # for k, v in ad.items(): # print k # for k, v in ad.items(): # print("ad:%s: %s"%(k,v)) # print(ad.get('title_text').get('tx')) title = ad.get('title_text').get('tx') # print(ad.get("hs1_title_text").get('tx')) # print(ad.get("hs1_cta_text").get('tx')) # print(ad.get("hs2_title_text").get('tx')) # print(ad.get("hs2_cta_text").get('tx')) for i in [1]: # do not change landscape_key = "image_fullscreen_%03d_landscape" % i # landscape_key = "image_fullscreen_%03d_portrait" % i landscape = ad.get(landscape_key) if not landscape: break # print(ad.get('image_fullscreen_001_portrait').get('u')) # url = ad.get('image_fullscreen_001_portrait').get('u') # print(ad.get('image_fullscreen_001_landscape').get('u')) url = landscape.get('u') sha256 = landscape.get('sha256') fileSize = landscape.get('fileSize') # json.dump(item_js.get('ad'), fp=sys.stdout, ensure_ascii=False, indent=2) # for k, v in item_js.get('ad').items(): # print("%s: %s"%(k,v)) # print repr(item.get('item')) m = url_pat.search(url) fn = m.group(1) save_path_tentative = title + '_' + fn + '.jpg' save_path = save_path_tentative.replace('?', '_') sys.stderr.write('[Info] downloading %s\n' % save_path) img_result = sess.get(url) jpeg_data = img_result.content sys.stderr.write('[Info] sanity check\n') if len(jpeg_data) != fileSize: Exception("fileSize is not consistent!") if hashlib.sha256(jpeg_data).hexdigest() != sha256: Exception("sha256 is not consistent!") # 0x010e: b'title' # 0x013b: b'creator' # 0x8298: b'copyright' # 0x9c9b: kenmei # 0x9c9c: comment # 0x9c9d: author # 0x9c9f: subject exif_0th = {} exif_0th[0x010e] = title.encode('utf-8') # exif_0th[0x013b] = "creator" exif_0th[0x8298] = ad.get('copyright_text').get('tx').encode( 'utf-8') # exif_0th[str(0x9c9b)] = title # exif_0th[str(0x9c9f)] = title exif_0th[0x9c9c] = "\n\n".join([ ad.get('title_text').get('tx'), edge_pat.sub("", ad.get('title_destination_url').get('u')), ad.get('hs1_title_text').get('tx'), ad.get('hs1_cta_text').get('tx'), edge_pat.sub("", ad.get('hs1_destination_url').get('u')), ad.get('hs2_title_text').get('tx'), ad.get('hs2_cta_text').get('tx'), edge_pat.sub("", ad.get('hs2_destination_url').get('u')) ]).encode('utf-16') exif = {'0th': exif_0th} exif_bytes = piexif.dump(exif) piexif.insert(exif_bytes, jpeg_data, save_path) # with open(save_path, 'wb') as save_file: # save_file.write(img_result.content) # break i += 1
# -*- coding: utf-8 -*- from PIL import Image import piexif src = Image.open("./data/lion3.jpg") zeroth_ifd = { piexif.ImageIFD.Artist: "koga", piexif.ImageIFD.Software: "iota-pic" } #exif_ifd = { # piexif.ExifIFD.DateTimeOriginal: "2099:09:23 10:10:10" #} #exif = piexif.dump({"0th": zeroth_ifd, "Exif": exif_ifd}) exif = piexif.dump({"0th": zeroth_ifd}) src.save("test.jpg", exif = exif) #dec_img = np.asarray(PIL_data) #cv2.imwrite("{}.jpg".format(tag), dec_img)
# filepath to the excel with all the photos and their info photo_list = r'P:\Projects\2016\South Wing and Pavilion\South Pavilion\Digital Photos\South Pavilion Photo List 2.1.2019.xlsx' # read the excel into a pandas dataframe md_df = pd.read_excel( photo_list, cols=['DESCRIPTION', 'DIRECTION', 'INITIALS', 'SourceFile']) for index, row in md_df.iterrows(): print('reading in exif for %s...' % row['SourceFile']) exif = piexif.load(row['SourceFile']) ## exif tags # 270 --> ImageDescription # 315 --> Artist # set artist exif['0th'][315] = row['INITIALS'] + ", Thomas Jefferson's Monticello" # set description with direction exif['0th'][270] = row['DESCRIPTION'] if row['DIRECTION'] != '': exif['0th'][270] += ', view %s' % row['DIRECTION'] # convert exif to bytes to prep loading into file exif_bytes = piexif.dump(exif) # replace existing exif with modified copy print(' ...replacing exif!') piexif.insert(exif_bytes, row['SourceFile'])
def test_dump_fail4(self): exif_ifd = {ExifIFD.OECF: (1, 2, 3, 4, 5)} exif_dict = {"Exif": exif_ifd} with self.assertRaises(ValueError): piexif.dump(exif_dict)
fakeImageExifData['Exif'][piexif.ExifIFD.DateTimeOriginal] = randomDictionary[0] # Writes randomized time to fakeImageGpsData. fakeImageExifData['Exif'][piexif.ExifIFD.DateTimeDigitized] = randomDictionary[0] # Writes randomized time to fakeImageGpsData. fakeImageGpsData[piexif.GPSIFD.GPSDateStamp] = randomDictionary[0] # Writes randomized date to fakeImageGpsData. fakeImageGpsData[piexif.GPSIFD.GPSLatitude] = randomDictionary[1] # Writes randomized latitude to fakeImageGpsData. fakeImageGpsData[piexif.GPSIFD.GPSLatitudeRef] = randomDictionary[2] # Writes randomized latitude reference to fakeImageGpsData. fakeImageGpsData[piexif.GPSIFD.GPSLongitude] = randomDictionary[3] # Writes randomized longitude to fakeImageGpsData. fakeImageGpsData[piexif.GPSIFD.GPSLongitudeRef] = randomDictionary[4] # Writes randomized longitude reference to fakeImageGpsData. # Displays gps data of falsified file. print() print('Falsified GPS data:') print('{}'.format(fakeImageGpsData)) exif_bytes = piexif.dump(fakeImageExifData) # Converts exif data dictanary into bytes. piexif.insert(exif_bytes, falseImageName) # Writes falsified data to new file. # Save location statement. print() print("File saved in script directory.") # TODO: delete if needed. #try: # if os.path.dirname(imageName) is not '': # shutil.move(falseImageName, os.path.dirname(imageName)) # Moves file to original image directory. # else: # print() # print("File saved in script directory because user did not specify original image directory.") #except: # os.remove(falseImageName) # Deletes new file if it cannot be moved to new directory.
def write_gps(filename, lat, longit, altitude): #lat and long are decimals gps = {} #create array #Altitude if altitude<0: gps[piexif.GPSIFD.GPSAltitudeRef] = 1; #Below see level else: gps[piexif.GPSIFD.GPSAltitudeRef] = 0; #Above see level gps[piexif.GPSIFD.GPSAltitude]= (int(abs(altitude)*100),100) #Latitude if lat<0: gps[piexif.GPSIFD.GPSLatitudeRef] = "S" else: gps[piexif.GPSIFD.GPSLatitudeRef] = "N" latd,latm,lats = ExifWriter._decdeg2dms(lat) gps[piexif.GPSIFD.GPSLatitude] = [(latd,1),(latm,1),(lats*100,100)]; #Longitude if longit<0: gps[piexif.GPSIFD.GPSLongitudeRef] = "W" else: gps[piexif.GPSIFD.GPSLongitudeRef] = "E" longd,longm,longs = ExifWriter._decdeg2dms(longit) gps[piexif.GPSIFD.GPSLongitude] = [(longd,1),(longm,1),(longs*100,100)]; exifdict = piexif.load(filename) exifdict["GPS"] = gps exif_bytes = piexif.dump(exifdict) piexif.insert(exif_bytes, filename) exifdict = piexif.load(filename)