[Pkg-mozext-commits] [adblock-plus] 09/41: Issue 1897 - Compress auto-generated images with pngout

David Prévot taffit at moszumanska.debian.org
Wed Mar 18 18:21:37 UTC 2015


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository adblock-plus.

commit 992c2cf5c54b5f94c633b7c058f75627c317d3a7
Author: Sebastian Noack <sebastian at adblockplus.org>
Date:   Wed Jan 28 20:10:49 2015 +0100

    Issue 1897 - Compress auto-generated images with pngout
---
 imageCompression.py | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 imageConversion.py  | 12 ++++----
 2 files changed, 89 insertions(+), 5 deletions(-)

diff --git a/imageCompression.py b/imageCompression.py
new file mode 100644
index 0000000..6ffe46a
--- /dev/null
+++ b/imageCompression.py
@@ -0,0 +1,82 @@
+# coding: utf-8
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import os
+import subprocess
+import threading
+import errno
+import logging
+from StringIO import StringIO
+
+try:
+  from PIL import Image
+except ImportError:
+  import Image
+
+use_pngout = True
+
+class Pngout:
+  def __init__(self, image):
+    args = ['pngout', '-', '-', '-q']
+
+    # Preserve mode for grayscale images. pngout tends to convert
+    # everyting to palette. However, the toolbar icons for Safari
+    # require the grayscale+alpha mode. Moreover, pngout seems to
+    # generate smaller files when forced to preserve grayscale mode.
+    if image.mode == 'LA' and any(px < 0xff for px in image.split()[1].getdata()):
+      args.append('-c4')  # grayscale+alpha
+    elif Image.getmodebase(image.mode) == 'L':
+      args.append('-c0')  # grayscale
+
+    self._pngout = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+
+    # Writing will block when the buffer is full until we read more data
+    # from the output. Reading the output will block when the input isn't
+    # complete yet. So we have to use threads to do both at the same time.
+    self._thread = threading.Thread(target=self._run_thread, args=(image,))
+    self._thread.daemon = True
+    self._thread.start()
+
+  # This is supposed to be a file-like object, reading the compressed PNG file.
+  # So proxy methods like read() to the stdout of the underlying subprocess.
+  def __getattr__(self, name):
+    return getattr(self._pngout.stdout, name)
+
+  def _run_thread(self, image):
+    image.save(self._pngout.stdin, 'PNG')
+    self._pngout.stdin.close()
+
+  def close(self):
+    self._thread.join()
+    self._pngout.stdout.close()
+    self._pngout.wait()
+
+class ImageCompressor:
+  use_pngout = True
+
+  def make_uncompressed_file(self, image, filename):
+    file = StringIO()
+    file.name = filename  # Set the 'name' attribute, so that PIL can determine
+                          # the correct image type based on the file extension
+    image.save(file)
+    file.seek(0)
+
+    return file
+
+  def make_file(self, image, filename):
+    if self.use_pngout and os.path.splitext(filename)[1].lower() == '.png':
+      try:
+        return Pngout(image)
+      except OSError, e:
+        if e.errno != errno.ENOENT:
+          raise
+
+        logging.warning("Couldn't find 'pngout', can't compress images")
+        self.use_pngout = False
+
+    return self.make_uncompressed_file(image, filename)
+
+image_to_file = ImageCompressor().make_file
diff --git a/imageConversion.py b/imageConversion.py
index e56dae7..021a762 100644
--- a/imageConversion.py
+++ b/imageConversion.py
@@ -6,7 +6,6 @@
 
 import os
 import re
-from StringIO import StringIO
 
 try:
   from PIL import Image
@@ -15,6 +14,8 @@ except ImportError:
   import Image
   import ImageOps
 
+from imageCompression import image_to_file
+
 def get_alpha(image):
   if image.mode in ('RGBA', 'LA'):
     return image.split()[image.getbands().index('A')]
@@ -95,7 +96,8 @@ def convertImages(params, files):
       args = re.split(r'\s*,\s*', args) if args else ()
       image = globals()['filter_' + filter](image, baseDir, *args)
 
-    f = StringIO()
-    f.name = filename
-    image.save(f)
-    files[filename] = f.getvalue()
+    file = image_to_file(image, filename)
+    try:
+      files[filename] = file.read()
+    finally:
+      file.close()

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/adblock-plus.git



More information about the Pkg-mozext-commits mailing list