def file_to_meta(fn): xmp_files = XMPFiles() with open(fn, 'r') as fp: header = fp.readline() if "xpacket" in header: # the file is already in a compatible format for the XMP parser. xmp_files.open_file(fn, open_read=True) xmp_obj = xmp_files.get_xmp() else: # need to wrap the file with a header and footer that allows # the XMP parser to parse the file into a dict. # we will only transform the data in a temporary file, leaving # the original file untouched. with NamedTemporaryFile(mode='w', delete=False) as fp,\ open(fn, 'r') as raw_fp: temp_fn = fp.name fp.write(XMP_XPACKET_HEADER + "\n") for line in raw_fp: fp.write("{line}\n".format(line=line)) fp.write(XMP_XPACKET_FOOTER + "\n") xmp_files.open_file(temp_fn, open_read=True, open_onlyxmp=True) xmp_obj = xmp_files.get_xmp() os.remove(temp_fn) return xmp_obj
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 test_open_open_limitscanning(self): """Verify this library failure.""" # Issue 5 filenames = [pkg.resource_filename(__name__, "samples/BlueSquare.pdf"), pkg.resource_filename(__name__, "samples/BlueSquare.xmp")] xmpfile = XMPFiles() for filename in filenames: with self.assertRaises(XMPError): xmpfile.open_file(filename, open_limitscanning=True)
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 test_write_in_readonly(self): """If not "open_forupdate = True", should raise exception""" # Note, the file should have been opened with "open_forupdate = True" # so let's check if XMPMeta is raising an Exception. xmpfile = XMPFiles() filename = os.path.join(self.tempdir, 'sig05-002a.tif') xmpfile.open_file(filename) xmp_data = xmpfile.get_xmp() xmp_data.set_property( NS_PHOTOSHOP, 'Headline', "Some text") self.assertRaises( XMPError, xmpfile.put_xmp, xmp_data ) self.assertEqual( xmpfile.can_put_xmp( xmp_data ), False )
def test_write_in_readonly(self): """If not "open_forupdate = True", should raise exception""" # Note, the file should have been opened with "open_forupdate = True" # so let's check if XMPMeta is raising an Exception. xmpfile = XMPFiles() filename = os.path.join(self.tempdir, 'sig05-002a.tif') xmpfile.open_file(filename) xmp_data = xmpfile.get_xmp() xmp_data.set_property(NS_PHOTOSHOP, 'Headline', "Some text") self.assertRaises(XMPError, xmpfile.put_xmp, xmp_data) self.assertEqual(xmpfile.can_put_xmp(xmp_data), False)
def test_open_open_limitscanning(self): """Verify this library failure.""" # Issue 5 filenames = [ pkg.resource_filename(__name__, "samples/BlueSquare.pdf"), pkg.resource_filename(__name__, "samples/BlueSquare.xmp") ] xmpfile = XMPFiles() for filename in filenames: with self.assertRaises(XMPError): xmpfile.open_file(filename, open_limitscanning=True)
def test_open_use_smarthandler(self): """Verify this library failure.""" # Issue 5 filenames = [ pkg_resources.resource_filename(__name__, "samples/BlueSquare.pdf"), pkg_resources.resource_filename(__name__, "samples/BlueSquare.ai"), pkg_resources.resource_filename(__name__, "samples/BlueSquare.xmp") ] xmpfile = XMPFiles() for filename in filenames: with self.assertRaises(XMPError): xmpfile.open_file(filename, open_usesmarthandler=True)
def test_print_bom(self): """Should be able to print XMP packets despite BOM.""" # The BOM cannot be decoded from utf-8 into ascii, so a 2.7 XMPMeta # object's __repr__ function would error out on it. filename = pkg.resource_filename(__name__, "samples/BlueSquare.jpg") xmpf = XMPFiles() xmpf.open_file(file_path=filename) xmp = xmpf.get_xmp() with patch('sys.stdout', new=StringIO()) as fake_out: print(xmp) repr(xmp) self.assertTrue(True)
def test_open_use_smarthandler(self): """Verify this library failure.""" # Issue 5 filenames = [pkg_resources.resource_filename(__name__, "samples/BlueSquare.pdf"), pkg_resources.resource_filename(__name__, "samples/BlueSquare.ai"), pkg_resources.resource_filename(__name__, "samples/BlueSquare.xmp")] xmpfile = XMPFiles() for filename in filenames: with self.assertRaises(XMPError): xmpfile.open_file(filename, open_usesmarthandler=True)
def test_can_put_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)) and (not self.exempi_problem(flg, fmt)))): xmpfile = XMPFiles() xmpfile.open_file(filename, **kwargs) xmp = xmpfile.get_xmp() if flg == 'open_forupdate': self.assertTrue(xmpfile.can_put_xmp(xmp)) else: self.assertFalse(xmpfile.can_put_xmp(xmp))
def exempi_error(self): """ Test case that exposes an Exempi bug. Seems like xmp_files_can_put_xmp in exempi is missing a try/catch block. So loading a sidecar file and call can_put_xmp will kill python interpreter since a C++ exception is thrown. """ filename = pkg.resource_filename(__name__, "samples/sig05-002a.xmp") xmpfile = XMPFiles() xmpfile.open_file(filename, open_forupdate=True) xmp = xmpfile.get_xmp() xmpfile.can_put_xmp(xmp)
def test_can_put_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)) and (not self.exempi_problem(flg, fmt)))): xmpfile = XMPFiles() xmpfile.open_file( filename, **kwargs ) xmp = xmpfile.get_xmp() if flg == 'open_forupdate': self.assertTrue( xmpfile.can_put_xmp( xmp ) ) else: self.assertFalse( xmpfile.can_put_xmp( xmp ) )
def exempi_error(self): """ Test case that exposes an Exempi bug. Seems like xmp_files_can_put_xmp in exempi is missing a try/catch block. So loading a sidecar file and call can_put_xmp will kill python interpreter since a C++ exception is thrown. """ filename = pkg.resource_filename(__name__, "samples/sig05-002a.xmp") xmpfile = XMPFiles() xmpfile.open_file(filename, open_forupdate = True ) xmp = xmpfile.get_xmp() xmpfile.can_put_xmp( xmp )
def test_repr(self): """Test __repr__ and __str__ on XMPFiles objects.""" xmpf = XMPFiles() self.assertEqual(str(xmpf), 'XMPFiles()') self.assertEqual(repr(xmpf), 'XMPFiles()') # If the XMPFiles object has a file associated with it, then use a # regular expression to match the output. filename = pkg.resource_filename(__name__, "samples/BlueSquare.jpg") xmpf.open_file(file_path=filename) actual_value = str(xmpf) regex = re.compile(r"""XMPFiles\(file_path=""", re.VERBOSE) self.assertIsNotNone(regex.match(actual_value)) self.assertTrue(actual_value.endswith("BlueSquare.jpg')"))
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 test_exempi_bad_combinations(self): """ Verify bad combinations of formats and open flags. """ # Certain combinations of formats and open flags will raise an XMPError # when you try to open the XMP for flg in open_flags: kwargs = {flg: True} for filename, fmt in zip(self.samplefiles, self.formats): if not self.flg_fmt_combi(flg, fmt): xmpfile = XMPFiles() xmpfile.open_file(filename, **kwargs) xmpfile.get_xmp() else: xmpfile = XMPFiles() with self.assertRaises(XMPError): xmpfile.open_file(filename, **kwargs)
def test_exempi_bad_combinations(self): """ Verify bad combinations of formats and open flags. """ # Certain combinations of formats and open flags will raise an XMPError # when you try to open the XMP for flg in open_flags: kwargs = { flg: True } for filename, fmt in zip(self.samplefiles, self.formats): if not self.flg_fmt_combi(flg, fmt): xmpfile = XMPFiles() xmpfile.open_file( filename, **kwargs ) xmpfile.get_xmp() else: xmpfile = XMPFiles() with self.assertRaises(XMPError): xmpfile.open_file( filename, **kwargs )
def test_open_file_with_options(self): """Try all open options""" for flg in open_flags: kwargs = {flg: True} for filename in self.samplefiles: if flg == 'open_usesmarthandler': # We know these are problematic. suffices = ('.ai', '.pdf', '.xmp') if filename.lower().endswith(suffices): continue if flg == 'open_limitscanning': # We know these are problematic. suffices = ('.pdf', '.xmp') if filename.lower().endswith(suffices): continue xmpfile = XMPFiles() xmpfile.open_file(filename, **kwargs)
def test_open_file_with_options(self): """Try all open options""" for flg in open_flags: kwargs = { flg: True } for filename in self.samplefiles: if flg == 'open_usesmarthandler': # We know these are problematic. suffices = ('.ai', '.pdf', '.xmp') if filename.lower().endswith(suffices): continue if flg == 'open_limitscanning': # We know these are problematic. suffices = ('.pdf', '.xmp') if filename.lower().endswith(suffices): continue xmpfile = XMPFiles() xmpfile.open_file(filename, **kwargs)
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 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_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 test_non_ascii_filename(self): """ repr must not fail on files with non-ascii characters See issue 36 """ # Rename one of the test files to use non-ascii characters. relpath = os.path.join('samples', 'BlueSquare.tif') srcfile = pkg.resource_filename(__name__, relpath) tdir = tempfile.mkdtemp() destdir = os.path.join(tdir, u"éà*çc! teeest!!") os.makedirs(destdir) with tempfile.NamedTemporaryFile(dir=destdir, prefix="image", suffix=".tif") as tfile: with open(srcfile, 'rb') as srcfile: tfile.write(srcfile.read()) tfile.seek(0) xf = XMPFiles() xf.open_file(file_path=tfile.name) # This was the point of failure in python2 actual = repr(xf) self.assertTrue(actual.startswith("XMPFiles(file_path=")) if sys.hexversion < 0x03000000: # The directory path (up to the non-ascii portion) should be # in the output. self.assertIn(tdir, actual) else: # The complete directory path should be present in the repr-ed # string under python3. self.assertIn(destdir, actual) shutil.rmtree(tdir)
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_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)
from libxmp.utils import object_to_dict 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)
def readmetadata(fname): #read metadata from tiff xf = XMPFiles() xf.open_file(file) xmp = xf.get_xmp()
from glob import glob import time from libxmp import XMPFiles import uuid start = time.time() files = glob('*IMAGE*/*.tif*') nfiles = len(files) for file in files: #name for jp2 image fjp2 = "{}.jp2".format(file.split('.tif')[0]) #read metadata from tiff xf = XMPFiles() xf.open_file(file) xmp = xf.get_xmp() #read bitmap from tiff image = io.imread(file, plugin='tifffile') #write bitmap to jp2 image jp2 = glymur.Jp2k(fjp2, 'wb') jp2[:] = image #append metadata in uuid box xmp_uuid = uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac') box = glymur.jp2box.UUIDBox(xmp_uuid, str(xmp)) jp2.append(box) #write second resolution as thumbnail jt = glymur.Jp2k("thumb" + fjp2, 'wb') jt[:] = jp2.read(rlevel=2) end = time.time()
import time from libxmp import XMPFiles import uuid start = time.time() files = glob("*IMAGE*/*.tif*") nfiles = len(files) for file in files: # name for jp2 image fjp2 = "{}.jp2".format(file.split(".tif")[0]) # read metadata from tiff xf = XMPFiles() xf.open_file(file) xmp = xf.get_xmp() # read bitmap from tiff image = io.imread(file, plugin="tifffile") # write bitmap to jp2 image jp2 = glymur.Jp2k(fjp2, "wb") jp2[:] = image # append metadata in uuid box xmp_uuid = uuid.UUID("be7acfcb-97a9-42e8-9c71-999491e3afac") box = glymur.jp2box.UUIDBox(xmp_uuid, str(xmp)) jp2.append(box) # write second resolution as thumbnail jt = glymur.Jp2k("thumb" + fjp2, "wb") jt[:] = jp2.read(rlevel=2) end = time.time()