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='::')
@Marventex
Copy link

How can i put images? how can i make this server running on the app.. its been hours and still i dont have the solution.. please someone help me..

@musakhan666
Copy link

same here i also got stuck in that part of creating server

@Marventex
Copy link

Does yours crashes too when tapping on the add to cart button or going to the shopping cart screen?

@Marventex
Copy link

"The images should be named with the corresponding product ID, and jpg format is preferred. "
i really dont have any idea how to implement this..

@musakhan666
Copy link

same here it does crash

@Marventex
Copy link

do you think the images have something to do with it? the crashing ?
do you think if we can put images the app wont crash anymore?

@Marventex
Copy link

do you have any facebook account or email? so we can have a decent talk.

@kingsofcoms
Copy link

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: inline-block;
margin: 3em 14px;
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('.png'):
            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(host="127.0.0.1", port="3000")

install flask, pillow
Save as app.py
Run

python app.py

@mustafa-qamaruddin
Copy link

Very helpful, thank you
I only had to change StringIO to BytesIO

@daschkin
Copy link

Hello,
thank you a lot for this useful flask-app. I have a question:
If I run the app, then images in the same directory as app.py-file are displayed on website without any problems. If I change a directory to other path (not a subpath of current project), the app can lists the files, but doesn't display it. Can it be a rights issue? Or can you give me a hint, how I can solve this issue?
I thank you in advance for your help!

@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