1
0
mirror of https://github.com/ciromattia/kcc synced 2026-04-17 22:48:53 +00:00

Compare commits

..

13 Commits
4.0 ... 4.0.2

Author SHA1 Message Date
Paweł Jastrzębski
dc312f36c2 Updated OSX libs 2014-03-19 10:14:56 +01:00
Paweł Jastrzębski
4573ff6ec2 README update 2014-03-19 09:25:45 +01:00
Paweł Jastrzębski
d77498405b Updated to psutil 2.0 2014-03-13 21:58:15 +01:00
Paweł Jastrzębski
e491fca445 Version bump + README update 2014-03-13 21:26:26 +01:00
Paweł Jastrzębski
d22ee1a488 Tweaked HQ mode 2014-02-18 12:56:27 +01:00
Paweł Jastrzębski
7ebcccd8a2 Replaced os.rename with atomic os.replace
This should eliminate last problems with file locks on Windows
2014-02-13 18:35:17 +01:00
Paweł Jastrzębski
9a691c3c63 Windows: Fixed sys.stdout and sys.stderr 2014-02-06 11:45:37 +01:00
Paweł Jastrzębski
2b04a0298e Windows: Fixed abnormalities with version check
CX_Freeze working very, very strange with Python 3.3.3
2014-02-02 08:56:50 +01:00
Paweł Jastrzębski
9867f63d00 Version bump + README update 2014-02-01 19:13:03 +01:00
Paweł Jastrzębski
866f8898be Windows: Hopefully fixed all problems with file locks 2014-02-01 18:11:16 +01:00
Paweł Jastrzębski
9f2ac7a176 Windows: Truncated tracebacks 2014-02-01 16:14:23 +01:00
Paweł Jastrzębski
634213f380 WebToons: Improved performance of directory merger 2014-02-01 14:09:25 +01:00
Paweł Jastrzębski
ce82b5ec66 Tweaked margin color detection 2014-01-31 11:15:03 +01:00
13 changed files with 92 additions and 60 deletions

View File

@@ -43,7 +43,7 @@ You can find the latest released binary at the following links:
- Python 3.3 - Python 3.3
- [PyQt5](http://www.riverbankcomputing.co.uk/software/pyqt/download5) - [PyQt5](http://www.riverbankcomputing.co.uk/software/pyqt/download5)
- [Pillow](http://pypi.python.org/pypi/Pillow/) 2.3.0+ - [Pillow](http://pypi.python.org/pypi/Pillow/) 2.3.0+
- [psutil](https://pypi.python.org/pypi/psutil) - [psutil](https://pypi.python.org/pypi/psutil) 2.0+
- [python-slugify](http://pypi.python.org/pypi/python-slugify) - [python-slugify](http://pypi.python.org/pypi/python-slugify)
On Debian based distributions these two commands should install all dependencies: On Debian based distributions these two commands should install all dependencies:
@@ -53,8 +53,8 @@ sudo pip3 install pillow python-slugify psutil
``` ```
### For freezing code: ### For freezing code:
- Windows - [cx_Freeze](https://bitbucket.org/anthony_tuininga/cx_freeze) version 4.3.2 with [this](https://bitbucket.org/anthony_tuininga/cx_freeze/pull-request/29/conversions-to-support-untranslated-wide) patchset. - Windows - [cx_Freeze](https://bitbucket.org/anthony_tuininga/cx_freeze) HEAD version with [this](https://bitbucket.org/anthony_tuininga/cx_freeze/pull-request/29/conversions-to-support-untranslated-wide) patchset.
- OS X - [py2app](https://bitbucket.org/ronaldoussoren/py2app) HEAD version. - OS X - [py2app](https://bitbucket.org/ronaldoussoren/py2app) 0.8+
## USAGE ## USAGE
@@ -63,10 +63,10 @@ After completed conversion you should find ready file alongside the original inp
Please check [our wiki](https://github.com/ciromattia/kcc/wiki/) for more details. Please check [our wiki](https://github.com/ciromattia/kcc/wiki/) for more details.
### Standalone `comic2ebook.py` usage: ### Standalone `kcc-c2e.py` usage:
``` ```
Usage: comic2ebook.py [options] comic_file|comic_folder Usage: kcc-c2e [options] comic_file|comic_folder
Options: Options:
MAIN: MAIN:
@@ -108,10 +108,10 @@ Options:
-h, --help Show this help message and exit -h, --help Show this help message and exit
``` ```
### Standalone `comic2panel.py` usage: ### Standalone `kcc-c2p.py` usage:
``` ```
Usage: comic2panel.py [options] comic_folder Usage: kcc-c2p [options] comic_folder
Options: Options:
MANDATORY: MANDATORY:
@@ -333,6 +333,16 @@ The app relies and includes the following scripts/binaries:
* Fixed OSX file association support * Fixed OSX file association support
* Many extensive internal changes and tweaks * Many extensive internal changes and tweaks
####4.0.1:
* Fixed file lock problems that plagued some Windows users
* Fixed content server failing to start on Windows
* Improved performance of WebToon splitter
* Tweaked margin color detection
####4.0.2:
* Fixed some Windows and OSX specific bugs
* Fixed problem with marigns when using HQ mode
## KNOWN ISSUES ## KNOWN ISSUES
Please check [wiki page](https://github.com/ciromattia/kcc/wiki/Known-issues). Please check [wiki page](https://github.com/ciromattia/kcc/wiki/Known-issues).

View File

@@ -18,7 +18,7 @@
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE. # PERFORMANCE OF THIS SOFTWARE.
__version__ = '4.0' __version__ = '4.0.2'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>' __copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
@@ -32,7 +32,7 @@ if sys.version_info[0] != 3:
missing = [] missing = []
try: try:
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from psutil import TOTAL_PHYMEM, Popen from psutil import virtual_memory, Popen
except ImportError: except ImportError:
missing.append('psutil') missing.append('psutil')
try: try:

View File

@@ -23,7 +23,7 @@ if sys.version_info[0] != 3:
print('ERROR: This is Python 3 script!') print('ERROR: This is Python 3 script!')
exit(1) exit(1)
__version__ = '4.0' __version__ = '4.0.2'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>' __copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'

View File

@@ -1,5 +1,5 @@
#define MyAppName "Kindle Comic Converter" #define MyAppName "Kindle Comic Converter"
#define MyAppVersion "4.0" #define MyAppVersion "4.0.2"
#define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski" #define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
#define MyAppURL "http://kcc.vulturis.eu/" #define MyAppURL "http://kcc.vulturis.eu/"
#define MyAppExeName "KCC.exe" #define MyAppExeName "KCC.exe"

14
kcc.py
View File

@@ -18,7 +18,7 @@
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE. # PERFORMANCE OF THIS SOFTWARE.
__version__ = '4.0' __version__ = '4.0.2'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>' __copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
@@ -37,7 +37,7 @@ except ImportError:
missing.append('PyQt5') missing.append('PyQt5')
try: try:
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from psutil import TOTAL_PHYMEM, Popen from psutil import virtual_memory, Popen
except ImportError: except ImportError:
missing.append('psutil') missing.append('psutil')
try: try:
@@ -78,6 +78,16 @@ if sys.platform.startswith('darwin'):
elif sys.platform.startswith('win'): elif sys.platform.startswith('win'):
if getattr(sys, 'frozen', False): if getattr(sys, 'frozen', False):
os.chdir(os.path.dirname(os.path.abspath(sys.executable))) os.chdir(os.path.dirname(os.path.abspath(sys.executable)))
# Implementing dummy stdout and stderr for frozen Windows release
class fakestd(object):
def write(self, string):
pass
def flush(self):
pass
sys.stdout = fakestd()
sys.stderr = fakestd()
else: else:
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/;' + os.environ['PATH'] os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/;' + os.environ['PATH']
os.chdir(os.path.dirname(os.path.abspath(__file__))) os.chdir(os.path.dirname(os.path.abspath(__file__)))

View File

@@ -17,7 +17,7 @@
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE. # PERFORMANCE OF THIS SOFTWARE.
__version__ = '4.0' __version__ = '4.0.2'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>' __copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
@@ -36,7 +36,7 @@ from subprocess import STDOUT, PIPE
from PyQt5 import QtGui, QtCore, QtWidgets from PyQt5 import QtGui, QtCore, QtWidgets
from xml.dom.minidom import parse from xml.dom.minidom import parse
from html.parser import HTMLParser from html.parser import HTMLParser
from psutil import TOTAL_PHYMEM, Popen from psutil import virtual_memory, Popen
from .shared import md5Checksum from .shared import md5Checksum
from . import comic2ebook from . import comic2ebook
from . import kindlesplit from . import kindlesplit
@@ -195,6 +195,7 @@ class VersionThread(QtCore.QThread):
def run(self): def run(self):
try: try:
sleep(1)
XML = urlopen('http://kcc.vulturis.eu/Version.php') XML = urlopen('http://kcc.vulturis.eu/Version.php')
XML = parse(XML) XML = parse(XML)
except Exception: except Exception:
@@ -337,7 +338,7 @@ class WorkerThread(QtCore.QThread):
self.kindlegenErrorCode = [0] self.kindlegenErrorCode = [0]
self.workerOutput = [] self.workerOutput = []
# Let's make sure that we don't fill the memory # Let's make sure that we don't fill the memory
availableMemory = TOTAL_PHYMEM/1000000000 availableMemory = virtual_memory().total/1000000000
if availableMemory <= 2: if availableMemory <= 2:
self.threadNumber = 1 self.threadNumber = 1
elif 2 < availableMemory <= 4: elif 2 < availableMemory <= 4:
@@ -450,9 +451,9 @@ class WorkerThread(QtCore.QThread):
except Exception as err: except Exception as err:
GUI.progress.content = '' GUI.progress.content = ''
self.errors = True self.errors = True
type_, value_, traceback_ = sys.exc_info() _, _, traceback = sys.exc_info()
MW.showDialog.emit("Error during conversion %s:\n\n%s\n\nTraceback:\n%s" MW.showDialog.emit("Error during conversion %s:\n\n%s\n\nTraceback:\n%s"
% (jobargv[-1], str(err), format_tb(traceback_)), 'error') % (jobargv[-1], str(err), "".join(format_tb(traceback))), 'error')
MW.addMessage.emit('Failed to create EPUB!', 'error', False) MW.addMessage.emit('Failed to create EPUB!', 'error', False)
MW.addTrayMessage.emit('Failed to create EPUB!', 'Critical') MW.addTrayMessage.emit('Failed to create EPUB!', 'Critical')
if not self.conversionAlive: if not self.conversionAlive:

View File

@@ -1,4 +1,4 @@
__version__ = '4.0' __version__ = '4.0.2'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>' __copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'

View File

@@ -104,7 +104,7 @@ class CBxArchive:
for f in os.listdir(os.path.join(targetdir, adir[0])): for f in os.listdir(os.path.join(targetdir, adir[0])):
# If directory names contain UTF-8 chars shutil.move can't clean up the mess alone # If directory names contain UTF-8 chars shutil.move can't clean up the mess alone
if os.path.isdir(os.path.join(targetdir, f)): if os.path.isdir(os.path.join(targetdir, f)):
os.rename(os.path.join(targetdir, adir[0], f), os.path.join(targetdir, adir[0], f + '-A')) os.replace(os.path.join(targetdir, adir[0], f), os.path.join(targetdir, adir[0], f + '-A'))
f += '-A' f += '-A'
move(os.path.join(targetdir, adir[0], f), targetdir) move(os.path.join(targetdir, adir[0], f), targetdir)
os.rmdir(os.path.join(targetdir, adir[0])) os.rmdir(os.path.join(targetdir, adir[0]))

View File

@@ -18,7 +18,7 @@
# PERFORMANCE OF THIS SOFTWARE. # PERFORMANCE OF THIS SOFTWARE.
# #
__version__ = '4.0' __version__ = '4.0.2'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>' __copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
@@ -320,11 +320,12 @@ def applyImgOptimization(img, opt, hqImage=None):
def dirImgProcess(path): def dirImgProcess(path):
global workerPool, workerOutput, theGreatIndex global workerPool, workerOutput, theGreatIndex, theGreatWipe
workerPool = Pool() workerPool = Pool()
workerOutput = [] workerOutput = []
work = [] work = []
theGreatIndex = {} theGreatIndex = {}
theGreatWipe = []
pagenumber = 0 pagenumber = 0
for (dirpath, dirnames, filenames) in os.walk(path): for (dirpath, dirnames, filenames) in os.walk(path):
for afile in filenames: for afile in filenames:
@@ -344,6 +345,9 @@ def dirImgProcess(path):
if len(workerOutput) > 0: if len(workerOutput) > 0:
rmtree(os.path.join(path, '..', '..'), True) rmtree(os.path.join(path, '..', '..'), True)
raise RuntimeError("One of workers crashed. Cause: " + workerOutput[0]) raise RuntimeError("One of workers crashed. Cause: " + workerOutput[0])
for file in theGreatWipe:
if os.path.isfile(file):
os.remove(file)
else: else:
rmtree(os.path.join(path, '..', '..'), True) rmtree(os.path.join(path, '..', '..'), True)
raise UserWarning("Source directory is empty.") raise UserWarning("Source directory is empty.")
@@ -356,9 +360,10 @@ def fileImgProcess_tick(output):
else: else:
for page in output: for page in output:
if page is not None: if page is not None:
if sys.platform.startswith('win'): if isinstance(page, str):
page[0] = page[0].replace('/', '\\') theGreatWipe.append(page)
theGreatIndex[page[0]] = page[1] else:
theGreatIndex[page[0]] = page[1]
if GUI: if GUI:
GUI.progressBarTick.emit('tick') GUI.progressBarTick.emit('tick')
if not GUI.conversionAlive: if not GUI.conversionAlive:
@@ -388,8 +393,8 @@ def fileImgProcess(work):
applyImgOptimization(img1, opt) applyImgOptimization(img1, opt)
output.append(img1.saveToDir(dirpath, opt.forcepng, opt.forcecolor)) output.append(img1.saveToDir(dirpath, opt.forcepng, opt.forcecolor))
if wipe: if wipe:
os.remove(img0.origFileName) output.append(img0.origFileName)
os.remove(img1.origFileName) output.append(img1.origFileName)
if opt.quality == 2: if opt.quality == 2:
img0b = image.ComicPage(splitter[0], opt.profileData, img0.fill) img0b = image.ComicPage(splitter[0], opt.profileData, img0.fill)
applyImgOptimization(img0b, opt, img0) applyImgOptimization(img0b, opt, img0)
@@ -397,14 +402,14 @@ def fileImgProcess(work):
img1b = image.ComicPage(splitter[1], opt.profileData, img1.fill) img1b = image.ComicPage(splitter[1], opt.profileData, img1.fill)
applyImgOptimization(img1b, opt, img1) applyImgOptimization(img1b, opt, img1)
output.append(img1b.saveToDir(dirpath, opt.forcepng, opt.forcecolor)) output.append(img1b.saveToDir(dirpath, opt.forcepng, opt.forcecolor))
os.remove(img0.origFileName) output.append(img0.origFileName)
os.remove(img1.origFileName) output.append(img1.origFileName)
os.remove(img.origFileName) output.append(img.origFileName)
else: else:
applyImgOptimization(img, opt) applyImgOptimization(img, opt)
output.append(img.saveToDir(dirpath, opt.forcepng, opt.forcecolor)) output.append(img.saveToDir(dirpath, opt.forcepng, opt.forcecolor))
if wipe: if wipe:
os.remove(img.origFileName) output.append(img.origFileName)
if opt.quality == 2: if opt.quality == 2:
img2 = image.ComicPage(os.path.join(dirpath, afile), opt.profileData, img.fill) img2 = image.ComicPage(os.path.join(dirpath, afile), opt.profileData, img.fill)
if img.rotated: if img.rotated:
@@ -412,7 +417,7 @@ def fileImgProcess(work):
img2.rotated = True img2.rotated = True
applyImgOptimization(img2, opt, img) applyImgOptimization(img2, opt, img)
output.append(img2.saveToDir(dirpath, opt.forcepng, opt.forcecolor)) output.append(img2.saveToDir(dirpath, opt.forcepng, opt.forcecolor))
os.remove(img.origFileName) output.append(img.origFileName)
return output return output
except Exception: except Exception:
return str(sys.exc_info()[1]) return str(sys.exc_info()[1])
@@ -668,7 +673,7 @@ def sanitizeTree(filetree):
newKey = os.path.join(root, slugified + splitname[1]) newKey = os.path.join(root, slugified + splitname[1])
key = os.path.join(root, name) key = os.path.join(root, name)
if key != newKey: if key != newKey:
os.rename(key, newKey) os.replace(key, newKey)
for name in dirs: for name in dirs:
if name.startswith('.'): if name.startswith('.'):
os.remove(os.path.join(root, name)) os.remove(os.path.join(root, name))
@@ -681,7 +686,7 @@ def sanitizeTree(filetree):
newKey = os.path.join(root, slugified) newKey = os.path.join(root, slugified)
key = os.path.join(root, name) key = os.path.join(root, name)
if key != newKey: if key != newKey:
os.rename(key, newKey) os.replace(key, newKey)
return chapterNames return chapterNames
@@ -878,7 +883,7 @@ def Usage():
def main(argv=None, qtGUI=None): def main(argv=None, qtGUI=None):
global parser, options, GUI global parser, options, GUI
parser = OptionParser(usage="Usage: %prog [options] comic_file|comic_folder", add_help_option=False) parser = OptionParser(usage="Usage: kcc-c2e [options] comic_file|comic_folder", add_help_option=False)
mainOptions = OptionGroup(parser, "MAIN") mainOptions = OptionGroup(parser, "MAIN")
processingOptions = OptionGroup(parser, "PROCESSING") processingOptions = OptionGroup(parser, "PROCESSING")
outputOptions = OptionGroup(parser, "OUTPUT SETTINGS") outputOptions = OptionGroup(parser, "OUTPUT SETTINGS")
@@ -946,8 +951,8 @@ def main(argv=None, qtGUI=None):
return return
path = getWorkFolder(args[0]) path = getWorkFolder(args[0])
print("\nChecking images...") print("\nChecking images...")
detectCorruption(path + "/OEBPS/Images/", args[0]) detectCorruption(os.path.join(path, "OEBPS", "Images"), args[0])
checkComicInfo(path + "/OEBPS/Images/", args[0]) checkComicInfo(os.path.join(path, "OEBPS", "Images"), args[0])
if options.webtoon: if options.webtoon:
if options.customheight > 0: if options.customheight > 0:
comic2panel.main(['-y ' + str(options.customheight), '-i', '-m', path], qtGUI) comic2panel.main(['-y ' + str(options.customheight), '-i', '-m', path], qtGUI)
@@ -957,7 +962,7 @@ def main(argv=None, qtGUI=None):
print("\nProcessing images...") print("\nProcessing images...")
if GUI: if GUI:
GUI.progressBarTick.emit('Processing images') GUI.progressBarTick.emit('Processing images')
dirImgProcess(path + "/OEBPS/Images/") dirImgProcess(os.path.join(path, "OEBPS", "Images"))
if GUI: if GUI:
GUI.progressBarTick.emit('1') GUI.progressBarTick.emit('1')
chapterNames = sanitizeTree(os.path.join(path, 'OEBPS', 'Images')) chapterNames = sanitizeTree(os.path.join(path, 'OEBPS', 'Images'))
@@ -986,7 +991,7 @@ def main(argv=None, qtGUI=None):
filepath.append(getOutputFilename(args[0], options.output, '.cbz', ' ' + str(tomeNumber))) filepath.append(getOutputFilename(args[0], options.output, '.cbz', ' ' + str(tomeNumber)))
else: else:
filepath.append(getOutputFilename(args[0], options.output, '.cbz', '')) filepath.append(getOutputFilename(args[0], options.output, '.cbz', ''))
makeZIP(tome + '_comic', tome + '/OEBPS/Images') makeZIP(tome + '_comic', os.path.join(tome, "OEBPS", "Images"))
else: else:
print("\nCreating EPUB structure...") print("\nCreating EPUB structure...")
genEpubStruct(tome, chapterNames) genEpubStruct(tome, chapterNames)
@@ -1010,9 +1015,10 @@ def getOutputFilename(srcpath, wantedname, ext, tomeNumber):
if wantedname.endswith(ext): if wantedname.endswith(ext):
filename = os.path.abspath(wantedname) filename = os.path.abspath(wantedname)
elif os.path.isdir(srcpath): elif os.path.isdir(srcpath):
filename = os.path.abspath(options.output) + "/" + os.path.basename(srcpath) + ext filename = os.path.join(os.path.abspath(options.output), os.path.basename(srcpath) + ext)
else: else:
filename = os.path.abspath(options.output) + "/" + os.path.basename(os.path.splitext(srcpath)[0]) + ext filename = os.path.join(os.path.abspath(options.output),
os.path.basename(os.path.splitext(srcpath)[0]) + ext)
elif os.path.isdir(srcpath): elif os.path.isdir(srcpath):
filename = srcpath + tomeNumber + ext filename = srcpath + tomeNumber + ext
else: else:

View File

@@ -18,7 +18,7 @@
# PERFORMANCE OF THIS SOFTWARE. # PERFORMANCE OF THIS SOFTWARE.
# #
__version__ = '4.0' __version__ = '4.0.2'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>' __copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
@@ -52,27 +52,31 @@ def mergeDirectory(work):
images = [] images = []
imagesClear = [] imagesClear = []
sizes = [] sizes = []
h = 0
for root, dirs, files in walkLevel(directory, 0): for root, dirs, files in walkLevel(directory, 0):
for name in files: for name in files:
if getImageFileName(name) is not None: if getImageFileName(name) is not None:
images.append([Image.open(os.path.join(root, name)), os.path.join(root, name)]) i = Image.open(os.path.join(root, name))
images.append([os.path.join(root, name), i.size[0], i.size[1]])
sizes.append(i.size[0])
if len(images) > 0: if len(images) > 0:
for i in images:
sizes.append(i[0].size[0])
mw = max(set(sizes), key=sizes.count) mw = max(set(sizes), key=sizes.count)
for i in images: for i in images:
if i[0].size[0] == mw: if i[1] == mw:
i[0] = i[0].convert('RGB') h += i[2]
imagesClear.append(i) imagesClear.append(i[0])
h = sum(i[0].size[1] for i in imagesClear) # Silently drop directories that contain too many images
if h > 262144:
return None
result = Image.new('RGB', (mw, h)) result = Image.new('RGB', (mw, h))
y = 0 y = 0
for i in imagesClear: for i in imagesClear:
result.paste(i[0], (0, y)) img = Image.open(i)
y += i[0].size[1] img = img.convert('RGB')
for i in imagesClear: result.paste(img, (0, y))
os.remove(i[1]) y += img.size[1]
savePath = os.path.split(imagesClear[0][1]) os.remove(i)
savePath = os.path.split(imagesClear[0])
result.save(os.path.join(savePath[0], os.path.splitext(savePath[1])[0] + '.png'), 'PNG') result.save(os.path.join(savePath[0], os.path.splitext(savePath[1])[0] + '.png'), 'PNG')
except Exception: except Exception:
return str(sys.exc_info()[1]) return str(sys.exc_info()[1])
@@ -209,7 +213,7 @@ def Copyright():
def main(argv=None, qtGUI=None): def main(argv=None, qtGUI=None):
global options, GUI, splitWorkerPool, splitWorkerOutput, mergeWorkerPool, mergeWorkerOutput global options, GUI, splitWorkerPool, splitWorkerOutput, mergeWorkerPool, mergeWorkerOutput
parser = OptionParser(usage="Usage: %prog [options] comic_folder", add_help_option=False) parser = OptionParser(usage="Usage: kcc-c2p [options] comic_folder", add_help_option=False)
mainOptions = OptionGroup(parser, "MANDATORY") mainOptions = OptionGroup(parser, "MANDATORY")
otherOptions = OptionGroup(parser, "OTHER") otherOptions = OptionGroup(parser, "OTHER")
mainOptions.add_option("-y", "--height", type="int", dest="height", default=0, mainOptions.add_option("-y", "--height", type="int", dest="height", default=0,

View File

@@ -223,6 +223,9 @@ class ComicPage:
self.size[0] and self.image.size[1] <= self.size[1]: self.size[0] and self.image.size[1] <= self.size[1]:
size = (self.size[0], self.size[1]) size = (self.size[0], self.size[1])
elif qualityMode == 1: elif qualityMode == 1:
# Forcing upscale to make sure that margins will be not too big
if not stretch:
upscale = True
size = (self.panelviewsize[0], self.panelviewsize[1]) size = (self.panelviewsize[0], self.panelviewsize[1])
elif qualityMode == 2 and not stretch and not upscale and self.image.size[0] <=\ elif qualityMode == 2 and not stretch and not upscale and self.image.size[0] <=\
self.size[0] and self.image.size[1] <= self.size[1]: self.size[0] and self.image.size[1] <= self.size[1]:
@@ -415,9 +418,6 @@ class ComicPage:
return False return False
def getImageFill(self, webtoon): def getImageFill(self, webtoon):
if not webtoon and self.color:
self.fill = 'black'
return
fill = 0 fill = 0
if not webtoon and not self.rotated: if not webtoon and not self.rotated:
# Search for horizontal solid lines # Search for horizontal solid lines

View File

@@ -14,7 +14,7 @@ if version_info[0] != 3:
exit(1) exit(1)
NAME = "KindleComicConverter" NAME = "KindleComicConverter"
VERSION = "4.0" VERSION = "4.0.2"
MAIN = "kcc.py" MAIN = "kcc.py"
if platform == "darwin": if platform == "darwin":
@@ -73,6 +73,7 @@ elif platform == "win32":
"copy_dependent_files": True, "copy_dependent_files": True,
"create_shared_zip": False, "create_shared_zip": False,
"append_script_to_exe": True, "append_script_to_exe": True,
"replace_paths": '*=',
"excludes": ['tkinter']}}, "excludes": ['tkinter']}},
executables=[Executable(MAIN, executables=[Executable(MAIN,
base=base, base=base,

View File

@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
# Linux Python package build script # Linux Python package build script
VERSION="4.0" VERSION="4.0.2"
cp kcc.py __main__.py cp kcc.py __main__.py
zip kcc.zip __main__.py kcc/*.py zip kcc.zip __main__.py kcc/*.py