mirror of
https://github.com/ciromattia/kcc
synced 2025-12-13 09:46:25 +00:00
10
README.md
10
README.md
@@ -90,7 +90,10 @@ Options:
|
||||
-f FORMAT, --format=FORMAT
|
||||
Output format (Available options: Auto, MOBI, EPUB,
|
||||
CBZ) [Default=Auto]
|
||||
-b, --batchsplit Split output into multiple files
|
||||
-b BATCHSPLIT, --batchsplit=BATCHSPLIT
|
||||
Split output into multiple files. 0: Don't split 1:
|
||||
Automatic mode 2: Consider every subdirectory as
|
||||
separate volume [Default=0]
|
||||
|
||||
PROCESSING:
|
||||
-u, --upscale Resize images smaller than device's resolution
|
||||
@@ -160,6 +163,11 @@ The app relies and includes the following scripts:
|
||||
* [Kobo Aura ONE](http://kcc.iosphe.re/Samples/Ubunchu-KoAO.kepub.epub)
|
||||
|
||||
## CHANGELOG
|
||||
####5.2.1:
|
||||
* Improved directory parsing
|
||||
* Tweaked margin detection algorithm
|
||||
* Improved error reporting
|
||||
|
||||
####5.2:
|
||||
* Added new Panel View options
|
||||
* Implemented new margin detection algorithm
|
||||
|
||||
@@ -228,12 +228,12 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="noDitheringBox">
|
||||
<widget class="QCheckBox" name="outputSplit">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p style='white-space:pre'>Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files <span style=" font-weight:600;">might</span> be smaller.<br/><span style=" font-weight:600;">MOBI conversion will be much slower.</span></p></body></html></string>
|
||||
<string><html><head/><body><p style='white-space:pre'><span style=" font-weight:600; text-decoration: underline;">Unchecked - Automatic mode<br/></span>Output will be splitted automatically.</p><p style='white-space:pre'><span style=" font-weight:600; text-decoration: underline;">Checked - Volume mode<br/></span>Every subdirectory will be considered as separate volume.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PNG output</string>
|
||||
<string>Output split</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -510,7 +510,7 @@
|
||||
<tabstop>upscaleBox</tabstop>
|
||||
<tabstop>gammaBox</tabstop>
|
||||
<tabstop>borderBox</tabstop>
|
||||
<tabstop>noDitheringBox</tabstop>
|
||||
<tabstop>outputSplit</tabstop>
|
||||
<tabstop>colorBox</tabstop>
|
||||
<tabstop>editorButton</tabstop>
|
||||
<tabstop>wikiButton</tabstop>
|
||||
|
||||
2
kcc.iss
2
kcc.iss
@@ -1,5 +1,5 @@
|
||||
#define MyAppName "Kindle Comic Converter"
|
||||
#define MyAppVersion "5.2"
|
||||
#define MyAppVersion "5.2.1"
|
||||
#define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
|
||||
#define MyAppURL "http://kcc.iosphe.re/"
|
||||
#define MyAppExeName "KCC.exe"
|
||||
|
||||
@@ -21,17 +21,15 @@ import os
|
||||
import sys
|
||||
from urllib.parse import unquote
|
||||
from urllib.request import urlopen, urlretrieve, Request
|
||||
from time import sleep, time
|
||||
from datetime import datetime
|
||||
from time import sleep
|
||||
from shutil import move
|
||||
from subprocess import STDOUT, PIPE
|
||||
from PyQt5 import QtGui, QtCore, QtWidgets, QtNetwork
|
||||
from xml.dom.minidom import parse, Document
|
||||
from xml.dom.minidom import parse
|
||||
from psutil import Popen, Process
|
||||
from copy import copy
|
||||
from distutils.version import StrictVersion
|
||||
from xml.sax.saxutils import escape
|
||||
from platform import platform
|
||||
from raven import Client
|
||||
from .shared import md5Checksum, HTMLStripper, sanitizeTrace, saferRemove
|
||||
from . import __version__
|
||||
@@ -270,8 +268,8 @@ class WorkerThread(QtCore.QThread):
|
||||
options.white_borders = True
|
||||
elif GUI.borderBox.checkState() == 2:
|
||||
options.black_borders = True
|
||||
if GUI.noDitheringBox.isChecked():
|
||||
options.forcepng = True
|
||||
if GUI.outputSplit.isChecked():
|
||||
options.batchsplit = 2
|
||||
if GUI.colorBox.isChecked():
|
||||
options.forcecolor = True
|
||||
if GUI.currentMode > 2:
|
||||
@@ -319,10 +317,15 @@ class WorkerThread(QtCore.QThread):
|
||||
GUI.progress.content = ''
|
||||
self.errors = True
|
||||
_, _, traceback = sys.exc_info()
|
||||
if len(err.args) == 1:
|
||||
MW.showDialog.emit("Error during conversion %s:\n\n%s\n\nTraceback:\n%s"
|
||||
% (jobargv[-1], str(err), sanitizeTrace(traceback)), 'error')
|
||||
else:
|
||||
MW.showDialog.emit("Error during conversion %s:\n\n%s\n\nTraceback:\n%s"
|
||||
% (jobargv[-1], str(err.args[0]), err.args[1]), 'error')
|
||||
GUI.sentry.extra_context({'realTraceback': err.args[1]})
|
||||
if ' is corrupted.' not in str(err):
|
||||
GUI.sentry.captureException()
|
||||
MW.showDialog.emit("Error during conversion %s:\n\n%s\n\nTraceback:\n%s"
|
||||
% (jobargv[-1], str(err), sanitizeTrace(traceback)), 'error')
|
||||
MW.addMessage.emit('Error during conversion! Please consult '
|
||||
'<a href="https://github.com/ciromattia/kcc/wiki/Error-messages">wiki</a> '
|
||||
'for more details.', 'error', False)
|
||||
@@ -528,7 +531,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
||||
def clearJobs(self):
|
||||
GUI.jobList.clear()
|
||||
|
||||
# noinspection PyCallByClass,PyTypeChecker,PyArgumentList
|
||||
# noinspection PyCallByClass,PyTypeChecker
|
||||
def openWiki(self):
|
||||
QtGui.QDesktopServices.openUrl(QtCore.QUrl('https://github.com/ciromattia/kcc/wiki'))
|
||||
|
||||
@@ -646,6 +649,11 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
||||
else:
|
||||
GUI.formatBox.setCurrentIndex(profile['DefaultFormat'])
|
||||
GUI.qualityBox.setEnabled(profile['PVOptions'])
|
||||
if str(GUI.formatBox.currentText()) == 'MOBI/AZW3':
|
||||
GUI.outputSplit.setEnabled(True)
|
||||
else:
|
||||
GUI.outputSplit.setEnabled(False)
|
||||
GUI.outputSplit.setChecked(False)
|
||||
|
||||
def stripTags(self, html):
|
||||
s = HTMLStripper()
|
||||
@@ -700,7 +708,6 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
||||
self.conversionAlive = False
|
||||
self.worker.sync()
|
||||
else:
|
||||
# noinspection PyArgumentList
|
||||
if QtWidgets.QApplication.keyboardModifiers() == QtCore.Qt.ShiftModifier:
|
||||
dname = QtWidgets.QFileDialog.getExistingDirectory(MW, 'Select output directory', self.lastPath)
|
||||
if dname != '':
|
||||
@@ -762,7 +769,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
||||
'upscaleBox': GUI.upscaleBox.checkState(),
|
||||
'borderBox': GUI.borderBox.checkState(),
|
||||
'webtoonBox': GUI.webtoonBox.checkState(),
|
||||
'noDitheringBox': GUI.noDitheringBox.checkState(),
|
||||
'outputSplit': GUI.outputSplit.checkState(),
|
||||
'colorBox': GUI.colorBox.checkState(),
|
||||
'widthBox': GUI.widthBox.value(),
|
||||
'heightBox': GUI.heightBox.value(),
|
||||
@@ -848,7 +855,6 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
||||
else:
|
||||
self.addMessage('Download it and place executable in /usr/local/bin directory.', 'error')
|
||||
|
||||
# noinspection PyArgumentList
|
||||
def __init__(self, KCCAplication, KCCWindow):
|
||||
global APP, MW, GUI
|
||||
APP = KCCAplication
|
||||
|
||||
@@ -97,9 +97,9 @@ class Ui_mainWindow(object):
|
||||
self.borderBox.setTristate(True)
|
||||
self.borderBox.setObjectName("borderBox")
|
||||
self.gridLayout_2.addWidget(self.borderBox, 2, 0, 1, 1)
|
||||
self.noDitheringBox = QtWidgets.QCheckBox(self.optionWidget)
|
||||
self.noDitheringBox.setObjectName("noDitheringBox")
|
||||
self.gridLayout_2.addWidget(self.noDitheringBox, 2, 1, 1, 1)
|
||||
self.outputSplit = QtWidgets.QCheckBox(self.optionWidget)
|
||||
self.outputSplit.setObjectName("outputSplit")
|
||||
self.gridLayout_2.addWidget(self.outputSplit, 2, 1, 1, 1)
|
||||
self.colorBox = QtWidgets.QCheckBox(self.optionWidget)
|
||||
self.colorBox.setObjectName("colorBox")
|
||||
self.gridLayout_2.addWidget(self.colorBox, 2, 2, 1, 1)
|
||||
@@ -219,8 +219,8 @@ class Ui_mainWindow(object):
|
||||
mainWindow.setTabOrder(self.webtoonBox, self.upscaleBox)
|
||||
mainWindow.setTabOrder(self.upscaleBox, self.gammaBox)
|
||||
mainWindow.setTabOrder(self.gammaBox, self.borderBox)
|
||||
mainWindow.setTabOrder(self.borderBox, self.noDitheringBox)
|
||||
mainWindow.setTabOrder(self.noDitheringBox, self.colorBox)
|
||||
mainWindow.setTabOrder(self.borderBox, self.outputSplit)
|
||||
mainWindow.setTabOrder(self.outputSplit, self.colorBox)
|
||||
mainWindow.setTabOrder(self.colorBox, self.editorButton)
|
||||
mainWindow.setTabOrder(self.editorButton, self.wikiButton)
|
||||
mainWindow.setTabOrder(self.wikiButton, self.jobList)
|
||||
@@ -251,8 +251,8 @@ class Ui_mainWindow(object):
|
||||
self.gammaBox.setText(_translate("mainWindow", "Custom gamma"))
|
||||
self.borderBox.setToolTip(_translate("mainWindow", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span>Color of margins fill will be detected automatically.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - White<br/></span>Margins will be filled with white color.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Black<br/></span>Margins will be filled with black color.</p></body></html>"))
|
||||
self.borderBox.setText(_translate("mainWindow", "W/B margins"))
|
||||
self.noDitheringBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Create PNG files instead JPEG.<br/>Quality increase is not noticeable on most of devices.<br/>Output files <span style=\" font-weight:600;\">might</span> be smaller.<br/><span style=\" font-weight:600;\">MOBI conversion will be much slower.</span></p></body></html>"))
|
||||
self.noDitheringBox.setText(_translate("mainWindow", "PNG output"))
|
||||
self.outputSplit.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Automatic mode<br/></span>Output will be splitted automatically.</p><p style=\'white-space:pre\'><span style=\" font-weight:600; text-decoration: underline;\">Checked - Volume mode<br/></span>Every subdirectory will be considered as separate volume.</p></body></html>"))
|
||||
self.outputSplit.setText(_translate("mainWindow", "Output split"))
|
||||
self.colorBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Disable conversion to grayscale.</p></body></html>"))
|
||||
self.colorBox.setText(_translate("mainWindow", "Color mode"))
|
||||
self.gammaLabel.setText(_translate("mainWindow", "Gamma: Auto"))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
__version__ = '5.2'
|
||||
__version__ = '5.2.1'
|
||||
__license__ = 'ISC'
|
||||
__copyright__ = '2012-2016, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
@@ -46,7 +46,7 @@ try:
|
||||
from scandir import walk
|
||||
except ImportError:
|
||||
walk = os.walk
|
||||
from .shared import md5Checksum, getImageFileName, walkSort, walkLevel, saferReplace, saferRemove
|
||||
from .shared import md5Checksum, getImageFileName, walkSort, walkLevel, saferReplace, saferRemove, sanitizeTrace
|
||||
from . import comic2panel
|
||||
from . import image
|
||||
from . import cbxarchive
|
||||
@@ -93,7 +93,6 @@ def buildHTML(path, imgfile, imgfilepath):
|
||||
additionalStyle = 'background-color:#000000;'
|
||||
else:
|
||||
additionalStyle = 'background-color:#FFFFFF;'
|
||||
htmlpath = ''
|
||||
postfix = ''
|
||||
backref = 1
|
||||
head = path
|
||||
@@ -483,7 +482,7 @@ def imgDirectoryProcessing(path):
|
||||
raise UserWarning("Conversion interrupted.")
|
||||
if len(workerOutput) > 0:
|
||||
rmtree(os.path.join(path, '..', '..'), True)
|
||||
raise RuntimeError("One of workers crashed. Cause: " + workerOutput[0])
|
||||
raise RuntimeError("One of workers crashed. Cause: " + workerOutput[0][0], workerOutput[0][1])
|
||||
for file in options.imgPurgeIndex:
|
||||
if os.path.isfile(file):
|
||||
saferRemove(file)
|
||||
@@ -493,7 +492,7 @@ def imgDirectoryProcessing(path):
|
||||
|
||||
|
||||
def imgFileProcessingTick(output):
|
||||
if isinstance(output, str):
|
||||
if isinstance(output, tuple):
|
||||
workerOutput.append(output)
|
||||
workerPool.terminate()
|
||||
else:
|
||||
@@ -527,7 +526,7 @@ def imgFileProcessing(work):
|
||||
output.append(img.saveToDir())
|
||||
return output
|
||||
except Exception:
|
||||
return str(sys.exc_info()[:2])
|
||||
return str(sys.exc_info()[1]), sanitizeTrace(sys.exc_info()[2])
|
||||
|
||||
|
||||
def getWorkFolder(afile):
|
||||
@@ -734,63 +733,25 @@ def sanitizePermissions(filetree):
|
||||
os.chmod(os.path.join(root, name), S_IWRITE | S_IREAD | S_IEXEC)
|
||||
|
||||
|
||||
# noinspection PyUnboundLocalVariable
|
||||
def splitDirectory(path):
|
||||
# Detect directory stucture
|
||||
for root, dirs, files in walkLevel(os.path.join(path, 'OEBPS', 'Images'), 0):
|
||||
subdirectoryNumber = len(dirs)
|
||||
filesNumber = len(files)
|
||||
if subdirectoryNumber == 0:
|
||||
# No subdirectories
|
||||
mode = 0
|
||||
level = -1
|
||||
for root, _, files in os.walk(os.path.join(path, 'OEBPS', 'Images')):
|
||||
for f in files:
|
||||
if f.endswith('.jpg') or f.endswith('.jpeg') or f.endswith('.png') or f.endswith('.gif'):
|
||||
newLevel = os.path.join(root, f).replace(os.path.join(path, 'OEBPS', 'Images'), '').count(os.sep)
|
||||
if level != -1 and level != newLevel:
|
||||
level = 0
|
||||
break
|
||||
else:
|
||||
level = newLevel
|
||||
if level > 0:
|
||||
splitter = splitProcess(os.path.join(path, 'OEBPS', 'Images'), level)
|
||||
path = [path]
|
||||
for tome in splitter:
|
||||
path.append(tome)
|
||||
return path
|
||||
else:
|
||||
if filesNumber > 0:
|
||||
print('WARNING: Automatic output splitting failed.')
|
||||
if GUI:
|
||||
GUI.addMessage.emit('Automatic output splitting failed. <a href='
|
||||
'"https://github.com/ciromattia/kcc/wiki'
|
||||
'/Automatic-output-splitting">'
|
||||
'More details.</a>', 'warning', False)
|
||||
GUI.addMessage.emit('', '', False)
|
||||
return [path]
|
||||
detectedSubSubdirectories = False
|
||||
detectedFilesInSubdirectories = False
|
||||
for root, dirs, files in walkLevel(os.path.join(path, 'OEBPS', 'Images'), 1):
|
||||
if root != os.path.join(path, 'OEBPS', 'Images'):
|
||||
if len(dirs) != 0:
|
||||
detectedSubSubdirectories = True
|
||||
elif len(dirs) == 0 and detectedSubSubdirectories:
|
||||
print('WARNING: Automatic output splitting failed.')
|
||||
if GUI:
|
||||
GUI.addMessage.emit('Automatic output splitting failed. <a href='
|
||||
'"https://github.com/ciromattia/kcc/wiki'
|
||||
'/Automatic-output-splitting">'
|
||||
'More details.</a>', 'warning', False)
|
||||
GUI.addMessage.emit('', '', False)
|
||||
return [path]
|
||||
if len(files) != 0:
|
||||
detectedFilesInSubdirectories = True
|
||||
if detectedSubSubdirectories:
|
||||
# Two levels of subdirectories
|
||||
mode = 2
|
||||
else:
|
||||
# One level of subdirectories
|
||||
mode = 1
|
||||
if detectedFilesInSubdirectories and detectedSubSubdirectories:
|
||||
print('WARNING: Automatic output splitting failed.')
|
||||
if GUI:
|
||||
GUI.addMessage.emit('Automatic output splitting failed. <a href='
|
||||
'"https://github.com/ciromattia/kcc/wiki'
|
||||
'/Automatic-output-splitting">'
|
||||
'More details.</a>', 'warning', False)
|
||||
GUI.addMessage.emit('', '', False)
|
||||
return [path]
|
||||
# Split directories
|
||||
splitter = splitProcess(os.path.join(path, 'OEBPS', 'Images'), mode)
|
||||
path = [path]
|
||||
for tome in splitter:
|
||||
path.append(tome)
|
||||
return path
|
||||
raise UserWarning('Unsupported directory structure.')
|
||||
|
||||
|
||||
def splitProcess(path, mode):
|
||||
@@ -801,10 +762,15 @@ def splitProcess(path, mode):
|
||||
targetSize = 104857600
|
||||
else:
|
||||
targetSize = 419430400
|
||||
if mode == 0:
|
||||
if options.batchsplit == 2 and mode == 2:
|
||||
mode = 3
|
||||
if mode < 3:
|
||||
for root, dirs, files in walkLevel(path, 0):
|
||||
for name in files:
|
||||
size = os.path.getsize(os.path.join(root, name))
|
||||
for name in files if mode == 1 else dirs:
|
||||
if mode == 1:
|
||||
size = os.path.getsize(os.path.join(root, name))
|
||||
else:
|
||||
size = getDirectorySize(os.path.join(root, name))
|
||||
if currentSize + size > targetSize:
|
||||
currentTarget, pathRoot = createNewTome()
|
||||
output.append(pathRoot)
|
||||
@@ -813,48 +779,16 @@ def splitProcess(path, mode):
|
||||
currentSize += size
|
||||
if path != currentTarget:
|
||||
move(os.path.join(root, name), os.path.join(currentTarget, name))
|
||||
elif mode == 1:
|
||||
for root, dirs, files in walkLevel(path, 0):
|
||||
for name in dirs:
|
||||
size = getDirectorySize(os.path.join(root, name))
|
||||
if currentSize + size > targetSize:
|
||||
currentTarget, pathRoot = createNewTome()
|
||||
output.append(pathRoot)
|
||||
currentSize = size
|
||||
else:
|
||||
currentSize += size
|
||||
if path != currentTarget:
|
||||
move(os.path.join(root, name), os.path.join(currentTarget, name))
|
||||
elif mode == 2:
|
||||
else:
|
||||
firstTome = True
|
||||
for root, dirs, files in walkLevel(path, 0):
|
||||
for name in dirs:
|
||||
size = getDirectorySize(os.path.join(root, name))
|
||||
currentSize = 0
|
||||
if size > targetSize:
|
||||
if not firstTome:
|
||||
currentTarget, pathRoot = createNewTome()
|
||||
output.append(pathRoot)
|
||||
else:
|
||||
firstTome = False
|
||||
for rootInside, dirsInside, filesInside in walkLevel(os.path.join(root, name), 0):
|
||||
for nameInside in dirsInside:
|
||||
size = getDirectorySize(os.path.join(rootInside, nameInside))
|
||||
if currentSize + size > targetSize:
|
||||
currentTarget, pathRoot = createNewTome()
|
||||
output.append(pathRoot)
|
||||
currentSize = size
|
||||
else:
|
||||
currentSize += size
|
||||
if path != currentTarget:
|
||||
move(os.path.join(rootInside, nameInside), os.path.join(currentTarget, nameInside))
|
||||
if not firstTome:
|
||||
currentTarget, pathRoot = createNewTome()
|
||||
output.append(pathRoot)
|
||||
move(os.path.join(root, name), os.path.join(currentTarget, name))
|
||||
else:
|
||||
if not firstTome:
|
||||
currentTarget, pathRoot = createNewTome()
|
||||
output.append(pathRoot)
|
||||
move(os.path.join(root, name), os.path.join(currentTarget, name))
|
||||
else:
|
||||
firstTome = False
|
||||
firstTome = False
|
||||
return output
|
||||
|
||||
|
||||
@@ -947,8 +881,9 @@ def makeParser():
|
||||
help="Comic title [Default=filename or directory name]")
|
||||
outputOptions.add_option("-f", "--format", action="store", dest="format", default="Auto",
|
||||
help="Output format (Available options: Auto, MOBI, EPUB, CBZ) [Default=Auto]")
|
||||
outputOptions.add_option("-b", "--batchsplit", action="store_true", dest="batchsplit", default=False,
|
||||
help="Split output into multiple files"),
|
||||
outputOptions.add_option("-b", "--batchsplit", type="int", dest="batchsplit", default="0",
|
||||
help="Split output into multiple files. 0: Don't split 1: Automatic mode "
|
||||
"2: Consider every subdirectory as separate volume [Default=0]")
|
||||
|
||||
processingOptions.add_option("-u", "--upscale", action="store_true", dest="upscale", default=False,
|
||||
help="Resize images smaller than device's resolution")
|
||||
@@ -1006,8 +941,8 @@ def checkOptions():
|
||||
if options.black_borders:
|
||||
options.bordersColor = 'black'
|
||||
# Splitting MOBI is not optional
|
||||
if options.format == 'MOBI':
|
||||
options.batchsplit = True
|
||||
if options.format == 'MOBI' and options.batchsplit != 2:
|
||||
options.batchsplit = 1
|
||||
# Older Kindle don't need higher resolution files due lack of Panel View.
|
||||
if options.profile == 'K1' or options.profile == 'K2' or options.profile == 'K3' or options.profile == 'KDX':
|
||||
options.panelview = False
|
||||
@@ -1092,8 +1027,8 @@ def makeBook(source, qtGUI=None):
|
||||
getComicInfo(os.path.join(path, "OEBPS", "Images"), source)
|
||||
detectCorruption(os.path.join(path, "OEBPS", "Images"), source)
|
||||
if options.webtoon:
|
||||
if image.ProfileData.Profiles[options.profile][1][1] > 1000:
|
||||
y = 1000
|
||||
if image.ProfileData.Profiles[options.profile][1][1] > 1024:
|
||||
y = 1024
|
||||
else:
|
||||
y = image.ProfileData.Profiles[options.profile][1][1]
|
||||
comic2panel.main(['-y ' + str(y), '-i', '-m', path], qtGUI)
|
||||
@@ -1106,7 +1041,7 @@ def makeBook(source, qtGUI=None):
|
||||
chapterNames = sanitizeTree(os.path.join(path, 'OEBPS', 'Images'))
|
||||
if 'Ko' in options.profile and options.format == 'CBZ':
|
||||
sanitizeTreeKobo(os.path.join(path, 'OEBPS', 'Images'))
|
||||
if options.batchsplit:
|
||||
if options.batchsplit > 0:
|
||||
tomes = splitDirectory(path)
|
||||
else:
|
||||
tomes = [path]
|
||||
|
||||
@@ -24,7 +24,7 @@ from shutil import rmtree, copytree, move
|
||||
from optparse import OptionParser, OptionGroup
|
||||
from multiprocessing import Pool
|
||||
from PIL import Image, ImageStat, ImageOps
|
||||
from .shared import getImageFileName, walkLevel, walkSort, saferRemove
|
||||
from .shared import getImageFileName, walkLevel, walkSort, saferRemove, sanitizeTrace
|
||||
try:
|
||||
from PyQt5 import QtCore
|
||||
except ImportError:
|
||||
@@ -81,7 +81,7 @@ def mergeDirectory(work):
|
||||
savePath = os.path.split(imagesValid[0])
|
||||
result.save(os.path.join(savePath[0], os.path.splitext(savePath[1])[0] + '.png'), 'PNG')
|
||||
except Exception:
|
||||
return str(sys.exc_info()[1])
|
||||
return str(sys.exc_info()[1]), sanitizeTrace(sys.exc_info()[2])
|
||||
|
||||
|
||||
def sanitizePanelSize(panel, opt):
|
||||
@@ -205,7 +205,7 @@ def splitImage(work):
|
||||
pageNumber += 1
|
||||
saferRemove(filePath)
|
||||
except Exception:
|
||||
return str(sys.exc_info()[1])
|
||||
return str(sys.exc_info()[1]), sanitizeTrace(sys.exc_info()[2])
|
||||
|
||||
|
||||
def main(argv=None, qtGUI=None):
|
||||
@@ -267,7 +267,7 @@ def main(argv=None, qtGUI=None):
|
||||
raise UserWarning("Conversion interrupted.")
|
||||
if len(mergeWorkerOutput) > 0:
|
||||
rmtree(options.targetDir, True)
|
||||
raise RuntimeError("One of workers crashed. Cause: " + mergeWorkerOutput[0])
|
||||
raise RuntimeError("One of workers crashed. Cause: " + mergeWorkerOutput[0][0], mergeWorkerOutput[0][1])
|
||||
print("Splitting images...")
|
||||
for root, dirs, files in walk(options.targetDir, False):
|
||||
for name in files:
|
||||
@@ -290,7 +290,7 @@ def main(argv=None, qtGUI=None):
|
||||
raise UserWarning("Conversion interrupted.")
|
||||
if len(splitWorkerOutput) > 0:
|
||||
rmtree(options.targetDir, True)
|
||||
raise RuntimeError("One of workers crashed. Cause: " + splitWorkerOutput[0])
|
||||
raise RuntimeError("One of workers crashed. Cause: " + splitWorkerOutput[0][0], splitWorkerOutput[0][1])
|
||||
if options.inPlace:
|
||||
rmtree(options.sourceDir)
|
||||
move(options.targetDir, options.sourceDir)
|
||||
|
||||
@@ -318,7 +318,7 @@ class ComicPage:
|
||||
tmpImg = tmpImg.point(lambda x: x and 255)
|
||||
tmpImg = tmpImg.filter(ImageFilter.MinFilter(size=3))
|
||||
tmpImg = tmpImg.filter(ImageFilter.GaussianBlur(radius=5))
|
||||
tmpImg = tmpImg.point(lambda x: (x >= 48 * power) and x)
|
||||
tmpImg = tmpImg.point(lambda x: (x >= 16 * power) and x)
|
||||
self.image = self.image.crop(tmpImg.getbbox()) if tmpImg.getbbox() else self.image
|
||||
|
||||
def cropMargin(self, power):
|
||||
|
||||
@@ -61,7 +61,6 @@ class PdfJpgExtract:
|
||||
iend += endfix
|
||||
jpg = pdf[istart:iend]
|
||||
jpgfile = open(self.path + "/jpg%d.jpg" % njpg, "wb")
|
||||
# noinspection PyTypeChecker
|
||||
jpgfile.write(jpg)
|
||||
jpgfile.close()
|
||||
njpg += 1
|
||||
|
||||
@@ -144,7 +144,10 @@ def removeFromZIP(zipfname, *filenames):
|
||||
|
||||
def sanitizeTrace(traceback):
|
||||
return ''.join(format_tb(traceback))\
|
||||
.replace('C:\\Users\\Pawel\\Documents\\Projekty\\KCC\\', '') \
|
||||
.replace('C:/Users/Pawel/Documents/Projekty/KCC/', '')\
|
||||
.replace('C:/Python35/', '')\
|
||||
.replace('c:/python35/', '')\
|
||||
.replace('C:\\Users\\Pawel\\Documents\\Projekty\\KCC\\', '')\
|
||||
.replace('C:\\Python35\\', '')\
|
||||
.replace('c:\\python35\\', '')
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>MacOS/Kindle Comic Converter</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>KindleComicConverter 5.2, written 2012-2016 by Ciro Mattia Gonano and Pawel Jastrzebski</string>
|
||||
<string>KindleComicConverter 5.2.1, written 2012-2016 by Ciro Mattia Gonano and Pawel Jastrzebski</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>comic2ebook.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
@@ -21,11 +21,11 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>5.2.0</string>
|
||||
<string>5.2.1</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>5.2.0</string>
|
||||
<string>5.2.1</string>
|
||||
<key>LSEnvironment</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
|
||||
Reference in New Issue
Block a user