Add cover images to albums. If a cover.jpg doesn't exist, use the first image
This commit is contained in:
parent
2875805444
commit
217950eeaf
3 changed files with 62 additions and 16 deletions
|
@ -2,7 +2,7 @@ import logging
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
from typing import Iterator
|
from typing import Iterator, Optional
|
||||||
|
|
||||||
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
||||||
from PIL import Image, UnidentifiedImageError
|
from PIL import Image, UnidentifiedImageError
|
||||||
|
@ -20,6 +20,8 @@ class ImageDirectory:
|
||||||
images: list["ImagePath"]
|
images: list["ImagePath"]
|
||||||
is_root: bool = False
|
is_root: bool = False
|
||||||
|
|
||||||
|
cover_path: Optional["ImagePath"] = None
|
||||||
|
|
||||||
def walk(self) -> Iterator["ImageDirectory"]:
|
def walk(self) -> Iterator["ImageDirectory"]:
|
||||||
yield self
|
yield self
|
||||||
for child in self.children:
|
for child in self.children:
|
||||||
|
@ -34,6 +36,13 @@ class ImageDirectory:
|
||||||
images += image_dir.images
|
images += image_dir.images
|
||||||
return images
|
return images
|
||||||
|
|
||||||
|
def cover_image_paths(self) -> list["ImagePath"]:
|
||||||
|
images = []
|
||||||
|
for image_dir in self.walk():
|
||||||
|
if image_dir.cover_path is not None:
|
||||||
|
images.append(image_dir.cover_path)
|
||||||
|
return images
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ImagePath:
|
class ImagePath:
|
||||||
|
@ -97,8 +106,20 @@ def find_images(root_path: Path) -> ImageDirectory:
|
||||||
for filename in sorted(filenames):
|
for filename in sorted(filenames):
|
||||||
file_path = dirpath / filename
|
file_path = dirpath / filename
|
||||||
if is_image(file_path):
|
if is_image(file_path):
|
||||||
image_dir.images.append(ImagePath(file_path))
|
ip = ImagePath(file_path)
|
||||||
|
|
||||||
|
# Set a cover image for the album. Use "cover.jpg" if one exists,
|
||||||
|
# otherwise use the first image we find.
|
||||||
|
if file_path.stem == "cover":
|
||||||
|
image_dir.cover_path = ip
|
||||||
|
# Don't add the cover image to the list of images, we want to handle
|
||||||
|
# that separately
|
||||||
|
continue
|
||||||
|
|
||||||
|
image_dir.images.append(ip)
|
||||||
|
|
||||||
|
if image_dir.cover_path is None and len(image_dir.images) > 0:
|
||||||
|
image_dir.cover_path = image_dir.images[0]
|
||||||
image_dirs[image_dir.path] = image_dir
|
image_dirs[image_dir.path] = image_dir
|
||||||
|
|
||||||
return image_dirs[root_path]
|
return image_dirs[root_path]
|
||||||
|
@ -119,8 +140,10 @@ def generate_thumbnails(config: Config, root_dir: ImageDirectory) -> None:
|
||||||
"""
|
"""
|
||||||
Find all of the images and generate thumbnails and on-screen versions
|
Find all of the images and generate thumbnails and on-screen versions
|
||||||
"""
|
"""
|
||||||
for image_path in track(root_dir.image_paths(), description="Making thumbnails..."):
|
# Include cover images here because we want thumbnails for all of them
|
||||||
logger.debug(image_path)
|
|
||||||
|
all_images = root_dir.image_paths() + root_dir.cover_image_paths()
|
||||||
|
for image_path in track(all_images, description="Making thumbnails..."):
|
||||||
orig_img = Image.open(image_path.path)
|
orig_img = Image.open(image_path.path)
|
||||||
|
|
||||||
slides_path = image_path.path.parent / "slides"
|
slides_path = image_path.path.parent / "slides"
|
||||||
|
@ -156,9 +179,7 @@ def generate_html(config: Config, root_dir: ImageDirectory) -> None:
|
||||||
|
|
||||||
for album_dir in root_dir.walk():
|
for album_dir in root_dir.walk():
|
||||||
html_path = album_dir.path / "index.html"
|
html_path = album_dir.path / "index.html"
|
||||||
root_path = root_dir.path.relative_to(
|
root_path = root_dir.path.relative_to(html_path.parent, walk_up=True)
|
||||||
html_path.parent, walk_up=True
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.debug(f"Rendering {html_path}")
|
logger.debug(f"Rendering {html_path}")
|
||||||
with html_path.open("w") as f:
|
with html_path.open("w") as f:
|
||||||
|
@ -172,18 +193,19 @@ def generate_html(config: Config, root_dir: ImageDirectory) -> None:
|
||||||
for pos, image_path in enumerate(album_dir.images):
|
for pos, image_path in enumerate(album_dir.images):
|
||||||
# TODO: If a file with a matching name but .txt or .md, add that as the
|
# TODO: If a file with a matching name but .txt or .md, add that as the
|
||||||
# description for the image
|
# description for the image
|
||||||
|
if image_path.path.stem == "cover":
|
||||||
|
continue
|
||||||
|
|
||||||
html_path = image_path.html_path()
|
html_path = image_path.html_path()
|
||||||
root_path = root_dir.path.relative_to(
|
root_path = root_dir.path.relative_to(html_path.parent, walk_up=True)
|
||||||
html_path.parent, walk_up=True
|
|
||||||
)
|
|
||||||
html_path.parent.mkdir(exist_ok=True)
|
html_path.parent.mkdir(exist_ok=True)
|
||||||
|
|
||||||
prev_image = None
|
prev_image = None
|
||||||
next_image = None
|
next_image = None
|
||||||
if pos != 0:
|
if pos != 0:
|
||||||
prev_image = album_dir.images[pos-1]
|
prev_image = album_dir.images[pos - 1]
|
||||||
if pos < len(album_dir.images) - 1:
|
if pos < len(album_dir.images) - 1:
|
||||||
next_image = album_dir.images[pos+1]
|
next_image = album_dir.images[pos + 1]
|
||||||
|
|
||||||
logger.debug(f"Rendering {html_path}")
|
logger.debug(f"Rendering {html_path}")
|
||||||
with html_path.open("w") as f:
|
with html_path.open("w") as f:
|
||||||
|
|
|
@ -9,19 +9,30 @@
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if not album_dir.is_root %}
|
||||||
|
<h1>{{album_dir.path.name}}</h1>
|
||||||
|
{% endif %}
|
||||||
{% if album_dir.children %}
|
{% if album_dir.children %}
|
||||||
<ul id="album-children">
|
<div id="album-children">
|
||||||
{% for child in album_dir.children %}
|
{% for child in album_dir.children %}
|
||||||
<li class="album">
|
<div class="album">
|
||||||
<a href="{{child.path.name}}/">
|
<a href="{{child.path.name}}/">
|
||||||
|
<div>
|
||||||
|
{% if child.cover_path %}
|
||||||
|
<img src="{{child.path.name}}/slides/{{child.cover_path.thumbnail_filename()}}" />
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
{{child.path.name}}
|
{{child.path.name}}
|
||||||
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if album_dir.images %}
|
{% if album_dir.images %}
|
||||||
|
<h2>Photos</h2>
|
||||||
<div id="album-photos">
|
<div id="album-photos">
|
||||||
{% for image in album_dir.images %}
|
{% for image in album_dir.images %}
|
||||||
<div class="thumbnail">
|
<div class="thumbnail">
|
||||||
|
|
|
@ -25,6 +25,7 @@ body {
|
||||||
|
|
||||||
#content > * {
|
#content > * {
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
|
margin-top: 1em;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
@ -33,6 +34,18 @@ ul {
|
||||||
padding-left: 1.5em;
|
padding-left: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#album-children {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#album-children > * {
|
||||||
|
margin: 1em;
|
||||||
|
padding: 0.75em;
|
||||||
|
background-color: lightgrey;
|
||||||
|
}
|
||||||
|
|
||||||
#album-photos {
|
#album-photos {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
Loading…
Add table
Reference in a new issue