1
0
mirror of https://github.com/ciromattia/kcc synced 2026-04-15 21:48:44 +00:00

Compare commits

..

19 Commits
4.1 ... 4.2.1

Author SHA1 Message Date
Paweł Jastrzębski
56f23ab488 Merge pull request #108 from ciromattia/4.x
4.2.1
2014-08-03 11:22:28 +02:00
Paweł Jastrzębski
996af59e00 Updated README + version bump 2014-08-03 11:21:43 +02:00
Paweł Jastrzębski
37aa84c4aa Fixed MOBI processing anomalies 2014-08-02 07:54:15 +02:00
Paweł Jastrzębski
50574632e6 Replaced margin color detection algorithm 2014-08-01 07:23:55 +02:00
Paweł Jastrzębski
0afb9e8c0b Kindle: Fixed high quality mode (close #106) 2014-07-31 21:49:03 +02:00
Paweł Jastrzębski
7511c7eed6 Kindle DX: Changed default output format to CBZ 2014-07-29 19:59:21 +02:00
Paweł Jastrzębski
836a4146f9 MCD: Fixed small bug 2014-07-23 20:55:31 +02:00
Paweł Jastrzębski
15a240ccea Merge pull request #103 from ciromattia/4.x
Version 4.2
2014-07-18 10:29:14 +02:00
Paweł Jastrzębski
0722ddf8b0 Updated README + version bump 2014-07-18 08:45:57 +02:00
Paweł Jastrzębski
b3159b94e7 Prevented hypothetical problems with batch processing 2014-07-18 08:24:12 +02:00
Paweł Jastrzębski
ef5207c990 Dropped Windows XP support 2014-07-10 19:11:04 +02:00
Paweł Jastrzębski
db77d89817 Fixed Other profile 2014-07-05 09:38:10 +02:00
Paweł Jastrzębski
4571fadadb Resolved problems with page order on Kobo 2014-07-04 09:59:21 +02:00
Paweł Jastrzębski
94f56238ae Corruption detection now also delete non-image files (close #99) 2014-07-03 18:16:57 +02:00
Paweł Jastrzębski
5efb5d6dbb Updated Pillow (close #95) 2014-07-03 18:16:57 +02:00
Paweł Jastrzębski
623f615dd9 Added Manga Cover Database support 2014-07-03 18:16:56 +02:00
Paweł Jastrzębski
39fbbc42b3 Made KindleGen detection more foolproof 2014-07-03 18:16:56 +02:00
Paweł Jastrzębski
99405ab8a6 Disabled ultra quality mode for CBZ format 2014-07-03 18:16:55 +02:00
Paweł Jastrzębski
aadfca8306 Code cleanup 2014-07-03 18:16:54 +02:00
12 changed files with 660 additions and 617 deletions

View File

@@ -26,7 +26,7 @@ If you find **KCC** valuable you can consider donating to the authors:
## BINARY RELEASES
You can find the latest released binary at the following links:
- **Windows:** [http://kcc.iosphe.re/Windows/](http://kcc.iosphe.re/Windows/)
- **Windows (Vista or newer):** [http://kcc.iosphe.re/Windows/](http://kcc.iosphe.re/Windows/)
- **Linux:** [http://kcc.iosphe.re/Linux/](http://kcc.iosphe.re/Linux/)
- **OS X (10.8+):** [http://kcc.iosphe.re/OSX/](http://kcc.iosphe.re/OSX/)
@@ -46,7 +46,7 @@ You can find the latest released binary at the following links:
### For running from source:
- Python 3.3+
- [PyQt5](http://www.riverbankcomputing.co.uk/software/pyqt/download5) 5.2.0+
- [Pillow](http://pypi.python.org/pypi/Pillow/) 2.3.0+
- [Pillow](http://pypi.python.org/pypi/Pillow/) 2.5.0+
- [psutil](https://pypi.python.org/pypi/psutil) 2.0+
- [python-slugify](http://pypi.python.org/pypi/python-slugify)
@@ -354,6 +354,20 @@ The app relies and includes the following scripts/binaries:
* Fixed _No optimization_ mode
* Multiple small tweaks nad minor bug fixes
####4.2:
* Added [Manga Cover Database](http://manga.joentjuh.nl/) support
* Officially dropped Windows XP support
* Fixed _Other_ profile
* Fixed problems with page order on stock KOBO CBZ reader
* Many other small bug fixes and tweaks
####4.2.1:
* Improved margin color detection
* Fixed random crashes of MOBI processing step
* Fixed resizing problems in high quality mode
* Fixed some MCD support bugs
* Default output format for Kindle DX is now CBZ
## 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.1'
__version__ = '4.2.1'
__license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
__docformat__ = 'restructuredtext en'
@@ -40,10 +40,10 @@ except ImportError:
try:
# noinspection PyUnresolvedReferences
import PIL
if tuple(map(int, ('2.3.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))):
missing.append('Pillow 2.3.0+')
if tuple(map(int, ('2.5.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))):
missing.append('Pillow 2.5.0+')
except ImportError:
missing.append('Pillow 2.3.0+')
missing.append('Pillow 2.5.0+')
try:
# noinspection PyUnresolvedReferences
import slugify
@@ -63,10 +63,10 @@ if len(missing) > 0:
exit(1)
from multiprocessing import freeze_support
from kcc.comic2ebook import main, Copyright
from kcc.comic2ebook import main
if __name__ == "__main__":
freeze_support()
Copyright()
print(('comic2ebook v%(__version__)s. Written by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals()))
main(sys.argv[1:])
sys.exit(0)

View File

@@ -18,7 +18,7 @@
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
__version__ = '4.1'
__version__ = '4.2.1'
__license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
__docformat__ = 'restructuredtext en'
@@ -33,10 +33,10 @@ missing = []
try:
# noinspection PyUnresolvedReferences
import PIL
if tuple(map(int, ('2.3.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))):
missing.append('Pillow 2.3.0+')
if tuple(map(int, ('2.5.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))):
missing.append('Pillow 2.5.0+')
except ImportError:
missing.append('Pillow 2.3.0+')
missing.append('Pillow 2.5.0+')
if len(missing) > 0:
try:
# noinspection PyUnresolvedReferences
@@ -51,10 +51,10 @@ if len(missing) > 0:
exit(1)
from multiprocessing import freeze_support
from kcc.comic2panel import main, Copyright
from kcc.comic2panel import main
if __name__ == "__main__":
freeze_support()
Copyright()
print(('comic2ebook v%(__version__)s. Written by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals()))
main(sys.argv[1:])
sys.exit(0)

View File

@@ -1,5 +1,5 @@
#define MyAppName "Kindle Comic Converter"
#define MyAppVersion "4.1"
#define MyAppVersion "4.2.1"
#define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
#define MyAppURL "http://kcc.iosphe.re/"
#define MyAppExeName "KCC.exe"
@@ -30,6 +30,7 @@ UninstallDisplayIcon={app}\{#MyAppExeName}
ChangesAssociations=True
InfoAfterFile=other\InstallWarning.rtf
SignTool=SignTool /d $q{#MyAppName}$q /du $q{#MyAppURL}$q $f
MinVersion=0,6.0
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

8
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.1'
__version__ = '4.2.1'
__license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
__docformat__ = 'restructuredtext en'
@@ -47,10 +47,10 @@ except ImportError:
try:
# noinspection PyUnresolvedReferences
import PIL
if tuple(map(int, ('2.3.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))):
missing.append('Pillow 2.3.0+')
if tuple(map(int, ('2.5.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))):
missing.append('Pillow 2.5.0+')
except ImportError:
missing.append('Pillow 2.3.0+')
missing.append('Pillow 2.5.0+')
try:
# noinspection PyUnresolvedReferences
import slugify

View File

@@ -17,7 +17,7 @@
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
__version__ = '4.1'
__version__ = '4.2.1'
__license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
__docformat__ = 'restructuredtext en'
@@ -38,6 +38,7 @@ from xml.dom.minidom import parse
from html.parser import HTMLParser
from psutil import virtual_memory, Popen, Process
from uuid import uuid4
from copy import copy
from .shared import md5Checksum
from . import comic2ebook
from . import dualmetafix
@@ -196,7 +197,6 @@ class VersionThread(QtCore.QThread):
def run(self):
try:
sleep(1)
XML = urlopen('http://kcc.iosphe.re/Version.php')
XML = parse(XML)
except Exception:
@@ -422,9 +422,6 @@ class WorkerThread(QtCore.QThread):
if GUI.ColorBox.isChecked():
options.forcecolor = True
comic2ebook.options = options
comic2ebook.checkOptions()
for i in range(GUI.JobList.count()):
# Make sure that we don't consider any system message as job to do
if GUI.JobList.item(i).icon().isNull():
@@ -446,7 +443,8 @@ class WorkerThread(QtCore.QThread):
jobargv = list(argv)
jobargv.append(job)
try:
comic2ebook.options.title = 'defaulttitle'
comic2ebook.options = copy(options)
comic2ebook.checkOptions()
outputPath = comic2ebook.makeBook(job, self)
MW.hideProgressBar.emit()
except UserWarning as warn:
@@ -493,7 +491,8 @@ class WorkerThread(QtCore.QThread):
worker.signals.result.connect(self.addResult)
self.pool.start(worker)
self.pool.waitForDone()
sleep(0.5)
while len(self.workerOutput) != len(outputPath):
sleep(0.1)
self.kindlegenErrorCode = [0]
for errors in self.workerOutput:
if errors[0] != 0:
@@ -503,7 +502,6 @@ class WorkerThread(QtCore.QThread):
for item in outputPath:
if os.path.exists(item):
os.remove(item)
sleep(1)
if os.path.exists(item.replace('.epub', '.mobi')):
os.remove(item.replace('.epub', '.mobi'))
self.clean()
@@ -521,7 +519,8 @@ class WorkerThread(QtCore.QThread):
worker.signals.result.connect(self.addResult)
self.pool.start(worker)
self.pool.waitForDone()
sleep(0.5)
while len(self.workerOutput) != len(outputPath):
sleep(0.1)
for success in self.workerOutput:
if not success[0]:
self.errors = True
@@ -555,7 +554,6 @@ class WorkerThread(QtCore.QThread):
for item in outputPath:
if os.path.exists(item):
os.remove(item)
sleep(1)
if os.path.exists(item.replace('.epub', '.mobi')):
os.remove(item.replace('.epub', '.mobi'))
MW.addMessage.emit('KindleGen failed to create MOBI!', 'error', False)
@@ -834,6 +832,9 @@ class KCCGUI(KCC_ui.Ui_KCC):
if value == 2 and 'Kobo' in str(GUI.DeviceBox.currentText()):
self.addMessage('Kobo devices can\'t use ultra quality mode!', 'warning')
GUI.QualityBox.setCheckState(0)
elif value == 2 and 'CBZ' in str(GUI.FormatBox.currentText()):
self.addMessage('CBZ format don\'t support ultra quality mode!', 'warning')
GUI.QualityBox.setCheckState(0)
def changeGamma(self, value):
value = float(value)
@@ -861,7 +862,7 @@ class KCCGUI(KCC_ui.Ui_KCC):
GUI.AdvModeButton.setEnabled(True)
if self.currentMode == 3:
self.modeBasic()
self.changeFormat()
self.changeFormat(event=False)
GUI.GammaSlider.setValue(0)
self.changeGamma(0)
if profile['DefaultUpscale']:
@@ -870,19 +871,12 @@ class KCCGUI(KCC_ui.Ui_KCC):
self.addMessage('<a href="https://github.com/ciromattia/kcc/wiki/NonKindle-devices">'
'List of supported Non-Kindle devices.</a>', 'info')
def changeFormat(self, outputFormat=None):
def changeFormat(self, outputFormat=None, event=True):
profile = GUI.profiles[str(GUI.DeviceBox.currentText())]
if outputFormat is not None:
GUI.FormatBox.setCurrentIndex(outputFormat)
else:
if GUI.FormatBox.count() == 3:
GUI.FormatBox.setCurrentIndex(profile['DefaultFormat'])
else:
if profile['DefaultFormat'] != 0:
tmpFormat = profile['DefaultFormat'] - 1
else:
tmpFormat = 0
GUI.FormatBox.setCurrentIndex(tmpFormat)
GUI.FormatBox.setCurrentIndex(profile['DefaultFormat'])
if GUI.WebtoonBox.isChecked():
GUI.MangaBox.setEnabled(False)
GUI.QualityBox.setEnabled(False)
@@ -895,6 +889,10 @@ class KCCGUI(KCC_ui.Ui_KCC):
if GUI.ProcessingBox.isChecked():
GUI.QualityBox.setEnabled(False)
GUI.QualityBox.setChecked(False)
if event and GUI.QualityBox.isEnabled() and 'CBZ' in str(GUI.FormatBox.currentText()) and\
GUI.QualityBox.checkState() == 2:
self.addMessage('CBZ format don\'t support ultra quality mode!', 'warning')
GUI.QualityBox.setCheckState(0)
def stripTags(self, html):
s = HTMLStripper()
@@ -973,6 +971,15 @@ class KCCGUI(KCC_ui.Ui_KCC):
self.addMessage('Target resolution is not set!', 'error')
self.needClean = True
return
if str(GUI.FormatBox.currentText()) == 'MOBI' and not GUI.KindleGen:
self.addMessage('Cannot find <a href="http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211">'
'<b>KindleGen</b></a>! MOBI conversion is not possible!', 'error')
if sys.platform.startswith('win'):
self.addMessage('Download it and place EXE in KCC directory.', 'error')
else:
self.addMessage('Download it, and place executable in /usr/local/bin directory.', 'error')
self.needClean = True
return
self.worker.start()
def hideProgressBar(self):
@@ -1118,7 +1125,7 @@ class KCCGUI(KCC_ui.Ui_KCC):
'DefaultUpscale': False, 'Label': 'KHD'},
"Kindle": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'K345'},
"Kindle DX/DXG": {'Quality': False, 'ForceExpert': False, 'DefaultFormat': 0,
"Kindle DX/DXG": {'Quality': False, 'ForceExpert': False, 'DefaultFormat': 2,
'DefaultUpscale': False, 'Label': 'KDX'},
"Kindle Fire": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'KF'},
@@ -1196,7 +1203,6 @@ class KCCGUI(KCC_ui.Ui_KCC):
kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True)
if kindleGenExitCode.wait() == 0:
self.KindleGen = True
formats = ['MOBI', 'EPUB', 'CBZ']
versionCheck = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True)
for line in versionCheck.stdout:
line = line.decode("utf-8")
@@ -1210,13 +1216,6 @@ class KCCGUI(KCC_ui.Ui_KCC):
break
else:
self.KindleGen = False
formats = ['EPUB', 'CBZ']
if sys.platform.startswith('win'):
self.addMessage('Cannot find <a href="http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211">'
'kindlegen</a> in KCC directory! MOBI creation will be disabled.', 'warning')
else:
self.addMessage('Cannot find <a href="http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211">'
'kindlegen</a> in PATH! MOBI creation will be disabled.', 'warning')
rarExitCode = Popen('unrar', stdout=PIPE, stderr=STDOUT, shell=True)
rarExitCode = rarExitCode.wait()
if rarExitCode == 0 or rarExitCode == 7:
@@ -1271,7 +1270,7 @@ class KCCGUI(KCC_ui.Ui_KCC):
GUI.DeviceBox.addItem(self.icons.deviceKobo, profile)
else:
GUI.DeviceBox.addItem(self.icons.deviceKindle, profile)
for f in formats:
for f in ['MOBI', 'EPUB', 'CBZ']:
GUI.FormatBox.addItem(eval('self.icons.' + f + 'Format'), f)
if self.lastDevice > GUI.DeviceBox.count():
self.lastDevice = 0
@@ -1282,7 +1281,7 @@ class KCCGUI(KCC_ui.Ui_KCC):
GUI.DeviceBox.setCurrentIndex(self.lastDevice)
self.changeDevice()
if self.currentFormat != self.profiles[str(GUI.DeviceBox.currentText())]['DefaultFormat']:
self.changeFormat(self.currentFormat)
self.changeFormat(self.currentFormat, False)
for option in self.options:
if str(option) == "customWidth":
GUI.customWidth.setText(str(self.options[option]))

View File

@@ -1,4 +1,4 @@
__version__ = '4.1'
__version__ = '4.2.1'
__license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
__docformat__ = 'restructuredtext en'

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,7 @@
# PERFORMANCE OF THIS SOFTWARE.
#
__version__ = '4.1'
__version__ = '4.2.1'
__license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
__docformat__ = 'restructuredtext en'
@@ -36,7 +36,7 @@ except ImportError:
QtCore = None
def mergeDirectory_tick(output):
def mergeDirectoryTick(output):
if output:
mergeWorkerOutput.append(output)
mergeWorkerPool.terminate()
@@ -108,7 +108,7 @@ def sanitizePanelSize(panel, opt):
return newPanels
def splitImage_tick(output):
def splitImageTick(output):
if output:
splitWorkerOutput.append(output)
splitWorkerPool.terminate()
@@ -207,10 +207,6 @@ def splitImage(work):
return str(sys.exc_info()[1])
def Copyright():
print(('comic2panel v%(__version__)s. Written by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals()))
def main(argv=None, qtGUI=None):
global options, GUI, splitWorkerPool, splitWorkerOutput, mergeWorkerPool, mergeWorkerOutput
parser = OptionParser(usage="Usage: kcc-c2p [options] comic_folder", add_help_option=False)
@@ -261,7 +257,7 @@ def main(argv=None, qtGUI=None):
GUI.progressBarTick.emit('Combining images')
GUI.progressBarTick.emit(str(directoryNumer))
for i in mergeWork:
mergeWorkerPool.apply_async(func=mergeDirectory, args=(i, ), callback=mergeDirectory_tick)
mergeWorkerPool.apply_async(func=mergeDirectory, args=(i, ), callback=mergeDirectoryTick)
mergeWorkerPool.close()
mergeWorkerPool.join()
if GUI and not GUI.conversionAlive:
@@ -284,7 +280,7 @@ def main(argv=None, qtGUI=None):
GUI.progressBarTick.emit('tick')
if len(work) > 0:
for i in work:
splitWorkerPool.apply_async(func=splitImage, args=(i, ), callback=splitImage_tick)
splitWorkerPool.apply_async(func=splitImage, args=(i, ), callback=splitImageTick)
splitWorkerPool.close()
splitWorkerPool.join()
if GUI and not GUI.conversionAlive:

View File

@@ -16,11 +16,15 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
__version__ = '4.2.1'
__license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
__docformat__ = 'restructuredtext en'
import os
from io import BytesIO
from urllib.request import Request, urlopen
from urllib.parse import quote
from functools import reduce
from PIL import Image, ImageOps, ImageStat, ImageChops
from .shared import md5Checksum
@@ -400,50 +404,44 @@ class ComicPage:
def getImageHistogram(self, image):
histogram = image.histogram()
RBGW = []
pixelCount = 0
for i in range(256):
pixelCount += histogram[i] + histogram[256 + i] + histogram[512 + i]
RBGW.append(histogram[i] + histogram[256 + i] + histogram[512 + i])
white = 0
black = 0
for i in range(251, 256):
white += RBGW[i]
for i in range(5):
black += RBGW[i]
if black > pixelCount*0.8 and white == 0:
return 1
elif white > pixelCount*0.8 and black == 0:
if histogram[0] == 0:
return -1
elif histogram[255] == 0:
return 1
else:
return False
return 0
def getImageFill(self, webtoon):
fill = 0
if not webtoon and not self.rotated:
# Search for horizontal solid lines
startY = 0
while startY < self.image.size[1]:
if startY + 5 > self.image.size[1]:
startY = self.image.size[1] - 5
checkSolid = self.getImageHistogram(self.image.crop((0, startY, self.image.size[0], startY+5)))
if checkSolid:
fill += checkSolid
startY += 5
def getImageFill(self):
bw = self.image.convert('L').point(lambda x: 0 if x < 128 else 255, '1')
imageBoxA = bw.getbbox()
imageBoxB = ImageChops.invert(bw).getbbox()
if imageBoxA is None or imageBoxB is None:
surfaceB, surfaceW = 0, 0
else:
# Search for vertical solid lines
startX = 0
while startX < self.image.size[0]:
if startX + 5 > self.image.size[0]:
startX = self.image.size[0] - 5
checkSolid = self.getImageHistogram(self.image.crop((startX, 0, startX+5, self.image.size[1])))
if checkSolid:
fill += checkSolid
startX += 5
if fill > 0:
surfaceB = (imageBoxA[2] - imageBoxA[0]) * (imageBoxA[3] - imageBoxA[1])
surfaceW = (imageBoxB[2] - imageBoxB[0]) * (imageBoxB[3] - imageBoxB[1])
if surfaceW < surfaceB:
self.fill = 'white'
elif surfaceW > surfaceB:
self.fill = 'black'
else:
self.fill = 'white'
fill = 0
startY = 0
while startY < bw.size[1]:
if startY + 5 > bw.size[1]:
startY = bw.size[1] - 5
fill += self.getImageHistogram(bw.crop((0, startY, bw.size[0], startY+5)))
startY += 5
startX = 0
while startX < bw.size[0]:
if startX + 5 > bw.size[0]:
startX = bw.size[0] - 5
fill += self.getImageHistogram(bw.crop((startX, 0, startX+5, bw.size[1])))
startX += 5
if fill > 0:
self.fill = 'black'
else:
self.fill = 'white'
def isImageColor(self):
v = ImageStat.Stat(self.image).var
@@ -472,14 +470,37 @@ class ComicPage:
class Cover:
def __init__(self, source, target):
def __init__(self, source, target, opt, tomeNumber):
self.options = opt
self.source = source
self.target = target
self.image = Image.open(source)
if tomeNumber == 0:
self.tomeNumber = 1
else:
self.tomeNumber = tomeNumber
if self.tomeNumber in self.options.remoteCovers:
try:
source = urlopen(Request(quote(self.options.remoteCovers[self.tomeNumber]).replace('%3A', ':', 1),
headers={'User-Agent': 'KindleComicConverter/' + __version__})).read()
self.image = Image.open(BytesIO(source))
self.processExternal()
except Exception:
self.image = Image.open(source)
self.processInternal()
else:
self.image = Image.open(source)
self.processInternal()
def processInternal(self):
self.image = self.image.convert('RGB')
self.process()
self.image = self.trim()
self.save()
def processExternal(self):
self.image = self.image.convert('RGB')
self.image.thumbnail(self.options.profileData[1], Image.ANTIALIAS)
self.save(True)
def trim(self):
bg = Image.new(self.image.mode, self.image.size, self.image.getpixel((0, 0)))
diff = ImageChops.difference(self.image, bg)
@@ -490,12 +511,13 @@ class Cover:
else:
return self.image
def process(self):
self.image = self.trim()
def save(self):
def save(self, external=False):
if external:
source = self.options.remoteCovers[self.tomeNumber].split('/')[-1]
else:
source = self.source
try:
if os.path.splitext(self.source)[1].lower() == '.png':
if os.path.splitext(source)[1].lower() == '.png':
self.image.save(self.target, "PNG", optimize=1)
else:
self.image.save(self.target, "JPEG", optimize=1)

View File

@@ -14,7 +14,7 @@ if version_info[0] != 3:
exit(1)
NAME = "KindleComicConverter"
VERSION = "4.1"
VERSION = "4.2.1"
MAIN = "kcc.py"
if platform == "darwin":

View File

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