diff --git a/Dockerfile b/Dockerfile index e8181a2..f3c09be 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,15 +27,12 @@ COPY --from=requirements /usr/src/app/requirements.txt . RUN apk add --no-cache --virtual .deps \ build-base \ - git \ - libffi-dev \ libjpeg-turbo-dev \ libwebp-dev \ zlib-dev \ && pip install -r requirements.txt \ && apk del .deps \ && apk add --no-cache \ - libffi \ libjpeg-turbo \ libwebp diff --git a/Pipfile b/Pipfile index d5f4025..aa98980 100644 --- a/Pipfile +++ b/Pipfile @@ -11,7 +11,6 @@ pillow = "*" flask-cors = "*" gunicorn = "*" flask-caching = "*" -webp = {editable = true,git = "https://github.com/sbruder/pywebp"} [requires] python_version = "3.7" diff --git a/Pipfile.lock b/Pipfile.lock index 5a20fc0..eff3f1a 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "5a623242219f0ec36e67df9c0caaadf71b39cfd21f5ed070f2766f9df8d3fd4d" + "sha256": "92afeeaf4d754a31e04e294f6974bd9616eb0f388ce3d977ae235f3d49fa2eae" }, "pipfile-spec": 6, "requires": { @@ -16,39 +16,6 @@ ] }, "default": { - "cffi": { - "hashes": [ - "sha256:041c81822e9f84b1d9c401182e174996f0bae9991f33725d059b771744290774", - "sha256:046ef9a22f5d3eed06334d01b1e836977eeef500d9b78e9ef693f9380ad0b83d", - "sha256:066bc4c7895c91812eff46f4b1c285220947d4aa46fa0a2651ff85f2afae9c90", - "sha256:066c7ff148ae33040c01058662d6752fd73fbc8e64787229ea8498c7d7f4041b", - "sha256:2444d0c61f03dcd26dbf7600cf64354376ee579acad77aef459e34efcb438c63", - "sha256:300832850b8f7967e278870c5d51e3819b9aad8f0a2c8dbe39ab11f119237f45", - "sha256:34c77afe85b6b9e967bd8154e3855e847b70ca42043db6ad17f26899a3df1b25", - "sha256:46de5fa00f7ac09f020729148ff632819649b3e05a007d286242c4882f7b1dc3", - "sha256:4aa8ee7ba27c472d429b980c51e714a24f47ca296d53f4d7868075b175866f4b", - "sha256:4d0004eb4351e35ed950c14c11e734182591465a33e960a4ab5e8d4f04d72647", - "sha256:4e3d3f31a1e202b0f5a35ba3bc4eb41e2fc2b11c1eff38b362de710bcffb5016", - "sha256:50bec6d35e6b1aaeb17f7c4e2b9374ebf95a8975d57863546fa83e8d31bdb8c4", - "sha256:55cad9a6df1e2a1d62063f79d0881a414a906a6962bc160ac968cc03ed3efcfb", - "sha256:5662ad4e4e84f1eaa8efce5da695c5d2e229c563f9d5ce5b0113f71321bcf753", - "sha256:59b4dc008f98fc6ee2bb4fd7fc786a8d70000d058c2bbe2698275bc53a8d3fa7", - "sha256:73e1ffefe05e4ccd7bcea61af76f36077b914f92b76f95ccf00b0c1b9186f3f9", - "sha256:a1f0fd46eba2d71ce1589f7e50a9e2ffaeb739fb2c11e8192aa2b45d5f6cc41f", - "sha256:a2e85dc204556657661051ff4bab75a84e968669765c8a2cd425918699c3d0e8", - "sha256:a5457d47dfff24882a21492e5815f891c0ca35fefae8aa742c6c263dac16ef1f", - "sha256:a8dccd61d52a8dae4a825cdbb7735da530179fea472903eb871a5513b5abbfdc", - "sha256:ae61af521ed676cf16ae94f30fe202781a38d7178b6b4ab622e4eec8cefaff42", - "sha256:b012a5edb48288f77a63dba0840c92d0504aa215612da4541b7b42d849bc83a3", - "sha256:d2c5cfa536227f57f97c92ac30c8109688ace8fa4ac086d19d0af47d134e2909", - "sha256:d42b5796e20aacc9d15e66befb7a345454eef794fdb0737d1af593447c6c8f45", - "sha256:dee54f5d30d775f525894d67b1495625dd9322945e7fee00731952e0368ff42d", - "sha256:e070535507bd6aa07124258171be2ee8dfc19119c28ca94c9dfb7efd23564512", - "sha256:e1ff2748c84d97b065cc95429814cdba39bcbd77c9c85c89344b317dc0d9cbff", - "sha256:ed851c75d1e0e043cbf5ca9a8e1b13c4c90f3fbd863dacb01c0808e2b5204201" - ], - "version": "==1.12.3" - }, "click": { "hashes": [ "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", @@ -135,27 +102,6 @@ ], "version": "==1.1.1" }, - "numpy": { - "hashes": [ - "sha256:03e311b0a4c9f5755da7d52161280c6a78406c7be5c5cc7facfbcebb641efb7e", - "sha256:0cdd229a53d2720d21175012ab0599665f8c9588b3b8ffa6095dd7b90f0691dd", - "sha256:312bb18e95218bedc3563f26fcc9c1c6bfaaf9d453d15942c0839acdd7e4c473", - "sha256:464b1c48baf49e8505b1bb754c47a013d2c305c5b14269b5c85ea0625b6a988a", - "sha256:5adfde7bd3ee4864536e230bcab1c673f866736698724d5d28c11a4d63672658", - "sha256:7724e9e31ee72389d522b88c0d4201f24edc34277999701ccd4a5392e7d8af61", - "sha256:8d36f7c53ae741e23f54793ffefb2912340b800476eb0a831c6eb602e204c5c4", - "sha256:910d2272403c2ea8a52d9159827dc9f7c27fb4b263749dca884e2e4a8af3b302", - "sha256:951fefe2fb73f84c620bec4e001e80a80ddaa1b84dce244ded7f1e0cbe0ed34a", - "sha256:9588c6b4157f493edeb9378788dcd02cb9e6a6aeaa518b511a1c79d06cbd8094", - "sha256:9ce8300950f2f1d29d0e49c28ebfff0d2f1e2a7444830fbb0b913c7c08f31511", - "sha256:be39cca66cc6806652da97103605c7b65ee4442c638f04ff064a7efd9a81d50a", - "sha256:c3ab2d835b95ccb59d11dfcd56eb0480daea57cdf95d686d22eff35584bc4554", - "sha256:eb0fc4a492cb896346c9e2c7a22eae3e766d407df3eb20f4ce027f23f76e4c54", - "sha256:ec0c56eae6cee6299f41e780a0280318a93db519bbb2906103c43f3e2be1206c", - "sha256:f4e4612de60a4f1c4d06c8c2857cdcb2b8b5289189a12053f37d3f41f06c60d0" - ], - "version": "==1.17.0" - }, "pillow": { "hashes": [ "sha256:0804f77cb1e9b6dbd37601cee11283bba39a8d44b9ddb053400c58e0c0d7d9de", @@ -188,12 +134,6 @@ "index": "pypi", "version": "==6.1.0" }, - "pycparser": { - "hashes": [ - "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3" - ], - "version": "==2.19" - }, "six": { "hashes": [ "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", @@ -201,11 +141,6 @@ ], "version": "==1.12.0" }, - "webp": { - "editable": true, - "git": "https://github.com/sbruder/pywebp", - "ref": "39e39c0e1071985b7944651cc13ec11834751ce3" - }, "werkzeug": { "hashes": [ "sha256:87ae4e5b5366da2347eb3116c0e6c681a0e939a33b2805e2c0cbd282664932c4", diff --git a/backend.py b/backend.py index 9860bb9..e08ec47 100644 --- a/backend.py +++ b/backend.py @@ -6,7 +6,6 @@ from zipfile import ZipFile from zlib import crc32 import os.path import sqlite3 -import webp import werkzeug.exceptions as exceptions mimetypes['.webp'] = 'image/webp' @@ -52,24 +51,25 @@ def generate_thumbnail(filepath): class CalibreDB: - def __init__(self, path='metadata.db', enable_webp=True, webp_quality=80, webp_size=2048): + def __init__(self, path='metadata.db', enable_webp=True, webp_quality=80, webp_method=0, webp_size=2048): self.database_path = f'file:{path}?mode=ro' self.webp = enable_webp if self.webp is True: - if webp_quality == 101: - lossless = True - webp_quality = 100 + # lossy: 0-100 (used as quality) + # lossless: 101-201 (101 subtracted and used as quality) + if webp_quality > 100: + webp_lossless = True + webp_quality = webp_quality - 101 else: - lossless = False + webp_lossless = False - self.webp_config = webp.WebPConfig.new( - preset=webp.WebPPreset.DRAWING, - quality=webp_quality, - lossless=lossless - ) - - self.webp_size = webp_size + self.webp_config = { + 'quality': webp_quality, + 'method': webp_method, + 'lossless': webp_lossless, + 'size': webp_size + } def create_cursor(self): conn = sqlite3.connect(self.database_path, uri=True) @@ -241,10 +241,17 @@ class CalibreDB: except FileNotFoundError: with volume.open(page_filename) as orig_page_data: image = Image.open(orig_page_data) - image.thumbnail((self.webp_size, self.webp_size)) - image = image.convert('RGB') - image = webp.WebPPicture.from_pil(image) - page_data = BytesIO(image.encode(self.webp_config).buffer()) + image.thumbnail(tuple([self.webp_config['size']] * 2)) + page_data = BytesIO() + image.save( + page_data, + format='webp', + save_all=True, # + append_images=[image], # https://github.com/python-pillow/Pillow/issues/4042 + quality=self.webp_config['quality'], + method=self.webp_config['method'], + lossless=self.webp_config['lossless'] + ) disk_cache.set(f'{volume_id}-{page_number}', page_data) page_data.seek(0)