Skip to content

Instantly share code, notes, and snippets.

@pklaus
Last active December 26, 2020 16:17
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save pklaus/5a0b8dfbc97a8dd5f9aadf0da6393aa1 to your computer and use it in GitHub Desktop.
Save pklaus/5a0b8dfbc97a8dd5f9aadf0da6393aa1 to your computer and use it in GitHub Desktop.
pic_serve - A very minimal image web server written in Python using bottle.py. Start by providing on the command line a folder containing albums (subfolders) of images to view. Use left right arrow to navigate pictures, up arrow key to go to a different album (randomly).
#!/usr/bin/env python
import sys, random, glob, os
from bottle import get, run, static_file, redirect, response
PAGE = """
<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<title>pic_serve</title>
</head>
<body style="background-color:#333; color:#eee;">
<div style="position:fixed !important; position:absolute; top:0; right:0; bottom:0; left:0;" align="center" valign="center">
<img src="{this_src}" style="max-height:100%; max-width:100%; height:100%; image-orientation:from-image;" />
</div>
<div style="position:fixed !important; position:absolute; top:0; right:0; bottom:0; left:0;text-align:right;">
<b>{album}</b> {picture}/{len_pictures}
</div>
<script>
window.addEventListener("keydown", dealWithKeyboard, false);
function dealWithKeyboard(e) {{
switch(e.keyCode) {{
case 37:
// left key pressed
window.location = "{prev_href}";
break;
case 38:
// up key pressed
window.location = "{random_href}";
break;
case 39:
// right key pressed
window.location = "{next_href}";
break;
case 40:
// down key pressed
break;
}}
}}
function preloadImage(url)
{{
var img=new Image();
img.src=url;
}}
preloadImage("{next_src}");
</script>
</body>
</html>
"""
os.chdir(sys.argv[1])
subfolders = glob.glob('*')
PICTURES = {}
def find_case_insensitve(glob_expr, extensions):
for filename in glob.glob(glob_expr):
base, ext = os.path.splitext(filename)
if ext.lower() in extensions:
yield filename
def glob_pictures(glob_expr):
return list(find_case_insensitve(glob_expr, ['.jpeg', '.png', '.jpg']))
def get_cached_pictures(subfolder):
global PICTURES
if subfolder not in PICTURES:
PICTURES[subfolder] = glob_pictures(subfolder + '/*')
return PICTURES[subfolder]
@get('/')
def index():
redirect('/album/%d' % random.randint(0, len(subfolders)))
@get('/album/<album:int>')
def album(album):
pictures = get_cached_pictures(subfolders[album])
if len(pictures) == 0: redirect('/')
redirect('/picture/%d/%d' % (album, random.randint(0, len(pictures))))
@get('/picture/<album:int>/<picture:int>')
def picture(album, picture):
pictures = get_cached_pictures(subfolders[album])
if len(pictures) == 0: redirect('/')
pic = pictures[picture]
this_src = '/pic/%d/%d' % (album, picture)
next_src = '/pic/%d/%d' % (album, (picture + 1) % len(pictures))
prev_href = '/picture/%d/%d' % (album, (picture - 1) % len(pictures))
next_href = '/picture/%d/%d' % (album, (picture + 1) % len(pictures))
random_href = '/album/%d' % random.randint(0, len(subfolders))
return PAGE.format(this_src=this_src, next_src=next_src, prev_href=prev_href, next_href=next_href, random_href=random_href, title=pic, album=subfolders[album], picture=picture+1, len_pictures=len(pictures))
@get('/pic/<album:int>/<picture:int>')
def pic(album, picture):
pictures = get_cached_pictures(subfolders[album])
fname = pictures[picture]
response = static_file(fname, root='.')
response.set_header("Cache-Control", "public, max-age=604800")
return response
run(debug=False)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment