def test_tiff(self): """Write to a TIFF that does not already have the XMP tag.""" srcfile = pkg_resources.resource_filename(__name__, "fixtures/zeros.tif") with tempfile.NamedTemporaryFile(suffix='.tif') as tfile: shutil.copyfile(srcfile, tfile.name) xmpf = XMPFiles() xmpf.open_file(file_path=tfile.name, open_forupdate=True) # Since it's a TIFF, it already has everything possible from the # TIFF IFD filled in into the TIFF namespace. xmp = xmpf.get_xmp() xmp.set_property(NS_DC, "rights", "no one in particular") xmpf.put_xmp(xmp) xmpf.close_file() xmpf.open_file(file_path=tfile.name) xmp = xmpf.get_xmp() xmpf.close_file() # TODO: explain why this happened. prop = xmp.get_property(NS_DC, "rights") prop2 = xmp.get_localized_text(NS_DC, "rights", None, "x-default") self.assertEqual(prop2, "no one in particular")
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()
def plot_file(self,date,p,var,dirout): ''' Red line is reference (biofloat, mooring or vessel) Blue line is model ''' floatname = p.name() filename =dirout+"/"+date.strftime('%Y%m%d') +"_"+floatname+"_"+var+ ".png" pl.figure() pl.plot(self.Model,self.Depth,label="Model") pl.plot(self.Ref,self.Depth,label="Float") pl.legend(loc='upper right') pl.ylabel("depth") figtitle = var+" date="+date.strftime('%Y/%m/%d')+" float="+floatname pl.title(figtitle) pl.gca().invert_yaxis() pl.savefig(filename) pl.close() import libxmp import libxmp.utils from libxmp import XMPFiles, consts xmpfile = XMPFiles( file_path=filename, open_forupdate=True ) xmp = xmpfile.get_xmp() if xmp is None: xmp = libxmp.XMPMeta() xmp.set_property(consts.XMP_NS_DC, 'float', floatname ) xmp.set_property(consts.XMP_NS_DC, 'date', date.strftime('%Y%m%d') ) xmp.set_property(consts.XMP_NS_DC, 'hour', date.strftime('%H:%M:%S') ) xmp.set_property(consts.XMP_NS_DC, 'var', var ) xmp.set_property(consts.XMP_NS_DC, 'position.lat',str(p.lat)+"N") xmp.set_property(consts.XMP_NS_DC, 'position.lon',str(p.lon)+"E") xmpfile.put_xmp(xmp) xmpfile.close_file()
def verify_metadatas_are_removed(self, file_path): # helper function that verifies that the provided image doesn't contain any sensitive metadata # empty exif self.assertEqual(piexif.load(file_path)["0th"], {}, msg="sensitive exif data left") self.assertEqual(piexif.load(file_path)["Exif"], {}, msg="sensitive exif data left") self.assertEqual(piexif.load(file_path)["GPS"], {}, msg="sensitive exif data left") self.assertEqual(piexif.load(file_path)["1st"], {}, msg="sensitive exif data left") # Imagine the following scenario: An image contains sensitive information, it gets modified to hide these. # If there is an exif-thumbnail it might represent the previous image and hence could leak those information. self.assertEqual(piexif.load(file_path)["thumbnail"], None, msg="The exif thumbnail has not been removed.") # verify that xmp is also empty. Normally the xmp content is stored in within the rdf tag xmp_file = XMPFiles(file_path=file_path) xmp_content = str(xmp_file.get_xmp()) # this won't match if there are any additional xmp elements left, because they would occur between the opening # of the rdf:Description tag and the closing of the rdf:RDF tag. sensitive_information = re.findall(" <rdf:Description.*\n </rdf:RDF>", xmp_content) self.assertEqual( len(sensitive_information), 1, msg="There are sensitive xmp-tags left:\n\n{}".format(xmp_content)) xmp_file.close_file()
def write_to_file(): filename = fileEdit.text() if os.path.isfile(filename) == False: print("Error: Media file or reference file missing") else: xmpfile = XMPFiles( file_path=filename, open_forupdate=True) xmp = XMPMeta() # Write creator xmp.append_array_item(consts.XMP_NS_DC, 'creator', escape(str(creatorEdit.text())), {'prop_array_is_ordered': True, 'prop_value_is_array': True}) # Write title xmp.append_array_item(consts.XMP_NS_DC, 'title', escape(str(titleEdit.text())), {'prop_array_is_ordered': True, 'prop_value_is_array': True}) # Write sources for line in referencesEdit.toPlainText().split("\n"): if (len(line) > 1): xmp.append_array_item(consts.XMP_NS_DC, 'source', escape(str(line)), {'prop_array_is_ordered': True, 'prop_value_is_array': True}) """ if (xmpfile.can_put_xmp(xmp) == False): editLabel.setText ('Error: Cannot write metadata to file.') else: """ xmpfile.put_xmp(xmp) xmpfile.close_file() editLabel.setText ('Success! Metadata written to file.')
def test_jpeg(self): """Create XMP from scratch to store in a jpeg.""" srcfile = pkg_resources.resource_filename(__name__, "samples/BlueSquare.jpg") with tempfile.NamedTemporaryFile(suffix='.tif', mode='wb') as tfile: # Do some surgery on the file, remove existing xmp. # The APP1 marker segment in question starts at byte 2156, has # length of 4813 with open(srcfile, 'rb') as infptr: # Write the SOI marker tfile.write(infptr.read(2)) # Skip over ALL the APP0, APP1 segments. infptr.seek(21619) tfile.write(infptr.read()) tfile.flush() xmpf = XMPFiles() xmpf.open_file(file_path=tfile.name, open_forupdate=True) xmp = xmpf.get_xmp() xmp.set_property(NS_DC, "Title", u'Stürm und Drang') # Construct the properties that would have been filled in had the # APP0 segment been left in place. xmp.set_property(NS_TIFF, "Orientation", "1") xmp.set_property(NS_TIFF, "XResolution", "720000/10000") xmp.set_property(NS_TIFF, "YResolution", "720000/10000") xmp.set_property(NS_TIFF, "ResolutionUnit", "2") xmpf.put_xmp(xmp) xmpf.close_file() xmpf = XMPFiles() xmpf.open_file(file_path=tfile.name) xmp = xmpf.get_xmp() prop = xmp.get_property(NS_DC, "Title") self.assertEqual(prop, u'Stürm und Drang') prop = xmp.get_property(NS_TIFF, "Orientation") self.assertEqual(prop, "1") prop = xmp.get_property(NS_TIFF, "XResolution") self.assertEqual(prop, "720000/10000") prop = xmp.get_property(NS_TIFF, "YResolution") self.assertEqual(prop, "720000/10000") prop = xmp.get_property(NS_TIFF, "ResolutionUnit") self.assertEqual(prop, "2") xmpf.close_file()
def main(): options = getoptions() logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s") logger = logging.getLogger() vars = { 'UsePanoramaViewer': 'True', 'ProjectionType': 'equirectangular', } for vstr in options.vars: for elem in vstr.split(','): key, value = elem.split('=') if key in namespace: vars[key] = value else: logger.warn("Key {0} is invalid.".format(key)) for filename in options.filenames: logger.info("Filename: {0}".format(filename)) xmpfile = XMPFiles(file_path=filename, open_forupdate=True) xmp = xmpfile.get_xmp() try: assert xmp is not None except AssertionError: logger.warn("Metadata is not available for {0}.".format(filename)) continue xmp.register_namespace(GPano, 'GPano') width, height = imagesize.get(filename) width = "{0}".format(width) height = "{0}".format(height) # width = xmp.get_property(consts.XMP_NS_EXIF, 'PixelXDimension' ) # height = xmp.get_property(consts.XMP_NS_EXIF, 'PixelYDimension' ) # assert width != '', "No width read." # assert height != '', "No height read." for name in namespace: if name in vars: if xmp.does_property_exist(GPano, name): logger.info("Overwrite: {0} {1}->{2}".format( name, xmp.get_property(GPano, name), vars[name])) else: logger.info("Set: {0} {1}".format(name, vars[name])) xmp.set_property(GPano, name, vars[name]) elif name in [ 'FullPanoWidthPixels', 'CroppedAreaImageWidthPixels' ]: if not xmp.does_property_exist(GPano, name): logger.info("Set default: {0} {1}".format(name, width)) xmp.set_property(GPano, name, width) elif name in [ 'FullPanoHeightPixels', 'CroppedAreaImageHeightPixels' ]: if not xmp.does_property_exist(GPano, name): logger.info("Set default: {0} {1}".format(name, height)) xmp.set_property(GPano, name, height) xmpfile.put_xmp(xmp) xmpfile.close_file()
def get_tags_from_xmp(self, file_path): xmpfile = XMPFiles(file_path=file_path, open_forupdate=True) xmp = xmpfile.get_xmp() property_was_removed = False for index in range(5, 0, -1): property_was_removed |= self.remove_geo_xmp_property( xmp, consts.XMP_NS_DC, 'subject[%s]' % (index)) if property_was_removed: print('Updating %s' % file_path) xmpfile.put_xmp(xmp) xmpfile.close_file() return
def check_inspo_xmp(file): #get xmp from file xmpfile = XMPFiles(file_path=file, open_forupdate=True) xmp = xmpfile.get_xmp() #check to see if xmp.does_property_exist(INSPO_URI, 'id') == True: xmpfile.close_file() return True else: xmpfile.close_file() return False
def update_xmp(imgpath, keywords): """ updates the xmp data in the image, or creates a sidecar xmp """ # Check if a sidecar file already exists if os.path.isfile(imgpath + '.xmp'): imgpath = imgpath + '.xmp' # NEF requires sidecar embeddedXmpFormats = ['jpg', 'png', 'tif', 'dng'] if not imgpath.lower().endswith(tuple(embeddedXmpFormats)): # create and use sidecar file imgpath = imgpath + '.xmp' with open(imgpath, 'w+') as f: f.write(blank_xmp()) print('wrote in' + imgpath) xmpfiledict = file_to_dict(imgpath) existing_keywords = [] try: dc = [] dc.append(xmpfiledict[consts.XMP_NS_DC]) existing_keywords = [x[1] for x in dc] except: print('nothing') print('existing_keywords') print(existing_keywords) xmpfile = XMPFiles(file_path=imgpath, open_forupdate=True) xmp = xmpfile.get_xmp() print(xmp) keywords_to_add = [x for x in keywords if x not in existing_keywords] print('keywords to add') print(keywords_to_add) def add_keyword(k): """ helper func """ xmp.append_array_item(consts.XMP_NS_DC, u'subject', k) _ = [add_keyword(x) for x in keywords_to_add] if xmpfile.can_put_xmp(xmp): xmpfile.put_xmp(xmp) else: xmpfile.close_file() raise Exception('Cannot write xmp to ' + imgpath) xmpfile.close_file() return 0
def check_xmp_writable(file): # get xmp from file xmpfile = XMPFiles(file_path=file, open_forupdate=True) xmp = xmpfile.get_xmp() try: #if you can write new xmp if xmpfile.can_put_xmp(xmp) == True: xmpfile.close_file() return True else: xmpfile.close_file() return False except Exception as e: print("Error: " + str(e))
def recuperar_informacion(self, img_name, tag): xmpfile = XMPFiles(file_path=img_name) xmp = xmpfile.get_xmp() tipo = Image.open(img_name).format # Obtenemos el tipo de la imagen. if tipo == 'JPEG': # Si la imagen es JPEG, obtenemos el contenido almacenado en los campos consts.XMP_NS_JPEG info = xmp.get_property(consts.XMP_NS_JPEG, tag) else: # Si la imagen es PNG, obtenemos el contenido almacenado en los campos consts.XMP_NS_PNG info = xmp.get_property(consts.XMP_NS_PNG, tag) xmpfile.close_file() return info
def test_cannot_inject_xmp_info_pdf(self): """Verify behavior of not being able to inject XMP into barren PDF""" # See issue 40 srcfile = pkg.resource_filename(__name__, os.path.join("fixtures", "zeros.pdf")) with tempfile.NamedTemporaryFile() as tfile: shutil.copyfile(srcfile, tfile.name) xmpf = XMPFiles() xmpf.open_file(tfile.name, open_forupdate=True) xmp = XMPMeta() xmp.set_property(NS_PHOTOSHOP, "ICCProfile", "foo") with self.assertRaises(XMPError): xmpf.put_xmp(xmp) xmpf.close_file()
def tag_images(docker_image): subprocess.call(['mkdir', '-p', 'figures']) subprocess.call("docker run --rm -v {}/figures:/figures " "{} make figures".format(os.getcwd(), docker_image), shell=True) figures = glob.glob('{}/figures/*.png'.format(os.getcwd())) for filename in figures: xmpfile = XMPFiles(file_path=filename, open_forupdate=True) xmp = xmpfile.get_xmp() if xmp == None: xmp = XMPMeta() xmp.append_array_item(libxmp.consts.XMP_NS_DC, 'creator', '{{ "im2sim" : "{}" }}'.format(docker_image), {'prop_array_is_ordered': True, 'prop_value_is_array': True}) xmpfile.put_xmp(xmp) xmpfile.close_file() return None
def test_get_xmp(self): for flg in open_flags: kwargs = {flg: True} for filename, fmt in zip(self.samplefiles, self.formats): # See test_exempi_error() if not self.flg_fmt_combi(flg, fmt): xmpfile = XMPFiles(file_path=filename, **kwargs) try: xmp = xmpfile.get_xmp() self.assertTrue(isinstance(xmp, XMPMeta), "Not an XMPMeta object") except XMPError: print(filename) print(flg) print(fmt) xmpfile.close_file()
def test_get_xmp(self): for flg in open_flags: kwargs = { flg: True } for filename, fmt in zip(self.samplefiles, self.formats): # See test_exempi_error() if not self.flg_fmt_combi(flg, fmt): xmpfile = XMPFiles( file_path=filename, **kwargs ) try: xmp = xmpfile.get_xmp() self.assertTrue(isinstance(xmp, XMPMeta), "Not an XMPMeta object" ) except XMPError: print(filename) print(flg) print(fmt) xmpfile.close_file()
def remove_XMPMeta(file): xmpfile = XMPFiles(file_path=file, open_forupdate=True) xmp = xmpfile.get_xmp() xmp.set_property(consts.XMP_NS_PDF, 'pdf:Producer', 'Document Converter') xmp.set_property(consts.XMP_NS_XMP, 'xmp:CreatorTool', 'Document Converter') xmp.set_property(consts.XMP_NS_XMP_MM , 'xmpMM:DocumentID', '') xmp.delete_property(consts.XMP_NS_DC, 'dc:format') xmp.delete_property(consts.XMP_NS_DC, 'dc:title') xmp.delete_property(consts.XMP_NS_DC, 'dc:creator') xmp.delete_property(consts.XMP_NS_DC, 'dc:description') try: xmpfile.put_xmp(xmp) except: xmpfile.close_file() return xmpfile.close_file()
def ocultar_informacion(self, img_name, tag, content): xmpfile = XMPFiles(file_path=img_name, open_forupdate=True) tipo = Image.open(img_name).format # Obtenemos el tipo de la imagen. if tipo == 'JPEG': # Si la imagen es JPEG, almacenamos el contenido en los campos consts.XMP_NS_JPEG xmp = xmpfile.get_xmp() xmp.set_property(consts.XMP_NS_JPEG, tag, content) else: # Si la imagen es PNG if xmpfile.get_xmp() is None: # Comprobamos si tiene campos XMP, sino, creamos uno vacío. xmp = XMPMeta() else: # Si tiene campos XMP, los cogemos. xmp = xmpfile.get_xmp() xmp.set_property(consts.XMP_NS_PNG, tag, content) # Almacenamos el contenido en los campos consts.XMP_NS_PNG xmpfile.put_xmp(xmp) xmpfile.close_file()
def mutate(self, info, input): abs_path = Path(BASE_DIR, input["path"]) if not abs_path.exists(): raise Exception("Image not found") if not (isinstance(input["rating"], int) and -1 <= input["rating"] <= 5): raise Exception("Rating must be an integer from 1 to 5") image = {"path": abs_path} xmpfile = XMPFiles(file_path=str(abs_path), open_forupdate=True) xmp = xmpfile.get_xmp() # WISHLIST don't write if rating didn't change xmp.set_property(XMP_NS_XMP, "xmp:Rating", str(input["rating"])) if not xmpfile.can_put_xmp(xmp): raise Exception("Can't write xmp metadata back to image") xmpfile.put_xmp(xmp) xmpfile.close_file() return SetRatingPayload(image=image)
def embed_xmp(filename, dt): t = calendar.timegm(dt.timetuple()) os.utime(filename, (t, t)) os.system('SetFile -d "%s" "%s"' % ( dt.strftime("%m/%d/%Y 00:00:00"), filename.encode('utf-8'), )) xmpfile = XMPFiles(file_path=filename, open_forupdate=True) xmp = xmpfile.get_xmp() xmp.set_property(consts.XMP_NS_XMP, "CreateDate", dt.isoformat()) if xmpfile.can_put_xmp(xmp): xmpfile.put_xmp(xmp) xmpfile.close_file() return True else: xmpfile.close() return False
def get(self, request, pk, format=None): try: # retrieve the item from the file system item = Item.objects.get(pk=pk) item_path = os.path.join(settings.MEDIA_ROOT, str(item.file)) # extract the XMP metadata xmpfile = XMPFiles() xmpfile.open_file(item_path) metadata = xmpfile.get_xmp() xmpfile.close_file() # save a new XMPMetadata object with the association obj = XMPMetadata() obj.item = item obj.metadata = metadata obj.save() # return the extracted metadata serializer = XMPMetadataSerializer(obj) return Response(serializer.data) except Exception as e: print e return Response(status=status.HTTP_404_NOT_FOUND)
def dictonary_write(file, dict): # get xmp from file xmpfile = XMPFiles(file_path=file, open_forupdate=True) xmp = xmpfile.get_xmp() if check_xmp_writable(file) == True: #if xmp can be written to file if check_inspo_xmp(file) == False: #if INSPO xmp does not exist # register or update INSPO namespace URI xmp.register_namespace(INSPO_URI, "INSPO") # for each possible article for article in ARTICLES: try: value = dict[article] xmp.set_property(INSPO_URI, article, value) except: pass xmpfile.put_xmp(xmp) xmpfile.close_file() return else: xmpfile.close_file() print("INSPO DATA ALREADY EXISTS") return else: xmpfile.close_file() print("XMP NOT WRITEABLE") return
def main(): path = cli() proj = path.parts[-1] stamp = path.joinpath(proj + "_PPKStamp.csv") cols = ["name","lat","lon","elev"] st = pd.read_csv(stamp, names=cols, comment='#') for i in range(len(st)): jpg = path.joinpath(st["name"][i] + ".JPG") exif = piexif.load(str(jpg)) xmpfile = XMPFiles(file_path=str(jpg), open_forupdate=True) xmp = xmpfile.get_xmp() DJIns = xmp.get_namespace_for_prefix("drone-dji") xmp.set_property(DJIns, 'AbsoluteAltitude', "+%.4f" % st["elev"][i]) xmp.set_property(DJIns, 'GpsLatitude', "%.10f" % st["lat"][i]) xmp.set_property(DJIns, 'GpsLongitude', "%.10f" % st["lon"][i]) #xmp.set_property(DJIns, 'GpsLongtitude', "+%.10f" % st["lon"][i]) xmpfile.put_xmp(xmp) xmpfile.close_file() lat = abs(st["lat"][i]) latd = int(lat) latm = int((lat-latd)*60) lats = (lat-latd-latm/60)*3600 lon = abs(st["lon"][i]) lond = int(lon) lonm = int((lon-lond)*60) lons = (lon-lond-lonm/60)*3600 exif["GPS"][2] = ((latd, 1), (latm, 1), (int(lats*1000000), 1000000)) exif["GPS"][4] = ((lond, 1), (lonm, 1), (int(lons*1000000), 1000000)) exif["GPS"][6] = (int(st["elev"][i]*1000), 1000) exifBytes = piexif.dump(exif) piexif.insert(exifBytes, str(jpg))
def terminal_write(file): # get xmp from file xmpfile = XMPFiles(file_path=file, open_forupdate=True) xmp = xmpfile.get_xmp() if check_xmp_writable(file) == True: #if xmp can be written to file if check_inspo_xmp(file) == False: #if INSPO xmp does not exist # register or update INSPO namespace URI xmp.register_namespace(INSPO_URI, "INSPO") # for each possible article for article in ARTICLES: value = input("What " + article + " are they wearing?: ") # ask if they are wearing a certain article of clothing if value == "": # if the value is empty then pass pass else: # else set that article of clothing xmp.set_property(INSPO_URI, article, value) xmpfile.put_xmp(xmp) xmpfile.close_file() else: xmpfile.close_file() print("INSPO DATA ALREADY EXISTS") return else: xmpfile.close_file() print("XMP NOT WRITEABLE") return
def test_open_file(self): # Non-existing file. xmpfile = XMPFiles() with self.assertRaises(IOError): xmpfile.open_file('') xmpfile = XMPFiles() xmpfile.open_file( self.samplefiles[0] ) self.assertRaises( XMPError, xmpfile.open_file, self.samplefiles[0] ) self.assertRaises( XMPError, xmpfile.open_file, self.samplefiles[1] ) xmpfile.close_file() xmpfile.open_file( self.samplefiles[1] ) self.assertRaises( XMPError, xmpfile.open_file, self.samplefiles[0] ) # Open all sample files. for filename in self.samplefiles: xmpfile = XMPFiles() xmpfile.open_file(filename) # Try using init for filename in self.samplefiles: xmpfile = XMPFiles(file_path=filename)
def test_tiff_smarthandler(self): """Verify action of TIFF smarthandler when tag length > 255""" # See issue 12 srcfile = pkg.resource_filename(__name__, "fixtures/zeros.tif") with tempfile.NamedTemporaryFile(suffix='.tif') as tfile: shutil.copyfile(srcfile, tfile.name) # Create a tag with 280 chars. xmpf = XMPFiles() xmpf.open_file(tfile.name, open_forupdate=True) xmp = xmpf.get_xmp() blurb = "Some really long text blurb " xmp.set_property(NS_PHOTOSHOP, 'Headline', blurb * 10) xmpf.put_xmp(xmp) xmpf.close_file() xmpf.open_file(tfile.name, usesmarthandler=True) xmp = xmpf.get_xmp() prop = xmp.get_property(NS_PHOTOSHOP, "Headline") xmpf.close_file() self.assertEqual(prop, blurb * 10)
def test_can_inject_xmp_info_png(self): """Verify behavior of being able to inject XMP into barren PNG""" # See issue 40 srcfile = pkg.resource_filename(__name__, os.path.join("fixtures", "zeros.png")) with tempfile.NamedTemporaryFile() as tfile: shutil.copyfile(srcfile, tfile.name) xmpf = XMPFiles() xmpf.open_file(tfile.name, open_forupdate=True) xmp = XMPMeta() xmp.set_property(NS_PHOTOSHOP, "ICCProfile", "foo") xmpf.put_xmp(xmp) xmpf.close_file() xmpf.open_file(tfile.name, usesmarthandler=True) xmp = xmpf.get_xmp() prop = xmp.get_property(NS_PHOTOSHOP, "ICCProfile") xmpf.close_file() self.assertEqual(prop, "foo")
def test_open_file(self): # Non-existing file. xmpfile = XMPFiles() with self.assertRaises(IOError): xmpfile.open_file('') xmpfile = XMPFiles() xmpfile.open_file(self.samplefiles[0]) self.assertRaises(XMPError, xmpfile.open_file, self.samplefiles[0]) self.assertRaises(XMPError, xmpfile.open_file, self.samplefiles[1]) xmpfile.close_file() xmpfile.open_file(self.samplefiles[1]) self.assertRaises(XMPError, xmpfile.open_file, self.samplefiles[0]) # Open all sample files. for filename in self.samplefiles: xmpfile = XMPFiles() xmpfile.open_file(filename) # Try using init for filename in self.samplefiles: xmpfile = XMPFiles(file_path=filename)
def test_sturm_und_drang(self): """Should be able to write a property which includes umlauts.""" srcfile = pkg_resources.resource_filename(__name__, "fixtures/zeros.tif") with tempfile.NamedTemporaryFile(suffix='.tif') as tfile: shutil.copyfile(srcfile, tfile.name) expected_value = u'Stürm und Drang' xmpf = XMPFiles() xmpf.open_file(file_path=tfile.name, open_forupdate=True) xmp = xmpf.get_xmp() xmp.set_property(NS_DC, "Title", expected_value) xmpf.put_xmp(xmp) xmpf.close_file() xmpf = XMPFiles() xmpf.open_file(file_path=tfile.name) xmp = xmpf.get_xmp() actual_value = xmp.get_property(NS_DC, "Title") xmpf.close_file() self.assertEqual(actual_value, expected_value)
def internal_to_sidecar(): if os.path.isfile(fileEdit.text()) == False: editLabel.setText ("Please enter a filepath into the file field") return filename = fileEdit.text() print(filename) xmpfile = XMPFiles( file_path=filename, open_forupdate=False) xmp = xmpfile.get_xmp() # Create external file and write to it handle = open (os.path.basename(filename) + '.xml', 'w') handle.write(str(xmp)) handle.close() xmpfile.close_file() fulltextEdit.setText (str(xmp)) editLabel.setText ("Loaded " + filename + " and created sidecar file at " + filename + ".xml") loadxmp_to_editor()
def write_xmp(filename, field, value, sidecar=False): """Write a field into a files XMP store, if sidecar is True and the file format doesn't support writing inline a sidecar .xmp file will be created. Args: filename (str): The full path to file read to write XMP data into field (str|None) sidecar (bool): If True and the file doesn't support XMP inline a .xmp file with the same name as the ``filename`` will be created with an .xmp extension. Example: test.txt -> test.txt.xmp Returns: On success: The path to the file written On failure: False """ xmpfile = XMPFiles(file_path=filename, open_forupdate=True) xmp = xmpfile.get_xmp() if xmp is None and sidecar: return write_xmp_sidecar(filename, field, value) elif xmp is None: return False if _read_xmp_field(xmp, field) == value: return filename xmp.set_property(consts.XMP_NS_DC, field, value) if xmpfile.can_put_xmp(xmp): xmpfile.put_xmp(xmp) xmpfile.close_file() return filename else: return False
def embed_xmp(filename, dt): t = calendar.timegm(dt.timetuple()) os.utime(filename, (t, t)) os.system('SetFile -d "%s" "%s"' % ( dt.strftime("%m/%d/%Y 00:00:00"), filename.encode('utf-8'), )) xmpfile = XMPFiles(file_path=filename, open_forupdate=True) xmp = xmpfile.get_xmp() xmp.set_property( consts.XMP_NS_XMP, "CreateDate", dt.isoformat() ) if xmpfile.can_put_xmp(xmp): xmpfile.put_xmp(xmp) xmpfile.close_file() return True else: xmpfile.close() return False
XMP_GIMAGE = 'http://ns.google.com/photos/1.0/image/' XMP_GPANO = 'http://ns.google.com/photos/1.0/panorama/' XMPMeta.register_namespace(XMP_GIMAGE, 'GImage') XMPMeta.register_namespace(XMP_GPANO, 'GPano') # Set GPano properties lxmp.set_property(XMP_GPANO, 'ProjectionType', 'equirectangular') lxmp.set_property_int(XMP_GPANO, 'CroppedAreaLeftPixels', image_width/2) lxmp.set_property_int(XMP_GPANO, 'CroppedAreaTopPixels', 0) lxmp.set_property_int(XMP_GPANO, 'CroppedAreaImageWidthPixels', image_width) lxmp.set_property_int(XMP_GPANO, 'CroppedAreaImageHeightPixels', image_height) lxmp.set_property_int(XMP_GPANO, 'FullPanoWidthPixels', image_width*2) lxmp.set_property_int(XMP_GPANO, 'FullPanoHeightPixels', image_height) lxmp.set_property_int(XMP_GPANO, 'InitialViewHeadingDegrees', 180) # Encode right image to BASE64 rimage_data = open(rimage_path, 'rt').read() rimage_base64 = base64.b64encode(rimage_data) # Set GImage properties lxmp.set_property(XMP_GIMAGE, 'Mime', 'image/jpeg') lxmp.set_property(XMP_GIMAGE, 'Data', rimage_base64) # Put XMP. if vrimage_file.can_put_xmp(lxmp): vrimage_file.put_xmp(lxmp) print(vrimage_file.get_xmp()) print("Done!") vrimage_file.close_file()
def test_get_xmp(self): for f in self.samplefiles: xmpfile = XMPFiles( file_path=f ) xmp = xmpfile.get_xmp() self.assertTrue( isinstance(xmp, XMPMeta), "Not an XMPMeta object" ) xmpfile.close_file()
EQUALS = '=' * 78 DASHES = '-' * 78 # def touch(fname, mode=0o666, dir_fd=None, **kwargs): # """https://stackoverflow.com/a/1160227/3249688""" # flags = os.O_CREAT | os.O_APPEND # with os.fdopen(os.open(fname, flags=flags, mode=mode, dir_fd=dir_fd)) as f: # os.utime(f.fileno() if os.utime in os.supports_fd else fname, # dir_fd=None if os.supports_fd else dir_fd, **kwargs) if __name__ == '__main__': xmpf = XMPFiles() xmpf.open_file("eric_john_berquist_etd.pdf") xmp = xmpf.get_xmp() xmpf.close_file() # Inspect the formatted XMP. xmpfilename = "eric_john_berquist_etd.xmp" with open(xmpfilename, 'w') as xmpfile: xmpfile.write(str(xmp)) d = object_to_dict(xmp) d_json = dict() for k in d: print(EQUALS) print(k) print(DASHES) for subheader in d[k]: key, value = subheader[:2]
#import files from libxmp import XMPFiles #set image to add data to image = "image.jpg" #read file xmpfile = XMPFiles(file_path=image, open_forupdate=True) #set INSPONIZER URI inspoURI = "https://www.claytondunavant.com/inspo" #get xmp from file xmp = xmpfile.get_xmp() #register or update INSPO namespace URI xmp.register_namespace(inspoURI, "INSPO") #set shirt property to UNIQLO xmp.set_property(inspoURI, u"shirt", u"Uniqlo U T-Shirt") #if you can write new xmp, write it if xmpfile.can_put_xmp(xmp) == True: xmpfile.put_xmp(xmp) #close the file xmpfile.close_file()
def parse_meta(filename): slide_file = parse_slide(filename) if slide_file is None: return None with ZipFile(filename, 'r') as z: with(z.open(slide_file[0])) as f: slide_type = slide_file[1] title_string = None description_string = None if slide_type == ".htm" or slide_type == ".html": soup = BeautifulSoup(f.read(), "lxml") title = soup.find('meta', {'name':'veeva_title'}) if title is not None: title_string = title.get('content', None) description = soup.find('meta', {'name':'veeva_description'}) if description is not None: description_string = description.get('content', None) if slide_type == ".pdf": doc = PDFDocument() parser = PDFParser(f) # omfg this is so janky, there needs to be a better library parser.set_document(doc) doc.set_parser(parser) metadata = doc.info if len(metadata) > 0: latest = metadata[-1] try: if latest['Title'] != '': title_string = latest['Title'] except KeyError: title_string = None try: if latest['Subject'] != '': description_string = latest['Subject'] except KeyError: description_string = None if slide_type == ".jpg" or slide_type == ".jpeg": tmp_file_name = str(uuid.uuid1()) + ".jpg" with open(tmp_file_name, 'wb') as tf: tf.write(f.read()) xmpfile = XMPFiles(file_path=tmp_file_name) xmp = xmpfile.get_xmp() xmpfile.close_file() try: title_string = xmp.get_localized_text(consts.XMP_NS_DC, 'title', None, 'x-default') except XMPError: title_string = None try: description_string = xmp.get_localized_text(consts.XMP_NS_DC, 'description', None, 'x-default') except XMPError: description_string = None os.remove(tmp_file_name) return {"filename": filename, "veeva_title": title_string, "veeva_description": description_string}
def parse_meta(filename, htmlonly=False): slide_file = parse_slide(filename) if slide_file is None: return { 'filename': os.path.basename(filename), 'veeva_title': os.path.splitext(os.path.basename(filename))[0], 'veeva_description': os.path.splitext(os.path.basename(filename))[0] } with ZipFile(filename, 'r') as z: with (z.open(slide_file[0])) as f: slide_type = slide_file[1] title_string = None description_string = None if slide_type == ".htm" or slide_type == ".html": soup = BeautifulSoup(f.read(), "lxml") title = soup.find('meta', {'name': 'veeva_title'}) if title is not None: title_string = title.get('content', None) description = soup.find('meta', {'name': 'veeva_description'}) if description is not None: description_string = description.get('content', None) if slide_type == ".pdf" and not htmlonly: doc = PDFDocument() parser = PDFParser(f) # omfg this is so janky, there needs to be a better library parser.set_document(doc) doc.set_parser(parser) metadata = doc.info if len(metadata) > 0: latest = metadata[-1] try: if latest['Title'] != '': title_string = latest['Title'] except KeyError: title_string = None try: if latest['Subject'] != '': description_string = latest['Subject'] except KeyError: description_string = None if slide_type == ".jpg" or slide_type == ".jpeg" and not htmlonly: tmp_file_name = str(uuid.uuid1()) + ".jpg" with open(tmp_file_name, 'wb') as tf: tf.write(f.read()) xmpfile = XMPFiles(file_path=tmp_file_name) xmp = xmpfile.get_xmp() xmpfile.close_file() try: title_string = xmp.get_localized_text( consts.XMP_NS_DC, 'title', None, 'x-default') except XMPError: title_string = None try: description_string = xmp.get_localized_text( consts.XMP_NS_DC, 'description', None, 'x-default') except XMPError: description_string = None os.remove(tmp_file_name) return { "filename": filename, "veeva_title": title_string, "veeva_description": description_string }
import glob from tqdm import tqdm directries = glob.glob("*_*") for directry in tqdm(directries): os.chdir(directry) files = glob.glob("*.JPG") os.chdir('..') try: os.mkdir('normal/%s_normal ' % directry) except FileExistsError: pass for file in files: ##OpenCV処理 image = cv2.imread('%s/%s' % (directry, file)) img_normal = (image - np.mean(image)) / np.std(image) * 55 + 140 cv2.imwrite('normal/%s_normal/%s' % (directry, file), img_normal) ##XMP処理 xmpfile = XMPFiles(file_path="%s/%s" % (directry, file), open_forupdate=True) xmp = xmpfile.get_xmp() xmpfile.close_file() xmpfile_normal = XMPFiles(file_path="normal/%s_normal/%s" % (directry, file), open_forupdate=True) xmp_normal = xmpfile_normal.get_xmp() xmp_normal = xmp xmpfile_normal.put_xmp(xmp_normal) xmpfile_normal.close_file()
def test_close_file(self): for filename in self.samplefiles: xmpfile = XMPFiles( file_path=filename ) xmpfile.close_file()
def create_images(): # actual image color: 255,0,0 img = Image.new("RGB", (100, 20), color='red') text = ImageDraw.Draw(img) text.text((10, 10), "Hello World", fill=(0, 0, 0)) image_wmeta = 'image_wmeta' # thumbnail color: 0,0,255 o = io.BytesIO() secret_thumbnail = Image.new("RGB", (120, 20), color='blue') text = ImageDraw.Draw(secret_thumbnail) text.text((10, 10), "secret thumbnail", fill=(0, 0, 0)) # transform it to bytes secret_thumbnail.save(o, "jpeg") secret_exif_thumbnail = o.getvalue() secret_thumbnail.close() # forbidden image_extension img.save(forbidden_img, "tiff") # bmp doesn't contain critical meta information img.save(image_wmeta + "_bmp" + '.bmp') # for some reasons some of these values don't match the relative specification: # rational numbers are separated at the comma, f.e. 13.37 is represented by [(13), (37)] # http://www.cipa.jp/std/documents/e/DC-008-2012_E.pdf#page=47 ... # http://www.cipa.jp/std/documents/e/DC-008-2012_E.pdf#page=87 jpg_exif = { "0th": { piexif.ImageIFD.ImageDescription: u"description", piexif.ImageIFD.StripOffsets: 3, piexif.ImageIFD.Artist: u"artist", piexif.ImageIFD.Copyright: u"copyright holder", piexif.ImageIFD.DateTime: u"2012:01:08 10:09:01", }, "Exif": { piexif.ExifIFD.DateTimeOriginal: u"2016:08:07 13:37:10", piexif.ExifIFD.DateTimeDigitized: u"2015:03:07 14:20:30", piexif.ExifIFD.OffsetTime: u"2017:05:09 08:04:04", piexif.ExifIFD.OffsetTimeOriginal: u"2017:04:12 18:15:00", piexif.ExifIFD.OffsetTimeDigitized: u"2016:02:10 11:10:03", piexif.ExifIFD.SubSecTime: u"2017:09:04 10:03:10", piexif.ExifIFD.SubSecTimeOriginal: u"2019:10:03 10:03:10", piexif.ExifIFD.SubSecTimeDigitized: u"2013:10:03 10:03:10", piexif.ExifIFD.CameraOwnerName: u"Cameraname", piexif.ExifIFD.BodySerialNumber: u"body serialnumber", piexif.ExifIFD.LensSerialNumber: u"lens serialnumber", piexif.ExifIFD.UserComment: b"secret comment", }, "GPS": { piexif.GPSIFD.GPSLatitudeRef: u"N", piexif.GPSIFD.GPSLatitude: [(10, 1), (20, 1), (0, 0)], piexif.GPSIFD.GPSLongitudeRef: u"W", piexif.GPSIFD.GPSLongitude: [(10, 1), (20, 1), (0, 0)], piexif.GPSIFD.GPSAltitudeRef: 0, piexif.GPSIFD.GPSAltitude: (200, 1), piexif.GPSIFD.GPSTimeStamp: [(10), (3)], piexif.GPSIFD.GPSSatellites: u"satellites", piexif.GPSIFD.GPSStatus: u"A", piexif.GPSIFD.GPSMeasureMode: u"3", piexif.GPSIFD.GPSDOP: [(1), (4)], piexif.GPSIFD.GPSSpeedRef: u"K", piexif.GPSIFD.GPSSpeed: [(42), (10)], piexif.GPSIFD.GPSTrackRef: u"T", piexif.GPSIFD.GPSTrack: [(21), (123)], piexif.GPSIFD.GPSImgDirectionRef: u"T", piexif.GPSIFD.GPSImgDirection: [(10), (12)], piexif.GPSIFD.GPSMapDatum: u"today", piexif.GPSIFD.GPSDestLatitudeRef: u"N", piexif.GPSIFD.GPSDestLatitude: [(8, 1), (30, 1), (0, 0)], piexif.GPSIFD.GPSDestLongitudeRef: u"E", piexif.GPSIFD.GPSDestLongitude: [(8), (30)], piexif.GPSIFD.GPSDestBearingRef: u"T", piexif.GPSIFD.GPSDestBearing: [(1), (10)], piexif.GPSIFD.GPSDestDistanceRef: u"K", piexif.GPSIFD.GPSDestDistance: [(10), (3)], piexif.GPSIFD.GPSProcessingMethod: b"WLAN", piexif.GPSIFD.GPSAreaInformation: b"area", piexif.GPSIFD.GPSDateStamp: u"2015:10:03 10:03:10", piexif.GPSIFD.GPSDifferential: 1, piexif.GPSIFD.GPSHPositioningError: [(2), (0)], }, "1st": { piexif.ImageIFD.ImageDescription: u"description", piexif.ImageIFD.StripOffsets: 3, piexif.ImageIFD.Artist: u"artist", piexif.ImageIFD.Copyright: u"copyright holder", piexif.ImageIFD.DateTime: u"2013:10:03 10:03:10", }, "thumbnail": secret_exif_thumbnail } png_dict = { "ImageDescription": u"description", "StripOffsets": "3", "Artist": u"artist", "Copyright": u"copyright holder", "DateTime": u"2012:01:08 10:09:01", "DateTimeOriginal": u"2016:08:07 13:37:10", "DateTimeDigitized": u"2015:03:07 14:20:30", "OffsetTime": u"2017:05:09 08:04:04", "OffsetTimeOriginal": u"2017:04:12 18:15:00", "OffsetTimeDigitized": u"2016:02:10 11:10:03", "SubSecTime": u"2017:09:04 10:03:10", "SubSecTimeOriginal": u"2019:10:03 10:03:10", "SubSecTimeDigitized": u"2013:10:03 10:03:10", "CameraOwnerName": u"Cameraname", "BodySerialNumber": u"body serialnumber", "LensSerialNumber": u"lens serialnumber", "UserComment": b"secret comment", "GPSLatitudeRef": u"N", "GPSLatitude": "3 deg 20' 0.00", "GPSLongitudeRef": u"W", "GPSLongitude": "3 deg 20.1' 0.00", "GPSAltitudeRef": "0", "GPSAltitude": "200 m Above Sea Level", "GPSTimeStamp": "03:19:59.999999", "GPSSatellites": u"satellites", "GPSStatus": u"A", "GPSMeasureMode": u"3", "GPSSpeedRef": u"K", "GPSSpeed": "4.2", "GPSTrackRef": u"T", "GPSTrack": "0.1707317073", "GPSImgDirectionRef": u"T", "GPSImgDirection": "0.6333333333", "GPSMapDatum": u"today", "GPSDestLatitudeRef": u"N", "GPSDestLatitude": "3 deg 30' 0.00", "GPSDestLongitudeRef": u"E", "GPSDestLongitude": "0 deg 16' 0.00", "GPSDestBearingRef": u"T", "GPSDestBearing": "0.1", "GPSDestDistanceRef": u"K", "GPSDestDistance": "3.333333333", "GPSProcessingMethod": b"WLAN", "GPSAreaInformation": b"area", "GPSDateStamp": u"2015:10:03 10:03:10", "GPSDifferential": "1", "ImageDescription": u"description", "StripOffsets": "3", "Artist": u"artist", "Copyright": u"copyright holder", "DateTime": u"2013:10:03 10:03:10", } # jpg with exif img.save(image_wmeta + '_jpg' + '.jpg', exif=piexif.dump(jpg_exif)) # copy jpg to jpe, jpeg copyfile(image_wmeta + '_jpg' + '.jpg', image_wmeta + '_jpe' + '.jpe') copyfile(image_wmeta + '_jpg' + '.jpg', image_wmeta + '_jpeg' + '.jpeg') # png exif-part png_info = PngImagePlugin.PngInfo() # copy png metadata for k, v in png_dict.items(): png_info.add_text(k, v, 0) img.save(image_wmeta + '_png' + '.png', "PNG", pnginfo=png_info) img.save(image_wmeta + '_gif' + '.gif') img.close() # xmp for gif and png xmp = XMPMeta() xmp.append_array_item(consts.XMP_NS_DC, 'secret', 'secret information', { 'prop_array_is_ordered': True, 'prop_value_is_array': True }) # gif xmp # TODO BUG Exempi library version >= 2.5 does not work with GIF images created by Pillow. # TODO BUG The format gets not recognized by Exempi. # TODO BUG Maybe a newer Pillow or Exempi version will fix this... # gif_image = XMPFiles(file_path=image_wmeta + '_gif' + ".gif", open_forupdate=True) # gif_image.put_xmp(xmp) # gif_image.close_file() # png part 2 png_image = XMPFiles(file_path=image_wmeta + '_png' + ".png", open_forupdate=True) png_image.put_xmp(xmp) png_image.close_file() return ((image_wmeta + '_' + suffix + "." + suffix) for suffix in ALLOWED_IMG_EXTENSIONS)
def test_object_to_dict(self): for filename in self.samplefiles: xmpfile = XMPFiles( file_path=filename ) xmp = xmpfile.get_xmp() self.assertTrue( object_to_dict( xmp ), "Not an XMPMeta object" ) xmpfile.close_file()