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": { "extensions": {
"recommendations": [ "recommendations": [
"charliermarsh.ruff", "charliermarsh.ruff",
"esbenp.prettier-vscode", "esbenp.prettier-vscode",
"ms-edgedevtools.vscode-edge-devtools", "ms-edgedevtools.vscode-edge-devtools",
"ms-python.debugpy", "ms-python.debugpy",
"ms-python.python", "ms-python.python",
"ms-python.vscode-pylance", "ms-python.vscode-pylance",
"samuelcolvin.jinjahtml", "samuelcolvin.jinjahtml",
"vscode.css-language-features", "vscode.css-language-features",
"vscode.html-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": [ "[jinja-css]": {
{ "editor.defaultFormatter": "vscode.css-language-features"
"name": "StaticGalleryBuilder", },
"path": "./", "[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": { "prettier.htmlWhitespaceSensitivity": "css",
"version": "0.2.0", "pylint.args": [
"configurations": [ "--disable=C0111",
{ "--disable=C0301",
"args": [ "--good-names-rgxs=^[_a-z][_a-z0-9]?$"
"-p", ],
"${workspaceFolder}/test", "python.analysis.inlayHints.callArgumentNames": "off",
"-w", "python.analysis.inlayHints.functionReturnTypes": false,
"file://${workspaceFolder}/test", "python.analysis.inlayHints.variableTypes": false,
"-t", "yaml.schemas": {
"Pictures", "https://raw.githubusercontent.com/pamburus/hl/master/schema/json/config.schema.json": "file:///home/user/git/github.com/greflm13/StaticGalleryBuilder/hl_config.yaml"
"--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",
}
],
}, },
"settings": { "ruff.lineLength": 180
"[css]": { },
"editor.defaultFormatter": "vscode.css-language-features", "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]": { "group": {
"editor.defaultFormatter": "vscode.css-language-features", "kind": "build",
"isDefault": true
}, },
"[jinja-html]": { "dependsOn": ["Clean"]
"editor.defaultFormatter": "vscode.html-language-features", },
{
"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]": { "group": "build"
"editor.defaultFormatter": "esbenp.prettier-vscode", },
}, {
"[python]": { "command": "LESS=-SR hl logs/latest.jsonl --config hl_config.yaml",
"editor.defaultFormatter": "charliermarsh.ruff", "isBackground": false,
}, "label": "View Latest Log",
"black-formatter.args": [ "problemMatcher": [],
"-l 260", "type": "shell",
], "presentation": {
"black-formatter.interpreter": [ "echo": false,
"/usr/bin/python3", "reveal": "always",
], "focus": true,
"editor.formatOnSave": false, "panel": "dedicated",
"emmet.includeLanguages": { "showReuseMessage": false,
"jinja-css": "css", "clear": true
"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
}
}
],
},
}

View File

@@ -9,6 +9,7 @@ from datetime import datetime
from tqdm.auto import tqdm from tqdm.auto import tqdm
from PIL import Image, ExifTags, TiffImagePlugin, UnidentifiedImageError from PIL import Image, ExifTags, TiffImagePlugin, UnidentifiedImageError
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
from defusedxml import ElementTree
from modules.logger import logger from modules.logger import logger
from modules import cclicense from modules import cclicense
@@ -34,6 +35,41 @@ info: dict[str, str] = {}
licens: 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]]: def initialize_metadata(folder: str) -> dict[str, dict[str, int]]:
""" """
Initializes the metadata JSON file if it doesn't exist. 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): if isinstance(tags, str):
tags = [tags] tags = [tags]
xmp = xmpdata xmp = xmpdata
if None in tags:
tags.remove(None)
return {"width": width, "height": height, "tags": tags, "exifdata": exifdata, "xmp": xmp} 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]: 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. 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) extsplit = os.path.splitext(item)
if item not in metadata or _args.reread_metadata: if item not in metadata or _args.reread_metadata:
metadata[item] = get_image_info(item, folder) 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 = { image = {
"url": f"{_args.web_root_url}{baseurl}{urllib.parse.quote(item)}", "url": f"{_args.web_root_url}{baseurl}{urllib.parse.quote(item)}",

View File

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

View File

@@ -257,6 +257,8 @@
} }
} }
} }
filter()
{%- endif %} {%- endif %}
</script> </script>
{%- endif %} {%- 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>