about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPaweł Jastrzębski <[email protected]>2017-04-09 15:35:41 +0200
committerGitHub <[email protected]>2017-04-09 15:35:41 +0200
commita5064a0c0a6d3a9cd4cf90a0628b965fbfda5f2a (patch)
tree306054863a915eeaa76f34fef3d8f70c57a3b522
parentMerge pull request #231 from ciromattia/dev (diff)
parentUpdated README + version bump (diff)
downloadkcc-a5064a0c0a6d3a9cd4cf90a0628b965fbfda5f2a.tar.gz
kcc-a5064a0c0a6d3a9cd4cf90a0628b965fbfda5f2a.tar.bz2
kcc-a5064a0c0a6d3a9cd4cf90a0628b965fbfda5f2a.zip
Merge pull request #233 from ciromattia/dev
5.4
-rw-r--r--README.md10
-rw-r--r--gui/KCC.ui62
-rwxr-xr-xkcc-c2p.py2
-rw-r--r--kcc.iss2
-rwxr-xr-xkcc.py2
-rw-r--r--kindlecomicconverter/KCC_gui.py25
-rw-r--r--kindlecomicconverter/KCC_ui.py7
-rw-r--r--kindlecomicconverter/__init__.py2
-rw-r--r--kindlecomicconverter/cbxarchive.py3
-rwxr-xr-xkindlecomicconverter/comic2ebook.py27
-rw-r--r--kindlecomicconverter/comic2panel.py127
-rwxr-xr-xkindlecomicconverter/image.py4
-rw-r--r--kindlecomicconverter/shared.py2
-rw-r--r--kindlecomicconverter/startup.py5
-rw-r--r--other/osx/Info.plist6
-rwxr-xr-xsetup.py22
16 files changed, 185 insertions, 123 deletions
diff --git a/README.md b/README.md
index a06ad77..cbdd012 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # KCC
 
-[![GitHub release](https://img.shields.io/github/release/ciromattia/kcc.svg)]() [![PyPI](https://img.shields.io/pypi/v/KindleComicConverter.svg)]() [![AUR](https://img.shields.io/aur/version/kcc.svg)]()
+[![GitHub release](https://img.shields.io/github/release/ciromattia/kcc.svg)](https://github.com/ciromattia/kcc/releases) [![PyPI](https://img.shields.io/pypi/v/KindleComicConverter.svg)](https://pypi.python.org/pypi/KindleComicConverter) [![AUR](https://img.shields.io/aur/version/kcc.svg)](https://aur.archlinux.org/packages/kcc/)
 
 **Kindle Comic Converter** is a Python app to convert comic/manga files or folders to EPUB, Panel View MOBI or E-Ink optimized CBZ.
 It was initially developed for Kindle but since version 4.6 it outputs valid EPUB 3.0 so _**despite its name, KCC is
@@ -72,7 +72,7 @@ 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.
 
-CLI version of **KCC** is intended for power users. It is not idiot-proof like GUI :-)
+CLI version of **KCC** is intended for power users. It allow to use options that might not be compatible and decrease quality of output. 
 
 ### Standalone `kcc-c2e.py` usage:
 
@@ -86,6 +86,7 @@ Options:
                         KDX, KPW, KV, KoMT, KoG, KoGHD, KoA, KoAHD, KoAH2O,
                         KoAO) [Default=KV]
     -m, --manga-style   Manga style (right-to-left reading and splitting)
+    -q, --hq            Try to increase the quality of magnification
     -2, --two-panel     Display two not four panels in Panel View mode
     -w, --webtoon       Webtoon processing mode
 
@@ -170,6 +171,11 @@ The app relies and includes the following scripts:
 * [Kobo Aura ONE](http://kcc.iosphe.re/Samples/Ubunchu-KoAO.kepub.epub)
 
 ## CHANGELOG
+#### 5.4:
+* Reimplemented high quality Panel View option
+* Improved webtoon splitter
+* Fixed page splitter
+
 #### 5.3.1:
 * Small increase of output quality
 * Improved error reporting
diff --git a/gui/KCC.ui b/gui/KCC.ui
index 5dc8697..56cc2b6 100644
--- a/gui/KCC.ui
+++ b/gui/KCC.ui
@@ -66,7 +66,16 @@
        <bool>false</bool>
       </property>
       <layout class="QGridLayout" name="gridLayout_3">
-       <property name="margin">
+       <property name="leftMargin">
+        <number>0</number>
+       </property>
+       <property name="topMargin">
+        <number>0</number>
+       </property>
+       <property name="rightMargin">
+        <number>0</number>
+       </property>
+       <property name="bottomMargin">
         <number>0</number>
        </property>
        <item row="0" column="2">
@@ -127,7 +136,16 @@
     <item row="4" column="0" colspan="2">
      <widget class="QWidget" name="optionWidget" native="true">
       <layout class="QGridLayout" name="gridLayout_2">
-       <property name="margin">
+       <property name="leftMargin">
+        <number>0</number>
+       </property>
+       <property name="topMargin">
+        <number>0</number>
+       </property>
+       <property name="rightMargin">
+        <number>0</number>
+       </property>
+       <property name="bottomMargin">
         <number>0</number>
        </property>
        <item row="0" column="0">
@@ -156,10 +174,13 @@
        <item row="0" column="2">
         <widget class="QCheckBox" name="qualityBox">
          <property name="toolTip">
-          <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style=\'white-space:pre\'&gt;&lt;span style=\&quot; font-weight:600; text-decoration: underline;\&quot;&gt;Unchecked - 4 panels&lt;br/&gt;&lt;/span&gt;Zoom each corner separately.&lt;/p&gt;&lt;p style=\'white-space:pre\'&gt;&lt;span style=\&quot; font-weight:600; text-decoration: underline;\&quot;&gt;Checked - 2 panels&lt;br/&gt;&lt;/span&gt;Zoom only the top and bottom of the page.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+          <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - 4 panels&lt;br/&gt;&lt;/span&gt;Zoom each corner separately.&lt;/p&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - 2 panels&lt;br/&gt;&lt;/span&gt;Zoom only the top and bottom of the page.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - 4 high quality panels&lt;br/&gt;&lt;/span&gt;Zoom each corner separately. Try to increase the quality of magnification. Check wiki for more details.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
          </property>
          <property name="text">
-          <string>Panel View 4/2</string>
+          <string>Panel View 4/2/HQ</string>
+         </property>
+         <property name="tristate">
+          <bool>true</bool>
          </property>
         </widget>
        </item>
@@ -238,7 +259,16 @@
        <bool>false</bool>
       </property>
       <layout class="QHBoxLayout" name="horizontalLayout_2">
-       <property name="margin">
+       <property name="leftMargin">
+        <number>0</number>
+       </property>
+       <property name="topMargin">
+        <number>0</number>
+       </property>
+       <property name="rightMargin">
+        <number>0</number>
+       </property>
+       <property name="bottomMargin">
         <number>0</number>
        </property>
        <item>
@@ -267,7 +297,16 @@
     <item row="0" column="0" colspan="2">
      <widget class="QWidget" name="toolWidget" native="true">
       <layout class="QHBoxLayout" name="horizontalLayout">
-       <property name="margin">
+       <property name="leftMargin">
+        <number>0</number>
+       </property>
+       <property name="topMargin">
+        <number>0</number>
+       </property>
+       <property name="rightMargin">
+        <number>0</number>
+       </property>
+       <property name="bottomMargin">
         <number>0</number>
        </property>
        <item>
@@ -316,7 +355,16 @@
        </sizepolicy>
       </property>
       <layout class="QGridLayout" name="gridLayout_4">
-       <property name="margin">
+       <property name="leftMargin">
+        <number>0</number>
+       </property>
+       <property name="topMargin">
+        <number>0</number>
+       </property>
+       <property name="rightMargin">
+        <number>0</number>
+       </property>
+       <property name="bottomMargin">
         <number>0</number>
        </property>
        <item row="0" column="0">
diff --git a/kcc-c2p.py b/kcc-c2p.py
index f1fb915..fca94fc 100755
--- a/kcc-c2p.py
+++ b/kcc-c2p.py
@@ -28,4 +28,4 @@ from kindlecomicconverter.startup import startC2P
 
 if __name__ == "__main__":
     freeze_support()
-    startC2P()
\ No newline at end of file
+    startC2P()
diff --git a/kcc.iss b/kcc.iss
index 7dea76f..ba63491 100644
--- a/kcc.iss
+++ b/kcc.iss
@@ -1,5 +1,5 @@
 #define MyAppName "Kindle Comic Converter"
-#define MyAppVersion "5.3.1"
+#define MyAppVersion "5.4"
 #define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
 #define MyAppURL "http://kcc.iosphe.re/"
 #define MyAppExeName "KCC.exe"
diff --git a/kcc.py b/kcc.py
index 445b0a3..afd4796 100755
--- a/kcc.py
+++ b/kcc.py
@@ -39,7 +39,7 @@ elif sys.platform.startswith('win'):
     class _Popen(forking.Popen):
         def __init__(self, *args, **kw):
             if hasattr(sys, 'frozen'):
-                # noinspection PyProtectedMember
+                # noinspection PyUnresolvedReferences,PyProtectedMember
                 os.putenv('_MEIPASS2', sys._MEIPASS)
             try:
                 super(_Popen, self).__init__(*args, **kw)
diff --git a/kindlecomicconverter/KCC_gui.py b/kindlecomicconverter/KCC_gui.py
index 5cf29d7..5a3b538 100644
--- a/kindlecomicconverter/KCC_gui.py
+++ b/kindlecomicconverter/KCC_gui.py
@@ -254,8 +254,10 @@ class WorkerThread(QtCore.QThread):
             options.splitter = 2
         elif GUI.rotateBox.checkState() == 2:
             options.splitter = 1
-        if GUI.qualityBox.isChecked():
+        if GUI.qualityBox.checkState() == 1:
             options.autoscale = True
+        elif GUI.qualityBox.checkState() == 2:
+            options.hq = True
         if GUI.webtoonBox.isChecked():
             options.webtoon = True
         if GUI.upscaleBox.checkState() == 1:
@@ -531,8 +533,8 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
     def clearJobs(self):
         GUI.jobList.clear()
 
-    # noinspection PyCallByClass,PyTypeChecker
     def openWiki(self):
+        # noinspection PyCallByClass
         QtGui.QDesktopServices.openUrl(QtCore.QUrl('https://github.com/ciromattia/kcc/wiki'))
 
     def modeChange(self, mode):
@@ -613,6 +615,18 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
             GUI.rotateBox.setEnabled(True)
             GUI.upscaleBox.setEnabled(True)
 
+    def togglequalityBox(self, value):
+        profile = GUI.profiles[str(GUI.deviceBox.currentText())]
+        if value == 2:
+            if profile['Label'] in ['KV']:
+                self.addMessage('This option is intended for older Kindle models.', 'warning')
+                self.addMessage('It might not provide any quality increase in this case.', 'warning')
+            GUI.upscaleBox.setEnabled(False)
+            GUI.upscaleBox.setChecked(True)
+        else:
+            GUI.upscaleBox.setEnabled(True)
+            GUI.upscaleBox.setChecked(profile['DefaultUpscale'])
+
     def changeGamma(self, value):
         valueRaw = int(5 * round(float(value) / 5))
         value = '%.2f' % (float(valueRaw) / 100)
@@ -634,7 +648,8 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
         self.changeFormat()
         GUI.gammaSlider.setValue(0)
         self.changeGamma(0)
-        GUI.qualityBox.setEnabled(profile['PVOptions'])
+        if not GUI.webtoonBox.isChecked():
+            GUI.qualityBox.setEnabled(profile['PVOptions'])
         GUI.upscaleBox.setChecked(profile['DefaultUpscale'])
         if not profile['PVOptions']:
             GUI.qualityBox.setChecked(False)
@@ -648,7 +663,8 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
             GUI.formatBox.setCurrentIndex(outputFormat)
         else:
             GUI.formatBox.setCurrentIndex(profile['DefaultFormat'])
-        GUI.qualityBox.setEnabled(profile['PVOptions'])
+        if not GUI.webtoonBox.isChecked():
+            GUI.qualityBox.setEnabled(profile['PVOptions'])
         if str(GUI.formatBox.currentText()) == 'MOBI/AZW3':
             GUI.outputSplit.setEnabled(True)
         else:
@@ -1002,6 +1018,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
         GUI.gammaSlider.valueChanged.connect(self.changeGamma)
         GUI.gammaBox.stateChanged.connect(self.togglegammaBox)
         GUI.webtoonBox.stateChanged.connect(self.togglewebtoonBox)
+        GUI.qualityBox.stateChanged.connect(self.togglequalityBox)
         GUI.deviceBox.activated.connect(self.changeDevice)
         GUI.formatBox.activated.connect(self.changeFormat)
         MW.progressBarTick.connect(self.updateProgressbar)
diff --git a/kindlecomicconverter/KCC_ui.py b/kindlecomicconverter/KCC_ui.py
index 71689ab..b23c981 100644
--- a/kindlecomicconverter/KCC_ui.py
+++ b/kindlecomicconverter/KCC_ui.py
@@ -2,7 +2,7 @@
 
 # Form implementation generated from reading ui file 'gui\KCC.ui'
 #
-# Created by: PyQt5 UI code generator 5.6
+# Created by: PyQt5 UI code generator 5.8.1
 #
 # WARNING! All changes made in this file will be lost!
 
@@ -81,6 +81,7 @@ class Ui_mainWindow(object):
         self.rotateBox.setObjectName("rotateBox")
         self.gridLayout_2.addWidget(self.rotateBox, 0, 1, 1, 1)
         self.qualityBox = QtWidgets.QCheckBox(self.optionWidget)
+        self.qualityBox.setTristate(True)
         self.qualityBox.setObjectName("qualityBox")
         self.gridLayout_2.addWidget(self.qualityBox, 0, 2, 1, 1)
         self.webtoonBox = QtWidgets.QCheckBox(self.optionWidget)
@@ -241,8 +242,8 @@ class Ui_mainWindow(object):
         self.mangaBox.setText(_translate("mainWindow", "Manga mode"))
         self.rotateBox.setToolTip(_translate("mainWindow", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Split<br/></span>Double page spreads will be cut into two separate pages.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Rotate and split<br/></span>Double page spreads will be displayed twice. First rotated and then split. </p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Rotate<br/></span>Double page spreads will be rotated.</p></body></html>"))
         self.rotateBox.setText(_translate("mainWindow", "Spread splitter"))
-        self.qualityBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - 4 panels<br/></span>Zoom each corner separately.</p><p style=\'white-space:pre\'><span style=\" font-weight:600; text-decoration: underline;\">Checked - 2 panels<br/></span>Zoom only the top and bottom of the page.</p></body></html>"))
-        self.qualityBox.setText(_translate("mainWindow", "Panel View 4/2"))
+        self.qualityBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - 4 panels<br/></span>Zoom each corner separately.</p><p style=\'white-space:pre\'><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - 2 panels<br/></span>Zoom only the top and bottom of the page.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - 4 high quality panels<br/></span>Zoom each corner separately. Try to increase the quality of magnification. Check wiki for more details.</p></body></html>"))
+        self.qualityBox.setText(_translate("mainWindow", "Panel View 4/2/HQ"))
         self.webtoonBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Enable special parsing mode for Korean Webtoons.</p></body></html>"))
         self.webtoonBox.setText(_translate("mainWindow", "Webtoon mode"))
         self.upscaleBox.setToolTip(_translate("mainWindow", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html>"))
diff --git a/kindlecomicconverter/__init__.py b/kindlecomicconverter/__init__.py
index 3622f15..a873448 100644
--- a/kindlecomicconverter/__init__.py
+++ b/kindlecomicconverter/__init__.py
@@ -1,4 +1,4 @@
-__version__ = '5.3.1'
+__version__ = '5.4'
 __license__ = 'ISC'
 __copyright__ = '2012-2017, Ciro Mattia Gonano <[email protected]>, Pawel Jastrzebski <[email protected]>'
 __docformat__ = 'restructuredtext en'
diff --git a/kindlecomicconverter/cbxarchive.py b/kindlecomicconverter/cbxarchive.py
index 7bd833f..7aba70f 100644
--- a/kindlecomicconverter/cbxarchive.py
+++ b/kindlecomicconverter/cbxarchive.py
@@ -16,12 +16,11 @@
 # PERFORMANCE OF THIS SOFTWARE.
 #
 
-import sys
 import os
 from zipfile import is_zipfile, ZipFile
 from subprocess import STDOUT, PIPE
 from psutil import Popen
-from shutil import move, copy
+from shutil import move
 from . import rarfile
 from .shared import check7ZFile as is_7zfile
 
diff --git a/kindlecomicconverter/comic2ebook.py b/kindlecomicconverter/comic2ebook.py
index f5c6320..1bffcc4 100755
--- a/kindlecomicconverter/comic2ebook.py
+++ b/kindlecomicconverter/comic2ebook.py
@@ -103,6 +103,10 @@ def buildHTML(path, imgfile, imgfilepath):
         os.makedirs(htmlpath)
     htmlfile = os.path.join(htmlpath, filename[0] + '.xhtml')
     imgsize = Image.open(os.path.join(head, "Images", postfix, imgfile)).size
+    if options.hq:
+        imgsizeframe = deviceres
+    else:
+        imgsizeframe = imgsize
     f = open(htmlfile, "w", encoding='UTF-8')
     f.writelines(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
                   "<!DOCTYPE html>\n",
@@ -111,17 +115,20 @@ def buildHTML(path, imgfile, imgfilepath):
                   "<title>", escape(filename[0]), "</title>\n",
                   "<link href=\"", "../" * (backref - 1), "style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n",
                   "<meta name=\"viewport\" "
-                  "content=\"width=" + str(deviceres[0]) + ", height=" + str(deviceres[1]) + "\"/>\n"
+                  "content=\"width=" + str(imgsize[0]) + ", height=" + str(imgsize[1]) + "\"/>\n"
                   "</head>\n",
                   "<body style=\"" + additionalStyle + "\">\n",
                   "<div style=\"text-align:center;top:" + getTopMargin(deviceres, imgsize) + "%;\">\n",
-                  "<img width=\"" + str(imgsize[0]) + "\" height=\"" + str(imgsize[1]) + "\" ",
+                  "<img width=\"" + str(imgsizeframe[0]) + "\" height=\"" + str(imgsizeframe[1]) + "\" ",
                   "src=\"", "../" * backref, "Images/", postfix, imgfile, "\"/>\n</div>\n"])
     if options.iskindle and options.panelview:
         if options.autoscale:
             size = (getPanelViewResolution(imgsize, deviceres))
         else:
-            size = (int(imgsize[0] * 1.5), int(imgsize[1] * 1.5))
+            if options.hq:
+                size = imgsize
+            else:
+                size = (int(imgsize[0] * 1.5), int(imgsize[1] * 1.5))
         if size[0] - deviceres[0] < deviceres[0] * 0.01:
             noHorizontalPV = True
         else:
@@ -455,7 +462,7 @@ def buildEPUB(path, chapterNames, tomeNumber):
 
 def imgDirectoryProcessing(path):
     global workerPool, workerOutput
-    workerPool = Pool()
+    workerPool = Pool(maxtasksperchild=100)
     workerOutput = []
     options.imgMetadata = {}
     options.imgOld = []
@@ -884,6 +891,8 @@ def makeParser():
                                 " KoA, KoAHD, KoAH2O, KoAO) [Default=KV]")
     mainOptions.add_option("-m", "--manga-style", action="store_true", dest="righttoleft", default=False,
                            help="Manga style (right-to-left reading and splitting)")
+    mainOptions.add_option("-q", "--hq", action="store_true", dest="hq", default=False,
+                           help="Try to increase the quality of magnification")
     mainOptions.add_option("-2", "--two-panel", action="store_true", dest="autoscale", default=False,
                            help="Display two not four panels in Panel View mode")
     mainOptions.add_option("-w", "--webtoon", action="store_true", dest="webtoon", default=False,
@@ -960,16 +969,20 @@ def checkOptions():
     # Older Kindle models don't support Panel View.
     if options.profile == 'K1' or options.profile == 'K2' or options.profile == 'KDX':
         options.panelview = False
+        options.hq = False
     # Webtoon mode mandatory options
     if options.webtoon:
         options.panelview = False
         options.righttoleft = False
         options.upscale = True
+        options.hq = False
     # Disable all Kindle features for other e-readers
     if options.profile == 'OTHER':
         options.panelview = False
+        options.hq = False
     if 'Ko' in options.profile:
         options.panelview = False
+        options.hq = False
     # CBZ files on Kindle DX/DXG support higher resolution
     if options.profile == 'KDX' and options.format == 'CBZ':
         options.customheight = 1200
@@ -1185,9 +1198,11 @@ def makeMOBI(work, qtGUI=None):
         threadNumber = 1
     elif 2 < availableMemory <= 4:
         threadNumber = 2
-    else:
+    elif 4 < availableMemory <= 8:
         threadNumber = 4
-    makeMOBIWorkerPool = Pool(threadNumber)
+    else:
+        threadNumber = None
+    makeMOBIWorkerPool = Pool(threadNumber, maxtasksperchild=10)
     for i in work:
         makeMOBIWorkerPool.apply_async(func=makeMOBIWorker, args=(i, ), callback=makeMOBIWorkerTick)
     makeMOBIWorkerPool.close()
diff --git a/kindlecomicconverter/comic2panel.py b/kindlecomicconverter/comic2panel.py
index e173575..2bb92b8 100644
--- a/kindlecomicconverter/comic2panel.py
+++ b/kindlecomicconverter/comic2panel.py
@@ -23,7 +23,7 @@ import sys
 from shutil import rmtree, copytree, move
 from optparse import OptionParser, OptionGroup
 from multiprocessing import Pool
-from PIL import Image, ImageStat, ImageOps
+from PIL import Image, ImageChops, ImageOps, ImageDraw
 from .shared import getImageFileName, walkLevel, walkSort, sanitizeTrace
 try:
     from PyQt5 import QtCore
@@ -67,8 +67,7 @@ def mergeDirectory(work):
             result = Image.new('RGB', (targetWidth, targetHeight))
             y = 0
             for i in imagesValid:
-                img = Image.open(i)
-                img = img.convert('RGB')
+                img = Image.open(i).convert('RGB')
                 if img.size[0] < targetWidth:
                     img = ImageOps.fit(img, (targetWidth, img.size[1]), method=Image.BICUBIC, centering=(0.5, 0.5))
                 result.paste(img, (0, y))
@@ -80,30 +79,8 @@ def mergeDirectory(work):
         return str(sys.exc_info()[1]), sanitizeTrace(sys.exc_info()[2])
 
 
-def sanitizePanelSize(panel, opt):
-    newPanels = []
-    if panel[2] > 6 * opt.height:
-        diff = int(panel[2] / 8)
-        newPanels.append([panel[0], panel[1] - diff * 7, diff])
-        newPanels.append([panel[1] - diff * 7, panel[1] - diff * 6, diff])
-        newPanels.append([panel[1] - diff * 6, panel[1] - diff * 5, diff])
-        newPanels.append([panel[1] - diff * 5, panel[1] - diff * 4, diff])
-        newPanels.append([panel[1] - diff * 4, panel[1] - diff * 3, diff])
-        newPanels.append([panel[1] - diff * 3, panel[1] - diff * 2, diff])
-        newPanels.append([panel[1] - diff * 2, panel[1] - diff, diff])
-        newPanels.append([panel[1] - diff, panel[1], diff])
-    elif panel[2] > 3 * opt.height:
-        diff = int(panel[2] / 4)
-        newPanels.append([panel[0], panel[1] - diff * 3, diff])
-        newPanels.append([panel[1] - diff * 3, panel[1] - diff * 2, diff])
-        newPanels.append([panel[1] - diff * 2, panel[1] - diff, diff])
-        newPanels.append([panel[1] - diff, panel[1], diff])
-    elif panel[2] > 1.5 * opt.height:
-        newPanels.append([panel[0], panel[1] - int(panel[2] / 2), int(panel[2] / 2)])
-        newPanels.append([panel[1] - int(panel[2] / 2), panel[1], int(panel[2] / 2)])
-    else:
-        newPanels = [panel]
-    return newPanels
+def detectSolid(img):
+    return not ImageChops.invert(img).getbbox() or not img.getbbox()
 
 
 def splitImageTick(output):
@@ -121,56 +98,60 @@ def splitImage(work):
         path = work[0]
         name = work[1]
         opt = work[2]
-        # Hardcoded options
-        threshold = 1.0
-        delta = 15
-        fileExpanded = os.path.splitext(name)
         filePath = os.path.join(path, name)
-        image = Image.open(filePath)
-        image = image.convert('RGB')
-        widthImg, heightImg = image.size
+        imgOrg = Image.open(filePath).convert('RGB')
+        imgProcess = Image.open(filePath).convert('1')
+        widthImg, heightImg = imgOrg.size
         if heightImg > opt.height:
             if opt.debug:
-                from PIL import ImageDraw
-                debugImage = Image.open(filePath)
-                draw = ImageDraw.Draw(debugImage)
+                drawImg = Image.open(filePath).convert(mode='RGBA')
+                draw = ImageDraw.Draw(drawImg)
 
             # Find panels
-            y1 = 0
-            y2 = 15
+            yWork = 0
+            panelDetected = False
             panels = []
-            while y2 < heightImg:
-                while ImageStat.Stat(image.crop([0, y1, widthImg, y2])).var[0] < threshold and y2 < heightImg:
-                    y2 += delta
-                y2 -= delta
-                y1Temp = y2
-                y1 = y2 + delta
-                y2 = y1 + delta
-                while ImageStat.Stat(image.crop([0, y1, widthImg, y2])).var[0] >= threshold and y2 < heightImg:
-                    y1 += delta
-                    y2 += delta
-                if y1 + delta >= heightImg:
-                    y1 = heightImg - 1
-                y2Temp = y1
-                if opt.debug:
-                    draw.line([(0, y1Temp), (widthImg, y1Temp)], fill=(0, 255, 0))
-                    draw.line([(0, y2Temp), (widthImg, y2Temp)], fill=(255, 0, 0))
-                panelHeight = y2Temp - y1Temp
-                if panelHeight > delta:
-                    # Panels that can't be cut nicely will be forcefully splitted
-                    panelsCleaned = sanitizePanelSize([y1Temp, y2Temp, panelHeight], opt)
-                    for panel in panelsCleaned:
-                        panels.append(panel)
+            while yWork < heightImg:
+                tmpImg = imgProcess.crop([0, yWork, widthImg, yWork + 4])
+                solid = detectSolid(tmpImg)
+                if not solid and not panelDetected:
+                    panelDetected = True
+                    panelY1 = yWork - 2
+                if solid and panelDetected:
+                    panelDetected = False
+                    panelY2 = yWork + 6
+                    panels.append((panelY1, panelY2, panelY2 - panelY1))
+                yWork += 5
+
+            # Split too big panels
+            panelsProcessed = []
+            for panel in panels:
+                if panel[2] <= opt.height * 1.5:
+                    panelsProcessed.append(panel)
+                elif panel[2] < opt.height * 2:
+                    diff = panel[2] - opt.height
+                    panelsProcessed.append((panel[0], panel[1] - diff, opt.height))
+                    panelsProcessed.append((panel[1] - opt.height, panel[1], opt.height))
+                else:
+                    parts = round(panel[2] / opt.height)
+                    diff = panel[2] // parts
+                    for x in range(0, parts):
+                        panelsProcessed.append((panel[0] + (x * diff), panel[1] - ((parts - x - 1) * diff), diff))
+
             if opt.debug:
+                for panel in panelsProcessed:
+                    # noinspection PyUnboundLocalVariable
+                    draw.rectangle([(0, panel[0]), (widthImg, panel[1])], (0, 255, 0, 128), (0, 0, 255, 255))
                 # noinspection PyUnboundLocalVariable
-                debugImage.save(os.path.join(path, fileExpanded[0] + '-debug.png'), 'PNG')
+                debugImage = Image.alpha_composite(imgOrg.convert(mode='RGBA'), drawImg)
+                debugImage.save(os.path.join(path, os.path.splitext(name)[0] + '-debug.png'), 'PNG')
 
             # Create virtual pages
             pages = []
             currentPage = []
             pageLeft = opt.height
             panelNumber = 0
-            for panel in panels:
+            for panel in panelsProcessed:
                 if pageLeft - panel[2] > 0:
                     pageLeft -= panel[2]
                     currentPage.append(panelNumber)
@@ -190,14 +171,14 @@ def splitImage(work):
                 pageHeight = 0
                 targetHeight = 0
                 for panel in page:
-                    pageHeight += panels[panel][2]
-                if pageHeight > delta:
+                    pageHeight += panelsProcessed[panel][2]
+                if pageHeight > 15:
                     newPage = Image.new('RGB', (widthImg, pageHeight))
                     for panel in page:
-                        panelImg = image.crop([0, panels[panel][0], widthImg, panels[panel][1]])
+                        panelImg = imgOrg.crop([0, panelsProcessed[panel][0], widthImg, panelsProcessed[panel][1]])
                         newPage.paste(panelImg, (0, targetHeight))
-                        targetHeight += panels[panel][2]
-                    newPage.save(os.path.join(path, fileExpanded[0] + '-' + str(pageNumber) + '.png'), 'PNG')
+                        targetHeight += panelsProcessed[panel][2]
+                    newPage.save(os.path.join(path, os.path.splitext(name)[0] + '-' + str(pageNumber) + '.png'), 'PNG')
                     pageNumber += 1
             os.remove(filePath)
     except Exception:
@@ -238,13 +219,13 @@ def main(argv=None, qtGUI=None):
             work = []
             pagenumber = 1
             splitWorkerOutput = []
-            splitWorkerPool = Pool()
+            splitWorkerPool = Pool(maxtasksperchild=10)
             if options.merge:
                 print("Merging images...")
                 directoryNumer = 1
                 mergeWork = []
                 mergeWorkerOutput = []
-                mergeWorkerPool = Pool()
+                mergeWorkerPool = Pool(maxtasksperchild=10)
                 mergeWork.append([options.targetDir])
                 for root, dirs, files in os.walk(options.targetDir, False):
                     dirs, files = walkSort(dirs, files)
@@ -263,7 +244,8 @@ 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][0], mergeWorkerOutput[0][1])
+                    raise RuntimeError("One of workers crashed. Cause: " + mergeWorkerOutput[0][0],
+                                       mergeWorkerOutput[0][1])
             print("Splitting images...")
             for root, _, files in os.walk(options.targetDir, False):
                 for name in files:
@@ -286,7 +268,8 @@ 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][0], splitWorkerOutput[0][1])
+                    raise RuntimeError("One of workers crashed. Cause: " + splitWorkerOutput[0][0],
+                                       splitWorkerOutput[0][1])
                 if options.inPlace:
                     rmtree(options.sourceDir)
                     move(options.targetDir, options.sourceDir)
diff --git a/kindlecomicconverter/image.py b/kindlecomicconverter/image.py
index 5035a9e..a380648 100755
--- a/kindlecomicconverter/image.py
+++ b/kindlecomicconverter/image.py
@@ -120,7 +120,7 @@ class ComicPageParser:
         width, height = self.image.size
         dstwidth, dstheight = self.size
         if (width > height) != (dstwidth > dstheight) and width <= dstheight and height <= dstwidth \
-                and not self.opt.webtoon:
+                and not self.opt.webtoon and self.opt.splitter == 1:
             self.payload.append(['R', self.source, self.image.rotate(90, Image.BICUBIC, True), self.color, self.fill])
         elif (width > height) != (dstwidth > dstheight) and not self.opt.webtoon:
             if self.opt.splitter != 1:
@@ -209,6 +209,8 @@ class ComicPage:
     def __init__(self, options, mode, path, image, color, fill):
         self.opt = options
         _, self.size, self.palette, self.gamma = self.opt.profileData
+        if self.opt.hq:
+            self.size = (int(self.size[0] * 1.5), int(self.size[1] * 1.5))
         self.image = image
         self.color = color
         self.fill = fill
diff --git a/kindlecomicconverter/shared.py b/kindlecomicconverter/shared.py
index 00ae3b9..89e0b19 100644
--- a/kindlecomicconverter/shared.py
+++ b/kindlecomicconverter/shared.py
@@ -17,11 +17,9 @@
 #
 
 import os
-from sys import version_info
 from hashlib import md5
 from html.parser import HTMLParser
 from distutils.version import StrictVersion
-from time import sleep
 from shutil import rmtree, copy
 from tempfile import mkdtemp
 from zipfile import ZipFile, ZIP_DEFLATED
diff --git a/kindlecomicconverter/startup.py b/kindlecomicconverter/startup.py
index 4c47a17..aa78a0a 100644
--- a/kindlecomicconverter/startup.py
+++ b/kindlecomicconverter/startup.py
@@ -23,6 +23,7 @@ import sys
 from . import __version__
 from .shared import dependencyCheck
 
+
 def start():
     dependencyCheck(3)
     from . import KCC_gui
@@ -40,14 +41,16 @@ def start():
             KCCUI.handleMessage(sys.argv[1])
         sys.exit(KCCAplication.exec_())
 
+
 def startC2E():
     dependencyCheck(2)
     from .comic2ebook import main
     print('comic2ebook v' + __version__ + ' - Written by Ciro Mattia Gonano and Pawel Jastrzebski.')
     sys.exit(main(sys.argv[1:]))
 
+
 def startC2P():
     dependencyCheck(1)
     from .comic2panel import main
     print('comic2panel v' + __version__ + ' - Written by Ciro Mattia Gonano and Pawel Jastrzebski.')
-    sys.exit(main(sys.argv[1:]))
\ No newline at end of file
+    sys.exit(main(sys.argv[1:]))
diff --git a/other/osx/Info.plist b/other/osx/Info.plist
index dce11bb..0b4d894 100644
--- a/other/osx/Info.plist
+++ b/other/osx/Info.plist
@@ -30,7 +30,7 @@
 	<key>CFBundleExecutable</key>
 	<string>MacOS/Kindle Comic Converter</string>
 	<key>CFBundleGetInfoString</key>
-	<string>KindleComicConverter 5.3.1, written 2012-2017 by Ciro Mattia Gonano and Pawel Jastrzebski</string>
+	<string>KindleComicConverter 5.4.0, written 2012-2017 by Ciro Mattia Gonano and Pawel Jastrzebski</string>
 	<key>CFBundleIconFile</key>
 	<string>comic2ebook.icns</string>
 	<key>CFBundleIdentifier</key>
@@ -42,11 +42,11 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>5.3.1</string>
+	<string>5.4.0</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
-	<string>5.3.1</string>
+	<string>5.4.0</string>
 	<key>LSEnvironment</key>
 	<dict>
 		<key>PATH</key>
diff --git a/setup.py b/setup.py
index 7e330fe..278c4a7 100755
--- a/setup.py
+++ b/setup.py
@@ -2,10 +2,10 @@
 """
 pip/pyinstaller build script for KCC.
 
-Usage (Windows):
-    py -3 setup.py build_binary
+Install as Python package:
+    python3 setup.py install
 
-Usage (Linux/OS X):
+Create EXE/APP/DEB:
     python3 setup.py build_binary
 """
 
@@ -14,32 +14,22 @@ import sys
 import shutil
 import setuptools
 import distutils.cmd
-from distutils.command.build import build
 from kindlecomicconverter import __version__
 
 NAME = 'KindleComicConverter'
 MAIN = 'kcc.py'
 VERSION = __version__
 
+
 class BuildBinaryCommand(distutils.cmd.Command):
     description = 'build binary release'
-    user_options = [
-        ('pyz', None, 'build PYZ package'),
-    ]
-
-    def initialize_options(self):
-        # noinspection PyAttributeOutsideInit
-        self.pyz = False
-
-    def finalize_options(self):
-        pass
 
     def run(self):
         if sys.platform == 'darwin':
             if os.path.isfile('Kindle Comic Converter.spec'):
                 os.system('pyinstaller "Kindle Comic Converter.spec"')
             else:
-                os.system('pyinstaller -y -F -i icons/comic2ebook.icns -n "Kindle Comic Converter" -w -s --noupx kcc.py')
+                os.system('pyinstaller -y -F -i icons/comic2ebook.icns -n "Kindle Comic Converter" -w -s kcc.py')
             shutil.copy('other/osx/7za', 'dist/Kindle Comic Converter.app/Contents/Resources')
             shutil.copy('other/osx/unrar', 'dist/Kindle Comic Converter.app/Contents/Resources')
             shutil.copy('other/osx/Info.plist', 'dist/Kindle Comic Converter.app/Contents')
@@ -92,6 +82,6 @@ setuptools.setup(
         'python-slugify>=1.2.1',
         'raven>=6.0.0',
     ],
-    classifiers = [],
+    classifiers=[],
     zip_safe=False,
 )