backend: use webp for thumbnails and cache them
continuous-integration/drone/push Build is passing Details

master
Simon Bruder 2019-07-19 15:50:04 +00:00
parent d1da8cd9e2
commit 9800befe37
No known key found for this signature in database
GPG Key ID: 6F03E0000CC5B62F
5 changed files with 39 additions and 15 deletions

View File

@ -27,11 +27,13 @@ COPY --from=requirements /usr/src/app/requirements.txt .
RUN apk add --no-cache --virtual .deps \
build-base \
libjpeg-turbo-dev \
libwebp-dev \
zlib-dev \
&& pip install -r requirements.txt \
&& apk del .deps \
&& apk add --no-cache \
libjpeg-turbo
libjpeg-turbo \
libwebp
COPY --from=frontend /usr/src/app/frontend/dist/ frontend/dist

View File

@ -10,6 +10,7 @@ Flask = "*"
pillow = "*"
flask-cors = "*"
gunicorn = "*"
flask-caching = "*"
[requires]
python_version = "3.7"

22
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "6bf198e4fcc5777632eb0d839a8259ef2fc737c6df23cbe2923d0d4593ab06e4"
"sha256": "92afeeaf4d754a31e04e294f6974bd9616eb0f388ce3d977ae235f3d49fa2eae"
},
"pipfile-spec": 6,
"requires": {
@ -25,11 +25,19 @@
},
"flask": {
"hashes": [
"sha256:a31adc27de06034c657a8dc091cc5fcb0227f2474798409bff0e9674de31a026",
"sha256:b5ae63812021cb04174fcff05d560a98387a44d9cccd4652a2bfa131ba4e4c9b"
"sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52",
"sha256:45eb5a6fd193d6cf7e0cf5d8a5b31f83d5faae0293695626f539a823e93b13f6"
],
"index": "pypi",
"version": "==1.1.0"
"version": "==1.1.1"
},
"flask-caching": {
"hashes": [
"sha256:52e236cbc836c41a5ced0c0a67b48ad180c9e2b5cb69e881089bba766db5569e",
"sha256:b0daabd5249bebfbae3da4c22987bac22047fc8b18ea2716c4fc63d57d218946"
],
"index": "pypi",
"version": "==1.7.2"
},
"flask-cors": {
"hashes": [
@ -135,10 +143,10 @@
},
"werkzeug": {
"hashes": [
"sha256:865856ebb55c4dcd0630cdd8f3331a1847a819dda7e8c750d3db6f2aa6c0209c",
"sha256:a0b915f0815982fb2a09161cb8f31708052d0951c3ba433ccc5e1aa276507ca6"
"sha256:87ae4e5b5366da2347eb3116c0e6c681a0e939a33b2805e2c0cbd282664932c4",
"sha256:a13b74dd3c45f758d4ebdb224be8f1ab8ef58b3c0ffc1783a8c7d9f4f50227e6"
],
"version": "==0.15.4"
"version": "==0.15.5"
}
},
"develop": {}

View File

@ -8,6 +8,8 @@ import werkzeug.exceptions as exceptions
mimetypes['.webp'] = 'image/webp'
thumbnail_cache = {}
# https://docs.python.org/3.7/library/sqlite3.html#sqlite3.Connection.row_factory
def dict_factory(cursor, row):
@ -18,12 +20,23 @@ def dict_factory(cursor, row):
def generate_thumbnail(filepath):
image = Image.open(filepath)
image.thumbnail((512, 512))
thumbnail = BytesIO()
image.save(thumbnail, format='jpeg')
if filepath in thumbnail_cache:
thumbnail = BytesIO()
thumbnail.write(thumbnail_cache[filepath])
else:
image = Image.open(filepath)
image.thumbnail((512, 512))
thumbnail = BytesIO()
image.save(thumbnail, 'webp')
thumbnail.seek(0)
thumbnail_cache[filepath] = thumbnail.read()
thumbnail.seek(0)
return thumbnail
return {
'data': thumbnail,
'mimetype': 'image/webp'
}
class CalibreDB:

View File

@ -51,7 +51,7 @@ def get_series_cover(series_id):
@app.route('/api/series/<int:series_id>/cover/thumbnail')
def get_series_cover_thumbnail(series_id):
thumbnail = db.get_series_cover_thumbnail(series_id)
return send_file_with_etag(thumbnail, mimetype='image/jpeg')
return send_file_with_etag(thumbnail['data'], mimetype=thumbnail['mimetype'])
@app.route('/api/series/<int:series_id>')
@ -67,7 +67,7 @@ def get_volume_cover(volume_id):
@app.route('/api/volume/<int:volume_id>/cover/thumbnail')
def get_volume_cover_thumbnail(volume_id):
thumbnail = db.get_volume_cover_thumbnail(volume_id)
return send_file_with_etag(thumbnail, mimetype='image/jpeg')
return send_file_with_etag(thumbnail['data'], mimetype=thumbnail['mimetype'])
@app.route('/api/volume/<int:volume_id>')