Skip to content

Instantly share code, notes, and snippets.

@mariocesar
Last active December 12, 2015 08:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mariocesar/4747598 to your computer and use it in GitHub Desktop.
Save mariocesar/4747598 to your computer and use it in GitHub Desktop.
Django custom storage backend that applies optimizations for png and jpg images
from django.contrib.staticfiles.storage import CachedFilesMixin, StaticFilesStorage
from pipeline.storage import PipelineMixin
def coroutine(func):
def start(*args, **kwargs):
cr = func(*args, **kwargs)
cr.next()
return cr
return start
class PipelineStorage(PipelineMixin, CachedFilesMixin, StaticFilesStorage):
def post_process(self, paths, dry_run=False, **options):
import shutil
import re
from fabric.api import local
@coroutine
def optimize(targets):
while True:
filename = (yield)
# Do not optimize files that are less than 5Kb
if 1024 * 4 < self.size(filename):
for target in targets:
target.send(filename)
@coroutine
def grep(pattern, target, inverse=False):
pattern = re.compile(pattern)
while True:
filename = (yield)
if pattern.match(filename):
print filename
target.send(filename)
@coroutine
def pngcrush():
while True:
filename = (yield)
local('pngcrush -q '
'-rem gAMA -rem cHRM '
'-rem iCCP -rem sRGB '
'-rem alla -rem text '
'-reduce -brute "%s" "%s"' % (
self.path(filename),
'%s.min' % self.path(filename)
)
)
self.delete(filename)
shutil.move('%s.min' % self.path(filename), self.path(filename))
@coroutine
def jpegtran():
while True:
filename = (yield)
local('jpegtran '
'-outfile "%s" '
'-optimize '
'-copy none "%s"' % (
'%s.min' % self.path(filename),
self.path(filename)
)
)
self.delete(filename)
shutil.move('%s.min' % self.path(filename), self.path(filename))
def process(post_paths, target):
for old_path, new_path, processed in post_paths:
target.send(new_path)
yield (old_path, new_path, processed)
self.delete(old_path)
target.close()
post_paths = list(super(PipelineStorage, self).post_process(paths, dry_run, **options))
new_paths = (process(post_paths, optimize([
grep('.+\.png$', pngcrush()),
grep('.+\.jpg$', jpegtran()),
])
))
for old_path, new_path, processed in new_paths:
new_path = self.hashed_name(new_path)
yield (old_path, new_path, processed)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment