def test_parse_from_str_3_bytes_per_codepoint(self): """ Verify that we can create and read back utf-8 where each character takes 3 bytes to encode. """ xmp = XMPMeta() rdf = xmpcoverage.RDFCoverage # Replace 'Simple2 value' with 'शिव' # This is 'Shiva' in Devanagari # शिव has code points [2358, 2367, 2357] expectedValue = u'शिव' if sys.hexversion < 0x03000000: rdf = unicode(rdf[0:272]) + expectedValue + unicode(rdf[285:]) #rdf = rdf[0:272] + expectedValue.encode('utf-8') + rdf[285:] #rdf = unicode(rdf) else: rdf = rdf[0:272] + expectedValue + rdf[285:] xmp.parse_from_str(rdf, xmpmeta_wrap=True) prop = xmp.get_property(xmpcoverage.NS1, "SimpleProp2") self.assertEqual(prop, expectedValue) del xmp
def test_serialize_and_format(self): xmp = XMPMeta() xmp.parse_from_str(xmpcoverage.RDFCoverage, xmpmeta_wrap=True) obj = xmp.serialize_and_format(padding=0, newlinechr='NEWLINE', tabchr = 'TAB', indent=6 ) if sys.hexversion >= 0x03000000: the_unicode_type = str else: the_unicode_type = unicode self.assertTrue(isinstance(obj, the_unicode_type), "Result is not the correct string" ) with self.assertRaises(XMPError): xmp.serialize_and_format(read_only_packet=True, omit_packet_wrapper=True) with self.assertRaises(XMPError): xmp.serialize_and_format(include_thumbnail_pad=True, omit_packet_wrapper=True) with self.assertRaises(XMPError): xmp.serialize_and_format(exact_packet_length=True, omit_packet_wrapper=True ) del xmp
def get_xmp_version(filename): meta = pikepdf.open(filename).open_metadata() xmp = XMPMeta(xmp_str=str(meta)) try: return xmp.get_property('http://ns.adobe.com/pdf/1.3/', 'PDFVersion') except XMPError: return ''
def test_skip(self): """Verify usage of XMPMeta skip method. """ filename = pkg_resources.resource_filename(__name__, "samples/test1.xmp") with open(filename, 'r') as fptr: strbuffer = fptr.read() xmp = XMPMeta() xmp.parse_from_str(strbuffer) iterator = iterator = iter(xmp) schemas = [] paths = [] props = [] for schema, path, prop, options in iterator: if schema == NS_TIFF: iterator.skip(iter_skipsubtree=True) else: schemas.append(schema) paths.append(path) props.append(prop) # If the iteration modification worked, there should be no TIFF # properties in the list of schemas. self.assertTrue(NS_TIFF not in schemas) self.assertTrue(NS_EXIF in schemas)
def test_parse_str(self): xmp = XMPMeta() xmp.parse_from_str( xmpcoverage.RDFCoverage, xmpmeta_wrap=True ) prop = xmp.get_property( xmpcoverage.NS1, "SimpleProp1" ) self.assertEqual(prop, "Simple1 value" ) self.assertEqual(prop, u"Simple1 value" ) del xmp
def test_delete_property(self): """ Verify the deleting a phony property does not raise an exception. """ xmp = XMPMeta() xmp.parse_from_str(xmpcoverage.RDFCoverage, xmpmeta_wrap=True ) xmp.delete_property(xmpcoverage.NS1, "NotReallyThere" )
def test_parse_from_str_3_bytes_per_codepoint(self): """ Verify that we can create and read back utf-8 where each character takes 3 bytes to encode. """ xmp = XMPMeta() rdf = xmpcoverage.RDFCoverage # Replace 'Simple2 value' with 'शिव' # This is 'Shiva' in Devanagari # शिव has code points [2358, 2367, 2357] expectedValue = u'शिव' if sys.hexversion < 0x03000000: rdf = unicode(rdf[0:272]) + expectedValue + unicode(rdf[285:]) #rdf = rdf[0:272] + expectedValue.encode('utf-8') + rdf[285:] #rdf = unicode(rdf) else: rdf = rdf[0:272] + expectedValue + rdf[285:] xmp.parse_from_str(rdf, xmpmeta_wrap=True ) prop = xmp.get_property(xmpcoverage.NS1, "SimpleProp2" ) self.assertEqual(prop, expectedValue) del xmp
def test_parse_str(self): xmp = XMPMeta() xmp.parse_from_str(xmpcoverage.RDFCoverage, xmpmeta_wrap=True) prop = xmp.get_property(xmpcoverage.NS1, "SimpleProp1") self.assertEqual(prop, "Simple1 value") self.assertEqual(prop, u"Simple1 value") del xmp
def test_serialize_str(self): xmp = XMPMeta() xmp.parse_from_str( xmpcoverage.RDFCoverage, xmpmeta_wrap=True ) obj = xmp.serialize_to_str(use_compact_format=True, omit_packet_wrapper=True) if sys.hexversion >= 0x03000000: the_unicode_type = str else: the_unicode_type = unicode self.assertTrue(isinstance(obj, the_unicode_type)) with self.assertRaises(XMPError): xmp.serialize_to_str(read_only_packet=True, omit_packet_wrapper=True) with self.assertRaises(XMPError): xmp.serialize_to_str(include_thumbnail_pad=True, omit_packet_wrapper=True) with self.assertRaises(XMPError): xmp.serialize_to_str(exact_packet_length=True, omit_packet_wrapper=True) del xmp
def test_serialize_unicode(self): """ Return type is unicode in 2.7, but str in 3.x """ xmp = XMPMeta() xmp.parse_from_str(xmpcoverage.RDFCoverage, xmpmeta_wrap=True) if sys.hexversion >= 0x03000000: the_unicode_type = str else: the_unicode_type = unicode obj = xmp.serialize_to_unicode(use_compact_format=True, omit_packet_wrapper=False) self.assertTrue(isinstance(obj, the_unicode_type ), "Incorrect string result type." ) with self.assertRaises(XMPError): xmp.serialize_to_unicode(read_only_packet=True, omit_packet_wrapper=True) with self.assertRaises(XMPError): xmp.serialize_to_unicode(include_thumbnail_pad=True, omit_packet_wrapper=True ) with self.assertRaises(XMPError): xmp.serialize_to_unicode(exact_packet_length=True, omit_packet_wrapper=True ) del xmp
def test_delete_property_bad_schema(self): """ Specifying a bad schema trigger an exception. """ xmp = XMPMeta() xmp.parse_from_str(xmpcoverage.RDFCoverage, xmpmeta_wrap=True ) with self.assertRaises(XMPError): xmp.delete_property("not really a schema", "NotReallyThere" )
def test_text_property_450(self): xmp = XMPMeta() xmp.parse_from_str( xmpcoverage.LongTextProperty, xmpmeta_wrap=True ) headline = xmp.get_property("http://ns.adobe.com/photoshop/1.0/", 'Headline' ) self.assertEqual( headline[-5:], "=END=" ) self.assertTrue(len(headline) > 450, "Not all text was extracted from headline property.")
def test_clone(self): xmp1 = XMPMeta() self.assertTrue( xmp1 == xmp1, "XMP1 not equal it self" ) self.assertFalse( xmp1 != xmp1, "XMP1 is equal it self" ) xmp2 = xmp1.clone() self.assertFalse( xmp1 == xmp2, "XMP1 is not equal XMP2" ) self.assertTrue( xmp1 != xmp2, "XMP1 is not equal XMP2" ) del xmp1 del xmp2
def test_shorthand_rdf(self): """ Tests pass so long as no error is issued. """ xmp = XMPMeta() xmp.parse_from_str( xmpcoverage.ShorthandRDF, xmpmeta_wrap=True ) prop = xmp.get_property( "http://ns.adobe.com/tiff/1.0", "Model" ) self.assertEqual(prop, "Canon PowerShot S300" ) del xmp
def test_python_xmp_validate_change(sandwich): with sandwich.open_metadata() as xmp: assert 'xmp:CreatorTool' in xmp xmp['xmp:CreatorTool'] = 'Creator' # Exists as a xml tag text xmp['pdf:Producer'] = 'Producer' # Exists as a tag node assert str(xmp) xmpmeta = XMPMeta(xmp_str=str(xmp)) assert xmpmeta.does_property_exist(XMP_NS_XMP, 'CreatorTool') assert xmpmeta.does_property_exist(XMP_NS_PDF, 'Producer')
def test_text_property_450(self): xmp = XMPMeta() xmp.parse_from_str(xmpcoverage.LongTextProperty, xmpmeta_wrap=True) headline = xmp.get_property("http://ns.adobe.com/photoshop/1.0/", 'Headline') self.assertEqual(headline[-5:], "=END=") self.assertTrue( len(headline) > 450, "Not all text was extracted from headline property.")
def test_clone(self): xmp1 = XMPMeta() self.assertTrue(xmp1 == xmp1, "XMP1 not equal it self") self.assertFalse(xmp1 != xmp1, "XMP1 is equal it self") xmp2 = xmp1.clone() self.assertFalse(xmp1 == xmp2, "XMP1 is not equal XMP2") self.assertTrue(xmp1 != xmp2, "XMP1 is not equal XMP2") del xmp1 del xmp2
def test_shorthand_rdf(self): """ Tests pass so long as no error is issued. """ xmp = XMPMeta() xmp.parse_from_str(xmpcoverage.ShorthandRDF, xmpmeta_wrap=True) prop = xmp.get_property("http://ns.adobe.com/tiff/1.0", "Model") self.assertEqual(prop, "Canon PowerShot S300") del xmp
def test_xmpmeta_unicode_27(self): """In 2.7, unicode(xmp) should return a unicode object.""" xmp = XMPMeta() rdf = xmpcoverage.RDFCoverage xmp.parse_from_str(rdf) if sys.hexversion < 0x03000000: self.assertTrue(isinstance(unicode(xmp), unicode)) else: # It's a no-op in 3.x. self.assertTrue(True)
def test_python_xmp_validate_change_list(graph): with graph.open_metadata() as xmp: assert 'dc:creator' in xmp xmp['dc:creator'] = ['Dobby', 'Kreacher'] assert str(xmp) if not XMPMeta: pytest.skip(msg='needs libxmp') xmpmeta = XMPMeta(xmp_str=str(xmp)) DC = XMP_NS_DC assert xmpmeta.does_array_item_exist(DC, 'creator', 'Dobby') assert xmpmeta.does_array_item_exist(DC, 'creator', 'Kreacher')
def test_get_localized_text(self): xmp = XMPMeta() xmp.parse_from_str(xmpcoverage.RDFCoverage, xmpmeta_wrap=True ) prop = xmp.get_property(xmpcoverage.NS1, "SimpleProp2" ) self.assertEqual(prop, "Simple2 value" ) ltext = xmp.get_localized_text(xmpcoverage.NS1, "ArrayProp2", 'x-one', 'x-one' ) self.assertEqual(ltext, "Item2.1 value" ) del xmp
def test_count_array_items(self): """Tests XMPMeta method count_array_items.""" filename = pkg_resources.resource_filename(__name__, "samples/test1.xmp") with open(filename, 'r') as fptr: strbuffer = fptr.read() xmp = XMPMeta() xmp.parse_from_str(strbuffer) xmp.set_array_item(NS_DC, "creator", 2, "foo") xmp.append_array_item(NS_DC, "creator", "bar") xmp.append_array_item(NS_DC, "creator", "donuts") self.assertEqual(xmp.count_array_items(NS_DC, "creator"), 4)
def test_does_array_item_exist(self): """Tests XMPMeta method does_array_item_exist. Issue #03""" filename = pkg_resources.resource_filename(__name__, "samples/test1.xmp") with open(filename, 'r') as fptr: strbuffer = fptr.read() xmp = XMPMeta() xmp.parse_from_str(strbuffer) xmp.set_array_item(NS_DC, "creator", 2, "foo") xmp.append_array_item(NS_DC, "creator", "bar") self.assertTrue(xmp.does_array_item_exist(NS_DC, "creator", "foo")) self.assertFalse(xmp.does_array_item_exist(NS_DC, "creator", "blah"))
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_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_get_localized_text(self): """ Verify that unicode string literals are properly interpreted. """ xmp = XMPMeta() xmp.parse_from_str(xmpcoverage.RDFCoverage, xmpmeta_wrap=True ) prop = xmp.get_property(xmpcoverage.NS1, "SimpleProp2" ) self.assertEqual(prop, u'Simple2 value' ) ltext = xmp.get_localized_text(xmpcoverage.NS1, "ArrayProp2", 'x-one', 'x-one' ) self.assertEqual(ltext, u'Item2.1 value' ) del xmp
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_xmpmeta_str(self): """In 2.7, str must return a byte string. In 3.x, it is a str.""" xmp = XMPMeta() xmp.set_property(NS_DC, "Title", 'Huckleberry Finn') self.assertTrue(isinstance(str(xmp), str)) xmp = XMPMeta() xmp.set_property(NS_DC, "Title", u'Stürm und Drang') self.assertTrue(isinstance(str(xmp), str)) # Something in Devanagari xmp = XMPMeta() xmp.set_property(NS_DC, "Title", u'शिव') self.assertTrue(isinstance(str(xmp), str))
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 get_img_info(self, filename): info_filename = filename.split('.')[0] + FileBackend.METADATA_EXTENSION info_path = os.path.join(FileBackend.METADATA_PATH, info_filename) # Regenerate the metadata file if it is missing. if not os.path.isfile(info_path): info = self.__img_info__(self.__img_path__(filename)) info['filename'] = filename pickle.dump(info, \ open(os.path.join(FileBackend.METADATA_PATH, info_filename), 'wb'), \ protocol=pickle.HIGHEST_PROTOCOL) info = pickle.load(open(info_path, 'rb')) # an XMP object can't be pickled, so we serialize it when saving and # deserialize it when loading xmp = XMPMeta() xmp.parse_from_str(info['xmp']) info['xmp'] = xmp return info
def test_delete_property(self): """ Verify the deleting a phony property does not raise an exception. """ xmp = XMPMeta() xmp.parse_from_str(xmpcoverage.RDFCoverage, xmpmeta_wrap=True) xmp.delete_property(xmpcoverage.NS1, "NotReallyThere")
def test_2bytes_codepoint(self): """ Verify that we can create and read back utf-8 where some characters takes 2 bytes to encode. """ xmp = XMPMeta() rdf = xmpcoverage.RDFCoverage # Replace 'Simple2 value' with 'stürm' # ü has code point 252, so takes 5+1=6 bytes to encode. expectedValue = u'stürm' if sys.hexversion < 0x03000000: rdf = unicode(rdf[0:272]) + expectedValue + unicode(rdf[285:]) else: rdf = rdf[0:272] + expectedValue + rdf[285:] xmp.parse_from_str(rdf, xmpmeta_wrap=True) prop = xmp.get_property(xmpcoverage.NS1, "SimpleProp2") self.assertEqual(prop, expectedValue) del xmp
def test_2bytes_codepoint(self): """ Verify that we can create and read back utf-8 where some characters takes 2 bytes to encode. """ xmp = XMPMeta() rdf = xmpcoverage.RDFCoverage # Replace 'Simple2 value' with 'stürm' # ü has code point 252, so takes 5+1=6 bytes to encode. expectedValue = u'stürm' if sys.hexversion < 0x03000000: rdf = unicode(rdf[0:272]) + expectedValue + unicode(rdf[285:]) else: rdf = rdf[0:272] + expectedValue + rdf[285:] xmp.parse_from_str(rdf, xmpmeta_wrap=True ) prop = xmp.get_property(xmpcoverage.NS1, "SimpleProp2" ) self.assertEqual(prop, expectedValue) del xmp
def loadXmp(inventory): for item in inventory: if 'xmp' in item: try: yield (item, object_to_dict(XMPMeta(xmp_str=item['xmp']))) except OSError: print("!!!WARN Failed to deserialize XMP data in {}".format( item['name'])) continue else: print( "!!!WARN: File metadata entry doesn't contain serialized xmp data, ignoring item from categories" )
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_delete_property_bad_schema(self): """ Specifying a bad schema trigger an exception. """ xmp = XMPMeta() xmp.parse_from_str(xmpcoverage.RDFCoverage, xmpmeta_wrap=True) with self.assertRaises(XMPError): xmp.delete_property("not really a schema", "NotReallyThere")
def get_xmp(self): """ Get XMP from file. :return: A new :class:`libxmp.core.XMPMeta` instance. :raises XMPError: in case of errors. """ xmpptr = _exempi.xmp_files_get_new_xmp(self.xmpfileptr) _check_for_error() if xmpptr: return XMPMeta(_xmp_internal_ref=xmpptr) else: return None
def test_get_localized_text(self): xmp = XMPMeta() xmp.parse_from_str(xmpcoverage.RDFCoverage, xmpmeta_wrap=True) prop = xmp.get_property(xmpcoverage.NS1, "SimpleProp2") self.assertEqual(prop, "Simple2 value") ltext = xmp.get_localized_text(xmpcoverage.NS1, "ArrayProp2", 'x-one', 'x-one') self.assertEqual(ltext, "Item2.1 value") del xmp
class XMPEmbedderImpl: def __init__(self): self._fc = Storage() def metadata_synch(self, component_id, changes): # get xmp # the filename is needed because the extension is unknown, the following line of code is # tmp code because c.ID will include extension file (not only basename) # in the new MediaDART release #print 'MediaDART resource path: ', md_res_path try: myxmpfilename = str(self._fc.abspath(component_id)) except Exception, err: print '\n found some problems getting filename, err: ', err, '\n' xmpfile = XMPFiles(file_path=myxmpfilename, open_forupdate=files.XMP_OPEN_FORUPDATE) xmp = xmpfile.get_xmp() if not xmp: xmp = XMPMeta() for ns in changes.keys(): #print 'Property ', str(i[0]),':', str(i[1]) # first of all check if namespace str(i[0]) and property name str(i[1]) exist prefix = None try: prefix = xmp.get_prefix_for_namespace(str(ns)) except XMPError, err: print 'Error in get_prefix_for_namespace: ', err if prefix == None: #print 'prefix ', prefix[:-1] , ' does not exist.' try: log.debug('%s %s' % (str(ns), str(changes[ns]['prefix']))) res = xmp.register_namespace( str(ns), str(changes[ns]['prefix'])) # CHANGE ME #print 'register_namespace gave res = ', res except XMPError, err: print 'Error in register_namespace: ', err
def test_get_localized_text(self): """ Verify that unicode string literals are properly interpreted. """ xmp = XMPMeta() xmp.parse_from_str(xmpcoverage.RDFCoverage, xmpmeta_wrap=True) prop = xmp.get_property(xmpcoverage.NS1, "SimpleProp2") self.assertEqual(prop, u'Simple2 value') ltext = xmp.get_localized_text(xmpcoverage.NS1, "ArrayProp2", 'x-one', 'x-one') self.assertEqual(ltext, u'Item2.1 value') del xmp
def test_python_xmp_validate_add(trivial): with trivial.open_metadata() as xmp: xmp['dc:creator'] = ['Bob', 'Doug'] xmp['dc:title'] = 'Title' xmp['dc:publisher'] = {'Mackenzie'} xmp_str = str(xmp).replace('\n', '') assert '<rdf:Seq><rdf:li>Bob</rdf:li><rdf:li>Doug</rdf:li>' in xmp_str assert '<rdf:Bag><rdf:li>Mackenzie</rdf:li>' in xmp_str xmpmeta = XMPMeta(xmp_str=str(xmp)) DC = XMP_NS_DC assert xmpmeta.does_array_item_exist(DC, 'creator', 'Bob') assert xmpmeta.does_array_item_exist(DC, 'creator', 'Doug') assert xmpmeta.get_localized_text(DC, 'title', None, 'x-default') == 'Title' assert xmpmeta.does_array_item_exist(DC, 'publisher', 'Mackenzie')
def test_init_del(self): xmp = XMPMeta() self.assertTrue(xmp.xmpptr) del xmp
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_write_new_struct_in_array(self): filename = pkg_resources.resource_filename(__name__, "samples/test1.xmp") with open(filename, 'r') as fptr: strbuffer = fptr.read() xmp = XMPMeta() xmp.parse_from_str(strbuffer) prefix = xmp.get_prefix_for_namespace(NS_DC) xmp.append_array_item(NS_DC, prefix + 'creator', None, prop_value_is_struct=True) xmp.set_property(NS_DC, prefix + 'creator[2]/' + prefix + 'TestProp', '100') self.assertTrue(xmp.does_property_exist(NS_DC, prefix + 'creator[2]')) prop = xmp.get_property(NS_DC, prefix + 'creator[2]/%sTestProp' % prefix) self.assertEqual(prop, '100') xpath = prefix + 'creator' xmp.set_array_item(NS_DC, xpath, 3, None, prop_value_is_struct=True) xpath += '[3]/%sTestProp' % prefix xmp.set_property(NS_DC, xpath, '200') self.assertTrue(xmp.does_property_exist(NS_DC, xpath)) prop = xmp.get_property(NS_DC, xpath) self.assertEqual(prop, '200') xpath = prefix + 'TestStruct/' + prefix + 'TestValue' xmp.set_property(NS_DC, xpath, '300') self.assertTrue(xmp.does_property_exist(NS_DC, xpath)) prop = xmp.get_property(NS_DC, xpath) self.assertEqual(prop, '300')
def test_exempi_core(self): """Corresponds to test_exempi.TestExempi.test_exempi_core""" filename = pkg_resources.resource_filename(__name__, "samples/test1.xmp") with open(filename, 'r') as fptr: strbuffer = fptr.read() xmp = XMPMeta() xmp.parse_from_str(strbuffer) self.assertTrue(xmp.does_property_exist(NS_TIFF, 'Make')) self.assertFalse(xmp.does_property_exist(NS_TIFF, 'Foo')) prop = xmp.get_property(NS_TIFF, 'Make') self.assertEqual(prop, 'Canon') xmp.set_property(NS_TIFF, 'Make', 'Leica') prop = xmp.get_property(NS_TIFF, 'Make') self.assertEqual(prop, 'Leica') # Some tests correspond to option masks not currently returned via # this interface. item = xmp.get_localized_text(NS_DC, 'rights', None, 'x-default') self.assertEqual(item, "2006, Hubert Figuiere") xmp.set_localized_text(NS_DC, 'rights', 'en', 'en-CA', 'Foo bar') item = xmp.get_localized_text(NS_DC, 'rights', 'en', 'en-US') # Can't look at the actual lang, unlike the original test. self.assertEqual(item, 'Foo bar') xmp.delete_localized_text(NS_DC, 'rights', 'en', 'en-CA') self.assertFalse(xmp.does_property_exist(NS_DC, "rights[1]")) xmp.set_array_item(NS_DC, "creator", 2, "foo") xmp.append_array_item(NS_DC, "creator", "bar") prop = xmp.get_array_item(NS_DC, "creator", 3) self.assertEqual(prop, "bar") xmp.delete_property(NS_DC, "creator[3]") self.assertFalse(xmp.does_property_exist(NS_DC, "creator[3]")) prop = xmp.get_property(NS_EXIF, "DateTimeOriginal") self.assertEqual(prop, "2006-12-07T23:20:43-05:00") the_prop = xmp.get_property_datetime(NS_EXIF, "DateTimeOriginal") self.assertEqual(the_prop.year, 2006) self.assertEqual(the_prop.minute, 20) self.assertEqual(the_prop.tzinfo, pytz.utc) prop = xmp.get_property(NS_XAP, "Rating") self.assertEqual(prop, "3") prop = xmp.get_property_float(NS_CAMERA_RAW_SETTINGS, "SharpenRadius") self.assertEqual(prop, 1.0) xmp.set_property_float(NS_CAMERA_RAW_SETTINGS, "SharpenRadius", 2.5) prop = xmp.get_property_float(NS_CAMERA_RAW_SETTINGS, "SharpenRadius") self.assertEqual(prop, 2.5) prop = xmp.get_property_bool(NS_CAMERA_RAW_SETTINGS, "AlreadyApplied") self.assertFalse(prop) xmp.set_property_bool(NS_CAMERA_RAW_SETTINGS, "AlreadyApplied", True) prop = xmp.get_property_bool(NS_CAMERA_RAW_SETTINGS, "AlreadyApplied") self.assertTrue(prop) prop = xmp.get_property_int(NS_EXIF, "MeteringMode") self.assertEqual(prop, 5) xmp.set_property_int(NS_EXIF, "MeteringMode", 10) prop = xmp.get_property_long(NS_EXIF, "MeteringMode") self.assertEqual(prop, 10) xmp.set_property_long(NS_EXIF, "MeteringMode", 32) prop = xmp.get_property_int(NS_EXIF, "MeteringMode") self.assertEqual(prop, 32)
""" import datetime from libxmp import XMPFiles, XMPMeta import pytz try: xmpfile = XMPFiles(file_path=raw_input('image file path:'), open_forupdate=True) except: print('file path invalid!') exit() # xmp = XMPMeta() xmp = xmpfile.get_xmp() if xmp is None: xmp = XMPMeta() GPANO = 'GPano' NS_GPANO = 'http://ns.google.com/photos/1.0/panorama/' ns = xmp.register_namespace(NS_GPANO, GPANO) print(ns) xmp.get_prefix_for_namespace(NS_GPANO) xmp.set_property_bool(NS_GPANO, 'UsePanaramaViewer', True) xmp.set_property(NS_GPANO, 'CaptureSoftware', 'Photo Sphere') xmp.set_property(NS_GPANO, 'StichingSoftware', 'Photo Sphere') xmp.set_property(NS_GPANO, 'ProjectionType', 'equirectangular') xmp.set_property_float(NS_GPANO, 'PoseHeadingDegrees', 350.0) xmp.set_property_float(NS_GPANO, 'InitialViewHeadingDegrees', 90.0) xmp.set_property_float(NS_GPANO, 'InitialViewPitchDegrees', 0.0) xmp.set_property_float(NS_GPANO, 'InitialViewRollDegrees', 0.0) xmp.set_property_float(NS_GPANO, 'InitialHorizontalFOVDegrees', 75.0) xmp.set_property_int(NS_GPANO, 'CroppedAreaLeftPixels', 0)
# Copy left image file limage_dir = os.path.split(limage_path)[0] limage_fname = os.path.splitext(os.path.split(limage_path)[1])[0] vrimage_path = os.path.join(limage_dir, limage_fname + '.vr.jpg') shutil.copyfile(limage_path, vrimage_path) # Load image's xmp vrimage_file = XMPFiles(file_path=vrimage_path, open_forupdate=True) lxmp = vrimage_file.get_xmp() #print(lxmp) # Google's namespace 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)
def export_to_xmp_files(args): tmp_faces, img_labels = utils.load_img_labels(args.imgs_root) faces = utils.FACES(tmp_faces) if len(faces.dict_by_files) == 0: print('no faces loaded') exit() total_images = utils.get_images_in_dir_rec(args.imgs_root) for f in total_images: img_path = os.path.splitext(f)[0] + os.path.splitext(f)[1].lower() if os.path.dirname( img_path ) != args.mask_folder and args.mask_folder != None or img_path.lower( ).endswith('.png'): continue xmp_path = os.path.splitext(f)[0] + '.xmp' if os.path.exists(xmp_path): with open(xmp_path, 'r') as fptr: strbuffer = fptr.read() xmp = XMPMeta() xmp.parse_from_str(strbuffer) else: xmpfile = XMPFiles(file_path=f, open_forupdate=True) xmp = xmpfile.get_xmp() # print(f) kw_faces, kw_tags, kw_categories, kw_labels, kw_miscs = get_keywords( xmp) kw_tags = [] kw_categories = [] kw_miscs = [] if img_path in faces.dict_by_files: names = faces.get_names(faces.dict_by_files[img_path]) # remove detected, deleted and unknown unwanted_names = {'detected', 'deleted', 'unknown'} names = [ele for ele in names if ele not in unwanted_names] face_names = prepare_names(names, 'f ') else: # if not os.path.exists(xmp_path): # continue face_names = [] labels = [] if img_path in img_labels: if len(img_labels[img_path].tags) != 0: labels += prepare_names([ t[0].lower() for t in img_labels[img_path].tags if t[1] >= 30 ], 'l ') if len(img_labels[img_path].categories) != 0: labels += prepare_names( [c[0].lower() for c in img_labels[img_path].categories], 'l ') if hasattr(img_labels[img_path], 'gcloud_labels'): labels += prepare_names( [l.lower() for l in img_labels[img_path].gcloud_labels], 'l ') if hasattr(img_labels[img_path], 'gcloud_objects'): labels += prepare_names( [l.lower() for l in img_labels[img_path].gcloud_objects], 'l ') if hasattr(img_labels[img_path], 'gcloud_web'): labels += prepare_names( [l.lower() for l in img_labels[img_path].gcloud_web], 'l ') if hasattr(img_labels[img_path], 'gcloud_landmarks'): labels += prepare_names([ l.lower() for l in img_labels[img_path].gcloud_landmarks[::2] ], 'l ') labels = list(set(labels)) if sorted(face_names) != sorted(kw_faces) or sorted(labels) != sorted( kw_labels) or not os.path.exists(xmp_path): xmp.delete_property(consts.XMP_NS_DC, 'subject') for face in face_names: xmp.append_array_item(consts.XMP_NS_DC, 'subject', face, { 'prop_array_is_ordered': True, 'prop_value_is_array': True }) for l in labels: xmp.append_array_item(consts.XMP_NS_DC, 'subject', l, { 'prop_array_is_ordered': True, 'prop_value_is_array': True }) print('exporting file: {}'.format(os.path.basename(xmp_path))) with open(xmp_path, 'w') as fptr: fptr.write(xmp.serialize_to_str(omit_packet_wrapper=True))
def write_async(self, outfile, process_semaphore, progress_cb=None): pdf_writer = PdfWriter(version="1.5") pdf_group = PdfDict() pdf_group.indirect = True pdf_group.CS = PdfName.DeviceRGB pdf_group.I = PdfBool(True) pdf_group.S = PdfName.Transparency pdf_font_mapping = PdfDict() pdf_font_mapping.indirect = True pdf_font_mapping.F1 = self._build_font() for _ in self._pages: pdf_page = PdfDict() pdf_page.Type = PdfName.Page pdf_writer.addpage(pdf_page) # pdfrw makes a internal copy of the pages # use the copy so that references to pages in links are correct pdf_pages = list(pdf_writer.pagearray) srgb_colorspace = PdfDict() srgb_colorspace.indirect = True srgb_colorspace.N = 3 # Number of components (red, green, blue) with open(SRGB_ICC_FILENAME, "rb") as f: srgb_colorspace_stream = f.read() srgb_colorspace.Filter = [PdfName.FlateDecode] srgb_colorspace.stream = zlib.compress(srgb_colorspace_stream, 9).decode("latin-1") srgb_colorspace.Length1 = len(srgb_colorspace_stream) default_rgb_colorspace = PdfArray([PdfName.ICCBased, srgb_colorspace]) default_rgb_colorspace.indirect = True # Handle all pages in parallel @asyncio.coroutine def make_page(page, pdf_page, psem): # Prepare everything in parallel @asyncio.coroutine def get_pdf_thumbnail(psem): if page.thumbnail is None: return None return (yield from page.thumbnail.pdf_thumbnail(psem)) @asyncio.coroutine def get_pdf_background(psem): if page.background is None: return None return (yield from page.background.pdf_image(psem)) @asyncio.coroutine def get_pdf_mask(foreground, psem): if foreground.color is not None: return None return (yield from foreground.pdf_mask(psem)) pdf_thumbnail, pdf_background, pdf_foregrounds, pdf_masks = ( yield from asyncio.gather( get_pdf_thumbnail(psem), get_pdf_background(psem), asyncio.gather( *[fg.pdf_image(psem) for fg in page.foreground]), asyncio.gather( *[get_pdf_mask(fg, psem) for fg in page.foreground]))) pdf_page.MediaBox = PdfArray( [0, 0, PdfNumber(page.width), PdfNumber(page.height)]) pdf_page.Group = pdf_group pdf_resources = PdfDict() pdf_colorspace = PdfDict() pdf_colorspace.DefaultRGB = default_rgb_colorspace pdf_resources.ColorSpace = pdf_colorspace pdf_xobject = PdfDict() if pdf_thumbnail is not None: pdf_page.Thumb = pdf_thumbnail im_index = 0 # Save graphics state and scale unity rectangle to page size matrix = TransformationMatrix() matrix.scale(page.width, page.height) before_graphics = ("q\n" + "%s cm\n" % matrix.to_pdf()) after_graphics = "\nQ\n" contents = "" graphics = "" current_color = None if page.color != self._factory.WHITE: if current_color != page.color: current_color = page.color graphics += page.color.to_pdf() + " rg " graphics += ("0 0 1 1 re " + "f\n") if pdf_background is not None: pdf_xobject[PdfName("Im%d" % im_index)] = pdf_background graphics += "/Im%d Do\n" % im_index im_index += 1 for foreground, pdf_foreground, pdf_mask in zip( page.foreground, pdf_foregrounds, pdf_masks): if pdf_mask is not None: pdf_xobject[PdfName("Im%d" % im_index)] = pdf_mask im_index += 1 pdf_xobject[PdfName("Im%d" % im_index)] = pdf_foreground if (foreground.color is not None and current_color != foreground.color): current_color = foreground.color graphics += foreground.color.to_pdf() + " rg " graphics += "/Im%d Do\n" % im_index im_index += 1 if graphics: contents += (before_graphics + graphics.rstrip(" \n") + after_graphics) current_color = None before_text = ("BT\n" + "/F1 1 Tf 3 Tr\n") after_text = "\nET\n" text = "" pdf_annots = [] for t in page.text: if t.text: matrix = TransformationMatrix() # Glyph size is 0.5 x 1 matrix.scale(2 / len(t.text), 1) matrix.translate(-0.5, -0.5) if t.direction == "ltr": pass elif t.direction == "rtl": matrix.translate(0, -1) elif t.direction == "ttb": matrix.rotate(90) matrix.rotate(-t.rotation) matrix.translate(0.5, 0.5) matrix.scale(t.width, t.height) matrix.translate(t.x, t.y) text += "%s Tm %s Tj\n" % ( matrix.to_pdf(), PdfString().from_bytes( t.text.encode("utf-16-be"), bytes_encoding="hex")) if t.external_link is not None or t.internal_link is not None: pdf_annot = PdfDict() pdf_annots.append(pdf_annot) pdf_annot.Type = PdfName.Annot pdf_annot.Subtype = PdfName.Link pdf_annot.Border = [0, 0, 0] pdf_annot.Rect = [ PdfNumber(t.x), PdfNumber(t.y), PdfNumber(t.x + t.width), PdfNumber(t.y + t.height) ] if t.external_link is not None: pdf_a = PdfDict() pdf_annot.A = pdf_a pdf_a.Type = PdfName.Action pdf_a.S = PdfName.URI pdf_a.URI = t.external_link.decode("latin-1") if t.internal_link is not None: pdf_target_page = pdf_pages[t.internal_link[0]] target_x, target_y = t.internal_link[1] pdf_annot.Dest = [ pdf_target_page, PdfName.XYZ, PdfNumber(target_x), PdfNumber(target_y), 0 ] text = text.rstrip(" \n") if text: pdf_resources.Font = pdf_font_mapping contents += (before_text + text + after_text) contents = contents.rstrip(" \n") if contents: pdf_contents = PdfDict() pdf_contents.indirect = True pdf_page.Contents = pdf_contents if COMPRESS_PAGE_CONTENTS: pdf_contents.Filter = [PdfName.FlateDecode] pdf_contents.stream = zlib.compress( contents.encode("latin-1"), 9).decode("latin-1") else: pdf_contents.stream = contents if pdf_annots: pdf_page.Annots = pdf_annots if pdf_xobject: pdf_resources.XObject = pdf_xobject if pdf_resources: pdf_page.Resources = pdf_resources # Report progress nonlocal finished_pages finished_pages += 1 if progress_cb: progress_cb(finished_pages / len(self._pages)) finished_pages = 0 yield from asyncio.gather(*[ make_page(page, pdf_page, process_semaphore) for page, pdf_page in zip(self._pages, pdf_pages) ]) trailer = pdf_writer.trailer document_id = PdfString().from_bytes(os.urandom(16)) trailer.ID = [document_id, document_id] mark_info = PdfDict() mark_info.Marked = PdfBool(True) trailer.Root.MarkInfo = mark_info struct_tree_root = PdfDict() struct_tree_root.Type = PdfName.StructTreeRoot trailer.Root.StructTreeRoot = struct_tree_root metadata = PdfDict() metadata.indirect = True metadata.Type = PdfName.Metadata metadata.Subtype = PdfName.XML xmp = XMPMeta() xmp.set_property(XMP_NS_PDFA_ID, "part", "2") xmp.set_property(XMP_NS_PDFA_ID, "conformance", "A") metadata_stream = xmp.serialize_to_str().encode("utf-8") metadata.Filter = [PdfName.FlateDecode] metadata.stream = zlib.compress(metadata_stream, 9).decode("latin-1") metadata.Length1 = len(metadata_stream) trailer.Root.Metadata = metadata with TemporaryDirectory(prefix="djpdf-") as temp_dir: pdf_writer.write(path.join(temp_dir, "temp.pdf")) cmd = [ QPDF_CMD, "--stream-data=preserve", "--object-streams=preserve", "--normalize-content=n", "--newline-before-endstream" ] if LINEARIZE_PDF: cmd.extend(["--linearize"]) cmd.extend([ path.abspath(path.join(temp_dir, "temp.pdf")), path.abspath(outfile) ]) yield from run_command_async(cmd, process_semaphore)
def test_write_new_property(self): """Corresponds to test-write-new-property.cpp""" filename = pkg_resources.resource_filename(__name__, "samples/test1.xmp") with open(filename, 'r') as fptr: strbuffer = fptr.read() xmp = XMPMeta() xmp.parse_from_str(strbuffer, xmpmeta_wrap=False) XMPMeta.register_namespace(NS_CC, "cc") reg_prefix = XMPMeta.get_namespace_for_prefix("cc") self.assertEqual(reg_prefix, NS_CC) reg_prefix = XMPMeta.get_prefix_for_namespace(NS_CC) self.assertEqual(reg_prefix, "cc:") xmp.set_property(NS_CC, "License", "Foo") self.assertEqual(xmp.get_property(NS_CC, "License"), "Foo") the_dt = datetime.datetime(2005, 12, 25, 12, 42, 42, tzinfo=pytz.utc) xmp.set_property_datetime(NS_EXIF, "DateTimeOriginal", the_dt) self.assertEqual(xmp.get_property(NS_EXIF, "DateTimeOriginal"), "2005-12-25T12:42:42") prop = xmp.get_property_datetime(NS_EXIF, "DateTimeOriginal") self.assertEqual(prop.year, 2005) self.assertEqual(prop.minute, 42) self.assertEqual(prop.tzinfo, pytz.utc)