From 9decf0e68e60d520a1ee34ad99ae6349f33f18fd Mon Sep 17 00:00:00 2001 From: Alex Xu Date: Thu, 3 Sep 2026 10:21:08 -0700 Subject: [PATCH] add wallpaper mode for KOreader (#1431) * add wallpaper mode for KOreader * fix wallpaper interactions with no rotate --- README.md | 1 + gui/KCC.ui | 12 ++++++++++++ kindlecomicconverter/KCC_gui.py | 13 +++++++++++++ kindlecomicconverter/KCC_ui.py | 11 +++++++++++ kindlecomicconverter/comic2ebook.py | 12 ++++++++---- kindlecomicconverter/image.py | 6 +++++- 6 files changed, 50 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c0afe7ad..a3e3376d 100644 --- a/README.md +++ b/README.md @@ -287,6 +287,7 @@ PROCESSING: --pdfwidth Render vector PDFs based on device width instead of height. -u, --upscale Resize images smaller than device's resolution -s, --stretch Stretch images to device's resolution + --wallpaper Crop images to to fill screen -r SPLITTER, --splitter SPLITTER Double page parsing mode. 0: Split 1: Rotate 2: Both [Default=0] -g GAMMA, --gamma GAMMA diff --git a/gui/KCC.ui b/gui/KCC.ui index 2b31b6d2..514afec2 100644 --- a/gui/KCC.ui +++ b/gui/KCC.ui @@ -693,6 +693,18 @@ Keeping this file may crash some readers like the Kobo native CBZ reader. + + + + Auto check various options intended for KOreader wallpapers. + +Will also crop images to fill the screen centered. + + + Wallpaper mode + + + diff --git a/kindlecomicconverter/KCC_gui.py b/kindlecomicconverter/KCC_gui.py index a1e4f0b7..09291b80 100644 --- a/kindlecomicconverter/KCC_gui.py +++ b/kindlecomicconverter/KCC_gui.py @@ -253,6 +253,8 @@ def get_options(): options.righttoleft = True if GUI.lightnovelBox.isChecked(): options.lightnovel = True + if GUI.wallpaperBox.isChecked(): + options.wallpaper = True if GUI.ebokBox.isChecked(): options.ebok = True if GUI.invertDirectionBox.isChecked(): @@ -969,6 +971,14 @@ class KCCGUI(KCC_ui.Ui_mainWindow): GUI.noQuantizeBox.setEnabled(False) GUI.forcePngRgbBox.setEnabled(False) + def toggleWallpaperBox(self, value): + if value == 2: + GUI.mozJpegBox.setCheckState(Qt.CheckState.PartiallyChecked) + GUI.pngLegacyBox.setChecked(True) + GUI.rotateBox.setChecked(True) + GUI.noRotateBox.setChecked(True) + GUI.upscaleBox.setChecked(True) + self.changeFormat(3) def togglechunkSizeCheckBox(self, value): GUI.chunkSizeWidget.setVisible(value) @@ -1071,6 +1081,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow): if GUI.formats[str(GUI.formatBox.currentText())]['format'] in ('CBZ', 'FOLDER', 'PDF') and not GUI.webtoonBox.isChecked(): self.addMessage("Partially check W/B Margins if you don't want KCC to extend the image margins.", 'info') GUI.borderBox.setCheckState(Qt.CheckState.PartiallyChecked) + GUI.mozJpegBox.setCheckState(Qt.CheckState.PartiallyChecked) else: GUI.borderBox.setCheckState(Qt.CheckState.Unchecked) @@ -1185,6 +1196,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow): self.settings.setValue('windowSize', str(MW.size().width()) + 'x' + str(MW.size().height())) self.settings.setValue('options', {'mangaBox': GUI.mangaBox.checkState(), 'lightnovelBox': GUI.lightnovelBox.checkState(), + 'wallpaperBox': GUI.wallpaperBox.checkState(), 'ebokBox': GUI.ebokBox.checkState(), 'invertDirectionBox': GUI.invertDirectionBox.checkState(), 'languageEdit': GUI.languageEdit.text(), @@ -1582,6 +1594,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow): GUI.webtoonBox.stateChanged.connect(self.togglewebtoonBox) GUI.qualityBox.stateChanged.connect(self.togglequalityBox) GUI.mozJpegBox.stateChanged.connect(self.toggleImageFormatBox) + GUI.wallpaperBox.stateChanged.connect(self.toggleWallpaperBox) GUI.chunkSizeCheckBox.stateChanged.connect(self.togglechunkSizeCheckBox) GUI.deviceBox.activated.connect(self.changeDevice) GUI.formatBox.activated.connect(self.changeFormat) diff --git a/kindlecomicconverter/KCC_ui.py b/kindlecomicconverter/KCC_ui.py index e8faa305..7a030d9e 100644 --- a/kindlecomicconverter/KCC_ui.py +++ b/kindlecomicconverter/KCC_ui.py @@ -352,6 +352,11 @@ class Ui_mainWindow(object): self.gridLayout_2.addWidget(self.keepComicInfoBox, 11, 3, 1, 1) + self.wallpaperBox = QCheckBox(self.optionWidget) + self.wallpaperBox.setObjectName(u"wallpaperBox") + + self.gridLayout_2.addWidget(self.wallpaperBox, 11, 0, 1, 1) + self.gridLayout.addWidget(self.optionWidget, 5, 0, 1, 2) @@ -854,6 +859,12 @@ class Ui_mainWindow(object): "Keeping this file may crash some readers like the Kobo native CBZ reader.", None)) #endif // QT_CONFIG(tooltip) self.keepComicInfoBox.setText(QCoreApplication.translate("mainWindow", u"Keep ComicInfo.xml", None)) +#if QT_CONFIG(tooltip) + self.wallpaperBox.setToolTip(QCoreApplication.translate("mainWindow", u"Auto check various options intended for KOreader wallpapers.\n" +"\n" +"Will also crop images to fill the screen centered.", None)) +#endif // QT_CONFIG(tooltip) + self.wallpaperBox.setText(QCoreApplication.translate("mainWindow", u"Wallpaper mode", None)) #if QT_CONFIG(tooltip) self.editorButton.setToolTip(QCoreApplication.translate("mainWindow", u"

Shift+Click to edit directory.

", None)) #endif // QT_CONFIG(tooltip) diff --git a/kindlecomicconverter/comic2ebook.py b/kindlecomicconverter/comic2ebook.py index 5c47c28a..9ff38643 100755 --- a/kindlecomicconverter/comic2ebook.py +++ b/kindlecomicconverter/comic2ebook.py @@ -1058,7 +1058,7 @@ def getWorkFolder(afile, options, workdir=None): def getOutputFilename(srcpath, wantedname, ext, tomenumber): - if options.format == 'CBZ' and options.skip_zip: + if options.folder_output: ext = '' source_path = Path(srcpath) if srcpath[-1] == os.path.sep: @@ -1071,7 +1071,7 @@ def getOutputFilename(srcpath, wantedname, ext, tomenumber): ext = '.kepub.epub' if wantedname is not None: wanted_root, wanted_ext = os.path.splitext(wantedname) - if wantedname.endswith(ext): + if not options.folder_output and wantedname.endswith(ext): filename = os.path.abspath(wantedname) elif wanted_ext == '.mobi' and ext == '.epub': filename = os.path.abspath(wanted_root + ext) @@ -1432,8 +1432,8 @@ def slugify(value, options, is_natural_sorted): return value def makeZIP(zipfilename, basedir, job_progress='', isepub=False): - if options.format == 'CBZ' and options.skip_zip: - os.rename(basedir, zipfilename) + if options.folder_output: + move(basedir, zipfilename) return zipfilename start = perf_counter() if SEVENZIP in available_archive_tools(): @@ -1480,6 +1480,8 @@ def makeParser(): help="Manga style (right-to-left reading and splitting)") main_options.add_argument("--lightnovel", action="store_true", dest="lightnovel", default=False, help="Only resize images and preserve original file structure.") + main_options.add_argument("--wallpaper", action="store_true", dest="wallpaper", default=False, + help="Crop to fill screen.") main_options.add_argument("--ebok", action="store_true", dest="ebok", default=False, help="Force EBOK tag instead of PDOC for MOBI") main_options.add_argument("--invertdirection", action="store_true", dest="invertdirection", default=False, @@ -1645,9 +1647,11 @@ def checkOptions(options): options.format = 'MOBI' options.kfx = False options.skip_zip = False + options.folder_output = False if options.format == 'FOLDER': options.format = 'CBZ' options.skip_zip = True + options.folder_output = True if options.format == 'Auto': if options.profile in ['KDX']: options.format = 'CBZ' diff --git a/kindlecomicconverter/image.py b/kindlecomicconverter/image.py index bd680e43..bc50038f 100755 --- a/kindlecomicconverter/image.py +++ b/kindlecomicconverter/image.py @@ -513,7 +513,9 @@ class ComicPage: self.image = erase_rainbow_artifacts(self.image, is_color) def resizeImage(self): - if self.opt.norotate and self.targetPathOrder in ('-kcc-a', '-kcc-d') and not self.opt.kindle_scribe_azw3: + if self.opt.wallpaper: + pass + elif self.opt.norotate and self.targetPathOrder in ('-kcc-a', '-kcc-d') and not self.opt.kindle_scribe_azw3: # TODO: Kindle Scribe case if self.opt.kindle_azw3 and any(dim > 1920 for dim in self.image.size): self.image = ImageOps.contain(self.image, (1920, 1920), Image.Resampling.LANCZOS) @@ -536,6 +538,8 @@ class ComicPage: self.image = ImageOps.pad(self.image, self.opt.kfx_resolution, method=method, color=self.fill) elif self.opt.stretch: self.image = self.image.resize(self.size, method) + elif self.opt.wallpaper: + self.image = ImageOps.fit(self.image, self.size, method=method) elif method == Image.Resampling.BICUBIC and not self.opt.upscale: pass else: # if image bigger than device resolution or smaller with upscaling