diff --git a/src/calibre/ebooks/conversion/config.py b/src/calibre/ebooks/conversion/config.py
index db30f2859b..168a68af6c 100644
--- a/src/calibre/ebooks/conversion/config.py
+++ b/src/calibre/ebooks/conversion/config.py
@@ -278,7 +278,7 @@ OPTIONS = {
'epub': (
'dont_split_on_page_breaks', 'flow_size', 'no_default_epub_cover',
'no_svg_cover', 'epub_inline_toc', 'epub_toc_at_end', 'toc_title',
- 'preserve_cover_aspect_ratio', 'epub_flatten', 'epub_version'),
+ 'preserve_cover_aspect_ratio', 'epub_flatten', 'epub_version', 'epub_max_image_size',),
'fb2': ('sectionize', 'fb2_genre'),
diff --git a/src/calibre/ebooks/conversion/plugins/epub_output.py b/src/calibre/ebooks/conversion/plugins/epub_output.py
index 012eb512b0..a6ed8e0b51 100644
--- a/src/calibre/ebooks/conversion/plugins/epub_output.py
+++ b/src/calibre/ebooks/conversion/plugins/epub_output.py
@@ -124,6 +124,17 @@ class EPUBOutput(OutputFormatPlugin):
' actually need it.')
),
+ OptionRecommendation(name='epub_max_image_size', recommended_value='none',
+ help=_('The maximum image size (width x height). A value of {0} means use the screen size from the output'
+ ' profile. A value of {1} means no maximum size is specified. For example, a value of {2}'
+ ' will cause all images to be resized so that their width is no more than {3} pixels and'
+ ' their height is no more than {4} pixels. Note that this only affects the size of the actual'
+ ' image files themselves. Any given image may be rendered at a different size depending on the styling'
+ ' applied to it in the document.'
+ ).format('none', 'profile', '100x200', 100, 200)
+ ),
+
+
}
recommendations = {('pretty_print', True, OptionRecommendation.HIGH)}
@@ -196,8 +207,9 @@ class EPUBOutput(OutputFormatPlugin):
self.workaround_ade_quirks()
self.workaround_webkit_quirks()
self.upshift_markup()
+
from calibre.ebooks.oeb.transforms.rescale import RescaleImages
- RescaleImages(check_colorspaces=True)(oeb, opts)
+ RescaleImages(check_colorspaces=True)(oeb, opts, max_size=self.opts.epub_max_image_size)
from calibre.ebooks.oeb.transforms.split import Split
split = Split(not self.opts.dont_split_on_page_breaks,
@@ -385,7 +397,6 @@ class EPUBOutput(OutputFormatPlugin):
from calibre.ebooks.oeb.base import XPath, XHTML, barename, urlunquote
stylesheet = self.oeb.manifest.main_stylesheet
-
# ADE cries big wet tears when it encounters an invalid fragment
# identifier in the NCX toc.
frag_pat = re.compile(r'[-A-Za-z0-9_:.]+$')
diff --git a/src/calibre/ebooks/conversion/plumber.py b/src/calibre/ebooks/conversion/plumber.py
index 667efa5c8b..b3a6945bad 100644
--- a/src/calibre/ebooks/conversion/plumber.py
+++ b/src/calibre/ebooks/conversion/plumber.py
@@ -140,7 +140,7 @@ OptionRecommendation(name='output_profile',
choices=[x.short_name for x in output_profiles()],
help=_('Specify the output profile. The output profile '
'tells the conversion system how to optimize the '
- 'created document for the specified device (such as by resizing images for the device screen size). In some cases, '
+ 'created document for the specified device. In some cases, '
'an output profile can be used to optimize the output for a particular device, but this is rarely necessary. '
'Choices are:') + ', '.join([
x.short_name for x in output_profiles()])
diff --git a/src/calibre/ebooks/oeb/transforms/rescale.py b/src/calibre/ebooks/oeb/transforms/rescale.py
index 958a013316..dc7bc12475 100644
--- a/src/calibre/ebooks/oeb/transforms/rescale.py
+++ b/src/calibre/ebooks/oeb/transforms/rescale.py
@@ -15,11 +15,11 @@ class RescaleImages:
def __init__(self, check_colorspaces=False):
self.check_colorspaces = check_colorspaces
- def __call__(self, oeb, opts):
+ def __call__(self, oeb, opts, max_size: str = 'profile'):
self.oeb, self.opts, self.log = oeb, opts, oeb.log
- self.rescale()
+ self.rescale(max_size)
- def rescale(self):
+ def rescale(self, max_size: str = 'profile'):
from PIL import Image
from io import BytesIO
@@ -32,6 +32,23 @@ class RescaleImages:
page_width -= (self.opts.margin_left + self.opts.margin_right) * self.opts.dest.dpi/72
page_height -= (self.opts.margin_top + self.opts.margin_bottom) * self.opts.dest.dpi/72
+ no_scale_size = 99999999999
+ if max_size == 'none':
+ page_width = page_height = no_scale_size
+ elif max_size != 'profile':
+ w, __, h = max_size.strip().lower().partition('x')
+ try:
+ page_width = int(w.strip())
+ except Exception:
+ page_width = no_scale_size
+ if page_width <= 0:
+ page_width = no_scale_size
+ try:
+ page_height = int(h.strip())
+ except Exception:
+ page_height = no_scale_size
+ if page_height <= 0:
+ page_height = no_scale_size
for item in self.oeb.manifest:
if item.media_type.startswith('image'):
ext = item.media_type.split('/')[-1].upper()
diff --git a/src/calibre/gui2/convert/epub_output.ui b/src/calibre/gui2/convert/epub_output.ui
index 448c6385b8..3370315b8b 100644
--- a/src/calibre/gui2/convert/epub_output.ui
+++ b/src/calibre/gui2/convert/epub_output.ui
@@ -14,10 +14,27 @@
Form
- -
-
+
-
+
- Preserve cover &aspect ratio
+ EP&UB version:
+
+
+ opt_epub_version
+
+
+
+ -
+
+
+ No default &cover
+
+
+
+ -
+
+
+ Insert inline &Table of Contents
@@ -31,6 +48,46 @@
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 262
+
+
+
+
+ -
+
+
+ No &SVG cover
+
+
+
+ -
+
+
+ -
+
+
+ &Flatten EPUB file structure
+
+
+
+ -
+
+
+ &Title for inserted ToC:
+
+
+ opt_toc_title
+
+
+
-
@@ -50,47 +107,6 @@
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 262
-
-
-
-
- -
-
-
- No default &cover
-
-
-
- -
-
-
- No &SVG cover
-
-
-
- -
-
-
- Insert inline &Table of Contents
-
-
-
- -
-
-
- Do not &split on page breaks
-
-
-
-
@@ -98,20 +114,17 @@
- -
-
+
-
+
- &Flatten EPUB file structure
+ Preserve cover &aspect ratio
- -
-
+
-
+
- &Title for inserted ToC:
-
-
- opt_toc_title
+ Do not &split on page breaks
@@ -123,17 +136,17 @@
-
-
+
- EP&UB version:
+ Shrink &images larger than:
- opt_epub_version
+ opt_epub_max_image_size
-
-
+
diff --git a/src/pyj/book_list/conversion_widgets.pyj b/src/pyj/book_list/conversion_widgets.pyj
index 49eb7346db..d7b94f5314 100644
--- a/src/pyj/book_list/conversion_widgets.pyj
+++ b/src/pyj/book_list/conversion_widgets.pyj
@@ -540,6 +540,7 @@ def epub_output(container):
g.appendChild(checkbox('epub_toc_at_end', _('Put inserted Table of Contents at the &end of the book')))
g.appendChild(lineedit('toc_title', _('&Title for inserted ToC:')))
g.appendChild(int_spin('flow_size', _('Split files &larger than:'), unit='KB', max=1000000, step=20))
+ g.appendChild(lineedit('epub_max_image_size', _('Shrink &images larger than:')))
g.appendChild(choices('epub_version', _('EP&UB version:'), ui_data.versions))
# }}}