diff --git a/.vscode/settings.json b/.vscode/settings.json index 274aa4e..ebbb9f4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "python.pythonPath": "F:\\Installations\\WPy64-3740\\python-3.7.4.amd64\\python.exe" + "python.pythonPath": "X:\\Users\\Xevion\\Anaconda3\\python.exe" } \ No newline at end of file diff --git a/package/__pycache__/xmp.cpython-37.pyc b/package/__pycache__/xmp.cpython-37.pyc index 99686cf..c9ba92f 100644 Binary files a/package/__pycache__/xmp.cpython-37.pyc and b/package/__pycache__/xmp.cpython-37.pyc differ diff --git a/package/app.py b/package/app.py index efce2e0..dd83c18 100644 --- a/package/app.py +++ b/package/app.py @@ -64,15 +64,19 @@ def process_file(file_name, xmp_name=None): response = client.label_detection(image=image) labels = [label.description for label in response.label_annotations] print('\tLabels: {}'.format(', '.join(labels))) + + # XMP sidecar file specified, write to it using XML module if xmp_name: print('\tWriting {} tags to output XMP...'.format(len(labels))) - xmp.writeXMP(os.path.join(input_path, xmp_name), os.path.join(output_path, xmp_name), labels) + parser = xmp.XMPParser(os.path.join(input_path, xmp_name)) + parser.add_keywords(labels) + parser.save(os.path.join(output_path, xmp_name)) + # No XMP file is specified, using IPTC tagging else: print('\tWriting {} tags to output {}'.format(len(labels), ext[1:].upper())) info = iptcinfo3.IPTCInfo(os.path.join(input_path, file_name)) info['keywords'].extend(labels) info.save() - print('\tMoving associated original image file...') # Copy dry-run shutil.copy2(os.path.join(input_path, file_name), os.path.join(output_path, file_name)) @@ -150,5 +154,6 @@ def run(): raise # Remove the directory, we are done here - print('Cleaning up temporary directory...') - os.rmdir(temp_path) \ No newline at end of file + print('Cleaning up temporary directory...', end=' ') + os.rmdir(temp_path) + print('Complete.') \ No newline at end of file diff --git a/package/xmp.py b/package/xmp.py index 0bd05d4..10d500c 100644 --- a/package/xmp.py +++ b/package/xmp.py @@ -1,28 +1,61 @@ -# from libxmp import file_to_dict -import os, sys, re +import xml.etree.ElementTree as ET +import pprint as pp +import random, string -mainPattern = r'\n\s+\n(?: .+<\/rdf:li>\n)*\s+<\/rdf:Bag>\n\s+<\/dc:subject>\n' -subPattern = r'(.*)\n' -subFormatPattern = ' {}\n' +rnd = lambda length=10 : ''.join(random.choices(list(string.ascii_letters), k=length)) +toText = lambda items : list(map(lambda item : item.text, items)) -# Write tags to an XMP file, using regex patterns -def writeXMP(inputPath, outputPath, tags): - data = open(inputPath, 'r').read() - # Detect and find the \n \n \n """ - look = data.find('') + 13 - data = data[:look] + addition + data[look:] - match = re.search(mainPattern, data) - # Get last matching tag - submatch = None - for submatch in re.finditer(subPattern, match.group(0)): - pass - # Calculate very end - spanend = match.span()[0] + (submatch.span()[1] if submatch else 0) - # add tags to end - data = data[:spanend] + ''.join(subFormatPattern.format(tag) for tag in tags) + data[spanend:] - # Write file to disk - open(outputPath, 'w+').write( data) \ No newline at end of file +# Constant Namespace Types +RDF = '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}RDF' +SUBJECT = '{http://purl.org/dc/elements/1.1/}subject' +DESCRIPTION = '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}Description' +DESCRIPTION_LOWER = '{http://purl.org/dc/elements/1.1/}description' +ALT = '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}Alt' +LI = '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}li' +BAG = '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}Bag' + +class XMPParser(object): + def __init__(self, path): + # Root tag area + self.path = path + self.xmp = ET.parse(path) + self.root = self.xmp.getroot() + self.root = self.root.find(RDF) + self.root = self.root.find(DESCRIPTION) + + # Description Tag + # self._ready_descrition() + # self.description = self.root.find(DESCRIPTION_LOWER) + # if self.description: + # self.description = self.description.find(ALT) + # self.description = self.description.find(LI) + + # Keyword Tag + self._ready_keywords() + self.keywords = self.root.find(SUBJECT) + self.keywords = self.keywords.find(BAG) + + def _ready_keywords(self): + subject = self.root.find(SUBJECT) + if subject: + bag = subject.find(BAG) + if bag: + self.keywords = bag + else: + subject.append(ET.Element(BAG)) + else: + subject = ET.Element(SUBJECT) + subject.append(ET.Element(BAG)) + self.root.append(subject) + + def save(self, outpath=None): + self.xmp.write(outpath or self.path) + + def add_keywords(self, keywords): + elements = [ET.Element(LI) for key in keywords] + for i, key in enumerate(elements): + key.text = keywords[i] + self.keywords.extend(elements) + + def add_keyword(self, keyword): + self.add_keywords([keyword]) \ No newline at end of file