mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Edit book: Fix compress images losslessly failing for a few images on windows when there are a lot of images in the book. Fixes #1877066 [Error in Compressing images losslessly](https://bugs.launchpad.net/calibre/+bug/1877066)
This commit is contained in:
parent
b76b0a6c53
commit
319f289851
@ -16,9 +16,9 @@ class Worker(Thread):
|
|||||||
|
|
||||||
daemon = True
|
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)
|
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.progress_callback = progress_callback
|
||||||
self.jpeg_quality = jpeg_quality
|
self.jpeg_quality = jpeg_quality
|
||||||
self.abort = abort
|
self.abort = abort
|
||||||
@ -27,11 +27,11 @@ class Worker(Thread):
|
|||||||
def run(self):
|
def run(self):
|
||||||
while not self.abort.is_set():
|
while not self.abort.is_set():
|
||||||
try:
|
try:
|
||||||
name = self.queue.get_nowait()
|
name, path, mt = self.queue.get_nowait()
|
||||||
except Empty:
|
except Empty:
|
||||||
break
|
break
|
||||||
try:
|
try:
|
||||||
self.compress(name)
|
self.compress(name, path, mt)
|
||||||
except Exception:
|
except Exception:
|
||||||
import traceback
|
import traceback
|
||||||
self.results[name] = (False, traceback.format_exc())
|
self.results[name] = (False, traceback.format_exc())
|
||||||
@ -43,16 +43,14 @@ class Worker(Thread):
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
self.queue.task_done()
|
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
|
from calibre.utils.img import optimize_png, optimize_jpeg, encode_jpeg
|
||||||
mt = self.container.mime_map[name]
|
if 'png' in mime_type:
|
||||||
if 'png' in mt:
|
|
||||||
func = optimize_png
|
func = optimize_png
|
||||||
elif self.jpeg_quality is None:
|
elif self.jpeg_quality is None:
|
||||||
func = optimize_jpeg
|
func = optimize_jpeg
|
||||||
else:
|
else:
|
||||||
func = partial(encode_jpeg, quality=self.jpeg_quality)
|
func = partial(encode_jpeg, quality=self.jpeg_quality)
|
||||||
path = self.container.get_file_path_for_processing(name)
|
|
||||||
before = os.path.getsize(path)
|
before = os.path.getsize(path)
|
||||||
with lopen(path, 'rb') as f:
|
with lopen(path, 'rb') as f:
|
||||||
old_data = f.read()
|
old_data = f.read()
|
||||||
@ -80,17 +78,24 @@ def compress_images(container, report=None, names=None, jpeg_quality=None, progr
|
|||||||
results = {}
|
results = {}
|
||||||
queue = Queue()
|
queue = Queue()
|
||||||
abort = Event()
|
abort = Event()
|
||||||
for name in images:
|
seen = set()
|
||||||
queue.put(name)
|
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):
|
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:
|
if not keep_going:
|
||||||
abort.set()
|
abort.set()
|
||||||
progress_callback(0, len(images), '')
|
progress_callback(0, num_to_process, '')
|
||||||
[Worker(abort, 'CompressImage%d' % i, queue, results, container, jpeg_quality, pc) for i in range(min(detect_ncpus(), len(images)))]
|
[Worker(abort, 'CompressImage%d' % i, queue, results, jpeg_quality, pc) for i in range(min(detect_ncpus(), num_to_process))]
|
||||||
queue.join()
|
queue.join()
|
||||||
before_total = after_total = 0
|
before_total = after_total = 0
|
||||||
|
processed_num = 0
|
||||||
changed = False
|
changed = False
|
||||||
for name, (ok, res) in iteritems(results):
|
for name, (ok, res) in iteritems(results):
|
||||||
name = force_unicode(name, filesystem_encoding)
|
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
|
before, after = res
|
||||||
if before != after:
|
if before != after:
|
||||||
changed = True
|
changed = True
|
||||||
|
processed_num += 1
|
||||||
before_total += before
|
before_total += before
|
||||||
after_total += after
|
after_total += after
|
||||||
if report:
|
if report:
|
||||||
@ -112,8 +118,8 @@ def compress_images(container, report=None, names=None, jpeg_quality=None, progr
|
|||||||
if report:
|
if report:
|
||||||
if changed:
|
if changed:
|
||||||
report('')
|
report('')
|
||||||
report(_('Total image filesize reduced from {0} to {1} [{2:.1%} reduction]').format(
|
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))
|
human_readable(before_total), human_readable(after_total), (before_total - after_total)/before_total, processed_num))
|
||||||
else:
|
else:
|
||||||
report(_('Images are already fully optimized'))
|
report(_('Images are already fully optimized'))
|
||||||
return changed, results
|
return changed, results
|
||||||
|
Loading…
x
Reference in New Issue
Block a user