flask image gallery
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

131 lines
3.2 KiB

import os
import re
from PIL import Image
from flask import (Blueprint, current_app, redirect, render_template, url_for,
send_from_directory, Response)
bp = Blueprint('default_routes', __name__)
VALID_CHARS = re.compile(r"^[a-zA-Z0-9_\-\.]+$")
IMAGE_DIR = 'images'
#
# Routes
#
@bp.route('/')
def index() -> Response:
image_dir = getImageDir()
albums = []
entries = sorted(os.listdir(image_dir))
for e in entries:
albums.append(getAlbumDetails(entries, e))
return render_template('index.j2', albums = albums)
@bp.route('/album/<path>')
def album(path:str = '') -> Response:
image_dir = getImageDir()
album_dir = joinPath(image_dir, path)
images = []
if not validateDir(image_dir, path):
return redirect(url_for('.index'))
for entry in os.scandir(album_dir):
if entry.is_file():
createThumbnail(entry, path)
images.append(entry.name)
return render_template('album.j2',
img_root = f'/image/{path}/',
album = path,
images = sorted(images)
)
@bp.route('/image/<path>/<img>')
def image(path:str, img:str) -> Response:
album_dir = joinPath(getImageDir(), path)
return send_from_directory(album_dir, img)
@bp.route('/thumbs/<path>/<img>')
def thumbs(path:str, img:str) -> Response:
base_dir = joinPath(current_app.instance_path, 'thumbnails')
album_dir = joinPath(base_dir, path)
return send_from_directory(album_dir, img)
#
# Helpers
#
def getImageDir() -> os.PathLike:
return joinPath(current_app.instance_path, IMAGE_DIR)
def joinPath(base:os.PathLike, path:str) -> os.PathLike:
return os.path.join(base, os.path.basename(path))
def validateDir(base:os.PathLike, path:str) -> bool:
if VALID_CHARS.match(path):
path = joinPath(base, path)
if os.path.exists(path) and os.path.isdir(path):
return True
return False
def validateFile(base:os.PathLike, path:str) -> bool:
if VALID_CHARS.match(path) and os.path.exists(joinPath(base, path)):
return True
return False
def getAlbumDetails(dir_list:list, album:str) -> dict:
image_dir = getImageDir()
if not validateDir(image_dir, album):
return None
album_dir = joinPath(image_dir, album)
entries = os.scandir(album_dir)
entries = sorted(os.scandir(album_dir),
key=lambda e: e.name)
if len(entries) > 0:
image = entries[0].name
createThumbnail(entries[0], album)
else:
image = None
return { 'name': album, 'image': image, 'count': len(entries) }
def getImageDetails(entry:os.PathLike) -> dict:
return {
'name': entry.name,
'date': '...',
'dims': '...',
'size': '...'
}
def createThumbnail(image:os.DirEntry, album:str) -> None:
thumb_path = joinPath(current_app.instance_path, 'thumbnails')
thumb_path = joinPath(thumb_path, album)
# NOTE: check for existing thumbnail
if validateFile(thumb_path, image.name):
return
# NOTE: ensure thumbnail album directory exists
try: os.makedirs(thumb_path)
except OSError: pass
with Image.open(image.path) as im:
im.thumbnail([300, 300])
im.save(joinPath(thumb_path, image.name), "JPEG")