Skip to content

Instantly share code, notes, and snippets.

@goldhand
Last active March 4, 2016 23:45
Show Gist options
  • Select an option

  • Save goldhand/047790b420be4e778103 to your computer and use it in GitHub Desktop.

Select an option

Save goldhand/047790b420be4e778103 to your computer and use it in GitHub Desktop.
Generate then render a series of imgages that incrementally increase in quality. This is targeted towards large image files like hero images that take a long time to load.
<html>
<img class="lowq"
data-src="/static/orginal-img.png"
data-lowq_path='/static/lowq_imgs/' data-qualities="5,10,15,20,25,30,35,50,60,70">
<script src="/main.js"></script>
</html>
from PIL import Image
from os import listdir
from os.path import isfile, join
import imghdr
IMG_QUALITIES = [5, 10, 15, 20, 25, 30, 35, 50, 60, 70]
def list_files(dir_path):
'''
list files in a dir and join name to path
'''
return [join(dir_path, f) for f in listdir(dir_path) if isfile(join(dir_path, f))]
def lowq_copies(img_file_path, qualities, output_dir=None):
'''
make copies of img for qualties
'''
img = Image.open(img_file_path)
og_img_path = img_file_path.split('/')[:-1]
og_img_name = img_file_path.split('/')[-1]
if not output_dir:
output_dir = og_img_path
new_filename = og_img_name.split('.')[:-1]
new_filename.append('.jpg') # image type should be jpg
new_filename.insert(0, '_lowq_{{quality}}__') # set prefix
new_filename.insert(0, output_dir) # prepend output directory
new_filename = ''.join(new_filename)
# result is _lowq_<quality>__<filename>.jpg
new_imgs = []
for q in qualities:
imgname = new_filename.replace('{{quality}}', str(q))
img.save(imgname, format='JPEG', quality=q, optimize=True)
new_imgs.append(imgname)
return new_imgs
def lowq_dir(dir_path, qualities=IMG_QUALITIES, output_dir=None):
'''
makes copies of all images in a dir
'''
imgs = filter(imghdr.what, list_files(dir_path))
return map(lambda img: {
'og': img,
'copies': lowq_copies(img, qualities, output_dir)
}, imgs)
const lowqName = (fname, quality) => `_lowq_${quality}__${fname}.jpg`;
function lowqLoader(elem, arr) {
// loads each image in the array on the same element
if (arr.length) {
elem.setAttribute('src', arr.shift());
elem.onload = function() {lowqLoader(elem, arr)};
} else {
elem.onload = undefined;
elem.setAttribute('src', elem.dataset.src);
};
}
function extractConfig(elem) {
// get all the variables from the element dataset for lowqLoader
let
{src, lowq_path, qualities} = elem.dataset,
fname = src.split('/').pop();
fname = fname.substr(0, fname.lastIndexOf('.'));
qualities = qualities.split(',');
return {
lowq_path,
fname,
qualities
};
}
export function lowqOnDOMLoad(elems) {
// run once on dom loaded event
for (let i = elems.length - 1; i >= 0; i--) {
let {lowq_path, fname, qualities} = extractConfig(elems[i]),
firstSrc = `${lowq_path}${lowqName(fname, qualities[0])}`;
elems[i].setAttribute('src', firstSrc);
}
}
export default function main(elems) {
// run after window loaded
for (let i = elems.length - 1; i >= 0; i--) {
let
elem = elems[i],
{lowq_path, fname, qualities} = extractConfig(elem),
lowq_array = qualities.map(q => `${lowq_path}${lowqName(fname, q)}`);
lowqLoader(elem, lowq_array);
}
}
/*
* Main project javascript
*/
import $ from 'jquery';
import lowqImgLoader, {lowqOnDOMLoad, } from './modules/lowqImgLoader';
let lowqElems;
$(document).ready(function() {
lowqElems = document.querySelectorAll('.lowq');
lowqOnDOMLoad(lowqElems);
});
$(window).on("load", () => {
// All images and DOM loaded
lowqImgLoader(lowqElems);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment