Skip to content

Instantly share code, notes, and snippets.

@peterkuma
Created February 10, 2014 14:22
Show Gist options
  • Save peterkuma/8916745 to your computer and use it in GitHub Desktop.
Save peterkuma/8916745 to your computer and use it in GitHub Desktop.
A flask server for serving all JPEG images in a local directory and subdirectories. Uses unveil.js for lazy-loading of images. Thumbnails are created on the fly by PIL.
#!/bin/python
import os
from flask import Flask, Response, request, abort, render_template_string, send_from_directory
import Image
import StringIO
app = Flask(__name__)
WIDTH = 1000
HEIGHT = 800
TEMPLATE = '''
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<style>
body {
margin: 0;
background-color: #333;
}
.image {
display: block;
margin: 2em auto;
background-color: #444;
box-shadow: 0 0 10px rgba(0,0,0,0.3);
}
img {
display: block;
}
</style>
<script src="https://code.jquery.com/jquery-1.10.2.min.js" charset="utf-8"></script>
<script src="http://luis-almeida.github.io/unveil/jquery.unveil.min.js" charset="utf-8"></script>
<script>
$(document).ready(function() {
$('img').unveil(1000);
});
</script>
</head>
<body>
{% for image in images %}
<a class="image" href="{{ image.src }}" style="width: {{ image.width }}px; height: {{ image.height }}px">
<img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="{{ image.src }}?w={{ image.width }}&amp;h={{ image.height }}" width="{{ image.width }}" height="{{ image.height }}" />
</a>
{% endfor %}
</body>
'''
@app.route('/<path:filename>')
def image(filename):
try:
w = int(request.args['w'])
h = int(request.args['h'])
except (KeyError, ValueError):
return send_from_directory('.', filename)
try:
im = Image.open(filename)
im.thumbnail((w, h), Image.ANTIALIAS)
io = StringIO.StringIO()
im.save(io, format='JPEG')
return Response(io.getvalue(), mimetype='image/jpeg')
except IOError:
abort(404)
return send_from_directory('.', filename)
@app.route('/')
def index():
images = []
for root, dirs, files in os.walk('.'):
for filename in [os.path.join(root, name) for name in files]:
if not filename.endswith('.jpg'):
continue
im = Image.open(filename)
w, h = im.size
aspect = 1.0*w/h
if aspect > 1.0*WIDTH/HEIGHT:
width = min(w, WIDTH)
height = width/aspect
else:
height = min(h, HEIGHT)
width = height*aspect
images.append({
'width': int(width),
'height': int(height),
'src': filename
})
return render_template_string(TEMPLATE, **{
'images': images
})
if __name__ == '__main__':
app.run(debug=True, host='::')
@eddie4
Copy link

eddie4 commented Jul 15, 2018

Thanks for this. I had to fix some indent stuff and a thing in the template. Have fun with it.

ps. replace if not filename.endswith('.jpg'): with you're extension

import os
from flask import Flask, Response, request, abort, render_template_string, send_from_directory
from PIL import Image
import StringIO

app = Flask(__name__)

WIDTH = 640
HEIGHT = 360

TEMPLATE = '''
<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <style>
body {
    margin: 0;
    background-color: #333;
}
.image {
    display: block;
    margin: 2em auto;
    background-color: #444;
    box-shadow: 0 0 10px rgba(0,0,0,0.3);
}
img {
    display: block;
}
    </style>
    <script src="https://code.jquery.com/jquery-1.10.2.min.js" charset="utf-8"></script>
    <script src="http://luis-almeida.github.io/unveil/jquery.unveil.min.js" charset="utf-8"></script>
    <script>
$(document).ready(function() {
    $('img').unveil(1000);
});
    </script>
</head>
<body>
    {% for image in images %}
        <a class="image" href="{{ image.src }}" style="width: {{ image.width }}px; height: {{ image.height }}px">
            <img src="{{ image.src }}" data-src="{{ image.src }}?w={{ image.width }}&amp;h={{ image.height }}" width="{{ image.width }}" height="{{ image.height }}" />
        </a>
    {% endfor %}
</body>
'''

@app.route('/<path:filename>')
def image(filename):
    try:
        w = int(request.args['w'])
        h = int(request.args['h'])
    except (KeyError, ValueError):
        return send_from_directory('.', filename)

    try:
        im = Image.open(filename)
        im.thumbnail((w, h), Image.ANTIALIAS)
        io = StringIO.StringIO()
        im.save(io, format='JPEG')
        return Response(io.getvalue(), mimetype='image/jpeg')

    except IOError:
        abort(404)

    return send_from_directory('.', filename)

@app.route('/')
def index():
    images = []
    for root, dirs, files in os.walk('.'):
        files.sort()
        for filename in [os.path.join(root, name) for name in files]:
            if not filename.endswith('.jpg'):
                continue
            im = Image.open(filename)
            w, h = im.size
            aspect = 1.0*w/h
            print filename
            if aspect > 1.0*WIDTH/HEIGHT:
                width = min(w, WIDTH)
                height = width/aspect
            else:
                height = min(h, HEIGHT)
                width = height*aspect
            images.append({
                'width': int(width),
                'height': int(height),
                'src': filename
            })
    return render_template_string(TEMPLATE, **{
        'images': images
    })

if __name__ == '__main__':
    app.run(host="127.0.0.1", port=3000)

@adv-ai-tech
Copy link

Extremely Thanks for the code. I had been trying this for past 6 hours!!

@roman-ku
Copy link

roman-ku commented Jan 1, 2019

After having trouble with all the scripts posted so far I made my own. Python 3.5+ compatible.

Here are the changes I had to make:

  • Change import Image to from PIL import Image
  • Change import StringIO to from io import BytesIO
  • Change io = StringIO.StringIO() to io = BytesIO()
  • Change $('img').unveil(1000); to $('img').unveil();
  • Change <script src="http://luis-almeida.github.io/unveil/jquery.unveil.min.js" charset="utf-8"></script> to <script src="jquery.unveil.js" charset="utf-8"></script>
  • Download the jquery.unveil.js script and place it in the same file as the server.py

You can find the updated code in my gist

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment