diff --git a/src/calibre/ebooks/metadata/sources/covers.py b/src/calibre/ebooks/metadata/sources/covers.py index 6a401dae60..5e1c0d7cf8 100644 --- a/src/calibre/ebooks/metadata/sources/covers.py +++ b/src/calibre/ebooks/metadata/sources/covers.py @@ -15,7 +15,7 @@ from io import BytesIO from calibre.customize.ui import metadata_plugins from calibre.ebooks.metadata.sources.base import create_log from calibre.ebooks.metadata.sources.prefs import msprefs -from calibre.utils.img import save_cover_data_to +from calibre.utils.img import save_cover_data_to, remove_borders, image_to_data, image_from_data from calibre.utils.imghdr import identify class Worker(Thread): @@ -61,11 +61,10 @@ def process_result(log, result): plugin, data = result try: if getattr(plugin, 'auto_trim_covers', False): - from calibre.utils.magick import Image - im = Image() - im.load(data) - im.trim(10) - data = im.export('JPEG') + img = image_from_data(data) + nimg = remove_borders(img) + if nimg is not img: + data = image_to_data(nimg) fmt, width, height = identify(data) if width < 0 or height < 0: raise ValueError('Could not read cover image dimensions') diff --git a/src/calibre/gui2/dialogs/metadata_bulk.py b/src/calibre/gui2/dialogs/metadata_bulk.py index f17adc3b40..9430826c7c 100644 --- a/src/calibre/gui2/dialogs/metadata_bulk.py +++ b/src/calibre/gui2/dialogs/metadata_bulk.py @@ -200,15 +200,15 @@ class MyBlockingBusy(QDialog): # {{{ if covers: cache.set_cover({book_id:covers[-1][0]}) elif args.cover_action == 'trim': - from calibre.utils.magick import Image + from calibre.utils.img import remove_borders, image_to_data, image_from_data for book_id in self.ids: cdata = cache.cover(book_id) if cdata: - im = Image() - im.load(cdata) - im.trim(tweaks['cover_trim_fuzz_value']) - cdata = im.export('jpg') - cache.set_cover({book_id:cdata}) + img = image_from_data(cdata) + nimg = remove_borders(img) + if nimg is not img: + cdata = image_to_data(nimg) + cache.set_cover({book_id:cdata}) elif args.cover_action == 'clone': cdata = None for book_id in self.ids: diff --git a/src/calibre/gui2/metadata/basic_widgets.py b/src/calibre/gui2/metadata/basic_widgets.py index cce340fed1..1eb239dbac 100644 --- a/src/calibre/gui2/metadata/basic_widgets.py +++ b/src/calibre/gui2/metadata/basic_widgets.py @@ -1105,15 +1105,15 @@ class Cover(ImageView): # {{{ self.current_val = None def trim_cover(self, *args): - from calibre.utils.magick import Image cdata = self.current_val if not cdata: return - im = Image() - im.load(cdata) - im.trim(tweaks['cover_trim_fuzz_value']) - self.current_val = im.export('png') - self.cdata_before_trim = cdata + from calibre.utils.img import remove_borders, image_to_data, image_from_data + img = image_from_data(cdata) + nimg = remove_borders(img) + if nimg is not img: + self.cdata_before_trim = cdata + self.current_val = image_to_data(nimg, fmt='png') def manual_trim_cover(self): cdata = self.current_val diff --git a/src/calibre/gui2/tweak_book/editor/canvas.py b/src/calibre/gui2/tweak_book/editor/canvas.py index 227dfa825a..62f077f9d5 100644 --- a/src/calibre/gui2/tweak_book/editor/canvas.py +++ b/src/calibre/gui2/tweak_book/editor/canvas.py @@ -19,8 +19,8 @@ from calibre.gui2 import error_dialog, pixmap_to_data from calibre.gui2.dnd import ( IMAGE_EXTENSIONS, dnd_has_extension, dnd_has_image, dnd_get_image, DownloadDialog) from calibre.gui2.tweak_book import capitalize -from calibre.utils.config_base import tweaks from calibre.utils.imghdr import identify +from calibre.utils.img import remove_borders from calibre.utils.magick import qimage_to_magick def painter(func): @@ -98,10 +98,7 @@ class AutoTrim(Trim): TEXT = _('Auto-trim image') def __call__(self, canvas): - img = canvas.current_image - i = qimage_to_magick(img) - i.trim(tweaks['cover_trim_fuzz_value']) - return i.to_qimage() + return remove_borders(canvas.current_image) class Rotate(Command): diff --git a/src/calibre/utils/img.py b/src/calibre/utils/img.py index 142212cf0a..5b9b079ce8 100644 --- a/src/calibre/utils/img.py +++ b/src/calibre/utils/img.py @@ -200,10 +200,15 @@ def flip_image(img, horizontal=False, vertical=False): return image_from_data(img).mirrored(horizontal, vertical) def remove_borders(img, fuzz=None): + ''' Try to auto-detect and remove any borders from the image. Returns + the image itself if no borders could be removed. `fuzz` is a measure of + what colors are considered identical (must be a number between 0 and 255 in + absolute intensity units). Default is from a tweak whose default value is 10. ''' if imageops is None: raise RuntimeError(imageops_err) fuzz = tweaks['cover_trim_fuzz_value'] if fuzz is None else fuzz - return imageops.remove_borders(image_from_data(img), max(0, fuzz)) + ans = imageops.remove_borders(image_from_data(img), max(0, fuzz)) + return ans if ans.size() != img.size() else img def run_optimizer(file_path, cmd, as_filter=False, input_data=None): file_path = os.path.abspath(file_path)