added support for xmp sidecar file tags

This commit is contained in:
2025-06-23 23:52:17 +02:00
parent 00b5020642
commit 350f41f439
12 changed files with 371 additions and 239 deletions

View File

@@ -1 +1 @@
2.7.1
2.7.2

View File

@@ -1,246 +1,263 @@
{
"extensions": {
"recommendations": [
"charliermarsh.ruff",
"esbenp.prettier-vscode",
"ms-edgedevtools.vscode-edge-devtools",
"ms-python.debugpy",
"ms-python.python",
"ms-python.vscode-pylance",
"samuelcolvin.jinjahtml",
"vscode.css-language-features",
"vscode.html-language-features",
"extensions": {
"recommendations": [
"charliermarsh.ruff",
"esbenp.prettier-vscode",
"ms-edgedevtools.vscode-edge-devtools",
"ms-python.debugpy",
"ms-python.python",
"ms-python.vscode-pylance",
"samuelcolvin.jinjahtml",
"vscode.css-language-features",
"vscode.html-language-features"
]
},
"folders": [
{
"name": "StaticGalleryBuilder",
"path": "./"
}
],
"launch": {
"version": "0.2.0",
"configurations": [
{
"args": [
"-p",
"${workspaceFolder}/test",
"-w",
"file://${workspaceFolder}/test",
"-t",
"Pictures",
"--theme",
"themes/alpenglow.css",
"--use-fancy-folders",
"--web-manifest",
"-l",
"cc-by-nc-sa",
"-n",
"-m",
"--reverse-sort",
// "--regenerate-thumbnails",
// "--reread-metadata",
"--folderthumbnails"
],
"console": "integratedTerminal",
"name": "Testfolder",
"postDebugTask": "Delete Lockfile",
"program": "${workspaceFolder}/builder.py",
"request": "launch",
"type": "debugpy"
},
{
"args": [
"-p",
"/home/user/woek/Pictures",
"-w",
"file:///home/user/woek/Pictures",
"-t",
"Pictures",
"--theme",
"themes/default.css",
"--use-fancy-folders",
"--web-manifest",
"-n",
"-m",
// "--regenerate-thumbnails",
// "--reread-metadata",
"--folderthumbnails"
],
"console": "integratedTerminal",
"name": "woek",
"postDebugTask": "Delete Lockfile 2",
"program": "${workspaceFolder}/builder.py",
"request": "launch",
"type": "debugpy"
},
{
"args": [
"--use-fancy-folders",
"-p",
"/mnt/nfs/pictures/",
"-w",
"https://pictures.sorogon.eu/",
"-t",
"Sorogon's Pictures",
"--theme",
"/home/user/git/github.com/greflm13/simple-picture-server/themes/alpenglow.css",
"-m",
"--exclude-folder",
"Scans",
"--exclude-folder",
"*/Galleries/*",
"--folderthumbnails",
"--reread-metadata"
],
"console": "integratedTerminal",
"name": "production",
"program": "${workspaceFolder}/builder.py",
"request": "launch",
"type": "debugpy"
},
{
"args": [
"${workspaceFolder}/themes",
"https://pictures.sorogon.eu/public/Example/"
],
"console": "integratedTerminal",
"name": "Generate Themes previews",
"program": "${workspaceFolder}/generate_previews.py",
"request": "launch",
"type": "debugpy"
}
]
},
"settings": {
"[css]": {
"editor.defaultFormatter": "vscode.css-language-features"
},
"folders": [
{
"name": "StaticGalleryBuilder",
"path": "./",
},
"[jinja-css]": {
"editor.defaultFormatter": "vscode.css-language-features"
},
"[jinja-html]": {
"editor.defaultFormatter": "vscode.html-language-features"
},
"[jinja-js]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff"
},
"black-formatter.args": ["-l 260"],
"black-formatter.interpreter": ["/usr/bin/python3"],
"editor.formatOnSave": false,
"emmet.includeLanguages": {
"jinja-css": "css",
"jinja-html": "html",
"jinja-js": "javascript",
"jinja-json": "json"
},
"files.associations": {
"**/*.css.j2": "jinja-css",
"**/*.css": "css",
"**/*.html.j2": "jinja-html"
},
"gitblame.inlineMessageEnabled": true,
"gitblame.inlineMessageFormat": "${author.name}, ${time.ago} • ${commit.summary}",
"gitblame.statusBarMessageFormat": "${author.name} (${time.ago})",
"html.format.indentHandlebars": true,
"html.format.templating": true,
"html.format.wrapAttributes": "preserve",
"html.format.wrapLineLength": 200,
"html.hover.documentation": true,
"html.suggest.html5": true,
"html.validate.scripts": true,
"html.validate.styles": true,
"json.schemaDownload.enable": true,
"json.schemas": [
{
"fileMatch": ["manifest.json.j2"],
"url": "https://json.schemastore.org/web-manifest-combined.json"
}
],
"launch": {
"version": "0.2.0",
"configurations": [
{
"args": [
"-p",
"${workspaceFolder}/test",
"-w",
"file://${workspaceFolder}/test",
"-t",
"Pictures",
"--theme",
"themes/alpenglow.css",
"--use-fancy-folders",
"--web-manifest",
"-l",
"cc-by-nc-sa",
"-n",
"-m",
"--reverse-sort",
"--regenerate-thumbnails",
"--reread-metadata",
"--folderthumbnails",
],
"console": "integratedTerminal",
"name": "Testfolder",
"postDebugTask": "Delete Lockfile",
"program": "${workspaceFolder}/builder.py",
"request": "launch",
"type": "debugpy",
},
{
"args": [
"-p",
"/home/user/woek/Pictures",
"-w",
"file:///home/user/woek/Pictures",
"-t",
"Pictures",
"--theme",
"themes/default.css",
"--use-fancy-folders",
"--web-manifest",
"-n",
"-m",
// "--regenerate-thumbnails",
// "--reread-metadata",
"--folderthumbnails",
],
"console": "integratedTerminal",
"name": "woek",
"postDebugTask": "Delete Lockfile 2",
"program": "${workspaceFolder}/builder.py",
"request": "launch",
"type": "debugpy",
},
{
"args": [
"${workspaceFolder}/themes",
"https://pictures.sorogon.eu/public/Example/"
],
"console": "integratedTerminal",
"name": "Generate Themes previews",
"program": "${workspaceFolder}/generate_previews.py",
"request": "launch",
"type": "debugpy",
}
],
"prettier.htmlWhitespaceSensitivity": "css",
"pylint.args": [
"--disable=C0111",
"--disable=C0301",
"--good-names-rgxs=^[_a-z][_a-z0-9]?$"
],
"python.analysis.inlayHints.callArgumentNames": "off",
"python.analysis.inlayHints.functionReturnTypes": false,
"python.analysis.inlayHints.variableTypes": false,
"yaml.schemas": {
"https://raw.githubusercontent.com/pamburus/hl/master/schema/json/config.schema.json": "file:///home/user/git/github.com/greflm13/StaticGalleryBuilder/hl_config.yaml"
},
"settings": {
"[css]": {
"editor.defaultFormatter": "vscode.css-language-features",
"ruff.lineLength": 180
},
"tasks": {
"version": "2.0.0",
"tasks": [
{
"command": "rm -f ${workspaceFolder}/test/.lock",
"isBackground": true,
"label": "Delete Lockfile",
"problemMatcher": [],
"type": "shell",
"presentation": {
"echo": false,
"reveal": "never",
"focus": false,
"panel": "shared",
"showReuseMessage": false,
"clear": true
}
},
{
"command": "rm -f /home/user/woek/Pictures/.lock",
"isBackground": true,
"label": "Delete Lockfile 2",
"problemMatcher": [],
"type": "shell",
"presentation": {
"echo": false,
"reveal": "never",
"focus": false,
"panel": "shared",
"showReuseMessage": false,
"clear": true
}
},
{
"command": "pyinstaller builder.py modules/*.py -n StaticGalleryBuilder-$(cat .version)-linux -F --add-data files:files --add-data templates:templates --add-data .version:.",
"isBackground": false,
"label": "Build",
"problemMatcher": [],
"type": "shell",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared",
"showReuseMessage": false,
"clear": false
},
"[jinja-css]": {
"editor.defaultFormatter": "vscode.css-language-features",
"group": {
"kind": "build",
"isDefault": true
},
"[jinja-html]": {
"editor.defaultFormatter": "vscode.html-language-features",
"dependsOn": ["Clean"]
},
{
"command": "rm -rf build dist",
"isBackground": true,
"label": "Clean",
"problemMatcher": [],
"type": "shell",
"presentation": {
"echo": true,
"reveal": "never",
"focus": false,
"panel": "shared",
"showReuseMessage": false,
"clear": true
},
"[jinja-js]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
},
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff",
},
"black-formatter.args": [
"-l 260",
],
"black-formatter.interpreter": [
"/usr/bin/python3",
],
"editor.formatOnSave": false,
"emmet.includeLanguages": {
"jinja-css": "css",
"jinja-html": "html",
"jinja-js": "javascript",
"jinja-json": "json",
},
"files.associations": {
"**/*.css.j2": "jinja-css",
"**/*.css": "css",
"**/*.html.j2": "jinja-html",
},
"gitblame.inlineMessageEnabled": true,
"gitblame.inlineMessageFormat": "${author.name}, ${time.ago} • ${commit.summary}",
"gitblame.statusBarMessageFormat": "${author.name} (${time.ago})",
"html.format.indentHandlebars": true,
"html.format.templating": true,
"html.format.wrapAttributes": "preserve",
"html.format.wrapLineLength": 200,
"html.hover.documentation": true,
"html.suggest.html5": true,
"html.validate.scripts": true,
"html.validate.styles": true,
"json.schemaDownload.enable": true,
"json.schemas": [
{
"fileMatch": [
"manifest.json.j2",
],
"url": "https://json.schemastore.org/web-manifest-combined.json",
},
],
"prettier.htmlWhitespaceSensitivity": "css",
"pylint.args": [
"--disable=C0111",
"--disable=C0301",
"--good-names-rgxs=^[_a-z][_a-z0-9]?$",
],
"python.analysis.inlayHints.callArgumentNames": "off",
"python.analysis.inlayHints.functionReturnTypes": false,
"python.analysis.inlayHints.variableTypes": false,
"yaml.schemas": {
"https://raw.githubusercontent.com/pamburus/hl/master/schema/json/config.schema.json": "file:///home/user/git/github.com/greflm13/StaticGalleryBuilder/hl_config.yaml"
},
"ruff.lineLength": 180,
},
"tasks": {
"version": "2.0.0",
"tasks": [
{
"command": "rm -f ${workspaceFolder}/test/.lock",
"isBackground": true,
"label": "Delete Lockfile",
"problemMatcher": [],
"type": "shell",
"presentation": {
"echo": false,
"reveal": "never",
"focus": false,
"panel": "shared",
"showReuseMessage": false,
"clear": true
}
},
{
"command": "rm -f /home/user/woek/Pictures/.lock",
"isBackground": true,
"label": "Delete Lockfile 2",
"problemMatcher": [],
"type": "shell",
"presentation": {
"echo": false,
"reveal": "never",
"focus": false,
"panel": "shared",
"showReuseMessage": false,
"clear": true
}
},
{
"command": "pyinstaller builder.py modules/*.py -n StaticGalleryBuilder-$(cat .version)-linux -F --add-data files:files --add-data templates:templates --add-data .version:.",
"isBackground": false,
"label": "Build",
"problemMatcher": [],
"type": "shell",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared",
"showReuseMessage": false,
"clear": false
},
"group": {
"kind": "build",
"isDefault": true
},
"dependsOn": [
"Clean"
]
},
{
"command": "rm -rf build dist",
"isBackground": true,
"label": "Clean",
"problemMatcher": [],
"type": "shell",
"presentation": {
"echo": true,
"reveal": "never",
"focus": false,
"panel": "shared",
"showReuseMessage": false,
"clear": true
},
"group": "build"
},
{
"command": "LESS=-SR hl logs/latest.jsonl --config hl_config.yaml",
"isBackground": false,
"label": "View Latest Log",
"problemMatcher": [],
"type": "shell",
"presentation": {
"echo": false,
"reveal": "always",
"focus": true,
"panel": "dedicated",
"showReuseMessage": false,
"clear": true
}
}
],
},
"group": "build"
},
{
"command": "LESS=-SR hl logs/latest.jsonl --config hl_config.yaml",
"isBackground": false,
"label": "View Latest Log",
"problemMatcher": [],
"type": "shell",
"presentation": {
"echo": false,
"reveal": "always",
"focus": true,
"panel": "dedicated",
"showReuseMessage": false,
"clear": true
}
}
]
}
}

View File

@@ -9,6 +9,7 @@ from datetime import datetime
from tqdm.auto import tqdm
from PIL import Image, ExifTags, TiffImagePlugin, UnidentifiedImageError
from jinja2 import Environment, FileSystemLoader
from defusedxml import ElementTree
from modules.logger import logger
from modules import cclicense
@@ -34,6 +35,41 @@ info: dict[str, str] = {}
licens: dict[str, str] = {}
def getxmp(strbuffer: str) -> dict[str, Any]:
"""
Returns a dictionary containing the XMP tags.
Requires defusedxml to be installed.
:returns: XMP tags in a dictionary.
"""
def get_name(tag: str) -> str:
return re.sub("^{[^}]+}", "", tag)
def get_value(element) -> str | dict[str, Any] | None:
value: dict[str, Any] = {get_name(k): v for k, v in element.attrib.items()}
children = list(element)
if children:
for child in children:
name = get_name(child.tag)
child_value = get_value(child)
if name in value:
if not isinstance(value[name], list):
value[name] = [value[name]]
value[name].append(child_value)
else:
value[name] = child_value
elif value:
if element.text:
value["text"] = element.text
else:
return element.text
return value
root = ElementTree.fromstring(strbuffer)
return {get_name(root.tag): get_value(root)}
def initialize_metadata(folder: str) -> dict[str, dict[str, int]]:
"""
Initializes the metadata JSON file if it doesn't exist.
@@ -162,9 +198,33 @@ def get_image_info(item: str, folder: str) -> dict[str, Any]:
if isinstance(tags, str):
tags = [tags]
xmp = xmpdata
if None in tags:
tags.remove(None)
return {"width": width, "height": height, "tags": tags, "exifdata": exifdata, "xmp": xmp}
def get_tags(sidecarfile: str) -> list[str]:
with open(sidecarfile) as sidecar:
strbuffer = sidecar.read()
xmpdata = getxmp(strbuffer)
tags = []
if xmpdata.get("xmpmeta", False):
if isinstance(xmpdata["xmpmeta"]["RDF"]["Description"], dict):
if xmpdata["xmpmeta"]["RDF"]["Description"].get("subject", False):
tags = xmpdata["xmpmeta"]["RDF"]["Description"]["subject"]["Bag"]["li"]
if isinstance(tags, str):
tags = [tags]
if xmpdata.get("xapmeta", False):
if isinstance(xmpdata["xapmeta"]["RDF"]["Description"], dict):
if xmpdata["xapmeta"]["RDF"]["Description"].get("subject", False):
tags = xmpdata["xapmeta"]["RDF"]["Description"]["subject"]["Bag"]["li"]
if isinstance(tags, str):
tags = [tags]
if None in tags:
tags.remove(None)
return tags
def process_image(item: str, folder: str, _args: Args, baseurl: str, metadata: dict[str, dict[str, int]], raw: list[str]) -> dict[str, Any]:
"""
Processes an image and prepares its data for the HTML template.
@@ -183,6 +243,9 @@ def process_image(item: str, folder: str, _args: Args, baseurl: str, metadata: d
extsplit = os.path.splitext(item)
if item not in metadata or _args.reread_metadata:
metadata[item] = get_image_info(item, folder)
sidecarfile = os.path.join(folder, item + ".xmp")
if os.path.exists(sidecarfile):
metadata[item]["tags"] = get_tags(sidecarfile)
image = {
"url": f"{_args.web_root_url}{baseurl}{urllib.parse.quote(item)}",

View File

@@ -1,4 +1,5 @@
CairoSVG==2.7.1
defusedxml==0.7.1
Jinja2==3.1.5
Pillow==11.1.0
pyinstaller==6.11.1

View File

@@ -257,6 +257,8 @@
}
}
}
filter()
{%- endif %}
</script>
{%- endif %}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmpMM:DerivedFrom="DSC00009.jpg">
<dc:subject><rdf:Bag><rdf:li></rdf:li><rdf:li>aqueduct</rdf:li><rdf:li>arch</rdf:li><rdf:li>arch bridge</rdf:li><rdf:li>bridge</rdf:li><rdf:li>hillside</rdf:li><rdf:li>passenger train</rdf:li><rdf:li>railroad</rdf:li><rdf:li>railroad bridge</rdf:li><rdf:li>span</rdf:li><rdf:li>train track</rdf:li><rdf:li>tree</rdf:li><rdf:li>viaduct</rdf:li></rdf:Bag></dc:subject><lr:hierarchicalSubject><rdf:Bag><rdf:li>|aqueduct</rdf:li><rdf:li>|arch</rdf:li><rdf:li>|arch bridge</rdf:li><rdf:li>|bridge</rdf:li><rdf:li>|hillside</rdf:li><rdf:li>|passenger train</rdf:li><rdf:li>|railroad</rdf:li><rdf:li>|railroad bridge</rdf:li><rdf:li>|span</rdf:li><rdf:li>|train track</rdf:li><rdf:li>|tree</rdf:li><rdf:li>|viaduct</rdf:li></rdf:Bag></lr:hierarchicalSubject></rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmpMM:DerivedFrom="DSC01106.jpg">
<dc:subject><rdf:Bag><rdf:li></rdf:li><rdf:li>clear</rdf:li><rdf:li>dark</rdf:li><rdf:li>moon</rdf:li><rdf:li>night</rdf:li><rdf:li>night sky</rdf:li><rdf:li>sky</rdf:li></rdf:Bag></dc:subject><lr:hierarchicalSubject><rdf:Bag><rdf:li>|clear</rdf:li><rdf:li>|dark</rdf:li><rdf:li>|moon</rdf:li><rdf:li>|night</rdf:li><rdf:li>|night sky</rdf:li><rdf:li>|sky</rdf:li></rdf:Bag></lr:hierarchicalSubject></rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmpMM:DerivedFrom="DSC03470.JPG">
<dc:subject><rdf:Bag><rdf:li></rdf:li><rdf:li>bus</rdf:li><rdf:li>illuminate</rdf:li><rdf:li>neon</rdf:li><rdf:li>neon light</rdf:li><rdf:li>night</rdf:li><rdf:li>sign</rdf:li><rdf:li>train car</rdf:li><rdf:li>trolley</rdf:li><rdf:li>window</rdf:li></rdf:Bag></dc:subject><lr:hierarchicalSubject><rdf:Bag><rdf:li>|bus</rdf:li><rdf:li>|illuminate</rdf:li><rdf:li>|neon</rdf:li><rdf:li>|neon light</rdf:li><rdf:li>|night</rdf:li><rdf:li>|sign</rdf:li><rdf:li>|train car</rdf:li><rdf:li>|trolley</rdf:li><rdf:li>|window</rdf:li></rdf:Bag></lr:hierarchicalSubject></rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmpMM:DerivedFrom="DSC03508.ARW">
<dc:subject><rdf:Bag><rdf:li></rdf:li><rdf:li>building</rdf:li><rdf:li>ceiling</rdf:li><rdf:li>pillar</rdf:li><rdf:li>display</rdf:li><rdf:li>rail</rdf:li><rdf:li>steam engine</rdf:li><rdf:li>steam locomotive</rdf:li><rdf:li>train</rdf:li><rdf:li>train car</rdf:li><rdf:li>train track</rdf:li></rdf:Bag></dc:subject><lr:hierarchicalSubject><rdf:Bag><rdf:li>|building</rdf:li><rdf:li>|ceiling</rdf:li><rdf:li>|pillar</rdf:li><rdf:li>|display</rdf:li><rdf:li>|rail</rdf:li><rdf:li>|steam engine</rdf:li><rdf:li>|steam locomotive</rdf:li><rdf:li>|train</rdf:li><rdf:li>|train car</rdf:li><rdf:li>|train track</rdf:li></rdf:Bag></lr:hierarchicalSubject></rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmpMM:DerivedFrom="DSC03508.JPG">
<dc:subject><rdf:Bag><rdf:li></rdf:li><rdf:li>attach</rdf:li><rdf:li>basement</rdf:li><rdf:li>beam</rdf:li><rdf:li>building</rdf:li><rdf:li>ceiling</rdf:li><rdf:li>equipment</rdf:li><rdf:li>floor</rdf:li><rdf:li>pipe</rdf:li><rdf:li>red</rdf:li><rdf:li>room</rdf:li><rdf:li>scaffold</rdf:li><rdf:li>tube</rdf:li><rdf:li>warehouse</rdf:li><rdf:li>water pipe</rdf:li></rdf:Bag></dc:subject><lr:hierarchicalSubject><rdf:Bag><rdf:li>|attach</rdf:li><rdf:li>|basement</rdf:li><rdf:li>|beam</rdf:li><rdf:li>|building</rdf:li><rdf:li>|ceiling</rdf:li><rdf:li>|equipment</rdf:li><rdf:li>|floor</rdf:li><rdf:li>|pipe</rdf:li><rdf:li>|red</rdf:li><rdf:li>|room</rdf:li><rdf:li>|scaffold</rdf:li><rdf:li>|tube</rdf:li><rdf:li>|warehouse</rdf:li><rdf:li>|water pipe</rdf:li></rdf:Bag></lr:hierarchicalSubject></rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmpMM:DerivedFrom="example.jpg">
<dc:subject><rdf:Bag><rdf:li></rdf:li><rdf:li>cloud</rdf:li><rdf:li>cloudy</rdf:li><rdf:li>evening sky</rdf:li><rdf:li>sea</rdf:li><rdf:li>sky</rdf:li><rdf:li>storm cloud</rdf:li><rdf:li>stormy</rdf:li><rdf:li>sun</rdf:li><rdf:li>sunset</rdf:li></rdf:Bag></dc:subject><lr:hierarchicalSubject><rdf:Bag><rdf:li>|cloud</rdf:li><rdf:li>|cloudy</rdf:li><rdf:li>|evening sky</rdf:li><rdf:li>|sea</rdf:li><rdf:li>|sky</rdf:li><rdf:li>|storm cloud</rdf:li><rdf:li>|stormy</rdf:li><rdf:li>|sun</rdf:li><rdf:li>|sunset</rdf:li></rdf:Bag></lr:hierarchicalSubject></rdf:Description>
</rdf:RDF>
</x:xmpmeta>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<x:xmpmeta x:xmptk="XMP Core 4.4.0-Exiv2" xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:exif="http://ns.adobe.com/exif/1.0/" xmlns:lr="http://ns.adobe.com/lightroom/1.0/" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmpMM:DerivedFrom="example.tif">
<dc:subject><rdf:Bag><rdf:li></rdf:li><rdf:li>cloud</rdf:li><rdf:li>cloudy</rdf:li><rdf:li>evening sky</rdf:li><rdf:li>sea</rdf:li><rdf:li>sky</rdf:li><rdf:li>storm cloud</rdf:li><rdf:li>stormy</rdf:li><rdf:li>sun</rdf:li><rdf:li>sunset</rdf:li></rdf:Bag></dc:subject><lr:hierarchicalSubject><rdf:Bag><rdf:li>|cloud</rdf:li><rdf:li>|cloudy</rdf:li><rdf:li>|evening sky</rdf:li><rdf:li>|sea</rdf:li><rdf:li>|sky</rdf:li><rdf:li>|storm cloud</rdf:li><rdf:li>|stormy</rdf:li><rdf:li>|sun</rdf:li><rdf:li>|sunset</rdf:li></rdf:Bag></lr:hierarchicalSubject></rdf:Description>
</rdf:RDF>
</x:xmpmeta>