mirror of
https://github.com/greflm13/StaticGalleryBuilder.git
synced 2026-02-05 02:59:27 +00:00
added support for xmp sidecar file tags
This commit is contained in:
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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)}",
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -257,6 +257,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filter()
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
</script>
|
</script>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|||||||
7
test/example/DSC00009.jpg.xmp
Normal file
7
test/example/DSC00009.jpg.xmp
Normal 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>
|
||||||
7
test/example/DSC01106.jpg.xmp
Normal file
7
test/example/DSC01106.jpg.xmp
Normal 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>
|
||||||
7
test/example/DSC03470.JPG.xmp
Normal file
7
test/example/DSC03470.JPG.xmp
Normal 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>
|
||||||
7
test/example/DSC03508.ARW.xmp
Normal file
7
test/example/DSC03508.ARW.xmp
Normal 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>
|
||||||
7
test/example/DSC03508.JPG.xmp
Normal file
7
test/example/DSC03508.JPG.xmp
Normal 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>
|
||||||
7
test/example/example.jpg.xmp
Normal file
7
test/example/example.jpg.xmp
Normal 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>
|
||||||
7
test/example/example.tif.xmp
Normal file
7
test/example/example.tif.xmp
Normal 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>
|
||||||
Reference in New Issue
Block a user