1
0
mirror of https://github.com/ciromattia/kcc synced 2026-04-16 14:08:45 +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
- [PyQt5](http://www.riverbankcomputing.co.uk/software/pyqt/download5)
- [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)
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:
- 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.
- OS X - [py2app](https://bitbucket.org/ronaldoussoren/py2app) HEAD version.
- 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) 0.8+
## 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.
### 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:
MAIN:
@@ -108,10 +108,10 @@ Options:
-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:
MANDATORY:
@@ -333,6 +333,16 @@ The app relies and includes the following scripts/binaries:
* Fixed OSX file association support
* 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
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
# PERFORMANCE OF THIS SOFTWARE.
__version__ = '4.0'
__version__ = '4.0.2'
__license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en'
@@ -32,7 +32,7 @@ if sys.version_info[0] != 3:
missing = []
try:
# noinspection PyUnresolvedReferences
from psutil import TOTAL_PHYMEM, Popen
from psutil import virtual_memory, Popen
except ImportError:
missing.append('psutil')
try:

View File

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

View File

@@ -1,5 +1,5 @@
#define MyAppName "Kindle Comic Converter"
#define MyAppVersion "4.0"
#define MyAppVersion "4.0.2"
#define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
#define MyAppURL "http://kcc.vulturis.eu/"
#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
# PERFORMANCE OF THIS SOFTWARE.
__version__ = '4.0'
__version__ = '4.0.2'
__license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en'
@@ -37,7 +37,7 @@ except ImportError:
missing.append('PyQt5')
try:
# noinspection PyUnresolvedReferences
from psutil import TOTAL_PHYMEM, Popen
from psutil import virtual_memory, Popen
except ImportError:
missing.append('psutil')
try:
@@ -78,6 +78,16 @@ if sys.platform.startswith('darwin'):
elif sys.platform.startswith('win'):
if getattr(sys, 'frozen', False):
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:
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/;' + os.environ['PATH']
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
# PERFORMANCE OF THIS SOFTWARE.
__version__ = '4.0'
__version__ = '4.0.2'
__license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en'
@@ -36,7 +36,7 @@ from subprocess import STDOUT, PIPE
from PyQt5 import QtGui, QtCore, QtWidgets
from xml.dom.minidom import parse
from html.parser import HTMLParser
from psutil import TOTAL_PHYMEM, Popen
from psutil import virtual_memory, Popen
from .shared import md5Checksum
from . import comic2ebook
from . import kindlesplit
@@ -195,6 +195,7 @@ class VersionThread(QtCore.QThread):
def run(self):
try:
sleep(1)
XML = urlopen('http://kcc.vulturis.eu/Version.php')
XML = parse(XML)
except Exception:
@@ -337,7 +338,7 @@ class WorkerThread(QtCore.QThread):
self.kindlegenErrorCode = [0]
self.workerOutput = []
# Let's make sure that we don't fill the memory
availableMemory = TOTAL_PHYMEM/1000000000
availableMemory = virtual_memory().total/1000000000
if availableMemory <= 2:
self.threadNumber = 1
elif 2 < availableMemory <= 4:
@@ -450,9 +451,9 @@ class WorkerThread(QtCore.QThread):
except Exception as err:
GUI.progress.content = ''
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"
% (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.addTrayMessage.emit('Failed to create EPUB!', 'Critical')
if not self.conversionAlive:

View File

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

View File

@@ -104,7 +104,7 @@ class CBxArchive:
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 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'
move(os.path.join(targetdir, adir[0], f), targetdir)
os.rmdir(os.path.join(targetdir, adir[0]))

View File

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

View File

@@ -18,7 +18,7 @@
# PERFORMANCE OF THIS SOFTWARE.
#
__version__ = '4.0'
__version__ = '4.0.2'
__license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en'
@@ -52,27 +52,31 @@ def mergeDirectory(work):
images = []
imagesClear = []
sizes = []
h = 0
for root, dirs, files in walkLevel(directory, 0):
for name in files:
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:
for i in images:
sizes.append(i[0].size[0])
mw = max(set(sizes), key=sizes.count)
for i in images:
if i[0].size[0] == mw:
i[0] = i[0].convert('RGB')
imagesClear.append(i)
h = sum(i[0].size[1] for i in imagesClear)
if i[1] == mw:
h += i[2]
imagesClear.append(i[0])
# Silently drop directories that contain too many images
if h > 262144:
return None
result = Image.new('RGB', (mw, h))
y = 0
for i in imagesClear:
result.paste(i[0], (0, y))
y += i[0].size[1]
for i in imagesClear:
os.remove(i[1])
savePath = os.path.split(imagesClear[0][1])
img = Image.open(i)
img = img.convert('RGB')
result.paste(img, (0, y))
y += img.size[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')
except Exception:
return str(sys.exc_info()[1])
@@ -209,7 +213,7 @@ def Copyright():
def main(argv=None, qtGUI=None):
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")
otherOptions = OptionGroup(parser, "OTHER")
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]:
size = (self.size[0], self.size[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])
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]:
@@ -415,9 +418,6 @@ class ComicPage:
return False
def getImageFill(self, webtoon):
if not webtoon and self.color:
self.fill = 'black'
return
fill = 0
if not webtoon and not self.rotated:
# Search for horizontal solid lines

View File

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

View File

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