about summary refs log tree commit diff
diff options
context:
space:
mode:
-rwxr-xr-xkcc-c2e.py3
-rwxr-xr-xkcc-c2p.py3
-rwxr-xr-xkcc/comic2ebook.py657
-rw-r--r--kcc/comic2panel.py6
-rwxr-xr-xkcc/image.py405
5 files changed, 446 insertions, 628 deletions
diff --git a/kcc-c2e.py b/kcc-c2e.py
index 0e0fb6a..0d3fbf6 100755
--- a/kcc-c2e.py
+++ b/kcc-c2e.py
@@ -33,5 +33,4 @@ from kcc.comic2ebook import main
 if __name__ == "__main__":
     freeze_support()
     print('comic2ebook v' + __version__ + ' - Written by Ciro Mattia Gonano and Pawel Jastrzebski.')
-    main(sys.argv[1:])
-    sys.exit(0)
+    sys.exit(main(sys.argv[1:]))
diff --git a/kcc-c2p.py b/kcc-c2p.py
index 7709306..a1ded61 100755
--- a/kcc-c2p.py
+++ b/kcc-c2p.py
@@ -33,5 +33,4 @@ from kcc.comic2panel import main
 if __name__ == "__main__":
     freeze_support()
     print('comic2panel v' + __version__ + ' - Written by Ciro Mattia Gonano and Pawel Jastrzebski.')
-    main(sys.argv[1:])
-    sys.exit(0)
+    sys.exit(main(sys.argv[1:]))
diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py
index 27b6753..199ab66 100755
--- a/kcc/comic2ebook.py
+++ b/kcc/comic2ebook.py
@@ -62,56 +62,37 @@ def main(argv=None):
     optionstemplate, args = parser.parse_args(argv)
     if len(args) == 0:
         parser.print_help()
-        return
+        return 0
     sources = set([source for arg in args for source in glob(arg)])
-    outputPath = []
     if len(sources) == 0:
         print('No matching files found.')
-        return
+        return 1
     for source in sources:
         source = source.rstrip('\\').rstrip('/')
         options = copy(optionstemplate)
         checkOptions()
         if len(sources) > 1:
-            print('\nWorking on ' + source)
-        outputPath = makeBook(source)
-    return outputPath
+            print('Working on ' + source + '...')
+        makeBook(source)
+    return 0
 
 
-def buildHTML(path, imgfile, imgfilepath, forcePV=False):
+def buildHTML(path, imgfile, imgfilepath):
     imgfilepath = md5Checksum(imgfilepath)
     filename = getImageFileName(imgfile)
-    additionalStyle = ''
-    if options.imgproc:
-        if "Rotated" in options.imgIndex[imgfilepath]:
-            rotatedPage = True
-        else:
-            rotatedPage = False
-        if "NoPanelView" in options.imgIndex[imgfilepath]:
-            noPV = True
-        else:
-            noPV = False
-        if "NoHorizontalPanelView" in options.imgIndex[imgfilepath]:
-            noHorizontalPV = True
-        else:
-            noHorizontalPV = False
-        if "NoVerticalPanelView" in options.imgIndex[imgfilepath]:
-            noVerticalPV = True
-        else:
-            noVerticalPV = False
-        if "BlackFill" in options.imgIndex[imgfilepath]:
-            additionalStyle = ' style="background-color:#000000" '
+    deviceres = options.profileData[1]
+    if "Rotated" in options.imgIndex[imgfilepath]:
+        rotatedPage = True
     else:
         rotatedPage = False
-        noPV = False
-        noHorizontalPV = False
-        noVerticalPV = False
-    if forcePV and noPV:
-        noPV = False
-        noHorizontalPV = True
-        noVerticalPV = True
+    if "BlackFill" in options.imgIndex[imgfilepath]:
+        additionalStyle = 'background-color:#000000;'
+    else:
+        additionalStyle = 'background-color:#FFFFFF;'
     htmlpath = ''
     postfix = ''
+    size = ''
+    imgfilepv = ''
     backref = 1
     head = path
     while True:
@@ -123,100 +104,94 @@ def buildHTML(path, imgfile, imgfilepath, forcePV=False):
         backref += 1
     if not os.path.exists(htmlpath):
         os.makedirs(htmlpath)
-    htmlfile = os.path.join(htmlpath, filename[0] + '.html')
+    htmlfile = os.path.join(htmlpath, filename[0] + '.xhtml')
     f = open(htmlfile, "w", encoding='UTF-8')
-    if options.iskindle:
-        f.writelines(["<?xml version=\"1.0\" encoding=\"utf-8\"?>\n",
-                      "<!DOCTYPE html>\n",
-                      "<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:epub=\"http://www.idpf.org/2007/ops\">\n",
-                      "<head>\n",
-                      "<title>", filename[0], "</title>\n",
-                      "<link href=\"", "../" * (backref - 1), "style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n",
-                      "<meta charset=\"utf-8\"/>\n",
-                      "</head>\n",
-                      "<body" + additionalStyle + ">\n",
-                      "<div class=\"fs\">\n",
-                      "<div><img src=\"", "../" * backref, "Images/", postfix, imgfile, "\" alt=\"",
-                      imgfile, "\" class=\"singlePage\"/></div>\n"
-                      ])
-        if (options.panelview or forcePV) and not noPV:
-            options.panelviewused = True
-            if not noHorizontalPV and not noVerticalPV:
-                if rotatedPage:
-                    if options.righttoleft:
-                        order = [1, 3, 2, 4]
-                    else:
-                        order = [2, 4, 1, 3]
+    f.writelines(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
+                  "<!DOCTYPE html>\n",
+                  "<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:epub=\"http://www.idpf.org/2007/ops\">\n",
+                  "<head>\n",
+                  "<title>", 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"
+                  "</head>\n",
+                  "<body style=\"background-image: ",
+                  "url('", "../" * backref, "Images/", postfix, imgfile, "'); " + additionalStyle + "\">\n"])
+    if options.iskindle and options.panelview:
+        if options.hqmode:
+            imgfilepv = list(os.path.splitext(imgfile))
+            imgfilepv[0] += "-hq"
+            imgfilepv = "".join(imgfilepv)
+            if os.path.isfile(os.path.join(head, "Images", postfix, imgfilepv)):
+                size = Image.open(os.path.join(head, "Images", postfix, imgfilepv)).size
+        if not options.hqmode or not size:
+            imgfilepv = imgfile
+            sizeTmp = Image.open(os.path.join(head, "Images", postfix, imgfilepv)).size
+            size = (int(sizeTmp[0] * 1.5), int(sizeTmp[1] * 1.5))
+        if size[0] <= deviceres[0]:
+            noHorizontalPV = True
+        else:
+            noHorizontalPV = False
+        if size[1] <= deviceres[1]:
+            noVerticalPV = True
+        else:
+            noVerticalPV = False
+        x, y = getPanelViewSize(deviceres, size)
+        boxStyles = {"PV-TL": "position:absolute;left:0;top:0;",
+                     "PV-TR": "position:absolute;right:0;top:0;",
+                     "PV-BL": "position:absolute;left:0;bottom:0;",
+                     "PV-BR": "position:absolute;right:0;bottom:0;",
+                     "PV-T": "position:absolute;top:0;left:" + x + "%;",
+                     "PV-B": "position:absolute;bottom:0;left:" + x + "%;",
+                     "PV-L": "position:absolute;left:0;top:" + y + "%;",
+                     "PV-R": "position:absolute;right:0;top:" + y + "%;"}
+        f.write("<div id=\"PV\">\n")
+        if not noHorizontalPV and not noVerticalPV:
+            if rotatedPage:
+                if options.righttoleft:
+                    order = [1, 3, 2, 4]
                 else:
-                    if options.righttoleft:
-                        order = [2, 1, 4, 3]
-                    else:
-                        order = [1, 2, 3, 4]
-                boxes = ["BoxTL", "BoxTR", "BoxBL", "BoxBR"]
-            elif noHorizontalPV and not noVerticalPV:
-                if rotatedPage:
-                    if options.righttoleft:
-                        order = [1, 2]
-                    else:
-                        order = [2, 1]
+                    order = [2, 4, 1, 3]
+            else:
+                if options.righttoleft:
+                    order = [2, 1, 4, 3]
                 else:
-                    order = [1, 2]
-                boxes = ["BoxT", "BoxB"]
-            elif not noHorizontalPV and noVerticalPV:
-                if rotatedPage:
+                    order = [1, 2, 3, 4]
+            boxes = ["PV-TL", "PV-TR", "PV-BL", "PV-BR"]
+        elif noHorizontalPV and not noVerticalPV:
+            if rotatedPage:
+                if options.righttoleft:
                     order = [1, 2]
                 else:
-                    if options.righttoleft:
-                        order = [2, 1]
-                    else:
-                        order = [1, 2]
-                boxes = ["BoxL", "BoxR"]
+                    order = [2, 1]
             else:
-                order = [1]
-                boxes = ["BoxC"]
-            for i in range(0, len(boxes)):
-                f.writelines(["<div id=\"" + boxes[i] + "\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
-                              "'{\"targetId\":\"" + boxes[i] + "-Panel-Parent\", \"ordinal\":" + str(order[i]),
-                              "}'></a></div>\n"])
-            if options.quality == 2 and not forcePV:
-                imgfilepv = imgfile.split(".")
-                imgfilepv[0] += "-hq"
-                imgfilepv = ".".join(imgfilepv)
+                order = [1, 2]
+            boxes = ["PV-T", "PV-B"]
+        elif not noHorizontalPV and noVerticalPV:
+            if rotatedPage:
+                order = [1, 2]
             else:
-                imgfilepv = imgfile
-            xl, yu, xr, yd = detectMargins(imgfilepath)
-            boxStyles = {"BoxTL": "left:" + xl + ";top:" + yu + ";",
-                         "BoxTR": "right:" + xr + ";top:" + yu + ";",
-                         "BoxBL": "left:" + xl + ";bottom:" + yd + ";",
-                         "BoxBR": "right:" + xr + ";bottom:" + yd + ";",
-                         "BoxT": "left:-25%;top:" + yu + ";",
-                         "BoxB": "left:-25%;bottom:" + yd + ";",
-                         "BoxL": "left:" + xl + ";top:-25%;",
-                         "BoxR": "right:" + xr + ";top:-25%;",
-                         "BoxC": "left:-25%;top:-25%;"
-                         }
-            for box in boxes:
-                f.writelines(["<div id=\"" + box + "-Panel-Parent\" class=\"target-mag-parent\"><div id=\"",
-                              "Generic-Panel\" class=\"target-mag\"><img style=\"" + boxStyles[box] + "\" src=\"",
-                              "../" * backref, "Images/", postfix, imgfilepv, "\" alt=\"" + imgfilepv,
-                              "\"/></div></div>\n",
-                              ])
-        f.writelines(["</div>\n</body>\n</html>"])
-    else:
-        f.writelines(["<?xml version=\"1.0\" encoding=\"utf-8\"?>\n",
-                      "<!DOCTYPE html>\n",
-                      "<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:epub=\"http://www.idpf.org/2007/ops\">\n",
-                      "<head>\n",
-                      "<title>", filename[0], "</title>\n",
-                      "<link href=\"", "../" * (backref - 1), "style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n",
-                      "<meta charset=\"utf-8\"/>\n",
-                      "</head>\n",
-                      "<body" + additionalStyle + ">\n",
-                      "<div class=\"epub:type=bodymatter\">\n",
-                      "<img src=\"", "../" * backref, "Images/", postfix, imgfile, "\"/>\n",
-                      "</div>\n",
-                      "</body>\n</html>"
-                      ])
+                if options.righttoleft:
+                    order = [2, 1]
+                else:
+                    order = [1, 2]
+            boxes = ["PV-L", "PV-R"]
+        else:
+            order = []
+            boxes = []
+        for i in range(0, len(boxes)):
+            f.writelines(["<div id=\"" + boxes[i] + "\">\n",
+                          "<a class=\"app-amzn-magnify\" data-app-amzn-magnify='{\"targetId\":\"" + boxes[i] +
+                          "-P\", \"ordinal\":" + str(order[i]) + "}'></a>\n",
+                          "</div>\n"])
+        for box in boxes:
+            f.writelines(["<div class=\"PV-P\" id=\"" + box + "-P\" style=\"" + additionalStyle + "\">\n",
+                          "<img style=\"" + boxStyles[box] + "\" src=\"", "../" * backref, "Images/", postfix,
+                          imgfilepv, "\" width=\"" + str(size[0]) + "\" height=\"" + str(size[1]) + "\"/>\n",
+                          "</div>\n"])
+        f.write("</div>\n")
+    f.writelines(["</body>\n",
+                  "</html>\n"])
     f.close()
     return path, imgfile
 
@@ -248,7 +223,7 @@ def buildNCX(dstdir, title, chapters, chapterNames):
             title = chapterNames[os.path.basename(folder)]
         f.write("<navPoint id=\"" + navID + "\"><navLabel><text>" +
                 title + "</text></navLabel><content src=\"" + filename[0].replace("\\", "/") +
-                ".html\"/></navPoint>\n")
+                ".xhtml\"/></navPoint>\n")
     f.write("</navMap>\n</ncx>")
     f.close()
 
@@ -273,7 +248,7 @@ def buildNAV(dstdir, title, chapters, chapterNames):
             title = chapterNames[chapter[1]]
         elif os.path.basename(folder) != "Text":
             title = chapterNames[os.path.basename(folder)]
-        f.write("<li><a href=\"" + filename[0].replace("\\", "/") + ".html\">" + title + "</a></li>\n")
+        f.write("<li><a href=\"" + filename[0].replace("\\", "/") + ".xhtml\">" + title + "</a></li>\n")
     f.writelines(["</ol>\n",
                   "</nav>\n",
                   "<nav epub:type=\"page-list\">\n",
@@ -286,14 +261,14 @@ def buildNAV(dstdir, title, chapters, chapterNames):
             title = chapterNames[chapter[1]]
         elif os.path.basename(folder) != "Text":
             title = chapterNames[os.path.basename(folder)]
-        f.write("<li><a href=\"" + filename[0].replace("\\", "/") + ".html\">" + title + "</a></li>\n")
+        f.write("<li><a href=\"" + filename[0].replace("\\", "/") + ".xhtml\">" + title + "</a></li>\n")
     f.write("</ol>\n</nav>\n</body>\n</html>")
     f.close()
 
 
 def buildOPF(dstdir, title, filelist, cover=None):
     opffile = os.path.join(dstdir, 'OEBPS', 'content.opf')
-    profilelabel, deviceres, palette, gamma, panelviewsize = options.profileData
+    deviceres = options.profileData[1]
     if options.righttoleft:
         writingmode = "horizontal-rl"
     else:
@@ -301,15 +276,15 @@ def buildOPF(dstdir, title, filelist, cover=None):
     f = open(opffile, "w", encoding='UTF-8')
     f.writelines(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
                   "<package version=\"3.0\" unique-identifier=\"BookID\" ",
-                  "prefix=\"rendition: http://www.idpf.org/vocab/rendition/#\" ",
                   "xmlns=\"http://www.idpf.org/2007/opf\">\n",
                   "<metadata xmlns:opf=\"http://www.idpf.org/2007/opf\" ",
                   "xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n",
                   "<dc:title>", title, "</dc:title>\n",
                   "<dc:language>en-US</dc:language>\n",
                   "<dc:identifier id=\"BookID\">urn:uuid:", options.uuid, "</dc:identifier>\n",
-                  "<dc:contributor id=\"contributor\">KindleComicConverter-" + __version__ + "</dc:contributor>\n",
-                  "<dc:description>", options.summary, "</dc:description>\n"])
+                  "<dc:contributor id=\"contributor\">KindleComicConverter-" + __version__ + "</dc:contributor>\n"])
+    if len(options.summary) > 0:
+        f.writelines(["<dc:description>", options.summary, "</dc:description>\n"])
     for author in options.authors:
         f.writelines(["<dc:creator>", author, "</dc:creator>\n"])
     f.writelines(["<meta property=\"dcterms:modified\">" + strftime("%Y-%m-%dT%H:%M:%SZ", gmtime()) + "</meta>\n",
@@ -347,7 +322,7 @@ def buildOPF(dstdir, title, filelist, cover=None):
         reflist.append(uniqueid)
         f.write("<item id=\"page_" + str(uniqueid) + "\" href=\"" +
                 folder.replace('Images', 'Text') + "/" + filename[0] +
-                ".html\" media-type=\"application/xhtml+xml\"/>\n")
+                ".xhtml\" media-type=\"application/xhtml+xml\"/>\n")
         if '.png' == filename[1]:
             mt = 'image/png'
         else:
@@ -359,6 +334,29 @@ def buildOPF(dstdir, title, filelist, cover=None):
         f.write("</manifest>\n<spine page-progression-direction=\"rtl\" toc=\"ncx\">\n")
     else:
         f.write("</manifest>\n<spine page-progression-direction=\"ltr\" toc=\"ncx\">\n")
+    # if options.iskindle and options.profile != 'Custom':
+    #     if options.righttoleft:
+    #         nextflow = 'right'
+    #     else:
+    #         nextflow = 'left'
+    #     for entry in reflist:
+    #         if '-kcc-b' in entry:
+    #             if options.righttoleft:
+    #                 f.write("<itemref idref=\"page_" + entry + "\" properties=\"page-spread-right\"/>\n")
+    #             else:
+    #                 f.write("<itemref idref=\"page_" + entry + "\" properties=\"page-spread-left\"/>\n")
+    #         elif '-kcc-c' in entry:
+    #             if options.righttoleft:
+    #                 f.write("<itemref idref=\"page_" + entry + "\" properties=\"page-spread-left\"/>\n")
+    #             else:
+    #                 f.write("<itemref idref=\"page_" + entry + "\" properties=\"page-spread-right\"/>\n")
+    #         else:
+    #             f.write("<itemref idref=\"page_" + entry + "\" properties=\"facing-page-" + nextflow + "\"/>\n")
+    #             if nextflow == 'right':
+    #                 nextflow = 'left'
+    #             else:
+    #                 nextflow = 'right'
+    # else:
     for entry in reflist:
         f.write("<itemref idref=\"page_" + entry + "\"/>\n")
     f.write("</spine>\n</package>\n")
@@ -378,139 +376,89 @@ def buildEPUB(path, chapterNames, tomeNumber):
     filelist = []
     chapterlist = []
     cover = None
-    lastfile = None
-    _, deviceres, _, _, panelviewsize = options.profileData
     os.mkdir(os.path.join(path, 'OEBPS', 'Text'))
     f = open(os.path.join(path, 'OEBPS', 'Text', 'style.css'), 'w', encoding='UTF-8')
-    if options.iskindle:
-        f.writelines(["@page {\n",
-                      "margin-bottom: 0;\n",
-                      "margin-top: 0\n",
-                      "}\n",
-                      "body {\n",
-                      "display: block;\n",
-                      "margin-bottom: 0;\n",
-                      "margin-left: 0;\n",
-                      "margin-right: 0;\n",
-                      "margin-top: 0;\n",
-                      "padding-bottom: 0;\n",
-                      "padding-left: 0;\n",
-                      "padding-right: 0;\n",
-                      "padding-top: 0;\n",
-                      "text-align: left\n",
-                      "}\n",
-                      "div.fs {\n",
-                      "height: ", str(deviceres[1]), "px;\n",
-                      "width: ", str(deviceres[0]), "px;\n",
-                      "position: relative;\n",
-                      "display: block;\n",
-                      "text-align: center\n",
-                      "}\n",
-                      "div.fs a {\n",
-                      "display: block;\n",
-                      "width : 100%;\n",
-                      "height: 100%;\n",
-                      "}\n",
-                      "div.fs div {\n",
-                      "position: absolute;\n",
-                      "}\n",
-                      "img.singlePage {\n",
-                      "position: absolute;\n",
-                      "height: ", str(deviceres[1]), "px;\n",
-                      "width: ", str(deviceres[0]), "px;\n",
-                      "}\n",
-                      "div.target-mag-parent {\n",
-                      "width:100%;\n",
-                      "height:100%;\n",
-                      "display:none;\n",
-                      "}\n",
-                      "div.target-mag {\n",
-                      "position: absolute;\n",
-                      "display: block;\n",
-                      "overflow: hidden;\n",
-                      "}\n",
-                      "div.target-mag img {\n",
-                      "position: absolute;\n",
-                      "height: ", str(panelviewsize[1]), "px;\n",
-                      "width: ", str(panelviewsize[0]), "px;\n",
-                      "}\n",
-                      "#Generic-Panel {\n",
-                      "top: 0;\n",
-                      "height: 100%;\n",
-                      "width: 100%;\n",
-                      "}\n",
-                      "#BoxC {\n",
-                      "top: 0;\n",
-                      "height: 100%;\n",
-                      "width: 100%;\n",
-                      "}\n",
-                      "#BoxT {\n",
-                      "top: 0;\n",
-                      "height: 50%;\n",
-                      "width: 100%;\n",
-                      "}\n",
-                      "#BoxB {\n",
-                      "bottom: 0;\n",
-                      "height: 50%;\n",
-                      "width: 100%;\n",
-                      "}\n",
-                      "#BoxL {\n",
-                      "left: 0;\n",
-                      "height: 100%;\n",
-                      "width: 50%;\n",
-                      "}\n",
-                      "#BoxR {\n",
-                      "right: 0;\n",
-                      "height: 100%;\n",
-                      "width: 50%;\n",
-                      "}\n",
-                      "#BoxTL {\n",
-                      "top: 0;\n",
-                      "left: 0;\n",
-                      "height: 50%;\n",
-                      "width: 50%;\n",
-                      "}\n",
-                      "#BoxTR {\n",
-                      "top: 0;\n",
-                      "right: 0;\n",
-                      "height: 50%;\n",
-                      "width: 50%;\n",
-                      "}\n",
-                      "#BoxBL {\n",
-                      "bottom: 0;\n",
-                      "left: 0;\n",
-                      "height: 50%;\n",
-                      "width: 50%;\n",
-                      "}\n",
-                      "#BoxBR {\n",
-                      "bottom: 0;\n",
-                      "right: 0;\n",
-                      "height: 50%;\n",
-                      "width: 50%;\n",
-                      "}",
-                      ])
-    else:
-        f.writelines([
-            "@namespace epub \"http://www.idpf.org/2007/ops\";\n",
-            "@charset \"UTF-8\";\n",
-            "body {\n",
-            "margin: 0;\n",
-            "}\n",
-            "img {\n",
-            "position: absolute;\n",
-            "margin: 0;\n",
-            "z-index: 0;\n",
-            "height: 100%;\n",
-            "}"])
+    f.writelines(["@page {\n",
+                  "margin: 0;\n",
+                  "}\n",
+                  "body {\n",
+                  "display: block;\n",
+                  "margin: 0;\n",
+                  "padding: 0;\n",
+                  "background-position: center center;\n",
+                  "background-repeat: no-repeat;\n",
+                  "background-size: auto auto;\n",
+                  "}\n",
+                  "#PV {\n",
+                  "position: absolute;\n",
+                  "width: 100%;\n",
+                  "height: 100%;\n",
+                  "}\n",
+                  "#PV-T {\n",
+                  "top: 0;\n",
+                  "width: 100%;\n",
+                  "height: 50%;\n",
+                  "}\n",
+                  "#PV-B {\n",
+                  "bottom: 0;\n",
+                  "width: 100%;\n",
+                  "height: 50%;\n",
+                  "}\n",
+                  "#PV-L {\n",
+                  "left: 0;\n",
+                  "width: 50%;\n",
+                  "height: 100%;\n",
+                  "float: left;\n",
+                  "}\n",
+                  "#PV-R {\n",
+                  "right: 0;\n",
+                  "width: 50%;\n",
+                  "height: 100%;\n",
+                  "float: right;\n",
+                  "}\n",
+                  "#PV-TL {\n",
+                  "top: 0;\n",
+                  "left: 0;\n",
+                  "width: 50%;\n",
+                  "height: 50%;\n",
+                  "float: left;\n",
+                  "}\n",
+                  "#PV-TR {\n",
+                  "top: 0;\n",
+                  "right: 0;\n",
+                  "width: 50%;\n",
+                  "height: 50%;\n",
+                  "float: right;\n",
+                  "}\n",
+                  "#PV-BL {\n",
+                  "bottom: 0;\n",
+                  "left: 0;\n",
+                  "width: 50%;\n",
+                  "height: 50%;\n",
+                  "float: left;\n",
+                  "}\n",
+                  "#PV-BR {\n",
+                  "bottom: 0;\n",
+                  "right: 0;\n",
+                  "width: 50%;\n",
+                  "height: 50%;\n",
+                  "float: right;\n",
+                  "}\n",
+                  ".PV-P {\n",
+                  "width: 100%;\n",
+                  "height: 100%;\n",
+                  "top: 0;\n",
+                  "position: absolute;\n",
+                  "display: none;\n",
+                  "}\n"])
     f.close()
     for (dirpath, dirnames, filenames) in walk(os.path.join(path, 'OEBPS', 'Images')):
         chapter = False
         dirnames, filenames = walkSort(dirnames, filenames)
         for afile in filenames:
             filename = getImageFileName(afile)
-            if '-kcc-hq' not in filename[0]:
+            if not filename[0].endswith('-hq'):
                 filelist.append(buildHTML(dirpath, afile, os.path.join(dirpath, afile)))
-                lastfile = (dirpath, afile, os.path.join(dirpath, afile))
                 if not chapter:
                     chapterlist.append((dirpath.replace('Images', 'Text'), filelist[-1][1]))
                     chapter = True
@@ -518,10 +466,6 @@ def buildEPUB(path, chapterNames, tomeNumber):
                     cover = os.path.join(os.path.join(path, 'OEBPS', 'Images'),
                                          'cover' + getImageFileName(filelist[-1][1])[1])
                     image.Cover(os.path.join(filelist[-1][0], filelist[-1][1]), cover, options, tomeNumber)
-    # Hack that force Panel View on at last one page
-    if lastfile and not options.panelviewused and 'Ko' not in options.profile \
-            and options.profile not in ['K1', 'K2', 'KDX', 'Custom']:
-        filelist[-1] = buildHTML(lastfile[0], lastfile[1], lastfile[2], True)
     # Overwrite chapternames if tree is flat and ComicInfo.xml has bookmarks
     if not chapterNames and options.chapters:
         chapterlist = []
@@ -529,9 +473,9 @@ def buildEPUB(path, chapterNames, tomeNumber):
         for aChapter in options.chapters:
             pageid = aChapter[0]
             for x in range(0, pageid + globaldiff + 1):
-                if '-aaa-kcc' in filelist[x][1]:
+                if '-kcc-b' in filelist[x][1]:
                     pageid += 1
-            if '-bbb-kcc' in filelist[pageid][1]:
+            if '-kcc-c' in filelist[pageid][1]:
                 pageid -= 1
             filename = filelist[pageid][1]
             chapterlist.append((filelist[pageid][0].replace('Images', 'Text'), filename))
@@ -542,21 +486,6 @@ def buildEPUB(path, chapterNames, tomeNumber):
     buildOPF(path, options.title, filelist, cover)
 
 
-def imgOptimization(img, opt):
-    if not img.fill:
-        img.getImageFill()
-    if not opt.webtoon:
-        img.cropWhiteSpace()
-    if opt.cutpagenumbers and not opt.webtoon:
-        img.cutPageNumber()
-    img.autocontrastImage()
-    img.resizeImage()
-    if not img.second and opt.panelview:
-        img.calculateBorder()
-    if opt.forcepng and not opt.forcecolor:
-        img.quantizeImage()
-
-
 def imgDirectoryProcessing(path):
     global workerPool, workerOutput
     workerPool = Pool()
@@ -597,10 +526,8 @@ def imgFileProcessingTick(output):
     else:
         for page in output:
             if page is not None:
-                if isinstance(page, str):
-                    options.imgPurgeIndex.append(page)
-                else:
-                    options.imgIndex[page[0]] = page[1]
+                options.imgIndex[page[0]] = page[1]
+                options.imgPurgeIndex.append(page[2])
     if GUI:
         GUI.progressBarTick.emit('tick')
         if not GUI.conversionAlive:
@@ -613,38 +540,18 @@ def imgFileProcessing(work):
         dirpath = work[1]
         opt = work[2]
         output = []
-        img = image.ComicPage(os.path.join(dirpath, afile), opt)
-        if opt.nosplitrotate:
-            splitter = None
-        else:
-            splitter = img.splitPage(dirpath)
-        if splitter is not None:
-            img0 = image.ComicPage(splitter[0], opt)
-            imgOptimization(img0, opt)
-            if not img0.noHQ:
-                output.append(img0.saveToDir(dirpath))
-            img1 = image.ComicPage(splitter[1], opt)
-            imgOptimization(img1, opt)
-            if not img1.noHQ:
-                output.append(img1.saveToDir(dirpath))
-            output.extend([img.origFileName, img0.origFileName, img1.origFileName])
-            if opt.quality == 2:
-                output.extend([img0.origFileName, img1.origFileName])
-                img0b = image.ComicPage(splitter[0], opt, img0)
-                imgOptimization(img0b, opt)
-                output.append(img0b.saveToDir(dirpath))
-                img1b = image.ComicPage(splitter[1], opt, img1)
-                imgOptimization(img1b, opt)
-                output.append(img1b.saveToDir(dirpath))
-        else:
-            output.append(img.origFileName)
-            imgOptimization(img, opt)
-            if not img.noHQ:
-                output.append(img.saveToDir(dirpath))
-            if opt.quality == 2:
-                img2 = image.ComicPage(os.path.join(dirpath, afile), opt, img)
-                imgOptimization(img2, opt)
-                output.append(img2.saveToDir(dirpath))
+        workImg = image.ComicPageParser((dirpath, afile), opt)
+        for i in workImg.payload:
+            img = image.ComicPage(i[0], i[1], i[2], i[3], i[4], opt)
+            if not opt.webtoon:
+                img.cropWhiteSpace()
+            if opt.cutpagenumbers and not opt.webtoon:
+                img.cutPageNumber()
+            img.autocontrastImage()
+            img.resizeImage()
+            if opt.forcepng and not opt.forcecolor:
+                img.quantizeImage()
+            output.append(img.saveToDir())
         return output
     except Exception:
         return str(sys.exc_info()[1])
@@ -789,6 +696,12 @@ def getDirectorySize(start_path='.'):
     return total_size
 
 
+def getPanelViewSize(deviceres, size):
+    x = int(deviceres[0] / 2 - size[0] / 2) / deviceres[0] * 100
+    y = int(deviceres[1] / 2 - size[1] / 2) / deviceres[1] * 100
+    return str(int(x)), str(int(y))
+
+
 def sanitizeTree(filetree):
     chapterNames = {}
     for root, dirs, files in walk(filetree, False):
@@ -851,7 +764,7 @@ def splitDirectory(path):
         mode = 0
     else:
         if filesNumber > 0:
-            print('\nWARNING: Automatic output splitting failed.')
+            print('WARNING: Automatic output splitting failed.')
             if GUI:
                 GUI.addMessage.emit('Automatic output splitting failed. <a href='
                                     '"https://github.com/ciromattia/kcc/wiki'
@@ -866,7 +779,7 @@ def splitDirectory(path):
                 if len(dirs) != 0:
                     detectedSubSubdirectories = True
                 elif len(dirs) == 0 and detectedSubSubdirectories:
-                    print('\nWARNING: Automatic output splitting failed.')
+                    print('WARNING: Automatic output splitting failed.')
                     if GUI:
                         GUI.addMessage.emit('Automatic output splitting failed. <a href='
                                             '"https://github.com/ciromattia/kcc/wiki'
@@ -883,7 +796,7 @@ def splitDirectory(path):
             # One level of subdirectories
             mode = 1
         if detectedFilesInSubdirectories and detectedSubSubdirectories:
-            print('\nWARNING: Automatic output splitting failed.')
+            print('WARNING: Automatic output splitting failed.')
             if GUI:
                 GUI.addMessage.emit('Automatic output splitting failed. <a href='
                                     '"https://github.com/ciromattia/kcc/wiki'
@@ -992,43 +905,14 @@ def detectCorruption(tmpPath, orgPath):
             else:
                 saferRemove(os.path.join(root, name))
     if imageSmaller > imageNumber * 0.25 and not options.upscale and not options.stretch:
-        print("\nMore than 25% of images are smaller than target device resolution. "
+        print("WARNING: More than 1/4 of images are smaller than target device resolution. "
               "Consider enabling stretching or upscaling to improve readability.")
         if GUI:
-            GUI.addMessage.emit('More than 25% of images are smaller than target device resolution.', 'warning', False)
+            GUI.addMessage.emit('More than 1/4 of images are smaller than target device resolution.', 'warning', False)
             GUI.addMessage.emit('Consider enabling stretching or upscaling to improve readability.', 'warning', False)
             GUI.addMessage.emit('', '', False)
 
 
-def detectMargins(path):
-    if options.imgproc:
-        for flag in options.imgIndex[path]:
-            if "Margins-" in flag:
-                flag = flag.split('-')
-                xl = flag[1]
-                yu = flag[2]
-                xr = flag[3]
-                yd = flag[4]
-                if xl != "0.0":
-                    xl = "-" + xl + "%"
-                else:
-                    xl = "0%"
-                if xr != "0.0":
-                    xr = "-" + xr + "%"
-                else:
-                    xr = "0%"
-                if yu != "0.0":
-                    yu = "-" + yu + "%"
-                else:
-                    yu = "0%"
-                if yd != "0.0":
-                    yd = "-" + yd + "%"
-                else:
-                    yd = "0%"
-                return xl, yu, xr, yd
-    return '0%', '0%', '0%', '0%'
-
-
 def createNewTome():
     tomePathRoot = mkdtemp('', 'KCC-')
     tomePath = os.path.join(tomePathRoot, 'OEBPS', 'Images')
@@ -1058,7 +942,6 @@ def makeZIP(zipFilename, baseDir, isEPUB=False):
 
 
 def makeParser():
-    """Create and return an option parser set up with KCC options."""
     psr = OptionParser(usage="Usage: kcc-c2e [options] comic_file|comic_folder", add_help_option=False)
 
     mainOptions = OptionGroup(psr, "MAIN")
@@ -1070,10 +953,8 @@ def makeParser():
     mainOptions.add_option("-p", "--profile", action="store", dest="profile", default="KV",
                            help="Device profile (Available options: K1, K2, K345, KDX, KPW, KV, KoMT, KoG, KoGHD,"
                                 " KoA, KoAHD, KoAH2O) [Default=KV]")
-    mainOptions.add_option("-q", "--quality", type="int", dest="quality", default="0",
-                           help="Quality of Panel View. 0 - Normal 1 - High 2 - Ultra [Default=0]")
     mainOptions.add_option("-m", "--manga-style", action="store_true", dest="righttoleft", default=False,
-                           help="Manga style (Right-to-left reading and splitting)")
+                           help="Manga style (right-to-left reading and splitting)")
     mainOptions.add_option("-w", "--webtoon", action="store_true", dest="webtoon", default=False,
                            help="Webtoon processing mode"),
 
@@ -1083,9 +964,19 @@ def makeParser():
                              help="Comic title [Default=filename or directory name]")
     outputOptions.add_option("-f", "--format", action="store", dest="format", default="Auto",
                              help="Output format (Available options: Auto, MOBI, EPUB, CBZ) [Default=Auto]")
-    outputOptions.add_option("--batchsplit", action="store_true", dest="batchsplit", default=False,
+    outputOptions.add_option("-b", "--batchsplit", action="store_true", dest="batchsplit", default=False,
                              help="Split output into multiple files"),
 
+    processingOptions.add_option("-u", "--upscale", action="store_true", dest="upscale", default=False,
+                                 help="Resize images smaller than device's resolution")
+    processingOptions.add_option("-s", "--stretch", action="store_true", dest="stretch", default=False,
+                                 help="Stretch images to device's resolution")
+    processingOptions.add_option("-r", "--splitter", type="int", dest="splitter", default="0",
+                                 help="Double page parsing mode. 0: Split 1: Rotate 2: Both [Default=0]")
+    processingOptions.add_option("-g", "--gamma", type="float", dest="gamma", default="0.0",
+                                 help="Apply gamma correction to linearize the image [Default=Auto]")
+    processingOptions.add_option("--hq", action="store_true", dest="hqmode", default=False,
+                                 help="Enable high quality Panel View")
     processingOptions.add_option("--blackborders", action="store_true", dest="black_borders", default=False,
                                  help="Disable autodetection and force black borders")
     processingOptions.add_option("--whiteborders", action="store_true", dest="white_borders", default=False,
@@ -1094,20 +985,8 @@ def makeParser():
                                  help="Don't convert images to grayscale")
     processingOptions.add_option("--forcepng", action="store_true", dest="forcepng", default=False,
                                  help="Create PNG files instead JPEG")
-    processingOptions.add_option("--gamma", type="float", dest="gamma", default="0.0",
-                                 help="Apply gamma correction to linearize the image [Default=Auto]")
     processingOptions.add_option("--nocutpagenumbers", action="store_false", dest="cutpagenumbers", default=True,
-                                 help="Don't try to cut page numbering on images")
-    processingOptions.add_option("--noprocessing", action="store_false", dest="imgproc", default=True,
-                                 help="Don't apply image preprocessing")
-    processingOptions.add_option("--nosplitrotate", action="store_true", dest="nosplitrotate", default=False,
-                                 help="Disable splitting and rotation")
-    processingOptions.add_option("--rotate", action="store_true", dest="rotate", default=False,
-                                 help="Rotate landscape pages instead of splitting them")
-    processingOptions.add_option("--stretch", action="store_true", dest="stretch", default=False,
-                                 help="Stretch images to device's resolution")
-    processingOptions.add_option("--upscale", action="store_true", dest="upscale", default=False,
-                                 help="Resize images smaller than device's resolution")
+                                 help="Don't try to cut page numbers from images")
 
     customProfileOptions.add_option("--customwidth", type="int", dest="customwidth", default=0,
                                     help="Replace screen width provided by device profile")
@@ -1128,7 +1007,6 @@ def makeParser():
 def checkOptions():
     global options
     options.panelview = True
-    options.panelviewused = False
     options.iskindle = False
     options.bordersColor = None
     if options.format == 'Auto':
@@ -1138,7 +1016,7 @@ def checkOptions():
             options.format = 'EPUB'
         elif options.profile in ['KDX']:
             options.format = 'CBZ'
-    if options.profile in ['K1', 'K2', 'K345', 'KPW', 'KV', 'OTHER']:
+    if options.profile in ['K1', 'K2', 'K345', 'KPW', 'KV']:
         options.iskindle = True
     if options.white_borders:
         options.bordersColor = 'white'
@@ -1149,28 +1027,24 @@ def checkOptions():
         options.batchsplit = True
     # Older Kindle don't need higher resolution files due lack of Panel View.
     if options.profile == 'K1' or options.profile == 'K2' or options.profile == 'KDX':
-        options.quality = 0
         options.panelview = False
+        options.hqmode = False
     # Webtoon mode mandatory options
     if options.webtoon:
-        options.nosplitrotate = True
-        options.quality = 0
         options.panelview = False
+        options.hqmode = False
+        options.righttoleft = False
+        options.upscale = True
     # Disable all Kindle features for other e-readers
     if options.profile == 'OTHER':
         options.panelview = False
-        options.quality = 0
+        options.hqmode = False
     if 'Ko' in options.profile:
         options.panelview = False
-        # Kobo models can't use ultra quality mode
-        if options.quality == 2:
-            options.quality = 1
+        options.hqmode = False
     # CBZ files on Kindle DX/DXG support higher resolution
     if options.profile == 'KDX' and options.format == 'CBZ':
         options.customheight = 1200
-    # Ultra mode don't work with CBZ format
-    if options.quality == 2 and options.format == 'CBZ':
-        options.quality = 1
     # Override profile data
     if options.customwidth != 0 or options.customheight != 0:
         X = image.ProfileData.Profiles[options.profile][1][0]
@@ -1192,18 +1066,18 @@ def checkTools(source):
         rarExitCode = Popen('unrar', stdout=PIPE, stderr=STDOUT, shell=True)
         rarExitCode = rarExitCode.wait()
         if rarExitCode != 0 and rarExitCode != 7:
-            print('\nUnRAR is missing!')
+            print('ERROR: UnRAR is missing!')
             exit(1)
     elif source.endswith('.CB7') or source.endswith('.7Z'):
         sevenzaExitCode = Popen('7za', stdout=PIPE, stderr=STDOUT, shell=True)
         sevenzaExitCode = sevenzaExitCode.wait()
         if sevenzaExitCode != 0 and sevenzaExitCode != 7:
-            print('\n7za is missing!')
+            print('ERROR: 7za is missing!')
             exit(1)
     if options.format == 'MOBI':
         kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True)
         if kindleGenExitCode.wait() != 0:
-            print('\nKindleGen is missing!')
+            print('ERROR: KindleGen is missing!')
             exit(1)
 
 
@@ -1226,7 +1100,6 @@ def checkPre(source):
 
 
 def makeBook(source, qtGUI=None):
-    """Generates MOBI/EPUB/CBZ comic ebook from a bunch of images."""
     global GUI
     GUI = qtGUI
     if GUI:
@@ -1234,17 +1107,21 @@ def makeBook(source, qtGUI=None):
     else:
         checkTools(source)
     checkPre(source)
+    print("Preparing source images...")
     path = getWorkFolder(source)
-    print("\nChecking images...")
+    print("Checking images...")
     getComicInfo(os.path.join(path, "OEBPS", "Images"), source)
     detectCorruption(os.path.join(path, "OEBPS", "Images"), source)
     if options.webtoon:
-        comic2panel.main(['-y ' + str(image.ProfileData.Profiles[options.profile][1][1]), '-i', '-m', path], qtGUI)
-    if options.imgproc:
-        print("\nProcessing images...")
-        if GUI:
-            GUI.progressBarTick.emit('Processing images')
-        imgDirectoryProcessing(os.path.join(path, "OEBPS", "Images"))
+        if image.ProfileData.Profiles[options.profile][1][1] > 1000:
+            y = 1000
+        else:
+            y = image.ProfileData.Profiles[options.profile][1][1]
+        comic2panel.main(['-y ' + str(y), '-i', '-m', path], qtGUI)
+    print("Processing images...")
+    if GUI:
+        GUI.progressBarTick.emit('Processing images')
+    imgDirectoryProcessing(os.path.join(path, "OEBPS", "Images"))
     if GUI:
         GUI.progressBarTick.emit('1')
     chapterNames = sanitizeTree(os.path.join(path, 'OEBPS', 'Images'))
@@ -1272,14 +1149,14 @@ def makeBook(source, qtGUI=None):
             tomeNumber += 1
             options.title = options.baseTitle + ' [' + str(tomeNumber) + '/' + str(len(tomes)) + ']'
         if options.format == 'CBZ':
-            print("\nCreating CBZ file...")
+            print("Creating CBZ file...")
             if len(tomes) > 1:
                 filepath.append(getOutputFilename(source, options.output, '.cbz', ' ' + str(tomeNumber)))
             else:
                 filepath.append(getOutputFilename(source, options.output, '.cbz', ''))
             makeZIP(tome + '_comic', os.path.join(tome, "OEBPS", "Images"))
         else:
-            print("\nCreating EPUB file...")
+            print("Creating EPUB file...")
             buildEPUB(tome, chapterNames, tomeNumber)
             if len(tomes) > 1:
                 filepath.append(getOutputFilename(source, options.output, '.epub', ' ' + str(tomeNumber)))
@@ -1291,20 +1168,20 @@ def makeBook(source, qtGUI=None):
         if GUI:
             GUI.progressBarTick.emit('tick')
     if not GUI and options.format == 'MOBI':
-        print("\nCreating MOBI file...")
+        print("Creating MOBI file...")
         work = []
         for i in filepath:
             work.append([i])
         output = makeMOBI(work, GUI)
         for errors in output:
             if errors[0] != 0:
-                print('KINDLEGEN ERROR!')
+                print('Error: KindleGen failed to create MOBI!')
                 print(errors)
                 return filepath
         for i in filepath:
             output = makeMOBIFix(i)
             if not output[0]:
-                print('DUALMETAFIX ERROR!')
+                print('Error: Failed to tweak KindleGen output!')
                 return filepath
             else:
                 os.remove(i.replace('.epub', '.mobi') + '_toclean')
diff --git a/kcc/comic2panel.py b/kcc/comic2panel.py
index 8625fb8..fa57535 100644
--- a/kcc/comic2panel.py
+++ b/kcc/comic2panel.py
@@ -232,7 +232,7 @@ def main(argv=None, qtGUI=None):
         GUI = None
     if len(args) != 1:
         parser.print_help()
-        return
+        return 1
     if options.height > 0:
         options.sourceDir = args[0]
         options.targetDir = args[0] + "-Splitted"
@@ -244,7 +244,7 @@ def main(argv=None, qtGUI=None):
             splitWorkerOutput = []
             splitWorkerPool = Pool()
             if options.merge:
-                print("\nMerging images...")
+                print("Merging images...")
                 directoryNumer = 1
                 mergeWork = []
                 mergeWorkerOutput = []
@@ -268,7 +268,7 @@ def main(argv=None, qtGUI=None):
                 if len(mergeWorkerOutput) > 0:
                     rmtree(options.targetDir, True)
                     raise RuntimeError("One of workers crashed. Cause: " + mergeWorkerOutput[0])
-            print("\nSplitting images...")
+            print("Splitting images...")
             for root, dirs, files in walk(options.targetDir, False):
                 for name in files:
                     if getImageFileName(name) is not None:
diff --git a/kcc/image.py b/kcc/image.py
index b98bc2a..dc6dbee 100755
--- a/kcc/image.py
+++ b/kcc/image.py
@@ -20,7 +20,6 @@ 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
 from . import __version__
@@ -94,73 +93,167 @@ class ProfileData:
     }
 
 
-class ComicPage:
-    def __init__(self, source, options, original=None):
-        try:
-            self.profile_label, self.size, self.palette, self.gamma, self.panelviewsize = options.profileData
-        except KeyError:
-            raise RuntimeError('Unexpected output device %s' % options.profileData)
-        self.origFileName = source
-        self.filename = os.path.basename(self.origFileName)
-        self.image = Image.open(source)
-        self.image = self.image.convert('RGB')
+class ComicPageParser:
+    def __init__(self, source, options):
         self.opt = options
-        if original:
-            self.second = True
-            self.rotated = original.rotated
-            self.border = original.border
-            self.noHPV = original.noHPV
-            self.noVPV = original.noVPV
-            self.noPV = original.noPV
-            self.noHQ = original.noHQ
-            self.fill = original.fill
-            self.color = original.color
-            if self.rotated:
-                self.image = self.image.rotate(90, Image.BICUBIC, True)
-            self.opt.quality = 0
+        self.source = source
+        self.size = self.opt.profileData[1]
+        self.payload = []
+        self.image = Image.open(os.path.join(source[0], source[1])).convert('RGB')
+        self.color = self.colorCheck()
+        self.fill = self.fillCheck()
+        self.splitCheck()
+        if self.opt.hqmode:
+            self.sizeCheck()
+
+    def getImageHistogram(self, image):
+        histogram = image.histogram()
+        if histogram[0] == 0:
+            return -1
+        elif histogram[255] == 0:
+            return 1
         else:
-            self.second = False
-            self.rotated = None
-            self.border = None
-            self.noHPV = None
-            self.noVPV = None
-            self.noPV = None
-            self.fill = None
-            self.noHQ = False
-            if options.webtoon:
-                self.color = True
+            return 0
+
+    def splitCheck(self):
+        width, height = self.image.size
+        dstwidth, dstheight = self.size
+        # Only split if origin is not oriented the same as target
+        if (width > height) != (dstwidth > dstheight) and not self.opt.webtoon:
+            if self.opt.splitter != 1:
+                if width > height:
+                    # Source is landscape, so split by the width
+                    leftbox = (0, 0, int(width / 2), height)
+                    rightbox = (int(width / 2), 0, width, height)
+                else:
+                    # Source is portrait and target is landscape, so split by the height
+                    leftbox = (0, 0, width, int(height / 2))
+                    rightbox = (0, int(height / 2), width, height)
+                if self.opt.righttoleft:
+                    pageone = self.image.crop(rightbox)
+                    pagetwo = self.image.crop(leftbox)
+                else:
+                    pageone = self.image.crop(leftbox)
+                    pagetwo = self.image.crop(rightbox)
+                self.payload.append(['S1', self.source, pageone, self.color, self.fill])
+                self.payload.append(['S2', self.source, pagetwo, self.color, self.fill])
+            if self.opt.splitter > 0:
+                self.payload.append(['R', self.source, self.image.rotate(90, Image.BICUBIC, True),
+                                    self.color, self.fill])
+        else:
+            self.payload.append(['N', self.source, self.image, self.color, self.fill])
+
+    def colorCheck(self):
+        if self.opt.webtoon:
+            return True
+        else:
+            img = self.image.copy()
+            bands = img.getbands()
+            if bands == ('R', 'G', 'B') or bands == ('R', 'G', 'B', 'A'):
+                thumb = img.resize((40, 40))
+                SSE, bias = 0, [0, 0, 0]
+                bias = ImageStat.Stat(thumb).mean[:3]
+                bias = [b - sum(bias) / 3 for b in bias]
+                for pixel in thumb.getdata():
+                    mu = sum(pixel) / 3
+                    SSE += sum((pixel[i] - mu - bias[i]) * (pixel[i] - mu - bias[i]) for i in [0, 1, 2])
+                MSE = float(SSE) / (40 * 40)
+                if MSE > 22:
+                    return True
+                else:
+                    return False
             else:
-                self.color = self.isImageColor()
+                return False
+
+    def fillCheck(self):
+        if self.opt.bordersColor:
+            return self.opt.bordersColor
+        else:
+            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
+                diff = 0
+            else:
+                surfaceB = (imageBoxA[2] - imageBoxA[0]) * (imageBoxA[3] - imageBoxA[1])
+                surfaceW = (imageBoxB[2] - imageBoxB[0]) * (imageBoxB[3] - imageBoxB[1])
+                diff = ((max(surfaceB, surfaceW) - min(surfaceB, surfaceW)) / min(surfaceB, surfaceW)) * 100
+            if diff > 0.5:
+                if surfaceW < surfaceB:
+                    return 'white'
+                elif surfaceW > surfaceB:
+                    return 'black'
+            else:
+                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:
+                    return 'black'
+                else:
+                    return 'white'
+
+    def sizeCheck(self):
+        additionalPayload = []
+        width, height = self.image.size
+        dstwidth, dstheight = self.size
+        for work in self.payload:
+            if width > dstwidth and height > dstheight:
+                additionalPayload.append([work[0] + '+', work[1], work[2].copy(), work[3], work[4]])
+        self.payload = self.payload + additionalPayload
+
+
+class ComicPage:
+    def __init__(self, mode, path, image, color, fill, options):
+        self.opt = options
+        _, self.size, self.palette, self.gamma, self.panelviewsize = self.opt.profileData
+        self.image = image
+        self.color = color
+        self.fill = fill
+        self.rotated = False
+        self.orgPath = os.path.join(path[0], path[1])
+        if '+' in mode:
+            self.hqMode = True
+        else:
+            self.hqMode = False
+        if 'N' in mode:
+            self.targetPath = os.path.join(path[0], os.path.splitext(path[1])[0]) + '-KCC'
+        elif 'R' in mode:
+            self.targetPath = os.path.join(path[0], os.path.splitext(path[1])[0]) + '-KCC-A'
+            self.rotated = True
+        elif 'S1' in mode:
+            self.targetPath = os.path.join(path[0], os.path.splitext(path[1])[0]) + '-KCC-B'
+        elif 'S2' in mode:
+            self.targetPath = os.path.join(path[0], os.path.splitext(path[1])[0]) + '-KCC-C'
 
-    def saveToDir(self, targetdir):
+    def saveToDir(self):
         try:
             flags = []
-            filename = os.path.join(targetdir, os.path.splitext(self.filename)[0]) + '-KCC'
             if not self.opt.forcecolor and not self.opt.forcepng:
                 self.image = self.image.convert('L')
             if self.rotated:
                 flags.append('Rotated')
-            if self.noPV:
-                flags.append('NoPanelView')
-            else:
-                if self.noHPV:
-                    flags.append('NoHorizontalPanelView')
-                if self.noVPV:
-                    flags.append('NoVerticalPanelView')
-                if self.border:
-                    flags.append('Margins-' + str(self.border[0]) + '-' + str(self.border[1]) + '-' +
-                                 str(self.border[2]) + '-' + str(self.border[3]))
             if self.fill != 'white':
                 flags.append('BlackFill')
-            if self.opt.quality == 2:
-                filename += '-HQ'
+            if self.hqMode:
+                self.targetPath += '-HQ'
             if self.opt.forcepng:
-                filename += '.png'
-                self.image.save(filename, 'PNG', optimize=1)
+                self.targetPath += '.png'
+                self.image.save(self.targetPath, 'PNG', optimize=1)
             else:
-                filename += '.jpg'
-                self.image.save(filename, 'JPEG', optimize=1, quality=80)
-            return [md5Checksum(filename), flags]
+                self.targetPath += '.jpg'
+                self.image.save(self.targetPath, 'JPEG', optimize=1, quality=80)
+            return [md5Checksum(self.targetPath), flags, self.orgPath]
         except IOError as e:
             raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
 
@@ -186,127 +279,42 @@ class ComicPage:
         # Quantize is deprecated but new function call it internally anyway...
         self.image = self.image.quantize(palette=palImg)
 
-    def calculateBorder(self):
-        if self.noPV:
-            self.border = [0.0, 0.0, 0.0, 0.0]
-            return
-        if self.fill == 'white':
-            border = ImageChops.invert(self.image).getbbox()
-        else:
-            border = self.image.getbbox()
-        if self.opt.quality == 2:
-            multiplier = 1.0
-        else:
-            multiplier = 1.5
-        if border is not None:
-            self.border = [round(float(border[0]) / float(self.image.size[0]) * 150, 3),
-                           round(float(border[1]) / float(self.image.size[1]) * 150, 3),
-                           round(float(self.image.size[0] - border[2]) / float(self.image.size[0]) * 150, 3),
-                           round(float(self.image.size[1] - border[3]) / float(self.image.size[1]) * 150, 3)]
-            if int((border[2] - border[0]) * multiplier) < self.size[0] + 10:
-                self.noHPV = True
-            if int((border[3] - border[1]) * multiplier) < self.size[1] + 10:
-                self.noVPV = True
-        else:
-            self.border = [0.0, 0.0, 0.0, 0.0]
-            self.noHPV = True
-            self.noVPV = True
-
     def resizeImage(self):
-        if self.opt.bordersColor:
-            fill = self.opt.bordersColor
-        else:
-            fill = self.fill
-        # Set target size
-        if self.opt.quality == 0:
-            size = (self.size[0], self.size[1])
-        elif self.opt.quality == 1 and not self.opt.stretch and not self.opt.upscale and self.image.size[0] <=\
-                self.size[0] and self.image.size[1] <= self.size[1]:
-            size = (self.size[0], self.size[1])
-        elif self.opt.quality == 1:
-            # Forcing upscale to make sure that margins will be not too big
-            if not self.opt.stretch:
-                self.opt.upscale = True
+        if self.hqMode:
             size = (self.panelviewsize[0], self.panelviewsize[1])
-        elif self.opt.quality == 2 and not self.opt.stretch and not self.opt.upscale and self.image.size[0] <=\
-                self.size[0] and self.image.size[1] <= self.size[1]:
-            # HQ version will not be needed
-            self.noHQ = True
-            return
+            if self.image.size[0] > size[0] or self.image.size[1] > size[1]:
+                self.image.thumbnail(size, Image.LANCZOS)
         else:
-            size = (self.panelviewsize[0], self.panelviewsize[1])
-        # If stretching is on - Resize without other considerations
-        if self.opt.stretch:
+            size = (self.size[0], self.size[1])
             if self.image.size[0] <= size[0] and self.image.size[1] <= size[1]:
                 method = Image.BICUBIC
             else:
                 method = Image.LANCZOS
-            self.image = self.image.resize(size, method)
-            return
-        # If image is smaller than target resolution and upscale is off - Just expand it by adding margins
-        if self.image.size[0] <= size[0] and self.image.size[1] <= size[1] and not self.opt.upscale:
-            borderw = int((size[0] - self.image.size[0]) / 2)
-            borderh = int((size[1] - self.image.size[1]) / 2)
-            # PV is disabled when source image is smaller than device screen and upscale is off
-            if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]:
-                self.noPV = True
-            self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=fill)
-            # Border can't be float so sometimes image might be 1px too small/large
-            if self.image.size[0] != size[0] or self.image.size[1] != size[1]:
-                self.image = ImageOps.fit(self.image, size, method=Image.BICUBIC, centering=(0.5, 0.5))
-            return
-        # Otherwise - Upscale/Downscale
-        ratioDev = float(size[0]) / float(size[1])
-        if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev:
-            diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
-            self.image = ImageOps.expand(self.image, border=(int(diff / 2), 0), fill=fill)
-        elif (float(self.image.size[0]) / float(self.image.size[1])) > ratioDev:
-            diff = int(self.image.size[0] / ratioDev) - self.image.size[1]
-            self.image = ImageOps.expand(self.image, border=(0, int(diff / 2)), fill=fill)
-        if self.image.size[0] <= size[0] and self.image.size[1] <= size[1]:
-            method = Image.BICUBIC
-        else:
-            method = Image.LANCZOS
-        self.image = ImageOps.fit(self.image, size, method=method, centering=(0.5, 0.5))
-        return
-
-    def splitPage(self, targetdir):
-        width, height = self.image.size
-        dstwidth, dstheight = self.size
-        # Only split if origin is not oriented the same as target
-        if (width > height) != (dstwidth > dstheight):
-            if self.opt.rotate:
-                self.image = self.image.rotate(90, Image.BICUBIC, True)
-                self.rotated = True
-                return None
+            if self.opt.stretch:
+                self.image = self.image.resize(size, method)
+            elif self.image.size[0] <= size[0] and self.image.size[1] <= size[1] and not self.opt.upscale:
+                if self.opt.format == 'CBZ':
+                    borderw = int((size[0] - self.image.size[0]) / 2)
+                    borderh = int((size[1] - self.image.size[1]) / 2)
+                    self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=self.fill)
+                    if self.image.size[0] != size[0] or self.image.size[1] != size[1]:
+                        self.image = ImageOps.fit(self.image, size, method=Image.BICUBIC, centering=(0.5, 0.5))
             else:
-                self.rotated = False
-                if width > height:
-                    # Source is landscape, so split by the width
-                    leftbox = (0, 0, int(width / 2), height)
-                    rightbox = (int(width / 2), 0, width, height)
+                if self.opt.format == 'CBZ':
+                    ratioDev = float(size[0]) / float(size[1])
+                    if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev:
+                        diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
+                        self.image = ImageOps.expand(self.image, border=(int(diff / 2), 0), fill=self.fill)
+                    elif (float(self.image.size[0]) / float(self.image.size[1])) > ratioDev:
+                        diff = int(self.image.size[0] / ratioDev) - self.image.size[1]
+                        self.image = ImageOps.expand(self.image, border=(0, int(diff / 2)), fill=self.fill)
+                    self.image = ImageOps.fit(self.image, size, method=method, centering=(0.5, 0.5))
                 else:
-                    # Source is portrait and target is landscape, so split by the height
-                    leftbox = (0, 0, width, int(height / 2))
-                    rightbox = (0, int(height / 2), width, height)
-                filename = os.path.splitext(self.filename)[0]
-                fileone = targetdir + '/' + filename + '-AAA.png'
-                filetwo = targetdir + '/' + filename + '-BBB.png'
-                try:
-                    if self.opt.righttoleft:
-                        pageone = self.image.crop(rightbox)
-                        pagetwo = self.image.crop(leftbox)
-                    else:
-                        pageone = self.image.crop(leftbox)
-                        pagetwo = self.image.crop(rightbox)
-                    pageone.save(fileone, 'PNG', optimize=1)
-                    pagetwo.save(filetwo, 'PNG', optimize=1)
-                except IOError as e:
-                    raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
-                return fileone, filetwo
-        else:
-            self.rotated = False
-            return None
+                    hpercent = size[1] / float(self.image.size[1])
+                    wsize = int((float(self.image.size[0]) * float(hpercent)))
+                    self.image = self.image.resize((wsize, size[1]), method)
+                    if self.image.size[0] > size[0] or self.image.size[1] > size[1]:
+                        self.image.thumbnail(size, Image.LANCZOS)
 
     def cutPageNumber(self):
         if ImageChops.invert(self.image).getbbox() is not None:
@@ -397,71 +405,6 @@ class ComicPage:
             diff -= delta
             self.image = self.image.crop((0, 0, widthImg - diff, heightImg))
 
-    def getImageHistogram(self, image):
-        histogram = image.histogram()
-        if histogram[0] == 0:
-            return -1
-        elif histogram[255] == 0:
-            return 1
-        else:
-            return 0
-
-    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
-            diff = 0
-        else:
-            surfaceB = (imageBoxA[2] - imageBoxA[0]) * (imageBoxA[3] - imageBoxA[1])
-            surfaceW = (imageBoxB[2] - imageBoxB[0]) * (imageBoxB[3] - imageBoxB[1])
-            diff = ((max(surfaceB, surfaceW) - min(surfaceB, surfaceW)) / min(surfaceB, surfaceW)) * 100
-        if diff > 0.5:
-            if surfaceW < surfaceB:
-                self.fill = 'white'
-            elif surfaceW > surfaceB:
-                self.fill = 'black'
-        else:
-            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):
-        img = self.image.copy()
-        bands = img.getbands()
-        if bands == ('R', 'G', 'B') or bands == ('R', 'G', 'B', 'A'):
-            thumb = img.resize((40, 40))
-            SSE, bias = 0, [0, 0, 0]
-            bias = ImageStat.Stat(thumb).mean[:3]
-            bias = [b - sum(bias) / 3 for b in bias]
-            for pixel in thumb.getdata():
-                mu = sum(pixel) / 3
-                SSE += sum((pixel[i] - mu - bias[i]) * (pixel[i] - mu - bias[i]) for i in [0, 1, 2])
-            MSE = float(SSE) / (40 * 40)
-            if MSE <= 22:
-                return False
-            else:
-                return True
-        elif len(bands) == 1:
-            return False
-        else:
-            return False
-
 
 class Cover:
     def __init__(self, source, target, opt, tomeNumber):