From 32391f6a5aa17696e57c8aa6da5675b977ccad0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Devernay?= Date: Wed, 6 Mar 2013 12:11:50 +0100 Subject: [PATCH 1/3] better epub support (grabbed from calibre): get rid of those small margins --- kcc/comic2ebook.py | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index 1cfdd9a..a22a90b 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -60,10 +60,12 @@ def buildHTML(path, imgfile): "\n", "", filename[0], "\n", "\n", + "\n", + "\n", "\n", - "\n", - "
\"",
\n", + "\n", + "
\"",
\n", #"
\n", #"\n", @@ -319,6 +321,34 @@ def genEpubStruct(path): chapterlist = [] cover = None os.mkdir(os.path.join(path, 'OEBPS', 'Text')) + f = open(os.path.join(path, 'OEBPS', 'Text', 'page_styles.css'), 'w') + f.writelines(["@page {\n", + " margin-bottom: 0;\n", + " margin-top: 0\n", + " }\n"]) + f.close() + f = open(os.path.join(path, 'OEBPS', 'Text', 'stylesheet.css'), 'w') + f.writelines([".kcc {\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", + ".kcc1 {\n", + " display: block;\n", + " text-align: center\n", + " }\n", + ".kcc2 {\n", + " height: auto;\n", + " width: auto\n", + " }\n"]) + f.close() for (dirpath, dirnames, filenames) in os.walk(os.path.join(path, 'OEBPS', 'Images')): chapter = False for afile in filenames: From 6a298175f02c6034c02a311bee7b7c5ce175c100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Wed, 6 Mar 2013 13:39:51 +0100 Subject: [PATCH 2/3] CSS Formatting --- kcc/comic2ebook.py | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index 4d20d03..05d6197 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -324,31 +324,31 @@ def genEpubStruct(path): os.mkdir(os.path.join(path, 'OEBPS', 'Text')) f = open(os.path.join(path, 'OEBPS', 'Text', 'page_styles.css'), 'w') f.writelines(["@page {\n", - " margin-bottom: 0;\n", - " margin-top: 0\n", - " }\n"]) + " margin-bottom: 0;\n", + " margin-top: 0\n", + "}\n"]) f.close() f = open(os.path.join(path, 'OEBPS', 'Text', 'stylesheet.css'), 'w') f.writelines([".kcc {\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", + " 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", ".kcc1 {\n", - " display: block;\n", - " text-align: center\n", - " }\n", + " display: block;\n", + " text-align: center\n", + "}\n", ".kcc2 {\n", - " height: auto;\n", - " width: auto\n", - " }\n"]) + " height: auto;\n", + " width: auto\n", + "}\n"]) f.close() for (dirpath, dirnames, filenames) in os.walk(os.path.join(path, 'OEBPS', 'Images')): chapter = False From 62475e12c67846966f1d0801ec219150c35b020f Mon Sep 17 00:00:00 2001 From: Ciro Mattia Gonano Date: Wed, 6 Mar 2013 16:29:56 +0100 Subject: [PATCH 3/3] Merge branch 'master' --- kcc/comic2ebook.py | 8 +++---- kcc/gui.py | 52 ++++++++++++++++++++++++++++++++++---------- kcc/image.py | 26 ++++++++++++---------- kcc/pdfjpgextract.py | 1 + 4 files changed, 61 insertions(+), 26 deletions(-) diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index 05d6197..134af2f 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -129,7 +129,7 @@ def buildNCX(dstdir, title, chapters): def buildOPF(profile, dstdir, title, filelist, cover=None, righttoleft=False): opffile = os.path.join(dstdir, 'OEBPS', 'content.opf') # read the first file resolution - profilelabel, deviceres, palette = image.ProfileData.Profiles[profile] + profilelabel, deviceres, palette, gamma = image.ProfileData.Profiles[profile] imgres = str(deviceres[0]) + "x" + str(deviceres[1]) if righttoleft: writingmode = "horizontal-rl" @@ -260,7 +260,7 @@ def applyImgOptimization(img, isSplit=False, toRight=False): img.cutPageNumber() img.resizeImage(options.upscale, options.stretch, options.black_borders, isSplit, toRight) if not options.notquantize: - img.quantizeImage() + img.quantizeImage() def dirImgProcess(path): @@ -430,8 +430,8 @@ def main(argv=None): help="Verbose output [default=False]") parser.add_option("--no-image-processing", action="store_false", dest="imgproc", default=True, help="Do not apply image preprocessing (page splitting and optimizations) [default=True]") - parser.add_option("--gamma", type="float", dest="gamma", default=2.2, - help="Apply gamma correction to linearize the image [default=2.2]") + parser.add_option("--gamma", type="float", dest="gamma", default="0.0", + help="Apply gamma correction to linearize the image [default=auto]") parser.add_option("--nodithering", action="store_true", dest="notquantize", default=False, help="Disable image quantization [default=False]") parser.add_option("--upscale-images", action="store_true", dest="upscale", default=False, diff --git a/kcc/gui.py b/kcc/gui.py index 2ce2bed..ad068a7 100644 --- a/kcc/gui.py +++ b/kcc/gui.py @@ -31,6 +31,7 @@ from subprocess import call import os import shutil import stat +import traceback class MainWindow: @@ -89,7 +90,7 @@ class MainWindow: 'rotate': IntVar(None, 0), 'cut_page_numbers': IntVar(None, 1), 'mangastyle': IntVar(None, 0), - 'image_gamma': DoubleVar(None, 2.2), + 'image_gamma': DoubleVar(None, 0.0), 'image_upscale': IntVar(None, 0), 'image_stretch': IntVar(None, 0), 'black_borders': IntVar(None, 0) @@ -102,26 +103,38 @@ class MainWindow: 'rotate': "Rotate landscape images instead of splitting them", 'cut_page_numbers': "Cut page numbers", 'mangastyle': "Manga mode", - 'image_gamma': "Gamma", + 'image_gamma': "Custom gamma\n(if 0.0 the default gamma for the profile will be used)", 'image_upscale': "Allow image upscaling", 'image_stretch': "Stretch images", 'black_borders': "Use black borders" } for key in self.options: - if isinstance( self.options[key], IntVar ) or isinstance( self.options[key], BooleanVar ): + if isinstance(self.options[key], IntVar) or isinstance(self.options[key], BooleanVar): aCheckButton = Checkbutton(self.master, text=self.optionlabels[key], variable=self.options[key]) aCheckButton.grid(columnspan=4, sticky=W + N + S) - elif isinstance( self.options[key], DoubleVar ): - aLabel = Label(self.master, text=self.optionlabels[key]) - aLabel.grid(column=2, sticky=W + N + S) + elif isinstance(self.options[key], DoubleVar): + aLabel = Label(self.master, text=self.optionlabels[key], justify=RIGHT) + aLabel.grid(column=0, columnspan=3, sticky=W + N + S) aEntry = Entry(self.master, textvariable=self.options[key]) - aEntry.grid(column=3, row=(self.master.grid_size()[1]-1), sticky=W + N + S) + aEntry.grid(column=3, row=(self.master.grid_size()[1] - 1), sticky=W + N + S) self.submit = Button(self.master, text="CONVERT", command=self.start_conversion, fg="red") self.submit.grid(columnspan=4, sticky=W + E + N + S) + aLabel = Label(self.master, text="file progress", justify=RIGHT) + aLabel.grid(column=0, sticky=E) + self.progress_file = ttk.Progressbar(orient=HORIZONTAL, length=200, mode='determinate', maximum=4) + self.progress_file.grid(column=1, columnspan=3, row=(self.master.grid_size()[1] - 1), sticky=W + E + N + S) + aLabel = Label(self.master, text="overall progress", justify=RIGHT) + aLabel.grid(column=0, sticky=E) + self.progress_overall = ttk.Progressbar(orient=HORIZONTAL, length=200, mode='determinate') + self.progress_overall.grid(column=1, columnspan=3, row=(self.master.grid_size()[1] - 1), sticky=W + E + N + S) def start_conversion(self): + self.submit['state'] = DISABLED + self.master.update() self.convert() + self.submit['state'] = NORMAL + self.master.update() def convert(self): if len(self.filelist) < 1: @@ -129,8 +142,9 @@ class MainWindow: return profilekey = ProfileData.ProfileLabels[self.profile.get()] argv = ["-p", profilekey] - argv.append("--gamma") - argv.append(self.options['image_gamma'].get()) + if self.options['image_gamma'].get() != 0.0: + argv.append("--gamma") + argv.append(self.options['image_gamma'].get()) if self.options['image_preprocess'].get() == 0: argv.append("--no-image-processing") if self.options['notquantize'].get() == 1: @@ -150,14 +164,24 @@ class MainWindow: if self.options['black_borders'].get() == 1: argv.append("--black-borders") errors = False + left_files = len(self.filelist) + filenum = 0 + self.progress_overall['value'] = 0 + self.progress_overall['maximum'] = left_files for entry in self.filelist: + filenum += 1 + self.progress_file['value'] = 1 self.master.update() subargv = list(argv) try: subargv.append(entry) epub_path = comic2ebook.main(subargv) - except Exception, err: - tkMessageBox.showerror('KCC Error', "Error on file %s:\n%s" % (subargv[-1], str(err))) + self.progress_file['value'] = 2 + self.master.update() + except Exception as err: + type_, value_, traceback_ = sys.exc_info() + tkMessageBox.showerror('KCC Error', "Error on file %s:\n%s\nTraceback:\n%s" % + (subargv[-1], str(err), traceback.format_tb(traceback_))) errors = True continue if self.options['epub_only'] == 1: @@ -168,6 +192,8 @@ class MainWindow: print >>sys.stderr, "Child was terminated by signal", -retcode else: print >>sys.stderr, "Child returned", retcode + self.progress_file['value'] = 3 + self.master.update() except OSError as e: tkMessageBox.showerror('KindleGen Error', "Error on file %s:\n%s" % (epub_path, e)) errors = True @@ -177,10 +203,14 @@ class MainWindow: shutil.move(mobifile, mobifile + '_tostrip') kindlestrip.main((mobifile + '_tostrip', mobifile)) os.remove(mobifile + '_tostrip') + self.progress_file['value'] = 4 + self.master.update() except Exception, err: tkMessageBox.showerror('Error', "Error on file %s:\n%s" % (mobifile, str(err))) errors = True continue + self.progress_overall['value'] = filenum + self.master.update() if errors: tkMessageBox.showinfo( "Done", diff --git a/kcc/image.py b/kcc/image.py index 3cac5b2..8eeae69 100755 --- a/kcc/image.py +++ b/kcc/image.py @@ -77,13 +77,13 @@ class ProfileData: ] Profiles = { - 'K1': ("Kindle", (600, 800), Palette4), - 'K2': ("Kindle 2", (600, 800), Palette15), - 'K3': ("Kindle 3/Keyboard", (600, 800), Palette16), - 'K4': ("Kindle 4/NT/Touch", (600, 800), Palette16), - 'KHD': ("Kindle Paperwhite", (758, 1024), Palette16), - 'KDX': ("Kindle DX", (824, 1200), Palette15), - 'KDXG': ("Kindle DXG", (824, 1200), Palette16) + 'K1': ("Kindle", (600, 800), Palette4, 1.8), + 'K2': ("Kindle 2", (600, 800), Palette15, 1.8), + 'K3': ("Kindle 3/Keyboard", (600, 800), Palette16, 1.8), + 'K4': ("Kindle 4/NT/Touch", (600, 800), Palette16, 1.8), + 'KHD': ("Kindle Paperwhite", (758, 1024), Palette16, 1.8), + 'KDX': ("Kindle DX", (824, 1200), Palette15, 1.8), + 'KDXG': ("Kindle DXG", (824, 1200), Palette16, 1.8) } ProfileLabels = { @@ -101,7 +101,7 @@ class ComicPage: def __init__(self, source, device): try: self.profile = device - self.profile_label, self.size, self.palette = ProfileData.Profiles[device] + self.profile_label, self.size, self.palette, self.gamma = ProfileData.Profiles[device] except KeyError: raise RuntimeError('Unexpected output device %s' % device) try: @@ -115,7 +115,7 @@ class ComicPage: filename = os.path.basename(self.origFileName) try: self.image = self.image.convert('L') # convert to grayscale - os.remove(os.path.join(targetdir,filename)) + os.remove(os.path.join(targetdir, filename)) if notquantize: self.image.save(os.path.join(targetdir, os.path.splitext(filename)[0] + ".jpg"), "JPEG") else: @@ -124,8 +124,12 @@ class ComicPage: raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e)) def optimizeImage(self, gamma): - self.image = ImageOps.autocontrast(Image.eval(self.image, lambda a: 255*(a/255.)**gamma)) - + if gamma < 0.1: + gamma = self.gamma + if gamma == 1.0: + self.image = ImageOps.autocontrast(self.image) + else: + self.image = ImageOps.autocontrast(Image.eval(self.image, lambda a: 255 * (a / 255.) ** gamma)) def quantizeImage(self): colors = len(self.palette) / 3 diff --git a/kcc/pdfjpgextract.py b/kcc/pdfjpgextract.py index 953428d..b1a95bd 100644 --- a/kcc/pdfjpgextract.py +++ b/kcc/pdfjpgextract.py @@ -70,3 +70,4 @@ class PdfJpgExtract: njpg += 1 i = iend + return self.path