diff --git a/src/calibre/ebooks/oeb/polish/images.py b/src/calibre/ebooks/oeb/polish/images.py index 1f31722d4f..c1165850cb 100644 --- a/src/calibre/ebooks/oeb/polish/images.py +++ b/src/calibre/ebooks/oeb/polish/images.py @@ -16,9 +16,9 @@ class Worker(Thread): daemon = True - def __init__(self, abort, name, queue, results, container, jpeg_quality, progress_callback): + def __init__(self, abort, name, queue, results, jpeg_quality, progress_callback): Thread.__init__(self, name=name) - self.queue, self.results, self.container = queue, results, container + self.queue, self.results = queue, results self.progress_callback = progress_callback self.jpeg_quality = jpeg_quality self.abort = abort @@ -27,11 +27,11 @@ class Worker(Thread): def run(self): while not self.abort.is_set(): try: - name = self.queue.get_nowait() + name, path, mt = self.queue.get_nowait() except Empty: break try: - self.compress(name) + self.compress(name, path, mt) except Exception: import traceback self.results[name] = (False, traceback.format_exc()) @@ -43,16 +43,14 @@ class Worker(Thread): traceback.print_exc() self.queue.task_done() - def compress(self, name): + def compress(self, name, path, mime_type): from calibre.utils.img import optimize_png, optimize_jpeg, encode_jpeg - mt = self.container.mime_map[name] - if 'png' in mt: + if 'png' in mime_type: func = optimize_png elif self.jpeg_quality is None: func = optimize_jpeg else: func = partial(encode_jpeg, quality=self.jpeg_quality) - path = self.container.get_file_path_for_processing(name) before = os.path.getsize(path) with lopen(path, 'rb') as f: old_data = f.read() @@ -80,17 +78,24 @@ def compress_images(container, report=None, names=None, jpeg_quality=None, progr results = {} queue = Queue() abort = Event() - for name in images: - queue.put(name) + seen = set() + num_to_process = 0 + for name in sorted(images): + path = os.path.normcase(os.path.abspath(container.get_file_path_for_processing(name))) + if path not in seen: + num_to_process += 1 + queue.put((name, path, container.mime_map[name])) + seen.add(path) def pc(name): - keep_going = progress_callback(len(results), len(images), name) + keep_going = progress_callback(len(results), num_to_process, name) if not keep_going: abort.set() - progress_callback(0, len(images), '') - [Worker(abort, 'CompressImage%d' % i, queue, results, container, jpeg_quality, pc) for i in range(min(detect_ncpus(), len(images)))] + progress_callback(0, num_to_process, '') + [Worker(abort, 'CompressImage%d' % i, queue, results, jpeg_quality, pc) for i in range(min(detect_ncpus(), num_to_process))] queue.join() before_total = after_total = 0 + processed_num = 0 changed = False for name, (ok, res) in iteritems(results): name = force_unicode(name, filesystem_encoding) @@ -98,6 +103,7 @@ def compress_images(container, report=None, names=None, jpeg_quality=None, progr before, after = res if before != after: changed = True + processed_num += 1 before_total += before after_total += after if report: @@ -112,8 +118,8 @@ def compress_images(container, report=None, names=None, jpeg_quality=None, progr if report: if changed: report('') - report(_('Total image filesize reduced from {0} to {1} [{2:.1%} reduction]').format( - human_readable(before_total), human_readable(after_total), (before_total - after_total)/before_total)) + report(_('Total image filesize reduced from {0} to {1} [{2:.1%} reduction, {3} images changed]').format( + human_readable(before_total), human_readable(after_total), (before_total - after_total)/before_total, processed_num)) else: report(_('Images are already fully optimized')) return changed, results