diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index f6d5bee..2ca9b3b 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -20,6 +20,7 @@ import os import sys +from time import strftime, gmtime from copy import copy from glob import glob from json import loads @@ -119,83 +120,98 @@ def buildHTML(path, imgfile, imgfilepath, forcePV=False): os.makedirs(htmlpath) htmlfile = os.path.join(htmlpath, filename[0] + '.html') f = open(htmlfile, "w", encoding='UTF-8') - f.writelines(["\n", - "\n", - "\n", - "", filename[0], "\n", - "\n", - "\n", - "\n", - "\n", - "
\n", - "
\"",
\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] + if options.iskindle: + f.writelines(["\n", + "\n", + "\n", + "\n", + "", filename[0], "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "
\"",
\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] else: - order = [2, 4, 1, 3] - 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] - else: - order = [1, 2] - boxes = ["BoxT", "BoxB"] - elif not noHorizontalPV and noVerticalPV: - if rotatedPage: - order = [1, 2] - else: - if options.righttoleft: - order = [2, 1] + 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] else: order = [1, 2] - boxes = ["BoxL", "BoxR"] - else: - order = [1] - boxes = ["BoxC"] - for i in range(0, len(boxes)): - f.writelines(["
\n"]) - if options.quality == 2 and not forcePV: - imgfilepv = imgfile.split(".") - imgfilepv[0] += "-hq" - imgfilepv = ".".join(imgfilepv) - 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(["
\""
\n", - ]) - f.writelines(["
\n\n"]) + boxes = ["BoxT", "BoxB"] + elif not noHorizontalPV and noVerticalPV: + if rotatedPage: + order = [1, 2] + else: + if options.righttoleft: + order = [2, 1] + else: + order = [1, 2] + boxes = ["BoxL", "BoxR"] + else: + order = [1] + boxes = ["BoxC"] + for i in range(0, len(boxes)): + f.writelines(["
\n"]) + if options.quality == 2 and not forcePV: + imgfilepv = imgfile.split(".") + imgfilepv[0] += "-hq" + imgfilepv = ".".join(imgfilepv) + 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(["
\""
\n", + ]) + f.writelines(["
\n\n"]) + else: + f.writelines(["\n", + "\n", + "\n", + "\n", + "", filename[0], "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "
\n", + "\n" + ]) f.close() return path, imgfile @@ -205,11 +221,9 @@ def buildNCX(dstdir, title, chapters, chapterNames): ncxfile = os.path.join(dstdir, 'OEBPS', 'toc.ncx') f = open(ncxfile, "w", encoding='UTF-8') f.writelines(["\n", - "\n", "\n", "\n", - "\n", + "\n", "\n", "\n", "\n", @@ -234,6 +248,35 @@ def buildNCX(dstdir, title, chapters, chapterNames): f.close() +def buildNAV(dstdir, title, chapters, chapterNames): + navfile = os.path.join(dstdir, 'OEBPS', 'nav.xhtml') + f = open(navfile, "w", encoding='UTF-8') + f.writelines(["\n", + "\n", + "\n", + "\n", + "" + title + "\n", + "\n", + "\n", + "\n", + "\n", + "\n\n") + f.close() + + def buildOPF(dstdir, title, filelist, cover=None): opffile = os.path.join(dstdir, 'OEBPS', 'content.opf') profilelabel, deviceres, palette, gamma, panelviewsize = options.profileData @@ -243,40 +286,47 @@ def buildOPF(dstdir, title, filelist, cover=None): writingmode = "horizontal-lr" f = open(opffile, "w", encoding='UTF-8') f.writelines(["\n", - "\n", "\n", "", title, "\n", "en-US\n", - "", options.uuid, "\n"]) + "urn:uuid:", options.uuid, "\n", + "KindleComicConverter-" + __version__ + "\n"]) for author in options.authors: f.writelines(["", author, "\n"]) - f.writelines(["\n", - "\n", - "\n", + f.writelines(["" + strftime("%Y-%m-%dT%H:%M:%SZ", gmtime()) + "\n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n" - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n\n\n"]) + "portrait\n", + "portrait\n", + "pre-paginated\n"]) + if options.iskindle and options.profile != 'OTHER': + f.writelines(["true\n", + "true\n", + "comic\n", + "true\n", + "true\n", + "true\n", + "portrait\n", + "", + str(deviceres[0]) + "x" + str(deviceres[1]) + "\n", + "" + writingmode + "\n", + "#ffffff\n", + "0\n"]) + f.writelines(["\n\n\n", + "\n"]) if cover is not None: filename = getImageFileName(cover.replace(os.path.join(dstdir, 'OEBPS'), '').lstrip('/').lstrip('\\\\')) if '.png' == filename[1]: mt = 'image/png' else: mt = 'image/jpeg' - f.write("\n") + f.write("\n") reflist = [] for path in filelist: folder = path[0].replace(os.path.join(dstdir, 'OEBPS'), '').lstrip('/').lstrip('\\\\').replace("\\", "/") @@ -299,7 +349,7 @@ def buildOPF(dstdir, title, filelist, cover=None): f.write("\n\n") for entry in reflist: f.write("\n") - f.write("\n\n\n\n") + f.write("\n\n") f.close() os.mkdir(os.path.join(dstdir, 'META-INF')) f = open(os.path.join(dstdir, 'META-INF', 'container.xml'), 'w', encoding='UTF-8') @@ -320,114 +370,126 @@ def buildEPUB(path, chapterNames, tomeNumber): _, 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') - # DON'T COMPRESS CSS. KINDLE WILL FAIL TO PARSE IT. - # Generic Panel View support + Margins fix for Non-Kindle devices. - 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", - "}", - ]) + 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.close() for (dirpath, dirnames, filenames) in walk(os.path.join(path, 'OEBPS', 'Images')): chapter = False @@ -464,6 +526,7 @@ def buildEPUB(path, chapterNames, tomeNumber): chapterNames[filename] = aChapter[1] globaldiff = pageid - (aChapter[0] + globaldiff) buildNCX(path, options.title, chapterlist, chapterNames) + buildNAV(path, options.title, chapterlist, chapterNames) buildOPF(path, options.title, filelist, cover) @@ -1045,6 +1108,10 @@ def checkOptions(): options.format = 'EPUB' elif options.profile in ['KDX', 'KoMT', 'KoG', 'KoGHD', 'KoA', 'KoAHD', 'KoAH2O']: options.format = 'CBZ' + if options.profile in ['K1', 'K2', 'K345', 'KPW', 'KV', 'KFHD', 'KFHDX', 'KFHDX8', 'KFA', 'OTHER']: + options.iskindle = True + else: + options.iskindle = False if options.white_borders: options.bordersColor = 'white' if options.black_borders: @@ -1211,7 +1278,7 @@ def makeMOBIFix(item): mobiPath = item.replace('.epub', '.mobi') move(mobiPath, mobiPath + '_toclean') try: - dualmetafix.DualMobiMetaFix(mobiPath + '_toclean', mobiPath, bytes(str(uuid4()), 'UTF-8')) + dualmetafix.DualMobiMetaFix(mobiPath + '_toclean', mobiPath, bytes(options.uuid, 'UTF-8')) return [True] except Exception as err: return [False, format(err)]