This commit is contained in:
2024-06-26 22:24:00 +02:00
parent 86d23defae
commit c8c58fd808

View File

@@ -1,78 +1,192 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import sys import sys
import os import os
import urllib.parse
from multiprocessing import Pool
import numpy as np
""" """
root and webroot must point to the same folder, one on filesystem and one on the webserver. Use absolut paths, e.g. /data/pictures/ and https://pictures.example.com/ root and webroot must point to the same folder, one on filesystem and one on the webserver. Use absolut paths, e.g. /data/pictures/ and https://pictures.example.com/
""" """
root = "/mnt/small-data/nfs/pictures/" ROOT = "/mnt/nfs/pictures/"
webroot = "https://pictures.sorogon.eu/" WEBROOT = "https://pictures.sorogon.eu/"
imgext = [".jpg", ".jpeg", ".JPG", ".JPEG"] imgext = [".jpg", ".jpeg", ".JPG", ".JPEG"]
rawext = [".ARW", ".tif", ".tiff", ".TIF", ".TIFF"] rawext = [".ARW", ".tif", ".tiff", ".TIF", ".TIFF"]
htmlheader = """ thumbnails: list[tuple[str, str]] = []
HTMLHEADER = """
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pictures</title> <title>Pictures</title>
<style> <style>
img { * {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Arial;
}
.header {
text-align: center;
padding: 32px;
display: -ms-flexbox; /* IE10 */
display: flex;
-ms-flex-wrap: wrap; /* IE10 */
flex-wrap: wrap;
justify-content: space-evenly;
}
.header img {
width: 100px; width: 100px;
}</style> vertical-align: middle;
</head> }
<body>
.row {
display: -ms-flexbox; /* IE10 */
display: flex;
-ms-flex-wrap: wrap; /* IE10 */
flex-wrap: wrap;
padding: 0 2px;
}
figure {
margin: 0;
}
/* Create four equal columns that sits next to each other */
.column {
-ms-flex: 12.5%; /* IE10 */
flex: 12.5%;
max-width: 12.5%;
padding: 0 4px;
}
.column img {
margin-top: 20px;
vertical-align: middle;
width: 100%;
}
/* Responsive layout - makes a four column-layout instead of eight columns */
@media screen and (max-width: 1000px) {
.column {
-ms-flex: 25%;
flex: 25%;
max-width: 25%;
}
.header img {
width: 80px;
}
}
/* Responsive layout - makes a two column-layout instead of four columns */
@media screen and (max-width: 800px) {
.column {
-ms-flex: 50%;
flex: 50%;
max-width: 50%;
}
.header img {
width: 60px;
}
}
/* Responsive layout - makes the two columns stack on top of each other instead of next to each other */
@media screen and (max-width: 600px) {
.column {
-ms-flex: 100%;
flex: 100%;
max-width: 100%;
}
.header img {
width: 50px;
}
}
.caption {
padding-top: 4px;
text-align: center;
font-style: italic;
font-size: 12px;
width: 100%;
display: block;
}
</style>
</head>
<body>
""" """
def thumbnail_convert(arguments: tuple[str, str]):
folder, item = arguments
os.system(f'magick "{os.path.join(folder, item)}" -quality 75% -define jpeg:size=1024x1024 -define jpeg:extent=100kb -thumbnail 512x512 -auto-orient "{os.path.join(ROOT, ".previews", folder.removeprefix(ROOT), item)}"')
def listfolder(folder: str): def listfolder(folder: str):
items: list[str] = os.listdir(folder) items: list[str] = os.listdir(folder)
items.sort() items.sort()
images: list[str] = [] images: list[str] = []
subfolders: list[str] = [] subfolders: list[str] = []
if not os.path.exists(os.path.join(root, ".previews", folder.removeprefix(root))): if not os.path.exists(os.path.join(ROOT, ".previews", folder.removeprefix(ROOT))):
os.mkdir(os.path.join(root, ".previews", folder.removeprefix(root))) os.mkdir(os.path.join(ROOT, ".previews", folder.removeprefix(ROOT)))
with open(os.path.join(folder, "list.txt"), "w", encoding="utf-8") as f: with open(os.path.join(folder, "index.html"), "w", encoding="utf-8") as f:
f.write(htmlheader) f.write(HTMLHEADER)
for item in items: for item in items:
if item != "Galleries" and item != ".previews": if item != "Galleries" and item != ".previews":
if os.path.isdir(os.path.join(folder, item)): if os.path.isdir(os.path.join(folder, item)):
subfolders.extend([f'<a href="{webroot}{folder.removeprefix(root)}/{item}">{item}</a><br>']) subfolders.extend([f'<figure><a href="{WEBROOT}{folder.removeprefix(ROOT)}/{item}"><img src="https://www.svgrepo.com/show/400249/folder.svg" alt="Folder icon"/></a><figcaption><a href="{WEBROOT}{folder.removeprefix(ROOT)}/{item}">{item}</a></figcaption></figure>'])
listfolder(os.path.join(folder, item)) listfolder(os.path.join(folder, item))
else: else:
if os.path.splitext(item)[1] in imgext: if os.path.splitext(item)[1] in imgext:
images.extend([f'<a href="{webroot}{folder.removeprefix(root)}/{item}"><img src="{webroot}{folder.removeprefix(root)}/{item}" alt="{item}"/></a><br>']) image = f'<figure><a href="{WEBROOT}{urllib.parse.quote(folder.removeprefix(ROOT))}/{urllib.parse.quote(item)}"><img src="{WEBROOT}.previews/{urllib.parse.quote(folder.removeprefix(ROOT))}/{urllib.parse.quote(item)}" alt="{item}"/></a><figcaption class="caption">{item}'
if not os.path.exists(os.path.join(root, ".previews", folder.removeprefix(root), item)): if not os.path.exists(os.path.join(ROOT, ".previews", folder.removeprefix(ROOT), item)):
# os.system(f'magick {os.path.join(folder, item)} -resize 1024x768! {os.path.join(root, ".previews", folder.removeprefix(root), item)}') thumbnails.append((folder, item))
print(f'magick {os.path.join(folder, item)} -resize 1024x768! {os.path.join(root, ".previews", folder.removeprefix(root), item)}')
for raw in rawext: for raw in rawext:
if os.path.exists(os.path.join(folder, os.path.splitext(item)[0] + raw)): if os.path.exists(os.path.join(folder, os.path.splitext(item)[0] + raw)):
images.extend([f'<a href="{webroot}{folder.removeprefix(root)}/{os.path.splitext(item)[0]}{raw}">RAW</a><br>']) image += f': <a href="{WEBROOT}{urllib.parse.quote(folder.removeprefix(ROOT))}/{urllib.parse.quote(os.path.splitext(item)[0])}{raw}">RAW</a>'
for image in images: image += "</figcaption></figure>"
f.write(image) images.extend([image])
f.write("\n") f.write(' <div class="header">\n')
for subfolder in subfolders: for subfolder in subfolders:
f.write(subfolder) f.write(subfolder)
f.write("\n") f.write("\n")
f.write("</body></html>") f.write(" </div>\n")
f.write(' <div class="row">\n')
for chunk in np.array_split(images, 8):
f.write(' <div class="column">\n')
for image in chunk:
f.write(f" {image}\n")
f.write(" </div>\n")
f.write(" </div>\n")
f.write(" </body>\n</html>")
f.close() f.close()
def main(): def main():
global root global ROOT
global webroot global WEBROOT
if not root.endswith("/"): if not ROOT.endswith("/"):
root += "/" ROOT += "/"
if not webroot.endswith("/"): if not WEBROOT.endswith("/"):
webroot += "/" WEBROOT += "/"
if not os.path.exists(os.path.join(root, ".previews")): if not os.path.exists(os.path.join(ROOT, ".previews")):
os.mkdir(os.path.join(root, ".previews")) os.mkdir(os.path.join(ROOT, ".previews"))
listfolder(root) print("Generating html files...")
# @TODO: write actual html files (and css 🙄) listfolder(ROOT)
with Pool(os.cpu_count()) as p:
print("Generating thumbnails...")
p.map(thumbnail_convert, thumbnails)
if __name__ == "__main__": if __name__ == "__main__":