added metadata regeneration option and display of date captured if avialable

This commit is contained in:
2024-09-20 10:17:13 +02:00
committed by Flo Greistorfer
parent 961d79754e
commit 9403e84d78
8 changed files with 37 additions and 20 deletions

View File

@@ -1 +1 @@
2.3.4
2.3.5

View File

@@ -44,20 +44,20 @@ The script supports several command-line options to customize its behavior. Belo
### Options
- `-h, --help`: Show the help message and exit.
- `-p ROOT, --root-directory ROOT`: Specify the root folder where the images are stored. This option is required.
- `-w URL, --web-root-url URL`: Specify the base URL for the web root of the image hosting site. This option is required.
- `-t TITLE, --site-title TITLE`: Specify the title of the image hosting site. This option is required.
- `-r, --regenerate-thumbnails`: Regenerate thumbnails even if they already exist.
- `-n, --non-interactive-mode`: Run in non-interactive mode, disabling progress bars.
- `-l LICENSE, --license-type LICENSE`: Specify the license type for the images. Choices are `cc-zero`, `cc-by`, `cc-by-sa`, `cc-by-nd`, `cc-by-nc`, `cc-by-nc-sa`, and `cc-by-nc-nd`.
- `-a AUTHOR, --author-name AUTHOR`: Specify the name of the author of the images. Default is "Author".
- `-e EXTENSION, --file-extensions EXTENSION`: Specify the file extensions to include. This option can be specified multiple times.
- `-l LICENSE, --license-type LICENSE`: Specify the license type for the images. Choices are `cc-zero`, `cc-by`, `cc-by-sa`, `cc-by-nd`, `cc-by-nc`, `cc-by-nc-sa`, and `cc-by-nc-nd`.
- `-m, --web-manifest`: Generate a web manifest file.
- `-n, --non-interactive-mode`: Run in non-interactive mode, disabling progress bars.
- `-p ROOT, --root-directory ROOT`: Specify the root folder where the images are stored. **(This option is required)**.
- `-t TITLE, --site-title TITLE`: Specify the title of the image hosting site. **(This option is required)**.
- `-w URL, --web-root-url URL`: Specify the base URL for the web root of the image hosting site. **(This option is required)**.
- `--exclude-folder FOLDER`: Specify folders to exclude from processing. This option can be specified multiple times.
- `--ignore-other-files`: Ignore files that do not match the specified extensions.
- `--regenerate-thumbnails`: Regenerate thumbnails even if they already exist.
- `--reread-metadata`: Reread image metadata if it already exists.
- `--theme-path PATH`: Specify the path to the CSS theme file. Default is the provided default theme.
- `--use-fancy-folders`: Enable fancy folder view instead of the default Apache directory listing.
- `--ignore-other-files`: Ignore files that do not match the specified extensions.
- `--exclude-folder FOLDER`: Specify folders to exclude from processing. This option can be specified multiple times.
- `-m, --web-manifest`: Generate a web manifest file.
### Examples

View File

@@ -39,7 +39,8 @@
"cc-by-nc-sa",
"-n",
"-m",
"-r"
"--regenerate-thumbnails",
"--reread-metadata",
],
"console": "integratedTerminal",
"name": "Testfolder",
@@ -62,7 +63,8 @@
"--web-manifest",
"-n",
"-m",
"-r",
"--regenerate-thumbnails",
"--reread-metadata",
],
"console": "integratedTerminal",
"name": "woek",

View File

@@ -196,11 +196,13 @@ def main() -> None:
lock_file = os.path.join(args.root_directory, ".lock")
if os.path.exists(lock_file):
print("Another instance of this program is running.")
logger.info("nother instance of this program is running")
logger.error("another instance of this program is running")
exit()
try:
Path(lock_file).touch()
if args.reread_metadata:
logger.warning("reread metadata flag is set to true, all image metadata will be reread")
if args.regenerate_thumbnails:
logger.warning("regenerate thumbnails flag is set to true, all thumbnails will be regenerated")
if os.path.exists(os.path.join(args.root_directory, ".thumbnails")):

View File

@@ -272,13 +272,14 @@ a.pswp__share--download:hover {
color: #BBB; }
.pswp__caption__center {
text-align: left;
text-align: center;
max-width: 420px;
margin: 0 auto;
font-size: 13px;
padding: 10px;
line-height: 20px;
color: #CCC; }
color: #CCC;
font-weight: bold; }
.pswp__caption--empty {
display: none; }

View File

@@ -58,6 +58,7 @@ class Args:
license_type: Optional[str]
non_interactive_mode: bool
regenerate_thumbnails: bool
reread_metadata: bool
root_directory: str
site_title: str
theme_path: str
@@ -75,6 +76,7 @@ class Args:
result["license_type"] = self.license_type
result["non_interactive_mode"] = self.non_interactive_mode
result["regenerate_thumbnails"] = self.regenerate_thumbnails
result["reread_metadata"] = self.reread_metadata
result["root_directory"] = self.root_directory
result["site_title"] = self.site_title
result["theme_path"] = self.theme_path
@@ -105,12 +107,13 @@ def parse_arguments(version: str) -> Args:
parser.add_argument("-m", "--web-manifest", help="Generate a web manifest file.", action="store_true", default=False, dest="generate_webmanifest")
parser.add_argument("-n", "--non-interactive-mode", help="Run in non-interactive mode, disabling progress bars.", action="store_true", default=False, dest="non_interactive_mode")
parser.add_argument("-p", "--root-directory", help="Root directory containing the images.", required=True, type=str, dest="root_directory", metavar="ROOT")
parser.add_argument("-r", "--regenerate-thumbnails", help="Regenerate thumbnails even if they already exist.", action="store_true", default=False, dest="regenerate_thumbnails")
parser.add_argument("-t", "--site-title", help="Title of the image hosting site.", required=True, type=str, dest="site_title", metavar="TITLE")
parser.add_argument("-w", "--web-root-url", help="Base URL of the web root for the image hosting site.", required=True, type=str, dest="web_root_url", metavar="URL")
parser.add_argument("--exclude-folder", help="Folders to exclude from processing, globs supported (can be specified multiple times).", action="append", dest="exclude_folders", metavar="FOLDER")
parser.add_argument("--generate-help-preview", action=HelpPreviewAction, path="help.svg", )
parser.add_argument("--ignore-other-files", help="Ignore files that do not match the specified extensions.", action="store_true", default=False, dest="ignore_other_files")
parser.add_argument("--regenerate-thumbnails", help="Regenerate thumbnails even if they already exist.", action="store_true", default=False, dest="regenerate_thumbnails")
parser.add_argument("--reread-metadata", help="Reread image metadata", action="store_true", default=False, dest="reread_metadata")
parser.add_argument("--theme-path", help="Path to the CSS theme file.", default=DEFAULT_THEME_PATH, type=str, dest="theme_path", metavar="PATH")
parser.add_argument("--use-fancy-folders", help="Enable fancy folder view instead of the default Apache directory listing.", action="store_true", default=False, dest="use_fancy_folders")
parser.add_argument("--version", action="version", version=f"%(prog)s {version}")
@@ -125,6 +128,7 @@ def parse_arguments(version: str) -> Args:
license_type=parsed_args.license_type,
non_interactive_mode=parsed_args.non_interactive_mode,
regenerate_thumbnails=parsed_args.regenerate_thumbnails,
reread_metadata=parsed_args.reread_metadata,
root_directory=parsed_args.root_directory,
site_title=parsed_args.site_title,
theme_path=parsed_args.theme_path,

View File

@@ -3,6 +3,7 @@ import urllib.parse
import fnmatch
import json
from typing import Any, Dict, List, Tuple
from datetime import datetime
import numpy as np
from tqdm.auto import tqdm
@@ -103,7 +104,7 @@ def get_image_info(item: str, folder: str) -> Dict[str, Any]:
tag = ExifTags.TAGS.get(tag_id, tag_id)
content = exifdatas.get(tag_id)
if isinstance(content, bytes):
content = content.hex(" ")
content = "0x" + content.hex()
if isinstance(content, TiffImagePlugin.IFDRational):
content = content.limit_rational(1000000)
if isinstance(content, tuple):
@@ -113,6 +114,8 @@ def get_image_info(item: str, folder: str) -> Dict[str, Any]:
newtuple = newtuple + (i.limit_rational(1000000),)
if newtuple:
content = newtuple
if tag in ["DateTime", "DateTimeOriginal", "DateTimeDigitized"]:
content = datetime.strptime(content, "%Y:%m:%d %H:%M:%S").strftime("%Y-%m-%d %H:%M:%S")
exifdata[tag] = content
if "Orientation" in exifdata and exifdata["Orientation"] in [6, 8]:
logger.info("image is rotated", extra={"file": file})
@@ -122,7 +125,7 @@ def get_image_info(item: str, folder: str) -> Dict[str, Any]:
del exifdata[key]
return {"width": width, "height": height, "exifdata": exifdata}
else:
return {"width": width, "height": height}
return {"width": width, "height": height, "exifdata": None}
def process_image(item: str, folder: str, _args: Args, baseurl: str, sizelist: Dict[str, Dict[str, int]], raw: List[str]) -> Dict[str, Any]:
@@ -141,7 +144,7 @@ def process_image(item: str, folder: str, _args: Args, baseurl: str, sizelist: D
Dict[str, Any]: Dictionary containing image details for HTML rendering.
"""
extsplit = os.path.splitext(item)
if item not in sizelist or _args.regenerate_thumbnails:
if item not in sizelist or _args.reread_metadata:
sizelist[item] = get_image_info(item, folder)
image = {
@@ -150,6 +153,7 @@ def process_image(item: str, folder: str, _args: Args, baseurl: str, sizelist: D
"name": item,
"width": sizelist[item]["width"],
"height": sizelist[item]["height"],
"exifdata": sizelist[item]["exifdata"],
}
path = os.path.join(_args.root_directory, ".thumbnails", baseurl, item + ".jpg")
if not os.path.exists(path) or _args.regenerate_thumbnails:

View File

@@ -147,7 +147,11 @@
var pswpElement = document.querySelectorAll('.pswp')[0];
var items = [
{%- for image in allimages %}
{%- if image.exifdata.DateTime %}
{ src: "{{ image.url }}", w: {{ image.width }}, h: {{ image.height }}, msrc: "{{ image.thumbnail }}", title: "Captured: {{ image.exifdata.DateTime }}" },
{%- else %}
{ src: "{{ image.url }}", w: {{ image.width }}, h: {{ image.height }}, msrc: "{{ image.thumbnail }}" },
{%- endif %}
{%- endfor %}
];
var re = /pid=(\d+)/;