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 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 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 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 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 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 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 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 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
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) xmp.set_property_int(NS_GPANO, 'CroppedAreaTopPixels', 0) xmp.set_property_int(NS_GPANO, 'CroppedAreaImageWidthPixels', 5100) xmp.set_property_int(NS_GPANO, 'CroppedAreaImageHeightPixels', 2550) xmp.set_property_int(NS_GPANO, 'FullPanoWidthPixels', 5100) xmp.set_property_int(NS_GPANO, 'FullPanoHeightPixels', 2550) dt = datetime.datetime(2012, 11, 7, 21, 3, 13, 465000, tzinfo=pytz.utc) xmp.set_property_datetime(NS_GPANO, 'FirstPhotoDate', dt) dt = datetime.datetime(2012, 11, 7, 21, 4, 10, 897000, tzinfo=pytz.utc) xmp.set_property_datetime(NS_GPANO, 'LastPhotoDate', dt) xmp.set_property_int(NS_GPANO, 'SourcePhotosCount', 50) xmp.set_property_bool(NS_GPANO, 'ExposureLockUsed', False) print(xmp) xmpfile.can_put_xmp(xmp) xmpfile.put_xmp(xmp) xmpfile.close_file() print('Done!')
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()
#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 worker(filepath): # initialize saucenao saucenao_core = SauceNao( directory='directory', databases=9, # 999 by default, 5 for pixiv, 9 for booru. minimum_similarity=65, combine_api_types=False, api_key=saucenao_api_key, exclude_categories='', move_to_categories=False, use_author_as_category=False, output_type=SauceNao.API_JSON_TYPE, start_file='', log_level=logging.ERROR, title_minimum_similarity=90) # search image on saucenao try: result = search(saucenao_core, filepath) except requests.exceptions.ConnectionError: print("Failed to connect saucenao!") return -1 except saucenao.exceptions.DailyLimitReachedException: print("Saucenao daily limit reached! try 1 hour later!") return -2 if (len(result) is 0): print('Image not found on danbooru!') return 1 else: danbooru_id = result[0]['data']['danbooru_id'] print('Image Found, ID=' + str(danbooru_id)) # GET danbooru tag json try: http = urllib3.PoolManager() # disable https cert check warning urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) url = 'https://danbooru.donmai.us/posts/' + str( danbooru_id) + '.json' headers = urllib3.util.make_headers(basic_auth=danbooru_login + ':' + danbooru_api_key) r = http.request('GET', url, headers=headers) r_data = r.data if isinstance(r_data, bytes): r_data = str(r_data, 'utf-8') tags = json.loads(r_data)['tag_string'] taglist = tags.split() except requests.exceptions.ConnectionError: print('failed to GET tag data from danbooru') return -1 # Write XMP Metadata to image xmpfile = XMPFiles(file_path=filepath, open_forupdate=True) xmp = xmpfile.get_xmp() # if image has no xmp data, create one if (xmp is None): xmp = XMPMeta() # write the tags for each in taglist: # check whether XMP includes 'subject' property, # if not, create a new one if (not xmp.does_property_exist(consts.XMP_NS_DC, 'subject')): xmp.append_array_item(consts.XMP_NS_DC, 'subject', each, { 'prop_array_is_ordered': True, 'prop_value_is_array': True }) # check whether tag has been written to file if (not xmp.does_array_item_exist(consts.XMP_NS_DC, 'subject', each)): xmp.append_array_item(consts.XMP_NS_DC, 'subject', each) if (xmpfile.can_put_xmp(xmp)): xmpfile.put_xmp(xmp) xmpfile.close_file() return 0 else: print('Unable to write XMP data!') return -1