From 723fa4c0b83e6b7f2949e8737c51989587043d52 Mon Sep 17 00:00:00 2001
From: tom <120112635+tswh0@users.noreply.github.com>
Date: Sun, 22 Feb 2026 20:34:10 +0100
Subject: [PATCH] Add exact cover fit option for device-sized cover cropping
(#1254)
* Add exact cover fit option for device-sized cover cropping
* Update README to move cover cropping from FAQ to USAGE
* rename to coverfill
* edit readme
---
README.md | 1 +
gui/KCC.ui | 12 ++++++++++++
kindlecomicconverter/KCC_gui.py | 3 +++
kindlecomicconverter/KCC_ui.py | 13 ++++++++++++-
kindlecomicconverter/comic2ebook.py | 2 ++
kindlecomicconverter/image.py | 5 ++++-
6 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 055fc6d..72e6609 100644
--- a/README.md
+++ b/README.md
@@ -269,6 +269,7 @@ PROCESSING:
Crop empty sections. 0: Disabled 1: Horizontally 2: Both [Default=0]
--blackborders Disable autodetection and force black borders
--whiteborders Disable autodetection and force white borders
+ --coverfill Center-crop only the cover to fill target device screen
--forcecolor Don't convert images to grayscale
--forcepng Create PNG files instead JPEG
--mozjpeg Create JPEG files using mozJpeg
diff --git a/gui/KCC.ui b/gui/KCC.ui
index 3359be8..9ea9ad7 100644
--- a/gui/KCC.ui
+++ b/gui/KCC.ui
@@ -908,6 +908,17 @@ Useful for really weird PDFs.
+ -
+
+
+ Resize cover to exact device resolution by center-cropping to aspect ratio first.
+May crop top/bottom or left/right depending on source aspect ratio.
+
+
+ Cover Fill
+
+
+
@@ -1037,6 +1048,7 @@ Useful for really weird PDFs.
noRotateBox
interPanelCropBox
metadataTitleBox
+ coverFillBox
chunkSizeCheckBox
chunkSizeBox
eraseRainbowBox
diff --git a/kindlecomicconverter/KCC_gui.py b/kindlecomicconverter/KCC_gui.py
index 047f977..456d529 100644
--- a/kindlecomicconverter/KCC_gui.py
+++ b/kindlecomicconverter/KCC_gui.py
@@ -329,6 +329,8 @@ class WorkerThread(QThread):
options.noprocessing = True
if GUI.pdfExtractBox.isChecked():
options.pdfextract = True
+ if GUI.coverFillBox.isChecked():
+ options.coverfill = True
if GUI.metadataTitleBox.checkState() == Qt.CheckState.PartiallyChecked:
options.metadatatitle = 1
elif GUI.metadataTitleBox.checkState() == Qt.CheckState.Checked:
@@ -1036,6 +1038,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
'eraseRainbowBox': GUI.eraseRainbowBox.checkState(),
'disableProcessingBox': GUI.disableProcessingBox.checkState(),
'pdfExtractBox': GUI.pdfExtractBox.checkState(),
+ 'coverFillBox': GUI.coverFillBox.checkState(),
'metadataTitleBox': GUI.metadataTitleBox.checkState(),
'mozJpegBox': GUI.mozJpegBox.checkState(),
'jpegQualityBox': GUI.jpegQualityBox.checkState(),
diff --git a/kindlecomicconverter/KCC_ui.py b/kindlecomicconverter/KCC_ui.py
index c781a97..98cf7f1 100644
--- a/kindlecomicconverter/KCC_ui.py
+++ b/kindlecomicconverter/KCC_ui.py
@@ -467,6 +467,11 @@ class Ui_mainWindow(object):
self.gridLayout_2.addWidget(self.pdfExtractBox, 9, 0, 1, 1)
+ self.coverFillBox = QCheckBox(self.optionWidget)
+ self.coverFillBox.setObjectName(u"coverFillBox")
+
+ self.gridLayout_2.addWidget(self.coverFillBox, 9, 1, 1, 1)
+
self.gridLayout.addWidget(self.optionWidget, 5, 0, 1, 2)
@@ -549,7 +554,8 @@ class Ui_mainWindow(object):
QWidget.setTabOrder(self.fileFusionBox, self.noRotateBox)
QWidget.setTabOrder(self.noRotateBox, self.interPanelCropBox)
QWidget.setTabOrder(self.interPanelCropBox, self.metadataTitleBox)
- QWidget.setTabOrder(self.metadataTitleBox, self.chunkSizeCheckBox)
+ QWidget.setTabOrder(self.metadataTitleBox, self.coverFillBox)
+ QWidget.setTabOrder(self.coverFillBox, self.chunkSizeCheckBox)
QWidget.setTabOrder(self.chunkSizeCheckBox, self.chunkSizeBox)
QWidget.setTabOrder(self.chunkSizeBox, self.eraseRainbowBox)
QWidget.setTabOrder(self.eraseRainbowBox, self.rotateFirstBox)
@@ -744,6 +750,11 @@ class Ui_mainWindow(object):
"Useful for really weird PDFs.", None))
#endif // QT_CONFIG(tooltip)
self.pdfExtractBox.setText(QCoreApplication.translate("mainWindow", u"PDF Legacy Extract", None))
+#if QT_CONFIG(tooltip)
+ self.coverFillBox.setToolTip(QCoreApplication.translate("mainWindow", u"Resize cover to exact device resolution by center-cropping to aspect ratio first.\n"
+"May crop top/bottom or left/right depending on source aspect ratio.", None))
+#endif // QT_CONFIG(tooltip)
+ self.coverFillBox.setText(QCoreApplication.translate("mainWindow", u"Cover Fill", None))
self.gammaLabel.setText(QCoreApplication.translate("mainWindow", u"Gamma: Auto", None))
self.jpegQualityLabel.setText(QCoreApplication.translate("mainWindow", u"JPEG Quality:", None))
# retranslateUi
diff --git a/kindlecomicconverter/comic2ebook.py b/kindlecomicconverter/comic2ebook.py
index cb23fbd..a9c9e38 100755
--- a/kindlecomicconverter/comic2ebook.py
+++ b/kindlecomicconverter/comic2ebook.py
@@ -1360,6 +1360,8 @@ def makeParser():
help="Do not modify image and ignore any profile or processing option")
processing_options.add_argument("--pdfextract", action="store_true", dest="pdfextract", default=False,
help="Use the legacy PDF image extraction method from KCC 8 and earlier")
+ processing_options.add_argument("--coverfill", action="store_true", dest="coverfill", default=False,
+ help="Crop cover to fill screen")
processing_options.add_argument("-u", "--upscale", action="store_true", dest="upscale", default=False,
help="Resize images smaller than device's resolution")
processing_options.add_argument("-s", "--stretch", action="store_true", dest="stretch", default=False,
diff --git a/kindlecomicconverter/image.py b/kindlecomicconverter/image.py
index 2acb60d..44a7532 100755
--- a/kindlecomicconverter/image.py
+++ b/kindlecomicconverter/image.py
@@ -569,7 +569,10 @@ class Cover:
if self.options.kindle_scribe_azw3:
size[0] = min(size[0], 1920)
size[1] = min(size[1], 1920)
- self.image.thumbnail(tuple(size), Image.Resampling.LANCZOS)
+ if self.options.coverfill:
+ self.image = ImageOps.fit(self.image, tuple(size), Image.Resampling.LANCZOS, centering=(0.5, 0.5))
+ else:
+ self.image.thumbnail(tuple(size), Image.Resampling.LANCZOS)
def crop_main_cover(self):
w, h = self.image.size