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