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 |