diff options
author | Paweł Jastrzębski <pawelj@iosphe.re> | 2018-03-08 16:15:42 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-08 16:15:42 +0100 |
commit | 34e2af3389acfdf32f18a06c77e75ce91deed42d (patch) | |
tree | 79fb5515fa273c1484b69fd25bbd5e9fd4e3b8e6 /kindlecomicconverter | |
parent | Updated build enviroment (diff) | |
parent | Version bump (diff) | |
download | kcc-34e2af3389acfdf32f18a06c77e75ce91deed42d.tar.gz kcc-34e2af3389acfdf32f18a06c77e75ce91deed42d.tar.bz2 kcc-34e2af3389acfdf32f18a06c77e75ce91deed42d.zip |
Merge pull request #261 from ciromattia/dev
5.4.4
Diffstat (limited to 'kindlecomicconverter')
-rw-r--r-- | kindlecomicconverter/KCC_gui.py | 22 | ||||
-rw-r--r-- | kindlecomicconverter/__init__.py | 4 | ||||
-rw-r--r-- | kindlecomicconverter/cbxarchive.py | 23 | ||||
-rwxr-xr-x | kindlecomicconverter/comic2ebook.py | 305 | ||||
-rw-r--r-- | kindlecomicconverter/comic2panel.py | 11 | ||||
-rw-r--r-- | kindlecomicconverter/dualmetafix.py | 2 | ||||
-rwxr-xr-x | kindlecomicconverter/image.py | 60 | ||||
-rw-r--r-- | kindlecomicconverter/kindle.py | 2 | ||||
-rw-r--r-- | kindlecomicconverter/metadata.py | 2 | ||||
-rw-r--r-- | kindlecomicconverter/pdfjpgextract.py | 13 | ||||
-rw-r--r-- | kindlecomicconverter/shared.py | 10 | ||||
-rw-r--r-- | kindlecomicconverter/startup.py | 2 |
12 files changed, 249 insertions, 207 deletions
diff --git a/kindlecomicconverter/KCC_gui.py b/kindlecomicconverter/KCC_gui.py index a98585a..71e06de 100644 --- a/kindlecomicconverter/KCC_gui.py +++ b/kindlecomicconverter/KCC_gui.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com> -# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re> +# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re> # # Permission to use, copy, modify, and/or distribute this software for # any purpose with or without fee is hereby granted, provided that the @@ -156,8 +156,8 @@ class VersionThread(QtCore.QThread): '(<a href="https://github.com/ciromattia/kcc/releases/">' 'Changelog</a>)', 'warning', False) - def setAnswer(self, dialogAnswer): - self.answer = dialogAnswer + def setAnswer(self, dialoganswer): + self.answer = dialoganswer def getNewVersion(self): while self.answer is None: @@ -180,8 +180,8 @@ class VersionThread(QtCore.QThread): MW.hideProgressBar.emit() MW.modeConvert.emit(1) - def getNewVersionTick(self, size, blockSize, totalSize): - progress = int((size / (totalSize // blockSize)) * 100) + def getNewVersionTick(self, size, blocksize, totalsize): + progress = int((size / (totalsize // blocksize)) * 100) if size == 0: MW.progressBarTick.emit('100') if progress > self.barProgress: @@ -667,10 +667,10 @@ class KCCGUI(KCC_ui.Ui_mainWindow): self.addMessage('<a href="https://github.com/ciromattia/kcc/wiki/NonKindle-devices">' 'List of supported Non-Kindle devices.</a>', 'info') - def changeFormat(self, outputFormat=None): + def changeFormat(self, outputformat=None): profile = GUI.profiles[str(GUI.deviceBox.currentText())] - if outputFormat is not None: - GUI.formatBox.setCurrentIndex(outputFormat) + if outputformat is not None: + GUI.formatBox.setCurrentIndex(outputformat) else: GUI.formatBox.setCurrentIndex(profile['DefaultFormat']) if not GUI.webtoonBox.isChecked(): @@ -881,10 +881,10 @@ class KCCGUI(KCC_ui.Ui_mainWindow): else: self.addMessage('Download it and place executable in /usr/local/bin directory.', 'error') - def __init__(self, KCCAplication, KCCWindow): + def __init__(self, kccapp, kccwindow): global APP, MW, GUI - APP = KCCAplication - MW = KCCWindow + APP = kccapp + MW = kccwindow GUI = self self.setupUi(MW) self.editor = KCCGUI_MetaEditor() diff --git a/kindlecomicconverter/__init__.py b/kindlecomicconverter/__init__.py index cdb3623..8cb3bad 100644 --- a/kindlecomicconverter/__init__.py +++ b/kindlecomicconverter/__init__.py @@ -1,4 +1,4 @@ -__version__ = '5.4.3' +__version__ = '5.4.4' __license__ = 'ISC' -__copyright__ = '2012-2017, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>' +__copyright__ = '2012-2018, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>' __docformat__ = 'restructuredtext en' diff --git a/kindlecomicconverter/cbxarchive.py b/kindlecomicconverter/cbxarchive.py index 7aba70f..40ce928 100644 --- a/kindlecomicconverter/cbxarchive.py +++ b/kindlecomicconverter/cbxarchive.py @@ -1,5 +1,5 @@ # Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com> -# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re> +# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re> # # Permission to use, copy, modify, and/or distribute this software for # any purpose with or without fee is hereby granted, provided that the @@ -26,13 +26,13 @@ from .shared import check7ZFile as is_7zfile class CBxArchive: - def __init__(self, origFileName): - self.origFileName = origFileName - if is_zipfile(origFileName): + def __init__(self, fname): + self.fname = fname + if is_zipfile(fname): self.compressor = 'zip' - elif rarfile.is_rarfile(origFileName): + elif rarfile.is_rarfile(fname): self.compressor = 'rar' - elif is_7zfile(origFileName): + elif is_7zfile(fname): self.compressor = '7z' else: self.compressor = None @@ -41,22 +41,19 @@ class CBxArchive: return self.compressor is not None def extractCBZ(self, targetdir): - cbzFile = ZipFile(self.origFileName) + cbzFile = ZipFile(self.fname) filelist = [] for f in cbzFile.namelist(): if f.startswith('__MACOSX') or f.endswith('.DS_Store') or f.endswith('humbs.db'): pass elif f.endswith('/'): - try: - os.makedirs(os.path.join(targetdir, f)) - except Exception: - pass + os.makedirs(os.path.join(targetdir, f), exist_ok=True) else: filelist.append(f) cbzFile.extractall(targetdir, filelist) def extractCBR(self, targetdir): - cbrFile = rarfile.RarFile(self.origFileName) + cbrFile = rarfile.RarFile(self.fname) cbrFile.extractall(targetdir) for root, _, filenames in os.walk(targetdir): for filename in filenames: @@ -64,7 +61,7 @@ class CBxArchive: os.remove(os.path.join(root, filename)) def extractCB7(self, targetdir): - output = Popen('7za x "' + self.origFileName + '" -xr!__MACOSX -xr!.DS_Store -xr!thumbs.db -xr!Thumbs.db -o"' + + output = Popen('7za x "' + self.fname + '" -xr!__MACOSX -xr!.DS_Store -xr!thumbs.db -xr!Thumbs.db -o"' + targetdir + '"', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) extracted = False for line in output.stdout: diff --git a/kindlecomicconverter/comic2ebook.py b/kindlecomicconverter/comic2ebook.py index e27d5e6..7aaf027 100755 --- a/kindlecomicconverter/comic2ebook.py +++ b/kindlecomicconverter/comic2ebook.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com> -# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re> +# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re> # # Permission to use, copy, modify, and/or distribute this software for # any purpose with or without fee is hereby granted, provided that the @@ -88,7 +88,7 @@ def buildHTML(path, imgfile, imgfilepath): if "BlackBackground" in options.imgMetadata[imgfilepath]: additionalStyle = 'background-color:#000000;' else: - additionalStyle = 'background-color:#FFFFFF;' + additionalStyle = '' postfix = '' backref = 1 head = path @@ -198,7 +198,7 @@ def buildHTML(path, imgfile, imgfilepath): return path, imgfile -def buildNCX(dstdir, title, chapters, chapterNames): +def buildNCX(dstdir, title, chapters, chapternames): ncxfile = os.path.join(dstdir, 'OEBPS', 'toc.ncx') f = open(ncxfile, "w", encoding='UTF-8') f.writelines(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", @@ -217,10 +217,10 @@ def buildNCX(dstdir, title, chapters, chapterNames): filename = getImageFileName(os.path.join(folder, chapter[1])) navID = folder.replace('/', '_').replace('\\', '_') if options.chapters: - title = chapterNames[chapter[1]] + title = chapternames[chapter[1]] navID = filename[0].replace('/', '_').replace('\\', '_') elif os.path.basename(folder) != "Text": - title = chapterNames[os.path.basename(folder)] + title = chapternames[os.path.basename(folder)] f.write("<navPoint id=\"" + navID + "\"><navLabel><text>" + escape(title) + "</text></navLabel><content src=\"" + filename[0].replace("\\", "/") + ".xhtml\"/></navPoint>\n") @@ -228,7 +228,7 @@ def buildNCX(dstdir, title, chapters, chapterNames): f.close() -def buildNAV(dstdir, title, chapters, chapterNames): +def buildNAV(dstdir, title, chapters, chapternames): navfile = os.path.join(dstdir, 'OEBPS', 'nav.xhtml') f = open(navfile, "w", encoding='UTF-8') f.writelines(["<?xml version=\"1.0\" encoding=\"utf-8\"?>\n", @@ -245,9 +245,9 @@ def buildNAV(dstdir, title, chapters, chapterNames): folder = chapter[0].replace(os.path.join(dstdir, 'OEBPS'), '').lstrip('/').lstrip('\\\\') filename = getImageFileName(os.path.join(folder, chapter[1])) if options.chapters: - title = chapterNames[chapter[1]] + title = chapternames[chapter[1]] elif os.path.basename(folder) != "Text": - title = chapterNames[os.path.basename(folder)] + title = chapternames[os.path.basename(folder)] f.write("<li><a href=\"" + filename[0].replace("\\", "/") + ".xhtml\">" + escape(title) + "</a></li>\n") f.writelines(["</ol>\n", "</nav>\n", @@ -257,9 +257,9 @@ def buildNAV(dstdir, title, chapters, chapterNames): folder = chapter[0].replace(os.path.join(dstdir, 'OEBPS'), '').lstrip('/').lstrip('\\\\') filename = getImageFileName(os.path.join(folder, chapter[1])) if options.chapters: - title = chapterNames[chapter[1]] + title = chapternames[chapter[1]] elif os.path.basename(folder) != "Text": - title = chapterNames[os.path.basename(folder)] + title = chapternames[os.path.basename(folder)] f.write("<li><a href=\"" + filename[0].replace("\\", "/") + ".xhtml\">" + escape(title) + "</a></li>\n") f.write("</ol>\n</nav>\n</body>\n</html>") f.close() @@ -287,20 +287,27 @@ def buildOPF(dstdir, title, filelist, cover=None): 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", - "<meta name=\"cover\" content=\"cover\"/>\n", - "<meta property=\"rendition:orientation\">portrait</meta>\n", - "<meta property=\"rendition:spread\">portrait</meta>\n", - "<meta property=\"rendition:layout\">pre-paginated</meta>\n"]) + "<meta name=\"cover\" content=\"cover\"/>\n"]) if options.iskindle and options.profile != 'Custom': - f.writelines(["<meta name=\"original-resolution\" content=\"", + f.writelines(["<meta name=\"fixed-layout\" content=\"true\"/>\n", + "<meta name=\"original-resolution\" content=\"", str(deviceres[0]) + "x" + str(deviceres[1]) + "\"/>\n", "<meta name=\"book-type\" content=\"comic\"/>\n", - "<meta name=\"RegionMagnification\" content=\"true\"/>\n", "<meta name=\"primary-writing-mode\" content=\"" + writingmode + "\"/>\n", "<meta name=\"zero-gutter\" content=\"true\"/>\n", "<meta name=\"zero-margin\" content=\"true\"/>\n", - "<meta name=\"ke-border-color\" content=\"#ffffff\"/>\n", + "<meta name=\"ke-border-color\" content=\"#FFFFFF\"/>\n", "<meta name=\"ke-border-width\" content=\"0\"/>\n"]) + if options.kfx: + f.writelines(["<meta name=\"orientation-lock\" content=\"none\"/>\n", + "<meta name=\"region-mag\" content=\"false\"/>\n"]) + else: + f.writelines(["<meta name=\"orientation-lock\" content=\"portrait\"/>\n", + "<meta name=\"region-mag\" content=\"true\"/>\n"]) + else: + f.writelines(["<meta property=\"rendition:orientation\">portrait</meta>\n", + "<meta property=\"rendition:spread\">portrait</meta>\n", + "<meta property=\"rendition:layout\">pre-paginated</meta>\n"]) f.writelines(["</metadata>\n<manifest>\n<item id=\"ncx\" href=\"toc.ncx\" ", "media-type=\"application/x-dtbncx+xml\"/>\n", "<item id=\"nav\" href=\"nav.xhtml\" ", @@ -331,10 +338,43 @@ def buildOPF(dstdir, title, filelist, cover=None): f.write("<item id=\"css\" href=\"Text/style.css\" media-type=\"text/css\"/>\n") if options.righttoleft: f.write("</manifest>\n<spine page-progression-direction=\"rtl\" toc=\"ncx\">\n") + pageside = "right" else: f.write("</manifest>\n<spine page-progression-direction=\"ltr\" toc=\"ncx\">\n") - for entry in reflist: - f.write("<itemref idref=\"page_" + entry + "\"/>\n") + pageside = "left" + if options.iskindle: + for entry in reflist: + if options.righttoleft: + if entry.endswith("-b"): + f.write("<itemref idref=\"page_" + entry + "\" linear=\"yes\" properties=\"page-spread-right\"/>\n") + pageside = "right" + elif entry.endswith("-c"): + f.write("<itemref idref=\"page_" + entry + "\" linear=\"yes\" properties=\"page-spread-left\"/>\n") + pageside = "right" + else: + f.write("<itemref idref=\"page_" + entry + "\" linear=\"yes\" properties=\"page-spread-" + + pageside + "\"/>\n") + if pageside == "right": + pageside = "left" + else: + pageside = "right" + else: + if entry.endswith("-b"): + f.write("<itemref idref=\"page_" + entry + "\" linear=\"yes\" properties=\"page-spread-left\"/>\n") + pageside = "left" + elif entry.endswith("-c"): + f.write("<itemref idref=\"page_" + entry + "\" linear=\"yes\" properties=\"page-spread-right\"/>\n") + pageside = "left" + else: + f.write("<itemref idref=\"page_" + entry + "\" linear=\"yes\" properties=\"page-spread-" + + pageside + "\"/>\n") + if pageside == "right": + pageside = "left" + else: + pageside = "right" + else: + for entry in reflist: + f.write("<itemref idref=\"page_" + entry + "\">\n") f.write("</spine>\n</package>\n") f.close() os.mkdir(os.path.join(dstdir, 'META-INF')) @@ -348,7 +388,7 @@ def buildOPF(dstdir, title, filelist, cover=None): f.close() -def buildEPUB(path, chapterNames, tomeNumber): +def buildEPUB(path, chapternames, tomenumber): filelist = [] chapterlist = [] cover = None @@ -361,71 +401,72 @@ def buildEPUB(path, chapterNames, tomeNumber): "display: block;\n", "margin: 0;\n", "padding: 0;\n", - "}\n", - "#PV {\n", - "position: absolute;\n", - "width: 100%;\n", - "height: 100%;\n", - "top: 0;\n", - "left: 0;\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: 49.5%;\n", - "height: 100%;\n", - "float: left;\n", - "}\n", - "#PV-R {\n", - "right: 0;\n", - "width: 49.5%;\n", - "height: 100%;\n", - "float: right;\n", - "}\n", - "#PV-TL {\n", - "top: 0;\n", - "left: 0;\n", - "width: 49.5%;\n", - "height: 50%;\n", - "float: left;\n", - "}\n", - "#PV-TR {\n", - "top: 0;\n", - "right: 0;\n", - "width: 49.5%;\n", - "height: 50%;\n", - "float: right;\n", - "}\n", - "#PV-BL {\n", - "bottom: 0;\n", - "left: 0;\n", - "width: 49.5%;\n", - "height: 50%;\n", - "float: left;\n", - "}\n", - "#PV-BR {\n", - "bottom: 0;\n", - "right: 0;\n", - "width: 49.5%;\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"]) + if options.iskindle and options.panelview: + f.writelines(["#PV {\n", + "position: absolute;\n", + "width: 100%;\n", + "height: 100%;\n", + "top: 0;\n", + "left: 0;\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: 49.5%;\n", + "height: 100%;\n", + "float: left;\n", + "}\n", + "#PV-R {\n", + "right: 0;\n", + "width: 49.5%;\n", + "height: 100%;\n", + "float: right;\n", + "}\n", + "#PV-TL {\n", + "top: 0;\n", + "left: 0;\n", + "width: 49.5%;\n", + "height: 50%;\n", + "float: left;\n", + "}\n", + "#PV-TR {\n", + "top: 0;\n", + "right: 0;\n", + "width: 49.5%;\n", + "height: 50%;\n", + "float: right;\n", + "}\n", + "#PV-BL {\n", + "bottom: 0;\n", + "left: 0;\n", + "width: 49.5%;\n", + "height: 50%;\n", + "float: left;\n", + "}\n", + "#PV-BR {\n", + "bottom: 0;\n", + "right: 0;\n", + "width: 49.5%;\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 os.walk(os.path.join(path, 'OEBPS', 'Images')): chapter = False @@ -439,9 +480,9 @@ def buildEPUB(path, chapterNames, tomeNumber): cover = os.path.join(os.path.join(path, 'OEBPS', 'Images'), 'cover' + getImageFileName(filelist[-1][1])[1]) options.covers.append((image.Cover(os.path.join(filelist[-1][0], filelist[-1][1]), cover, options, - tomeNumber), options.uuid)) + tomenumber), options.uuid)) # Overwrite chapternames if tree is flat and ComicInfo.xml has bookmarks - if not chapterNames and options.chapters: + if not chapternames and options.chapters: chapterlist = [] globaldiff = 0 for aChapter in options.chapters: @@ -453,10 +494,10 @@ def buildEPUB(path, chapterNames, tomeNumber): pageid -= 1 filename = filelist[pageid][1] chapterlist.append((filelist[pageid][0].replace('Images', 'Text'), filename)) - chapterNames[filename] = aChapter[1] + chapternames[filename] = aChapter[1] globaldiff = pageid - (aChapter[0] + globaldiff) - buildNCX(path, options.title, chapterlist, chapterNames) - buildNAV(path, options.title, chapterlist, chapterNames) + buildNCX(path, options.title, chapterlist, chapternames) + buildNAV(path, options.title, chapterlist, chapternames) buildOPF(path, options.title, filelist, cover) @@ -542,7 +583,7 @@ def getWorkFolder(afile): copytree(afile, fullPath) sanitizePermissions(fullPath) return workdir - except: + except Exception: rmtree(workdir, True) raise UserWarning("Failed to prepare a workspace.") elif os.path.isfile(afile): @@ -560,7 +601,7 @@ def getWorkFolder(afile): if cbx.isCbxFile(): try: path = cbx.extract(workdir) - except: + except Exception: rmtree(workdir, True) raise UserWarning("Failed to extract archive.") else: @@ -575,7 +616,7 @@ def getWorkFolder(afile): return newpath -def getOutputFilename(srcpath, wantedname, ext, tomeNumber): +def getOutputFilename(srcpath, wantedname, ext, tomenumber): if srcpath[-1] == os.path.sep: srcpath = srcpath[:-1] if 'Ko' in options.profile and options.format == 'EPUB': @@ -589,16 +630,16 @@ def getOutputFilename(srcpath, wantedname, ext, tomeNumber): filename = os.path.join(os.path.abspath(options.output), os.path.basename(os.path.splitext(srcpath)[0]) + ext) elif os.path.isdir(srcpath): - filename = srcpath + tomeNumber + ext + filename = srcpath + tomenumber + ext else: if 'Ko' in options.profile and options.format == 'EPUB': path = srcpath.split(os.path.sep) - path[-1] = ''.join(e for e in path[-1].split('.')[0] if e.isalnum()) + tomeNumber + ext + path[-1] = ''.join(e for e in path[-1].split('.')[0] if e.isalnum()) + tomenumber + ext if not path[-1].split('.')[0]: - path[-1] = 'KCCPlaceholder' + tomeNumber + ext + path[-1] = 'KCCPlaceholder' + tomenumber + ext filename = os.path.sep.join(path) else: - filename = os.path.splitext(srcpath)[0] + tomeNumber + ext + filename = os.path.splitext(srcpath)[0] + tomenumber + ext if os.path.isfile(filename): counter = 0 basename = os.path.splitext(filename)[0] @@ -608,7 +649,7 @@ def getOutputFilename(srcpath, wantedname, ext, tomeNumber): return filename -def getComicInfo(path, originalPath): +def getComicInfo(path, originalpath): xmlPath = os.path.join(path, 'ComicInfo.xml') options.authors = ['KCC'] options.remoteCovers = {} @@ -617,10 +658,10 @@ def getComicInfo(path, originalPath): titleSuffix = '' if options.title == 'defaulttitle': defaultTitle = True - if os.path.isdir(originalPath): - options.title = os.path.basename(originalPath) + if os.path.isdir(originalpath): + options.title = os.path.basename(originalpath) else: - options.title = os.path.splitext(os.path.basename(originalPath))[0] + options.title = os.path.splitext(os.path.basename(originalpath))[0] else: defaultTitle = False if os.path.exists(xmlPath): @@ -655,10 +696,10 @@ def getComicInfo(path, originalPath): os.remove(xmlPath) -def getCoversFromMCB(mangaID): +def getCoversFromMCB(mangaid): covers = {} try: - jsonRaw = urlopen(Request('http://mcd.iosphe.re/api/v1/series/' + mangaID + '/', + jsonRaw = urlopen(Request('http://mcd.iosphe.re/api/v1/series/' + mangaid + '/', headers={'User-Agent': 'KindleComicConverter/' + __version__})) jsonData = loads(jsonRaw.read().decode('utf-8')) for volume in jsonData['Covers']['a']: @@ -683,9 +724,9 @@ def getTopMargin(deviceres, size): return str(round(y, 1)) -def getPanelViewResolution(imageSize, deviceRes): - scale = float(deviceRes[0]) / float(imageSize[0]) - return int(deviceRes[0]), int(scale * imageSize[1]) +def getPanelViewResolution(imagesize, deviceres): + scale = float(deviceres[0]) / float(imagesize[0]) + return int(deviceres[0]), int(scale * imagesize[1]) def getPanelViewSize(deviceres, size): @@ -804,19 +845,19 @@ def splitProcess(path, mode): return output -def detectCorruption(tmpPath, orgPath): +def detectCorruption(tmppath, orgpath): imageNumber = 0 imageSmaller = 0 alreadyProcessed = False - for root, _, files in os.walk(tmpPath, False): + for root, _, files in os.walk(tmppath, False): for name in files: if getImageFileName(name) is not None: if not alreadyProcessed and getImageFileName(name)[0].endswith('-kcc'): alreadyProcessed = True path = os.path.join(root, name) - pathOrg = orgPath + path.split('OEBPS' + os.path.sep + 'Images')[1] + pathOrg = orgpath + path.split('OEBPS' + os.path.sep + 'Images')[1] if os.path.getsize(path) == 0: - rmtree(os.path.join(tmpPath, '..', '..'), True) + rmtree(os.path.join(tmppath, '..', '..'), True) raise RuntimeError('Image file %s is corrupted.' % pathOrg) try: img = Image.open(path) @@ -827,7 +868,7 @@ def detectCorruption(tmpPath, orgPath): if options.profileData[1][0] > img.size[0] and options.profileData[1][1] > img.size[1]: imageSmaller += 1 except Exception as err: - rmtree(os.path.join(tmpPath, '..', '..'), True) + rmtree(os.path.join(tmppath, '..', '..'), True) if 'decoder' in str(err) and 'not available' in str(err): raise RuntimeError('Pillow was compiled without JPG and/or PNG decoder.') else: @@ -856,28 +897,28 @@ def createNewTome(): return tomePath, tomePathRoot -def slugify(value, isDir): - if isDir: - value = slugifyExt(value, regex_pattern=r'[^-a-z0-9_\.]+') +def slugify(value, isdir): + if isdir: + value = slugifyExt(value, regex_pattern=r'[^-a-z0-9_\.]+').strip('.') else: - value = slugifyExt(value) + value = slugifyExt(value).strip('.') value = sub(r'0*([0-9]{4,})', r'\1', sub(r'([0-9]+)', r'0000\1', value, count=2)) return value -def makeZIP(zipFilename, baseDir, isEPUB=False): - zipFilename = os.path.abspath(zipFilename) + '.zip' - zipOutput = ZipFile(zipFilename, 'w', ZIP_DEFLATED) - if isEPUB: +def makeZIP(zipfilename, basedir, isepub=False): + zipfilename = os.path.abspath(zipfilename) + '.zip' + zipOutput = ZipFile(zipfilename, 'w', ZIP_DEFLATED) + if isepub: zipOutput.writestr('mimetype', 'application/epub+zip', ZIP_STORED) - for dirpath, _, filenames in os.walk(baseDir): + for dirpath, _, filenames in os.walk(basedir): for name in filenames: path = os.path.normpath(os.path.join(dirpath, name)) - aPath = os.path.normpath(os.path.join(dirpath.replace(baseDir, ''), name)) + aPath = os.path.normpath(os.path.join(dirpath.replace(basedir, ''), name)) if os.path.isfile(path): zipOutput.write(path, aPath) zipOutput.close() - return zipFilename + return zipfilename def makeParser(): @@ -906,7 +947,7 @@ def makeParser(): outputOptions.add_option("-t", "--title", action="store", dest="title", default="defaulttitle", 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]") + help="Output format (Available options: Auto, MOBI, EPUB, CBZ, KFX) [Default=Auto]") outputOptions.add_option("-b", "--batchsplit", type="int", dest="batchsplit", default="0", help="Split output into multiple files. 0: Don't split 1: Automatic mode " "2: Consider every subdirectory as separate volume [Default=0]") @@ -953,6 +994,7 @@ def checkOptions(): options.panelview = True options.iskindle = False options.bordersColor = None + options.kfx = False if options.format == 'Auto': if options.profile in ['K1', 'K2', 'K34', 'K578', 'KPW', 'KV', 'KO']: options.format = 'MOBI' @@ -967,7 +1009,7 @@ def checkOptions(): if options.black_borders: options.bordersColor = 'black' # Splitting MOBI is not optional - if options.format == 'MOBI' and options.batchsplit != 2: + if (options.format == 'MOBI' or options.format == 'KFX') and options.batchsplit != 2: options.batchsplit = 1 # Older Kindle models don't support Panel View. if options.profile == 'K1' or options.profile == 'K2' or options.profile == 'K34' or options.profile == 'KDX': @@ -989,6 +1031,11 @@ def checkOptions(): # CBZ files on Kindle DX/DXG support higher resolution if options.profile == 'KDX' and options.format == 'CBZ': options.customheight = 1200 + # KFX output create EPUB that might be can be by jhowell KFX Output Calibre plugin + if options.format == 'KFX': + options.format = 'EPUB' + options.kfx = True + options.panelview = False # Override profile data if options.customwidth != 0 or options.customheight != 0: X = image.ProfileData.Profiles[options.profile][1][0] @@ -1039,13 +1086,13 @@ def checkPre(source): try: with TemporaryFile(prefix='KCC-', dir=src): pass - except: + except Exception: raise UserWarning("Target directory is not writable.") -def makeBook(source, qtGUI=None): +def makeBook(source, qtgui=None): global GUI - GUI = qtGUI + GUI = qtgui if GUI: GUI.progressBarTick.emit('1') else: @@ -1061,7 +1108,7 @@ def makeBook(source, qtGUI=None): y = 1024 else: y = image.ProfileData.Profiles[options.profile][1][1] - comic2panel.main(['-y ' + str(y), '-i', '-m', path], qtGUI) + comic2panel.main(['-y ' + str(y), '-i', '-m', path], qtgui) print("Processing images...") if GUI: GUI.progressBarTick.emit('Processing images') @@ -1192,9 +1239,9 @@ def makeMOBIWorker(item): return [kindlegenErrorCode, kindlegenError, item] -def makeMOBI(work, qtGUI=None): +def makeMOBI(work, qtgui=None): global GUI, makeMOBIWorkerPool, makeMOBIWorkerOutput - GUI = qtGUI + GUI = qtgui makeMOBIWorkerOutput = [] availableMemory = virtual_memory().total / 1000000000 if availableMemory <= 2: diff --git a/kindlecomicconverter/comic2panel.py b/kindlecomicconverter/comic2panel.py index 14b3294..c3d9e1c 100644 --- a/kindlecomicconverter/comic2panel.py +++ b/kindlecomicconverter/comic2panel.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com> -# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re> +# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re> # # Permission to use, copy, modify, and/or distribute this software for # any purpose with or without fee is hereby granted, provided that the @@ -93,6 +93,7 @@ def splitImageTick(output): splitWorkerPool.terminate() +# noinspection PyUnboundLocalVariable def splitImage(work): try: path = work[0] @@ -140,9 +141,7 @@ def splitImage(work): 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 = Image.alpha_composite(imgOrg.convert(mode='RGBA'), drawImg) debugImage.save(os.path.join(path, os.path.splitext(name)[0] + '-debug.png'), 'PNG') @@ -185,7 +184,7 @@ def splitImage(work): return str(sys.exc_info()[1]), sanitizeTrace(sys.exc_info()[2]) -def main(argv=None, qtGUI=None): +def main(argv=None, qtgui=None): global options, GUI, splitWorkerPool, splitWorkerOutput, mergeWorkerPool, mergeWorkerOutput parser = OptionParser(usage="Usage: kcc-c2p [options] comic_folder", add_help_option=False) mainOptions = OptionGroup(parser, "MANDATORY") @@ -203,8 +202,8 @@ def main(argv=None, qtGUI=None): parser.add_option_group(mainOptions) parser.add_option_group(otherOptions) options, args = parser.parse_args(argv) - if qtGUI: - GUI = qtGUI + if qtgui: + GUI = qtgui else: GUI = None if len(args) != 1: diff --git a/kindlecomicconverter/dualmetafix.py b/kindlecomicconverter/dualmetafix.py index 566ceb5..e6be255 100644 --- a/kindlecomicconverter/dualmetafix.py +++ b/kindlecomicconverter/dualmetafix.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # Based on initial version of DualMetaFix. Copyright (C) 2013 Kevin Hendricks -# Changes for KCC Copyright (C) 2014-2017 Pawel Jastrzebski <pawelj@iosphe.re> +# Changes for KCC Copyright (C) 2014-2018 Pawel Jastrzebski <pawelj@iosphe.re> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/kindlecomicconverter/image.py b/kindlecomicconverter/image.py index e7f29a4..d7c05ec 100755 --- a/kindlecomicconverter/image.py +++ b/kindlecomicconverter/image.py @@ -2,7 +2,7 @@ # Copyright (C) 2011 Stanislav (proDOOMman) Kosolapov <prodoomman@gmail.com> # Copyright (c) 2016 Alberto Planas <aplanas@gmail.com> # Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com> -# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re> +# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -273,17 +273,17 @@ class ComicPage: method = Image.BICUBIC else: method = Image.LANCZOS - if self.opt.stretch: + if self.opt.stretch or (self.opt.kfx and ('-KCC-B' in self.targetPath or '-KCC-C' in self.targetPath)): self.image = self.image.resize(self.size, method) elif self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1] and not self.opt.upscale: - if self.opt.format == 'CBZ': + if self.opt.format == 'CBZ' or self.opt.kfx: borderw = int((self.size[0] - self.image.size[0]) / 2) borderh = int((self.size[1] - self.image.size[1]) / 2) self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=self.fill) if self.image.size[0] != self.size[0] or self.image.size[1] != self.size[1]: self.image = ImageOps.fit(self.image, self.size, method=Image.BICUBIC, centering=(0.5, 0.5)) else: - if self.opt.format == 'CBZ': + if self.opt.format == 'CBZ' or self.opt.kfx: ratioDev = float(self.size[0]) / float(self.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] @@ -299,53 +299,53 @@ class ComicPage: if self.image.size[0] > self.size[0] or self.image.size[1] > self.size[1]: self.image.thumbnail(self.size, Image.LANCZOS) - def getBoundingBox(self, tmpImg): - min_margin = [int(0.005 * i + 0.5) for i in tmpImg.size] - max_margin = [int(0.1 * i + 0.5) for i in tmpImg.size] - bbox = tmpImg.getbbox() + def getBoundingBox(self, tmptmg): + min_margin = [int(0.005 * i + 0.5) for i in tmptmg.size] + max_margin = [int(0.1 * i + 0.5) for i in tmptmg.size] + bbox = tmptmg.getbbox() bbox = ( max(0, min(max_margin[0], bbox[0] - min_margin[0])), max(0, min(max_margin[1], bbox[1] - min_margin[1])), - min(tmpImg.size[0], - max(tmpImg.size[0] - max_margin[0], bbox[2] + min_margin[0])), - min(tmpImg.size[1], - max(tmpImg.size[1] - max_margin[1], bbox[3] + min_margin[1])), + min(tmptmg.size[0], + max(tmptmg.size[0] - max_margin[0], bbox[2] + min_margin[0])), + min(tmptmg.size[1], + max(tmptmg.size[1] - max_margin[1], bbox[3] + min_margin[1])), ) return bbox def cropPageNumber(self, power): if self.fill != 'white': - tmpImg = self.image.convert(mode='L') + tmptmg = self.image.convert(mode='L') else: - tmpImg = ImageOps.invert(self.image.convert(mode='L')) - tmpImg = tmpImg.point(lambda x: x and 255) - tmpImg = tmpImg.filter(ImageFilter.MinFilter(size=3)) - tmpImg = tmpImg.filter(ImageFilter.GaussianBlur(radius=5)) - tmpImg = tmpImg.point(lambda x: (x >= 16 * power) and x) - self.image = self.image.crop(tmpImg.getbbox()) if tmpImg.getbbox() else self.image + tmptmg = ImageOps.invert(self.image.convert(mode='L')) + tmptmg = tmptmg.point(lambda x: x and 255) + tmptmg = tmptmg.filter(ImageFilter.MinFilter(size=3)) + tmptmg = tmptmg.filter(ImageFilter.GaussianBlur(radius=5)) + tmptmg = tmptmg.point(lambda x: (x >= 16 * power) and x) + self.image = self.image.crop(tmptmg.getbbox()) if tmptmg.getbbox() else self.image def cropMargin(self, power): if self.fill != 'white': - tmpImg = self.image.convert(mode='L') + tmptmg = self.image.convert(mode='L') else: - tmpImg = ImageOps.invert(self.image.convert(mode='L')) - tmpImg = tmpImg.filter(ImageFilter.GaussianBlur(radius=3)) - tmpImg = tmpImg.point(lambda x: (x >= 16 * power) and x) - self.image = self.image.crop(self.getBoundingBox(tmpImg)) if tmpImg.getbbox() else self.image + tmptmg = ImageOps.invert(self.image.convert(mode='L')) + tmptmg = tmptmg.filter(ImageFilter.GaussianBlur(radius=3)) + tmptmg = tmptmg.point(lambda x: (x >= 16 * power) and x) + self.image = self.image.crop(self.getBoundingBox(tmptmg)) if tmptmg.getbbox() else self.image class Cover: - def __init__(self, source, target, opt, tomeNumber): + def __init__(self, source, target, opt, tomeid): self.options = opt self.source = source self.target = target - if tomeNumber == 0: - self.tomeNumber = 1 + if tomeid == 0: + self.tomeid = 1 else: - self.tomeNumber = tomeNumber - if self.tomeNumber in self.options.remoteCovers: + self.tomeid = tomeid + if self.tomeid in self.options.remoteCovers: try: - source = urlopen(Request(quote(self.options.remoteCovers[self.tomeNumber]).replace('%3A', ':', 1), + source = urlopen(Request(quote(self.options.remoteCovers[self.tomeid]).replace('%3A', ':', 1), headers={'User-Agent': 'KindleComicConverter/' + __version__})).read() self.image = Image.open(BytesIO(source)) except Exception: diff --git a/kindlecomicconverter/kindle.py b/kindlecomicconverter/kindle.py index 1eea63c..f9595f6 100644 --- a/kindlecomicconverter/kindle.py +++ b/kindlecomicconverter/kindle.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re> +# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re> # # Permission to use, copy, modify, and/or distribute this software for # any purpose with or without fee is hereby granted, provided that the diff --git a/kindlecomicconverter/metadata.py b/kindlecomicconverter/metadata.py index 714dcd1..da16718 100644 --- a/kindlecomicconverter/metadata.py +++ b/kindlecomicconverter/metadata.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re> +# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re> # # Permission to use, copy, modify, and/or distribute this software for # any purpose with or without fee is hereby granted, provided that the diff --git a/kindlecomicconverter/pdfjpgextract.py b/kindlecomicconverter/pdfjpgextract.py index 90d0643..250cf35 100644 --- a/kindlecomicconverter/pdfjpgextract.py +++ b/kindlecomicconverter/pdfjpgextract.py @@ -1,5 +1,5 @@ # Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com> -# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re> +# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re> # # Based upon the code snippet by Ned Batchelder # (http://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html) @@ -25,17 +25,16 @@ from string import ascii_uppercase, digits class PdfJpgExtract: - def __init__(self, origFileName): - self.origFileName = origFileName - self.filename = os.path.splitext(origFileName) - # noinspection PyUnusedLocal - self.path = self.filename[0] + "-KCC-" + ''.join(choice(ascii_uppercase + digits) for x in range(3)) + def __init__(self, fname): + self.fname = fname + self.filename = os.path.splitext(fname) + self.path = self.filename[0] + "-KCC-" + ''.join(choice(ascii_uppercase + digits) for _ in range(3)) def getPath(self): return self.path def extract(self): - pdf = open(self.origFileName, "rb").read() + pdf = open(self.fname, "rb").read() startmark = b"\xff\xd8" startfix = 0 endmark = b"\xff\xd9" diff --git a/kindlecomicconverter/shared.py b/kindlecomicconverter/shared.py index c2a8ecf..6778621 100644 --- a/kindlecomicconverter/shared.py +++ b/kindlecomicconverter/shared.py @@ -1,5 +1,5 @@ # Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com> -# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re> +# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re> # # Permission to use, copy, modify, and/or distribute this software for # any purpose with or without fee is hereby granted, provided that the @@ -73,8 +73,8 @@ def walkLevel(some_dir, level=1): del dirs[:] -def md5Checksum(filePath): - with open(filePath, 'rb') as fh: +def md5Checksum(fpath): + with open(fpath, 'rb') as fh: m = md5() while True: data = fh.read(8192) @@ -84,8 +84,8 @@ def md5Checksum(filePath): return m.hexdigest() -def check7ZFile(filePath): - with open(filePath, 'rb') as fh: +def check7ZFile(fpath): + with open(fpath, 'rb') as fh: header = fh.read(6) return header == b"7z\xbc\xaf'\x1c" diff --git a/kindlecomicconverter/startup.py b/kindlecomicconverter/startup.py index aa78a0a..deb6313 100644 --- a/kindlecomicconverter/startup.py +++ b/kindlecomicconverter/startup.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com> -# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re> +# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re> # # Permission to use, copy, modify, and/or distribute this software for # any purpose with or without fee is hereby granted, provided that the |