From f5fe8d93b0e0c65d5583593c3434df4b11ffecc4 Mon Sep 17 00:00:00 2001 From: Alex Xu Date: Tue, 17 Mar 2026 13:41:41 -0700 Subject: [PATCH] color images are always saved as JPG by default (#1272) * use jpg for color images always * add colorOutput variable * fix typos * remove dither * add box * clarify png * remove debug code * remove unneeded check --- README.md | 3 ++- gui/KCC.ui | 12 +++++++++++- kindlecomicconverter/KCC_gui.py | 3 +++ kindlecomicconverter/KCC_ui.py | 11 ++++++++++- kindlecomicconverter/comic2ebook.py | 9 +++++---- kindlecomicconverter/image.py | 7 ++++--- 6 files changed, 35 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index e77da46..14501b2 100644 --- a/README.md +++ b/README.md @@ -272,7 +272,8 @@ PROCESSING: --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 + --forcepng Create PNG files instead JPEG for black and white images + --force-png-rgb Force color images to be saved as PNG --pnglegacy Use a more compatible 8 bit PNG instead of 4 bit. --noquantize Don't quantize PNG images to 16 colors --mozjpeg Create JPEG files using mozJpeg diff --git a/gui/KCC.ui b/gui/KCC.ui index 1020b6a..4e75811 100644 --- a/gui/KCC.ui +++ b/gui/KCC.ui @@ -801,7 +801,7 @@ Useful for really weird PDFs. - <html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - JPEG<br/></span>Use JPEG files</p><p><span style=" font-weight:600; text-decoration: underline;">Indeterminate - force PNG<br/></span>Create PNG files instead JPEG</p><p><span style=" font-weight:600; text-decoration: underline;">Checked - mozJpeg<br/></span>10-20% smaller JPEG file, with the same image quality, but processing time multiplied by 2</p></body></html> + <html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - JPEG<br/></span>Use JPEG files</p><p><span style=" font-weight:600; text-decoration: underline;">Indeterminate - force PNG<br/></span>Create PNG files instead JPEG for black and white images</p><p><span style=" font-weight:600; text-decoration: underline;">Checked - mozJpeg<br/></span>10-20% smaller JPEG file, with the same image quality, but processing time multiplied by 2</p></body></html> JPEG/PNG/mozJpeg @@ -965,6 +965,16 @@ May crop top/bottom or left/right depending on source aspect ratio. Not implemen + + + + Force full color images to be saved in lossless PNG format, dramatically increases the filesize. + + + Force PNG RGB + + + diff --git a/kindlecomicconverter/KCC_gui.py b/kindlecomicconverter/KCC_gui.py index 925a623..87910d5 100644 --- a/kindlecomicconverter/KCC_gui.py +++ b/kindlecomicconverter/KCC_gui.py @@ -351,6 +351,8 @@ class WorkerThread(QThread): options.rotateright = True if GUI.rotateFirstBox.isChecked(): options.rotatefirst = True + if GUI.forcePngRgbBox.isChecked(): + options.force_png_rgb = True if GUI.mozJpegBox.checkState() == Qt.CheckState.PartiallyChecked: options.forcepng = True elif GUI.mozJpegBox.checkState() == Qt.CheckState.Checked: @@ -1054,6 +1056,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow): 'coverFillBox': GUI.coverFillBox.checkState(), 'metadataTitleBox': GUI.metadataTitleBox.checkState(), 'mozJpegBox': GUI.mozJpegBox.checkState(), + 'forcePngRgbBox': GUI.forcePngRgbBox.checkState(), 'pngLegacyBox': GUI.pngLegacyBox.checkState(), 'noQuantizeBox': GUI.noQuantizeBox.checkState(), 'jpegQualityBox': GUI.jpegQualityBox.checkState(), diff --git a/kindlecomicconverter/KCC_ui.py b/kindlecomicconverter/KCC_ui.py index b2e2fba..5f0c473 100644 --- a/kindlecomicconverter/KCC_ui.py +++ b/kindlecomicconverter/KCC_ui.py @@ -492,6 +492,11 @@ class Ui_mainWindow(object): self.gridLayout_2.addWidget(self.pngLegacyBox, 11, 0, 1, 1) + self.forcePngRgbBox = QCheckBox(self.optionWidget) + self.forcePngRgbBox.setObjectName(u"forcePngRgbBox") + + self.gridLayout_2.addWidget(self.forcePngRgbBox, 11, 2, 1, 1) + self.gridLayout.addWidget(self.optionWidget, 5, 0, 1, 2) @@ -745,7 +750,7 @@ class Ui_mainWindow(object): #endif // QT_CONFIG(tooltip) self.qualityBox.setText(QCoreApplication.translate("mainWindow", u"Panel View 4/2/HQ", None)) #if QT_CONFIG(tooltip) - self.mozJpegBox.setToolTip(QCoreApplication.translate("mainWindow", u"

Unchecked - JPEG
Use JPEG files

Indeterminate - force PNG
Create PNG files instead JPEG

Checked - mozJpeg
10-20% smaller JPEG file, with the same image quality, but processing time multiplied by 2

", None)) + self.mozJpegBox.setToolTip(QCoreApplication.translate("mainWindow", u"

Unchecked - JPEG
Use JPEG files

Indeterminate - force PNG
Create PNG files instead JPEG for black and white images

Checked - mozJpeg
10-20% smaller JPEG file, with the same image quality, but processing time multiplied by 2

", None)) #endif // QT_CONFIG(tooltip) self.mozJpegBox.setText(QCoreApplication.translate("mainWindow", u"JPEG/PNG/mozJpeg", None)) #if QT_CONFIG(tooltip) @@ -797,6 +802,10 @@ class Ui_mainWindow(object): self.pngLegacyBox.setToolTip(QCoreApplication.translate("mainWindow", u"Use a more compatible 8 bit PNG instead of 4 bit.", None)) #endif // QT_CONFIG(tooltip) self.pngLegacyBox.setText(QCoreApplication.translate("mainWindow", u"PNG Legacy Mode", None)) +#if QT_CONFIG(tooltip) + self.forcePngRgbBox.setToolTip(QCoreApplication.translate("mainWindow", u"Force full color images to be saved in lossless PNG format, dramatically increases the filesize.", None)) +#endif // QT_CONFIG(tooltip) + self.forcePngRgbBox.setText(QCoreApplication.translate("mainWindow", u"Force PNG RGB", 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 40fe26d..9b017d4 100755 --- a/kindlecomicconverter/comic2ebook.py +++ b/kindlecomicconverter/comic2ebook.py @@ -689,7 +689,6 @@ def imgFileProcessing(work): workImg = image.ComicPageParser((dirpath, afile), opt) for i in workImg.payload: img = image.ComicPage(opt, *i) - is_color = (opt.forcecolor and img.color) if opt.cropping == 2 and not opt.webtoon: img.cropPageNumber(opt.croppingp, opt.croppingm) if opt.cropping == 1 and not opt.webtoon: @@ -701,9 +700,9 @@ def imgFileProcessing(work): img.autocontrastImage() img.resizeImage() - img.optimizeForDisplay(opt.eraserainbow, is_color) + img.optimizeForDisplay(opt.eraserainbow, img.colorOutput) - if is_color: + if img.colorOutput: pass elif opt.forcepng: img.convertToGrayscale() @@ -1412,7 +1411,9 @@ def makeParser(): output_options.add_argument("--eraserainbow", action="store_true", dest="eraserainbow", default=False, help="Erase rainbow effect on color eink screen by attenuating interfering frequencies") processing_options.add_argument("--forcepng", action="store_true", dest="forcepng", default=False, - help="Create PNG files instead JPEG") + help="Create PNG files instead JPEG for black and white images") + processing_options.add_argument("--force-png-rgb", action="store_true", dest="force_png_rgb", default=False, + help="Force color images to be saved as PNG") processing_options.add_argument("--pnglegacy", action="store_true", dest="pnglegacy", default=False, help="Use a more compatible 8 bit png instead of 4 bit") processing_options.add_argument("--noquantize", action="store_true", dest="noquantize", default=False, diff --git a/kindlecomicconverter/image.py b/kindlecomicconverter/image.py index 6583ace..376203c 100755 --- a/kindlecomicconverter/image.py +++ b/kindlecomicconverter/image.py @@ -277,6 +277,8 @@ class ComicPage: self.original_color_mode = image.mode # TODO: color check earlier self.image = image.convert("RGB") + self.color = self.colorCheck() + self.colorOutput = self.color and self.opt.forcecolor self.fill = fill self.rotated = False self.orgPath = os.path.join(path[0], path[1]) @@ -295,8 +297,7 @@ class ComicPage: if not hasattr(Image, 'Resampling'): Image.Resampling = Image - @cached_property - def color(self): + def colorCheck(self): if self.original_color_mode in ("L", "1"): return False if self.opt.webtoon: @@ -405,7 +406,7 @@ class ComicPage: raise RuntimeError('Cannot save image. ' + str(err)) def save_with_codec(self, image, targetPath): - if self.opt.forcepng: + if self.opt.forcepng and (not self.colorOutput or self.opt.force_png_rgb): image.info.pop('transparency', None) if self.opt.iskindle and ('MOBI' in self.opt.format or 'EPUB' in self.opt.format): targetPath += '.gif'