Compare commits

...
21 Commits
Author SHA1 Message Date
Alex Xu a1fd24d6a3 bump to 11.3.1 2026-09-15 18:59:29 -07:00
Alex Xu 4f06f4ef90 fix expert mode showing easy label 2026-09-15 18:58:47 -07:00
Alex Xu c611cf6dc7 bump to 11.3.0 2026-09-15 18:37:16 -07:00
dependabot[bot]andpublic 80fe280b50 Bump signpath/github-action-submit-signing-request from 2.3 to 3.0 (#1437)
Bumps [signpath/github-action-submit-signing-request](https://github.com/signpath/github-action-submit-signing-request) from 2.3 to 3.0.
- [Release notes](https://github.com/signpath/github-action-submit-signing-request/releases)
- [Commits](https://github.com/signpath/github-action-submit-signing-request/compare/v2.3...v3.0)

---
updated-dependencies:
- dependency-name: signpath/github-action-submit-signing-request
  dependency-version: '3.0'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-15 18:36:09 -07:00
Alex Xu ff9a5e518d fix expert button height on windows 2026-09-15 18:35:19 -07:00
Alex Xu 05e5844779 support Kindle Previewer 4 on Windows (#1440)
* initial commit

* refactor kindlegen check

* search for windows kindlegen

* increase search range
2026-09-15 18:27:43 -07:00
Alex Xu aaf3548595 increase search range 2026-09-15 18:25:32 -07:00
Alex Xu ea8a4db26e search for windows kindlegen 2026-09-15 18:25:32 -07:00
Alex Xu aa652ff6c0 refactor kindlegen check 2026-09-15 18:25:32 -07:00
Alex Xu a310d4c2b1 initial commit 2026-09-15 18:25:32 -07:00
Alex Xu 7245fdf2e1 support kindle previewer 4 (#1439) 2026-09-14 15:56:18 -07:00
Alex Xu fe85274105 implement custom covers for webtoon and fusion (#1438) 2026-09-14 13:06:53 -07:00
Alex Xu cb7592dcd0 fix cropping with edge imperfections (#1435)
* improve detection of edge imperfections for cropping

* increase imperfections ratio

* fil in edge too

* fine tune the constants
2026-09-12 17:35:05 -07:00
Alex Xu ea532c709b Update README.md 2026-09-08 13:19:05 -07:00
Alex Xu 1ce92bac83 Update README.md 2026-09-08 11:53:00 -07:00
Alex Xu 5b67d4019e Update README.md 2026-09-06 22:25:38 -07:00
Alex Xu 2423e2e44a Add files via upload 2026-09-06 22:22:59 -07:00
Alex Xu eb694b2dc3 bump to 11.2.0 2026-09-06 22:14:10 -07:00
Alex Xu 04aac3ffc0 add simple mode (#1434)
* add expert mode

* add helper text
2026-09-06 22:13:48 -07:00
Alex Xu 0f630c5804 fix 7zip warning 2026-09-06 20:56:32 -07:00
Alex Xu d272073748 Update README.md 2026-09-06 20:50:29 -07:00
13 changed files with 1653 additions and 1455 deletions
+1 -1
View File
@@ -58,7 +58,7 @@ jobs:
name: windows-build-${{ matrix.entry }}
path: dist/*.exe
- id: optional_step_id
uses: signpath/github-action-submit-signing-request@v2.3
uses: signpath/github-action-submit-signing-request@v3.0
if: ${{ github.repository == 'ciromattia/kcc' }}
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
+1 -1
View File
@@ -51,7 +51,7 @@ jobs:
name: windows7-build
path: dist/*.exe
- id: optional_step_id
uses: signpath/github-action-submit-signing-request@v2.3
uses: signpath/github-action-submit-signing-request@v3.0
if: ${{ github.repository == 'ciromattia/kcc' }}
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
+17 -11
View File
@@ -55,19 +55,23 @@ You can view the split halves either before or after combined spreads:
Just drop your input files into the KCC window, hit convert, and USB drop the output files onto your device's `documents` folder!
https://github.com/user-attachments/assets/da73d625-e082-482d-91a4-ae4765e96fd7
![settings](images/easy.png)
There are a lot of options, but most people only care about the ones checked above.
Hover over each option to see details in a tooltip.
NOTE: some checkboxes can have a half-check marks.
Then all your usb loaded comic files will show up next to all your normal books in your ereader library!
Here's a quick video demo of how the process works (using expert mode):
https://github.com/user-attachments/assets/da73d625-e082-482d-91a4-ae4765e96fd7
The final result looks incredible on my 10" Kindle Scribe: https://www.youtube.com/watch?v=2CIHW2N9Enc
**WARNING**: Kindle Scribe 2025 MOBI support may have blank pages. Use PDF instead.
The GUI looks like this, built in Qt6.
There are a lot of options, but most people only care about the ones checked below.
Hover over each option to see details in a tooltip.
![settings](images/settings.png)
**WARNING**: Kindle Scribe 2025 MOBI support is limited, converted books may have blank pages. Use PDF instead.
If you are on macOS and use a 2022+ Kindle, you may need to use Amazon USB File Manager for Mac or OpenMTP.
@@ -77,7 +81,7 @@ Installation tutorial: https://www.youtube.com/watch?v=IR2Fhcm9658
## Kindle Jailbreak for KOreader
Jailbreaking to use KOreader is optional. KCC works just fine with the native mobi manga viewer.
Jailbreaking to use KOreader is optional. MOBI manga converted by KCC can be opened in Kindles native reader just fine
But if you jailbreak your Kindle, you'll unlock additional features like:
@@ -86,6 +90,10 @@ But if you jailbreak your Kindle, you'll unlock additional features like:
2) no dependency on kindlegen, which can mean **twice as fast conversions** since you can convert to CBZ directly.
3) You can dither by partially checking the JPG/PNG box and can crop in KCC instead of KOreader. This may increase page turn speed and battery.
Common KOreader manga mistakes: https://youtu.be/gaakIh9p8tw?si=X7OgPJlAvL9XGbLR
Set per folder setting defaults: https://youtu.be/O9p6HVWIQ6s?si=Jtx607erCBA_auWM
### A word of warning
**KCC** _is not_ [Amazon's Kindle Comic Creator](http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1001103761) nor is in any way endorsed by Amazon.
Amazon's tool is for comic publishers and involves a lot of manual effort, while **KCC** is for comic/manga readers.
@@ -175,8 +183,6 @@ You'll need to install various tools to access important but optional features.
### KindleGen
(This is not needed for Koreader users on jailbroken Kindle. Just set output to CBZ instead.)
On Windows and macOS, install [Kindle Previewer](https://www.amazon.com/Kindle-Previewer/b?ie=UTF8&node=21381691011) and `kindlegen` will be autodetected from it.
If you have issues detecting it, get stuck on the MOBI conversion step, or use Linux AppImage or Flatpak, refer to the wiki: https://github.com/ciromattia/kcc/wiki/Installation#kindlegen
+686 -664
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 536 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 619 KiB

+2
View File
@@ -33,6 +33,7 @@ def modify_path():
mac_paths = [
'/Applications/Kindle Comic Creator/Kindle Comic Creator.app/Contents/MacOS',
'/Applications/Kindle Previewer 3.app/Contents/lib/fc/bin/',
'/Applications/Kindle Previewer 4.app/Contents/Resources/KFXGen/bin/'
]
if getattr(sys, 'frozen', False):
os.environ['PATH'] += os.pathsep + os.pathsep.join(mac_paths +
@@ -68,6 +69,7 @@ def modify_path():
os.path.expandvars('%LOCALAPPDATA%\\Amazon\\KC2'),
os.path.expandvars('%LOCALAPPDATA%\\Amazon\\Kindle Previewer 3\\lib\\fc\\bin\\'),
os.path.expandvars('%UserProfile%\\Kindle Previewer 3\\lib\\fc\\bin\\'),
'C:\\Tools',
'C:\\Apps\\Kindle Previewer 3\\lib\\fc\\bin',
'D:\\Apps\\Kindle Previewer 3\\lib\\fc\\bin',
'E:\\Apps\\Kindle Previewer 3\\lib\\fc\\bin',
+115 -37
View File
@@ -32,7 +32,6 @@ import sys
from urllib.parse import unquote
from time import sleep
from shutil import move, rmtree
from subprocess import STDOUT, PIPE, CalledProcessError
import requests
from xml.sax.saxutils import escape
@@ -45,9 +44,9 @@ from PIL.Image import Dither
from .KCC_spread_label import LabelSpreadsDialog
from .shared import HTMLStripper, sanitizeTrace, walkLevel, subprocess_run
from .shared import HTMLStripper, sanitizeTrace, walkLevel
from .comicarchive import SEVENZIP, TAR, available_archive_tools
from .comic2ebook import OS_SORT_KEY, flattenTree, getWorkFolder, removeNonImages, sanitizeTree
from .comic2ebook import OS_SORT_KEY, flattenTree, getWorkFolder, removeNonImages, sanitizeTree, detectKindleGen
from . import __version__
from . import comic2ebook
from . import metadata
@@ -155,17 +154,21 @@ class Icons:
class VersionThread(QThread):
def __init__(self):
def __init__(self, startNumber2):
QThread.__init__(self)
self.newVersion = ''
self.md5 = ''
self.barProgress = 0
self.answer = None
self.startNumber2 = startNumber2
def __del__(self):
self.wait()
def run(self):
if self.startNumber2 < 5:
return
try:
# unauthenticated API requests limit is 60 req/hour
if getattr(sys, 'frozen', False):
@@ -414,6 +417,7 @@ class WorkerThread(QThread):
if GUI.jobList.item(i).icon().isNull():
currentJobs.append(str(GUI.jobList.item(i).text()))
GUI.jobList.clear()
fusion_cover_path = None
if options.filefusion:
bookDir = []
MW.addMessage.emit('Attempting file fusion', 'info', False)
@@ -425,7 +429,8 @@ class WorkerThread(QThread):
if options.output is None:
options.output = fusion_source_parent
currentJobs.clear()
currentJobs.append(comic2ebook.makeFusion(bookDir))
job, fusion_cover_path = comic2ebook.makeFusion(bookDir)
currentJobs.append(job)
MW.addMessage.emit('Created fusion at ' + currentJobs[0], 'info', False)
except Exception as e:
print('Fusion Failed. ' + str(e))
@@ -459,7 +464,7 @@ class WorkerThread(QThread):
jobargv.append(job)
try:
comic2ebook.options = comic2ebook.checkOptions(copy(options))
outputPath = comic2ebook.makeBook(job, self, job_progress_number)
outputPath = comic2ebook.makeBook(job, fusion_cover_path, self, job_progress_number)
MW.hideProgressBar.emit()
except UserWarning as warn:
if not self.conversionAlive:
@@ -823,6 +828,91 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
# noinspection PyCallByClass
QDesktopServices.openUrl(QUrl('https://humblebundleinc.sjv.io/3JaR3A'))
def toggleExpert(self):
# noinspection PyCallByClass
if self.expertMode:
self.hide_expert_options()
self.expertMode = False
else:
self.show_expert_options()
self.expertMode = True
def show_expert_options(self):
GUI.spreadShiftBox.show()
GUI.fileFusionBox.show()
GUI.jpegQualityBox.show()
GUI.pngLegacyBox.show()
GUI.webpBox.show()
GUI.lightnovelBox.show()
GUI.wallpaperBox.show()
GUI.outputSplit.show()
GUI.maximizeStrips.show()
GUI.noRotateBox.show()
GUI.rotateFirstBox.show()
GUI.coverFillBox.show()
GUI.rotateRightBox.show()
GUI.smartCoverCropBox.show()
GUI.onePageLandscapeBox.show()
GUI.qualityBox.show()
GUI.gammaBox.show()
GUI.interPanelCropBox.show()
GUI.autoLevelBox.show()
GUI.autocontrastBox.show()
GUI.vertical4PanelBox.show()
GUI.tempDirBox.show()
GUI.deleteBox.show()
GUI.metadataTitleBox.show()
GUI.keepComicInfoBox.show()
GUI.pdfWidthBox.show()
GUI.chunkSizeCheckBox.show()
GUI.disableProcessingBox.show()
GUI.noQuantizeBox.show()
GUI.forcePngRgbBox.show()
GUI.invertDirectionBox.show()
GUI.ebokBox.show()
GUI.languageEdit.show()
GUI.labelSpreadsButton.show()
GUI.editorButton.show()
GUI.easyLabel.hide()
def hide_expert_options(self):
GUI.spreadShiftBox.hide()
GUI.fileFusionBox.hide()
GUI.jpegQualityBox.hide()
GUI.pngLegacyBox.hide()
GUI.webpBox.hide()
GUI.lightnovelBox.hide()
GUI.wallpaperBox.hide()
GUI.outputSplit.hide()
GUI.maximizeStrips.hide()
GUI.noRotateBox.hide()
GUI.rotateFirstBox.hide()
GUI.coverFillBox.hide()
GUI.rotateRightBox.hide()
GUI.smartCoverCropBox.hide()
GUI.onePageLandscapeBox.hide()
GUI.qualityBox.hide()
GUI.gammaBox.hide()
GUI.interPanelCropBox.hide()
GUI.autoLevelBox.hide()
GUI.autocontrastBox.hide()
GUI.vertical4PanelBox.hide()
GUI.tempDirBox.hide()
GUI.deleteBox.hide()
GUI.metadataTitleBox.hide()
GUI.keepComicInfoBox.hide()
GUI.pdfWidthBox.hide()
GUI.chunkSizeCheckBox.hide()
GUI.disableProcessingBox.hide()
GUI.noQuantizeBox.hide()
GUI.forcePngRgbBox.hide()
GUI.invertDirectionBox.hide()
GUI.ebokBox.hide()
GUI.languageEdit.hide()
GUI.labelSpreadsButton.hide()
GUI.editorButton.hide()
GUI.easyLabel.show()
def openYouTube(self):
# noinspection PyCallByClass
QDesktopServices.openUrl(QUrl('https://www.youtube.com/@eink-dude'))
@@ -1164,8 +1254,8 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.needClean = True
return
if 'MOBI' in GUI.formats[str(GUI.formatBox.currentText())]['format'] and not self.kindleGen:
self.detectKindleGen()
if not self.kindleGen:
if not detectKindleGen(GUI):
self.progress.stop()
GUI.jobList.clear()
self.display_kindlegen_missing()
self.needClean = True
@@ -1188,11 +1278,13 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
if not GUI.convertButton.isEnabled():
event.ignore()
self.settings.setValue('settingsVersion', __version__)
self.settings.setValue('expertMode', self.expertMode)
self.settings.setValue('lastPath', self.lastPath)
self.settings.setValue('defaultOutputFolder', self.defaultOutputFolder)
self.settings.setValue('lastDevice', GUI.deviceBox.currentIndex())
self.settings.setValue('currentFormat', GUI.formatBox.currentIndex())
self.settings.setValue('startNumber', self.startNumber + 1)
self.settings.setValue('startNumber2', self.startNumber2 + 1)
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(),
@@ -1291,32 +1383,6 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.saveSettings(None)
sys.exit(0)
def detectKindleGen(self, startup=False):
if not sys.platform.startswith('win'):
try:
os.chmod('/usr/local/bin/kindlegen', 0o755)
except Exception:
pass
try:
versionCheck = subprocess_run(['kindlegen', '-locale', 'en'], stdout=PIPE, stderr=STDOUT, encoding='UTF-8', errors='ignore', check=True)
self.kindleGen = True
for line in versionCheck.stdout.splitlines():
if 'Amazon kindlegen' in line:
versionCheck = line.split('V')[1].split(' ')[0]
if Version(versionCheck) < Version('2.9'):
self.addMessage('Your <a href="https://www.amazon.com/b?node=23496309011">KindleGen</a>'
' is outdated! MOBI conversion might fail.', 'warning')
break
except (FileNotFoundError, CalledProcessError):
self.kindleGen = False
if startup:
self.display_kindlegen_missing()
except OSError as e:
self.kindleGen = False
if startup:
error = f"kindlegen: {e.strerror}\n\n Re-install Rosetta/Kindle Previewer/other Intel app?\n\nPlease email Amazon to make Kindle Previewer Apple silicon native at amazon.com/kindle-help"
self.showDialog(error, 'error')
def __init__(self, kccapp, kccwindow):
global APP, MW, GUI
APP = kccapp
@@ -1332,11 +1398,18 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
if not os.path.exists(self.defaultOutputFolder):
self.defaultOutputFolder = ''
self.expertMode = self.settings.value('expertMode', False, type=bool)
if not self.expertMode:
GUI.hide_expert_options()
else:
GUI.easyLabel.hide()
# default is Kindle Paperwhite 12th Gen
self.lastDevice = self.settings.value('lastDevice', 3, type=int)
self.currentFormat = self.settings.value('currentFormat', 0, type=int)
self.startNumber = self.settings.value('startNumber', 0, type=int)
self.startNumber2 = self.settings.value('startNumber2', 0, type=int)
self.windowSize = self.settings.value('windowSize', '0x0', type=str)
default_options = {'gammaSlider': 0, 'croppingBox': 2, 'croppingPowerSlider': 100, 'rotateBox': 1, 'mangaBox': 2}
try:
@@ -1344,8 +1417,11 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
except Exception:
self.options = default_options
self.worker = WorkerThread()
self.versionCheck = VersionThread()
self.worker.setObjectName('worker')
self.versionCheck = VersionThread(self.startNumber2)
self.versionCheck.setObjectName('version')
self.progress = ProgressThread()
self.progress.setObjectName('progress')
self.tray = SystemTrayIcon()
self.conversionAlive = False
self.needClean = True
@@ -1562,8 +1638,10 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
statusBarLabel.setOpenExternalLinks(True)
GUI.statusBar.addPermanentWidget(statusBarLabel, 1)
self.addMessage('<b>Tip:</b> Hover mouse over options to see additional information in tooltips.', 'info')
self.addMessage('<b>Tip:</b> Hover mouse over options/buttons to see explanations. Boxes can be partially/fully checked.', 'info')
self.addMessage('<b>Tip:</b> You can drag and drop image folders or comic files/archives into this window to convert.', 'info')
self.addMessage("<b>Tip:</b> Calibre may add margins! USB drop directly into the device's documents folder instead.", 'info')
self.addMessage("<b>Tip:</b> You can toggle easy/expert mode using button at top right.", 'info')
if self.startNumber < 5:
self.addMessage('Since you are a new user of <b>KCC</b> please see few '
'<a href="https://github.com/ciromattia/kcc/wiki/Important-tips">important tips</a>.',
@@ -1574,7 +1652,6 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
if not any([self.tar, self.sevenzip]):
self.addMessage('<a href="https://github.com/ciromattia/kcc#7-zip">Install 7z (link)</a>'
' to enable CBZ/CBR/ZIP/etc processing.', 'warning')
self.detectKindleGen(True)
APP.messageFromOtherInstance.connect(self.handleMessage)
GUI.defaultOutputFolderButton.clicked.connect(self.selectDefaultOutputFolder)
@@ -1584,6 +1661,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
GUI.editorButton.clicked.connect(self.selectFileMetaEditor)
GUI.kofiButton.clicked.connect(self.openKofi)
GUI.humbleButton.clicked.connect(self.openHumble)
GUI.expertButton.clicked.connect(self.toggleExpert)
GUI.convertButton.clicked.connect(self.convertStart)
GUI.labelSpreadsButton.clicked.connect(self.labelSpreadsStart)
GUI.gammaSlider.valueChanged.connect(self.changeGamma)
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,4 +1,4 @@
__version__ = '11.1.0'
__version__ = '11.3.1'
__license__ = 'ISC'
__copyright__ = '2012-2022, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>, darodi'
__docformat__ = 'restructuredtext en'
+73 -14
View File
@@ -40,6 +40,7 @@ from shutil import move, copytree, rmtree
from multiprocessing import Pool, cpu_count
from uuid import uuid4
from natsort import os_sort_keygen, os_sorted
from packaging.version import Version
from slugify import slugify as slugify_ext
from PIL import Image, ImageFile, ImageOps
from pathlib import Path
@@ -77,9 +78,10 @@ def main(argv=None):
if len(sources) == 0:
print('No matching files found.')
return 1
fusion_cover_path = None
if options.filefusion:
fusion_source_parent = str(Path(sources[0]).parent)
fusion_path = makeFusion(list(sources))
fusion_path, fusion_cover_path = makeFusion(list(sources))
sources.clear()
sources.append(fusion_path)
for source in sources:
@@ -89,7 +91,7 @@ def main(argv=None):
options.output = fusion_source_parent
options = checkOptions(options)
print('Working on ' + source + '...')
makeBook(source)
makeBook(source, fusion_cover_path)
return 0
@@ -1748,17 +1750,58 @@ def checkTools(source):
print('ERROR: 7z is missing!')
sys.exit(1)
if options.format == 'MOBI':
try:
subprocess_run(['kindlegen', '-locale', 'en'], stdout=PIPE, stderr=STDOUT, check=True)
except (FileNotFoundError, CalledProcessError):
print('ERROR: KindleGen is missing!')
sys.exit(1)
except OSError as e:
print(f"kindlegen: {e.strerror}")
print('Re-install Rosetta/Kindle Previewer/other Intel app?')
print('Please email Amazon to make Kindle Previewer Apple silicon native at amazon.com/kindle-help')
if not detectKindleGen():
sys.exit(1)
def detectKindleGen(GUI=None):
if sys.platform.startswith('win'):
if not _detectKindleGen():
start = perf_counter()
try:
for i in range(0, 200):
for j in range(0, 20):
for k in range (0, 20):
path = f'C:\\Program Files\\WindowsApps\\KindlePreviewerApp_4.{i}.{j}.{k}_x64__ek06e0aw29nma'
if os.path.exists(path):
kindlegen_path = os.path.join(path, 'KindlePreviewerApp\\resources\\KFXGen\\bin\\kindlegen.exe')
tool_path = 'C:\\Tools'
if not os.path.isdir(tool_path):
os.mkdir(tool_path)
shutil.copy2(kindlegen_path, tool_path)
except Exception:
pass
end = perf_counter()
print(f"Search for Windows KindleGen: {end - start} sec")
return _detectKindleGen(GUI)
else:
try:
os.chmod('/usr/local/bin/kindlegen', 0o755)
except Exception:
pass
return _detectKindleGen(GUI)
def _detectKindleGen(GUI=None):
try:
versionCheck = subprocess_run(['kindlegen', '-locale', 'en'], stdout=PIPE, stderr=STDOUT, encoding='UTF-8', errors='ignore', check=True)
for line in versionCheck.stdout.splitlines():
if 'Amazon kindlegen' in line:
versionCheck = line.split('V')[1].split(' ')[0]
if Version(versionCheck) < Version('2.9'):
if GUI:
GUI.addMessage('Your <a href="https://www.amazon.com/b?node=23496309011">KindleGen</a>'
' is outdated! MOBI conversion might fail.', 'warning')
break
return True
except (FileNotFoundError, CalledProcessError):
print('ERROR: KindleGen is missing!')
return False
except (OSError, Exception) as e:
print(f"kindlegen: {e.strerror}")
print('Re-install or re-open Rosetta/Kindle Previewer/other Intel app?')
if GUI:
error = f"kindlegen: {e.strerror}\n\n Re-install or re-open Rosetta/Kindle Previewer/other Intel app?"
GUI.showDialog(error, 'error')
return False
def checkPre(source='KCC-'):
# Make sure that all temporary files are gone
@@ -1773,6 +1816,19 @@ def makeFusion(sources: List[str]):
start = perf_counter()
first_path = Path(sources[0])
fusion_cover_path = None
if first_path.parent.joinpath('Covers').is_dir():
covers = os.listdir(first_path.parent.joinpath('Covers'))
filtered_covers = []
for cover in covers:
_, cover_ext = getImageFileName(cover)
if cover_ext in IMAGE_TYPES:
filtered_covers.append(cover)
try:
fusion_cover_path = first_path.parent.joinpath('Covers', filtered_covers[0])
except IndexError:
pass
if options.tempdir:
fusion_parent = first_path.parent
else:
@@ -1814,10 +1870,10 @@ def makeFusion(sources: List[str]):
print(f"makefusion: {end - start} seconds")
print("Combined File: "+ str(fusion_path))
return str(fusion_path)
return str(fusion_path), fusion_cover_path
def makeBook(source, qtgui=None, job_progress=''):
def makeBook(source, fusion_cover_path=None, qtgui=None, job_progress=''):
start = perf_counter()
global GUI
GUI = qtgui
@@ -1912,9 +1968,12 @@ def makeBook(source, qtgui=None, job_progress=''):
options.customcover = True
except IndexError:
pass
if fusion_cover_path:
options.customcover = True
cover_path = fusion_cover_path
cover = None
if not options.webtoon:
if not options.webtoon or options.customcover:
cover = image.Cover(cover_path, options)
x, y = image.ProfileData.Profiles[options.profile][1]
+1 -1
View File
@@ -99,7 +99,7 @@ class ComicArchive:
pass
if missing:
raise OSError(f'Extraction failed, install <a href="https://github.com/ciromattia/kcc#7-zip">specialized extraction software.</a> ')
raise UserWarning(f'Extraction failed, install <a href="https://github.com/ciromattia/kcc#7-zip">specialized extraction software.</a> ')
else:
raise OSError(EXTRACTION_ERROR)
+27 -9
View File
@@ -1,4 +1,5 @@
from PIL import ImageOps, ImageFilter, ImageFile
from PIL.Image import Image
import numpy as np
from .common_crop import threshold_from_power, group_close_values
@@ -149,22 +150,39 @@ def get_bbox_crop_margin(img, power=1, background_color='white'):
return bw_img.getbbox()
def ignore_pixels_near_edge(bw_img):
def ignore_pixels_near_edge(bw_img: Image):
w, h = bw_img.size
# going 0.02-0.03 was too much
if int(0.02 * h) == int(0.025 * h):
return
if int(0.02 * w) == int(0.025 * w):
return
edge_bbox = [
(0, 0, w, int(0.02 * h)),
(0, int(0.98 * h), w, h),
(0, 0, int(0.02 * w), h),
(int(0.98 * w), 0, w, h)
]
for box in edge_bbox:
edge = bw_img.crop(box)
h = edge.histogram()
if not edge.height or not edge.width:
continue
imperfections = h[255] / (edge.height * edge.width)
if imperfections > 0 and imperfections < .02:
bw_img.paste(im=0, box=box)
inner_bbox = [
(int(0.02 * w), int(0.02 * h), int(0.98 * w), int(0.025 * h)), # top
(int(0.02 * w), int(0.975 * h), int(0.98 * w), int(0.98 * h)), # lower
(int(0.02 * w), int(0.02 * h), int(0.025 * w), int(0.98 * h)), # left
(int(0.975 * w), int(0.02 * h), int(0.98 * w), int(0.98 * h)), # right
]
for edge_box, inner_box in zip(edge_bbox, inner_bbox):
inner_edge = bw_img.crop(inner_box)
h = inner_edge.histogram()
imperfections = h[255] / (inner_edge.height * inner_edge.width)
if imperfections > 0 and imperfections < .001:
bw_img.paste(im=0, box=inner_box)
if imperfections < .001:
edge = bw_img.crop(edge_box)
edge_h = edge.histogram()
if edge_h[-1] != 0:
bw_img.paste(im=0, box=edge_box)
def box_intersect(box1, box2, max_dist):