| Left: | ||
| Right: |
| LEFT | RIGHT |
|---|---|
| 1 # coding: utf-8 | 1 # coding: utf-8 |
| 2 | 2 |
| 3 # This Source Code Form is subject to the terms of the Mozilla Public | 3 # This Source Code Form is subject to the terms of the Mozilla Public |
| 4 # License, v. 2.0. If a copy of the MPL was not distributed with this | 4 # License, v. 2.0. If a copy of the MPL was not distributed with this |
| 5 # file, You can obtain one at http://mozilla.org/MPL/2.0/. | 5 # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 6 | 6 |
| 7 import os | 7 import os |
| 8 import subprocess | 8 import subprocess |
| 9 import threading | 9 import threading |
| 10 import errno | 10 import errno |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 31 elif Image.getmodebase(image.mode) == 'L': | 31 elif Image.getmodebase(image.mode) == 'L': |
| 32 args.append('-c0') # grayscale | 32 args.append('-c0') # grayscale |
| 33 | 33 |
| 34 self._pngout = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subproce ss.PIPE) | 34 self._pngout = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subproce ss.PIPE) |
| 35 | 35 |
| 36 # Writing will block when the buffer is full until we read more data | 36 # Writing will block when the buffer is full until we read more data |
| 37 # from the output. Reading the output will block when the input isn't | 37 # from the output. Reading the output will block when the input isn't |
| 38 # complete yet. So we have to use threads to do both at the same time. | 38 # complete yet. So we have to use threads to do both at the same time. |
| 39 self._thread = threading.Thread(target=self._run_thread, args=(image,)) | 39 self._thread = threading.Thread(target=self._run_thread, args=(image,)) |
| 40 self._thread.daemon = True | 40 self._thread.daemon = True |
| 41 self._thread.start() | 41 self._thread.start() |
|
Wladimir Palant
2015/02/10 18:47:59
Why not use subprocess.communicate()? The files ar
Sebastian Noack
2015/02/10 19:23:56
So you mean I should save the image into a StringI
Wladimir Palant
2015/02/10 20:49:18
Seems a lot simpler than running a thread IMHO, es
| |
| 42 | 42 |
| 43 # This is supposed to be a file-like object, reading the compressed PNG file. | 43 # This is supposed to be a file-like object, reading the compressed PNG file. |
| 44 # So proxy methods like read() to the stdout of the underlying subprocess. | 44 # So proxy methods like read() to the stdout of the underlying subprocess. |
| 45 def __getattr__(self, name): | 45 def __getattr__(self, name): |
| 46 return getattr(self._pngout.stdout, name) | 46 return getattr(self._pngout.stdout, name) |
| 47 | 47 |
| 48 def _run_thread(self, image): | 48 def _run_thread(self, image): |
| 49 image.save(self._pngout.stdin, 'PNG') | 49 image.save(self._pngout.stdin, 'PNG') |
| 50 self._pngout.stdin.close() | 50 self._pngout.stdin.close() |
| 51 | 51 |
| 52 def close(self): | 52 def close(self): |
| 53 self._thread.join() | 53 self._thread.join() |
| 54 self._pngout.stdout.close() | 54 self._pngout.stdout.close() |
| 55 self._pngout.wait() | 55 self._pngout.wait() |
| 56 | 56 |
| 57 class ImageCompressor: | 57 class ImageCompressor: |
| 58 use_pngout = True | 58 use_pngout = True |
| 59 | 59 |
| 60 def make_uncompressed_file(self, image, filename): | 60 def make_uncompressed_file(self, image, filename): |
| 61 file = StringIO() | 61 file = StringIO() |
| 62 file.name = filename # Set the 'name' attribute, that PIL can determine | 62 file.name = filename # Set the 'name' attribute, so that PIL can determine |
|
kzar
2015/02/10 09:29:54
Nitpick: Comment should read "...so that PIL can..
Sebastian Noack
2015/02/10 09:57:38
Done.
| |
| 63 # the correct image type based on the file extension | 63 # the correct image type based on the file extension |
| 64 image.save(file) | 64 image.save(file) |
| 65 file.seek(0) | 65 file.seek(0) |
| 66 | 66 |
| 67 return file | 67 return file |
| 68 | 68 |
| 69 def make_file(self, image, filename): | 69 def make_file(self, image, filename): |
| 70 if self.use_pngout and os.path.splitext(filename)[1].lower() == '.png': | 70 if self.use_pngout and os.path.splitext(filename)[1].lower() == '.png': |
| 71 try: | 71 try: |
| 72 return Pngout(image) | 72 return Pngout(image) |
| 73 except OSError, e: | 73 except OSError, e: |
| 74 if e.errno != errno.ENOENT: | 74 if e.errno != errno.ENOENT: |
| 75 raise | 75 raise |
| 76 | 76 |
| 77 logging.warning("Couldn't find 'pngout', can't compress images") | 77 logging.warning("Couldn't find 'pngout', can't compress images") |
| 78 self.use_pngout = False | 78 self.use_pngout = False |
| 79 | 79 |
| 80 return self.make_uncompressed_file(image, filename) | 80 return self.make_uncompressed_file(image, filename) |
| 81 | 81 |
| 82 image_to_file = ImageCompressor().make_file | 82 image_to_file = ImageCompressor().make_file |
| LEFT | RIGHT |