Last active
September 21, 2017 14:44
-
-
Save david-batranu/fc9d877e2fd0e8bfdc39c93924b4b6b3 to your computer and use it in GitHub Desktop.
progressive-image-loader-helper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Progressive images | |
| window.loadProgressive = (function(){ | |
| function fetchAndUpdateTarget(target, url, doneClass) { | |
| var img = new Image(); | |
| img.onload = function() { | |
| if (target.tagName === 'IMG') { | |
| target.src = url; | |
| } | |
| else { | |
| target.style.backgroundImage = "url(" + url + ")"; | |
| } | |
| } | |
| img.src = url; | |
| } | |
| function run(target) { | |
| var bigURL = target.getAttribute('data-bigURL'); | |
| return bigURL ? fetchAndUpdateTarget(target, bigURL) : null; | |
| } | |
| return run; | |
| })(); | |
| // either leave this in or ... | |
| window.addEventListener('load', function(){ | |
| var SELECTOR = '[data-role="progressive-image"]'; | |
| var targets = document.querySelectorAll(SELECTOR); | |
| [].slice.call(targets).forEach(loadProgressive); | |
| }) | |
| // ... include the script as the last thing in the page and do | |
| // var SELECTOR = '[data-role="progressive-image"]'; | |
| // var targets = document.querySelectorAll(SELECTOR); | |
| // [].slice.call(targets).forEach(loadProgressive); | |
| // OR, call window.loadProgressive(elem) as desired. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #! /usr/bin/env python | |
| import io | |
| import sys | |
| import base64 | |
| from urllib.parse import quote | |
| from PIL import Image | |
| REDUCE_TO = 0.05 | |
| SVG_BLUR = """ | |
| <svg xmlns="http://www.w3.org/2000/svg" | |
| xmlns:xlink="http://www.w3.org/1999/xlink" | |
| width="{width}" height="{height}" | |
| viewBox="0 0 {width} {height}"> | |
| <filter | |
| id="blur" | |
| filterUnits="userSpaceOnUse" | |
| color-interpolation-filters="sRGB"> | |
| <feGaussianBlur stdDeviation="20 20" edgeMode="duplicate" /> | |
| <feComponentTransfer> | |
| <feFuncA type="discrete" tableValues="1 1" /> | |
| </feComponentTransfer> | |
| </filter> | |
| <image filter="url(#blur)" | |
| xlink:href="{b64_url}" | |
| x="0" y="0" | |
| height="100%" width="100%"/> | |
| </svg> | |
| """ | |
| def to_b64(thumb): | |
| return base64.b64encode(thumb.getvalue()).decode('utf-8') | |
| def get_thumb(image): | |
| dim = tuple(map(lambda dim: dim * REDUCE_TO, (image.width, image.height))) | |
| out = io.BytesIO() | |
| image.thumbnail(dim) | |
| image.save(out, 'PNG') | |
| return out | |
| def run(image): | |
| # shring the image | |
| thumb = get_thumb(image.copy()) | |
| # convert to data url | |
| b64_url = 'data:image/png;base64,{}'.format(to_b64(thumb)) | |
| # create svg at original dimensions, using the shrinked image data url | |
| svg = SVG_BLUR.format( | |
| width=image.width, | |
| height=image.height, | |
| b64_url=b64_url | |
| ).strip() | |
| return 'data:image/svg+xml;charset=utf-8,{}'.format(quote(svg)) | |
| def console(filename): | |
| """ Pass in an image filename. The output will be an encoded svg data url. | |
| Use the given url as such: | |
| <html><head> | |
| <style> | |
| .progressive-image { | |
| background-size: cover; | |
| background-image: url(DATA_URL); | |
| } | |
| </style></head> | |
| <body> | |
| <div class="progressive-image" | |
| data-bigURL="URL_TO_BIG_IMAGE" | |
| data-role="progressive-image"></div> | |
| <script> | |
| window.loadProgressive = (function(){ | |
| function fetchAndUpdateTarget(target, url, doneClass) { | |
| var img = new Image(); | |
| if (target.tagName === 'IMG') { | |
| target.src = url; | |
| } | |
| else { | |
| target.style.backgroundImage = "url(" + url + ")"; | |
| } | |
| img.src = url; | |
| } | |
| function run(target) { | |
| var bigURL = target.getAttribute('data-bigURL'); | |
| return bigURL ? fetchAndUpdateTarget(target, bigURL) : null; | |
| } | |
| return run; | |
| })(); | |
| window.addEventListener('DOMContentLoaded', function(){ | |
| var SELECTOR = '[data-role="progressive-image"]'; | |
| var targets = document.querySelectorAll(SELECTOR); | |
| [].slice.call(targets).forEach(loadProgressive); | |
| }) | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| return run(Image.open(filename)) | |
| if __name__ == '__main__': | |
| if len(sys.argv) > 1: | |
| print(console(sys.argv[1])) | |
| else: | |
| print(console.__doc__) |
Author
Author
Requires Python 3 and Pillow.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Inspired by the great tutorial: https://css-tricks.com/the-blur-up-technique-for-loading-background-images/ and the mentioned SVG encoder: https://codepen.io/yoksel/details/JDqvs/