mirror of
https://github.com/ciromattia/kcc
synced 2026-09-01 08:27:06 +00:00
add light novel mode (#1361)
* add a novel mode where it only resizes images * add GUI * cleanup * fix typo * fully cooked * remove print * clean up * cook * cook * handle LA case * cleanup
This commit is contained in:
@@ -239,6 +239,7 @@ MAIN:
|
|||||||
Device profile (Available options: K1, K2, K34, K578, KDX, KPW, KPW5, KV, KO, K11, KS, KoMT, KoG, KoGHD, KoA, KoAHD, KoAH2O, KoAO, KoN, KoC, KoCC, KoL, KoLC, KoF, KoS, KoE)
|
Device profile (Available options: K1, K2, K34, K578, KDX, KPW, KPW5, KV, KO, K11, KS, KoMT, KoG, KoGHD, KoA, KoAHD, KoAH2O, KoAO, KoN, KoC, KoCC, KoL, KoLC, KoF, KoS, KoE)
|
||||||
[Default=KV]
|
[Default=KV]
|
||||||
-m, --manga-style Manga style (right-to-left reading and splitting)
|
-m, --manga-style Manga style (right-to-left reading and splitting)
|
||||||
|
--lightnovel Only resize images and preserve original file structure.
|
||||||
--ebok Force EBOK tag instead of PDOC for MOBI
|
--ebok Force EBOK tag instead of PDOC for MOBI
|
||||||
--invertdirection Invert page turn direction
|
--invertdirection Invert page turn direction
|
||||||
-q, --hq Try to increase the quality of magnification
|
-q, --hq Try to increase the quality of magnification
|
||||||
|
|||||||
+12
@@ -990,6 +990,18 @@ Ignored for Kindle EPUB/MOBI and all PDF.</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="10" column="0">
|
||||||
|
<widget class="QCheckBox" name="lightnovelBox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Only resize images and preserve original file structure.
|
||||||
|
|
||||||
|
Ignores most options besides JPEG quality, color mode, output folder.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Light novel mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
@@ -273,6 +273,8 @@ class WorkerThread(QThread):
|
|||||||
options.format = gui_current_format
|
options.format = gui_current_format
|
||||||
if GUI.mangaBox.isChecked():
|
if GUI.mangaBox.isChecked():
|
||||||
options.righttoleft = True
|
options.righttoleft = True
|
||||||
|
if GUI.lightnovelBox.isChecked():
|
||||||
|
options.lightnovel = True
|
||||||
if GUI.ebokBox.isChecked():
|
if GUI.ebokBox.isChecked():
|
||||||
options.ebok = True
|
options.ebok = True
|
||||||
if GUI.invertDirectionBox.isChecked():
|
if GUI.invertDirectionBox.isChecked():
|
||||||
@@ -476,7 +478,7 @@ class WorkerThread(QThread):
|
|||||||
MW.addMessage.emit('Creating PDF files... <b>Done!</b>', 'info', True)
|
MW.addMessage.emit('Creating PDF files... <b>Done!</b>', 'info', True)
|
||||||
else:
|
else:
|
||||||
MW.addMessage.emit('Creating EPUB files... <b>Done!</b>', 'info', True)
|
MW.addMessage.emit('Creating EPUB files... <b>Done!</b>', 'info', True)
|
||||||
if 'MOBI' in gui_current_format:
|
if 'MOBI' in gui_current_format and not options.lightnovel:
|
||||||
MW.progressBarTick.emit(f'{job_progress_number}Creating MOBI files')
|
MW.progressBarTick.emit(f'{job_progress_number}Creating MOBI files')
|
||||||
MW.progressBarTick.emit(str(len(outputPath) * 2 + 1))
|
MW.progressBarTick.emit(str(len(outputPath) * 2 + 1))
|
||||||
MW.progressBarTick.emit('tick')
|
MW.progressBarTick.emit('tick')
|
||||||
@@ -1085,6 +1087,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
|||||||
self.settings.setValue('startNumber', self.startNumber + 1)
|
self.settings.setValue('startNumber', self.startNumber + 1)
|
||||||
self.settings.setValue('windowSize', str(MW.size().width()) + 'x' + str(MW.size().height()))
|
self.settings.setValue('windowSize', str(MW.size().width()) + 'x' + str(MW.size().height()))
|
||||||
self.settings.setValue('options', {'mangaBox': GUI.mangaBox.checkState(),
|
self.settings.setValue('options', {'mangaBox': GUI.mangaBox.checkState(),
|
||||||
|
'lightnovelBox': GUI.lightnovelBox.checkState(),
|
||||||
'ebokBox': GUI.ebokBox.checkState(),
|
'ebokBox': GUI.ebokBox.checkState(),
|
||||||
'invertDirectionBox': GUI.invertDirectionBox.checkState(),
|
'invertDirectionBox': GUI.invertDirectionBox.checkState(),
|
||||||
'languageEdit': GUI.languageEdit.text(),
|
'languageEdit': GUI.languageEdit.text(),
|
||||||
|
|||||||
@@ -502,6 +502,11 @@ class Ui_mainWindow(object):
|
|||||||
|
|
||||||
self.gridLayout_2.addWidget(self.ebokBox, 10, 3, 1, 1)
|
self.gridLayout_2.addWidget(self.ebokBox, 10, 3, 1, 1)
|
||||||
|
|
||||||
|
self.lightnovelBox = QCheckBox(self.optionWidget)
|
||||||
|
self.lightnovelBox.setObjectName(u"lightnovelBox")
|
||||||
|
|
||||||
|
self.gridLayout_2.addWidget(self.lightnovelBox, 10, 0, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
self.gridLayout.addWidget(self.optionWidget, 5, 0, 1, 2)
|
self.gridLayout.addWidget(self.optionWidget, 5, 0, 1, 2)
|
||||||
|
|
||||||
@@ -877,6 +882,12 @@ class Ui_mainWindow(object):
|
|||||||
self.ebokBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p>Force Kindle MOBI to be be tagged as EBOK instead of PDOC.</p><p>This may cause USB loaded books to be deleted if you go online after a month offline.</p></body></html>", None))
|
self.ebokBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p>Force Kindle MOBI to be be tagged as EBOK instead of PDOC.</p><p>This may cause USB loaded books to be deleted if you go online after a month offline.</p></body></html>", None))
|
||||||
#endif // QT_CONFIG(tooltip)
|
#endif // QT_CONFIG(tooltip)
|
||||||
self.ebokBox.setText(QCoreApplication.translate("mainWindow", u"Force EBOK", None))
|
self.ebokBox.setText(QCoreApplication.translate("mainWindow", u"Force EBOK", None))
|
||||||
|
#if QT_CONFIG(tooltip)
|
||||||
|
self.lightnovelBox.setToolTip(QCoreApplication.translate("mainWindow", u"Only resize images and preserve original file structure.\n"
|
||||||
|
"\n"
|
||||||
|
"Ignores most options besides JPEG quality, color mode, output folder.", None))
|
||||||
|
#endif // QT_CONFIG(tooltip)
|
||||||
|
self.lightnovelBox.setText(QCoreApplication.translate("mainWindow", u"Light novel mode", None))
|
||||||
#if QT_CONFIG(tooltip)
|
#if QT_CONFIG(tooltip)
|
||||||
self.hLabel.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Resolution of the target device.</p></body></html>", None))
|
self.hLabel.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Resolution of the target device.</p></body></html>", None))
|
||||||
#endif // QT_CONFIG(tooltip)
|
#endif // QT_CONFIG(tooltip)
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ from multiprocessing import Pool, cpu_count
|
|||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from natsort import os_sort_keygen, os_sorted
|
from natsort import os_sort_keygen, os_sorted
|
||||||
from slugify import slugify as slugify_ext
|
from slugify import slugify as slugify_ext
|
||||||
from PIL import Image, ImageFile
|
from PIL import Image, ImageFile, ImageOps
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from subprocess import STDOUT, PIPE, CalledProcessError
|
from subprocess import STDOUT, PIPE, CalledProcessError
|
||||||
from psutil import virtual_memory, disk_usage
|
from psutil import virtual_memory, disk_usage
|
||||||
@@ -965,6 +965,8 @@ def getWorkFolder(afile, workdir=None):
|
|||||||
try:
|
try:
|
||||||
cbx = comicarchive.ComicArchive(afile)
|
cbx = comicarchive.ComicArchive(afile)
|
||||||
path = cbx.extract(fullPath)
|
path = cbx.extract(fullPath)
|
||||||
|
if options.lightnovel:
|
||||||
|
return workdir
|
||||||
sanitizePermissions(path)
|
sanitizePermissions(path)
|
||||||
|
|
||||||
tdir = os.listdir(fullPath)
|
tdir = os.listdir(fullPath)
|
||||||
@@ -1448,6 +1450,8 @@ def makeParser():
|
|||||||
" [Default=KV]")
|
" [Default=KV]")
|
||||||
main_options.add_argument("-m", "--manga-style", action="store_true", dest="righttoleft", default=False,
|
main_options.add_argument("-m", "--manga-style", action="store_true", dest="righttoleft", default=False,
|
||||||
help="Manga style (right-to-left reading and splitting)")
|
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("--ebok", action="store_true", dest="ebok", default=False,
|
main_options.add_argument("--ebok", action="store_true", dest="ebok", default=False,
|
||||||
help="Force EBOK tag instead of PDOC for MOBI")
|
help="Force EBOK tag instead of PDOC for MOBI")
|
||||||
main_options.add_argument("--invertdirection", action="store_true", dest="invertdirection", default=False,
|
main_options.add_argument("--invertdirection", action="store_true", dest="invertdirection", default=False,
|
||||||
@@ -1582,6 +1586,9 @@ def checkOptions(options):
|
|||||||
else:
|
else:
|
||||||
options.isKobo = True
|
options.isKobo = True
|
||||||
|
|
||||||
|
if options.lightnovel:
|
||||||
|
options.noKepub = True
|
||||||
|
|
||||||
if not options.iskindle and ('MOBI' in options.format or 'EPUB-200MB' in options.format or 'KFX' in options.format):
|
if not options.iskindle and ('MOBI' in options.format or 'EPUB-200MB' in options.format or 'KFX' in options.format):
|
||||||
raise UserWarning('MOBI/Send to Kindle not supported for non-Kindle profiles')
|
raise UserWarning('MOBI/Send to Kindle not supported for non-Kindle profiles')
|
||||||
|
|
||||||
@@ -1779,6 +1786,35 @@ def makeBook(source, qtgui=None, job_progress=''):
|
|||||||
print(f"{job_progress}Preparing source images...")
|
print(f"{job_progress}Preparing source images...")
|
||||||
path = getWorkFolder(source)
|
path = getWorkFolder(source)
|
||||||
print(f"{job_progress}Checking images...")
|
print(f"{job_progress}Checking images...")
|
||||||
|
|
||||||
|
if options.lightnovel:
|
||||||
|
for root, _, files in os.walk(os.path.join(path, 'OEBPS', 'Images')):
|
||||||
|
for file in files:
|
||||||
|
_, ext = os.path.splitext(file)
|
||||||
|
if ext.lower() in ('.jpg', '.jpeg', '.png', '.webp', '.gif'):
|
||||||
|
with Image.open(os.path.join(root, file)) as img:
|
||||||
|
# TODO: detect BW images saved as RGB
|
||||||
|
if not options.forcecolor:
|
||||||
|
if img.mode == 'RGB':
|
||||||
|
img = img.convert('L')
|
||||||
|
elif img.mode == 'RGBA':
|
||||||
|
img = img.convert('LA')
|
||||||
|
x, y = image.ProfileData.Profiles[options.profile][1]
|
||||||
|
if options.iskindle:
|
||||||
|
x = min(x, 1920)
|
||||||
|
y = min(y, 1920)
|
||||||
|
if img.size[0] > x or img.size[1] > y:
|
||||||
|
img = ImageOps.contain(img, (x, y))
|
||||||
|
img.save(os.path.join(root, file), quality=options.jpegquality)
|
||||||
|
_, ext = os.path.splitext(source)
|
||||||
|
if ext != '.epub':
|
||||||
|
ext = '.cbz'
|
||||||
|
output_file = getOutputFilename(source, options.output, ext, '')
|
||||||
|
makeZIP(output_file, os.path.join(path, 'OEBPS', 'Images'), job_progress)
|
||||||
|
rmtree(path, True)
|
||||||
|
|
||||||
|
return [output_file]
|
||||||
|
|
||||||
getMetadata(os.path.join(path, "OEBPS", "Images"), source)
|
getMetadata(os.path.join(path, "OEBPS", "Images"), source)
|
||||||
removeNonImages(os.path.join(path, "OEBPS", "Images"))
|
removeNonImages(os.path.join(path, "OEBPS", "Images"))
|
||||||
detectSuboptimalProcessing(os.path.join(path, "OEBPS", "Images"), source)
|
detectSuboptimalProcessing(os.path.join(path, "OEBPS", "Images"), source)
|
||||||
@@ -1892,7 +1928,7 @@ def makeBook(source, qtgui=None, job_progress=''):
|
|||||||
rmtree(tome, True)
|
rmtree(tome, True)
|
||||||
if GUI:
|
if GUI:
|
||||||
GUI.progressBarTick.emit('tick')
|
GUI.progressBarTick.emit('tick')
|
||||||
if not GUI and options.format == 'MOBI':
|
if not GUI and options.format == 'MOBI' and not options.lightnovel:
|
||||||
print(f"{job_progress}Creating MOBI files...")
|
print(f"{job_progress}Creating MOBI files...")
|
||||||
work = []
|
work = []
|
||||||
for i in filepath:
|
for i in filepath:
|
||||||
|
|||||||
Reference in New Issue
Block a user