From 8d5ccf5d27763c931ae24668d08702572252c34a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Mon, 4 Mar 2013 11:36:57 +0100 Subject: [PATCH 1/9] Landscape mode support - EPUB part. Code create proper landscape enabled EPUB file. Rewritten itemref function (#198) ensures that splited pages will be displayed together. --- kcc/comic2ebook.py | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index 2805525..60fb549 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -86,6 +86,21 @@ def buildHTML(path, imgfile): f.close() return path, imgfile +def buildBlankHTML(path): + f = open(os.path.join(path, 'blank.html'), "w") + f.writelines(["\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "" + ]) + f.close() + return path def buildNCX(dstdir, title, chapters): ncxfile = os.path.join(dstdir, 'OEBPS', 'toc.ncx') @@ -121,8 +136,14 @@ def buildOPF(profile, dstdir, title, filelist, cover=None, righttoleft=False): imgres = str(deviceres[0]) + "x" + str(deviceres[1]) if righttoleft: writingmode = "horizontal-rl" + facing = "right" + facing1 = "right" + facing2 = "left" else: writingmode = "horizontal-lr" + facing = "left" + facing1 = "left" + facing2 = "right" from uuid import uuid4 uuid = str(uuid4()) uuid = uuid.encode('utf-8') @@ -140,11 +161,11 @@ def buildOPF(profile, dstdir, title, filelist, cover=None, righttoleft=False): "\n", "\n", "\n", - "\n", + "\n", "\n", "\n", "\n", - "\n", + "\n", "\n\n\n" ]) @@ -171,9 +192,25 @@ def buildOPF(profile, dstdir, title, filelist, cover=None, righttoleft=False): mt = 'image/jpeg' f.write("\n") + f.write("\n") f.write("\n\n") for entry in reflist: - f.write("\n") + if entry.endswith("-1"): + if (righttoleft and facing == 'left') or (not righttoleft and facing == 'right'): + f.write("\n") + f.write("\n") + elif entry.endswith("-2"): + f.write("\n") + if righttoleft: + facing = "right" + else: + facing = "left" + else: + f.write("\n") + if facing == 'right': + facing = 'left' + else: + facing = 'right' f.write("\n\n\n\n") f.close() # finish with standard ePub folders @@ -278,6 +315,7 @@ def genEpubStruct(path): alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)] filelist.sort(key=lambda name: (alphanum_key(name[0].lower()), alphanum_key(name[1].lower()))) buildOPF(options.profile, path, options.title, filelist, cover, options.righttoleft) + filelist.append(buildBlankHTML(os.path.join(path, 'OEBPS', 'Text'))) def getWorkFolder(afile): From 7275856549a8b5afd126dca74e1f2447140d06e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Mon, 4 Mar 2013 15:22:00 +0100 Subject: [PATCH 2/9] Landscape mode support - Image part. Not perfect. New resizeImage function to properly display splitted pages in landscape mode. Enabling upscaling or stretching might result with not correct display of splitted pages in landscape mode. --- kcc/comic2ebook.py | 14 ++++++++++---- kcc/image.py | 20 +++++++++++++++----- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index 60fb549..514575c 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -248,12 +248,12 @@ def isInFilelist(filename, filelist): return seen -def applyImgOptimization(img): +def applyImgOptimization(img, isSplit=False, toRight=False): img.optimizeImage() img.cropWhiteSpace(10.0) if options.cutpagenumbers: img.cutPageNumber() - img.resizeImage(options.upscale, options.stretch, options.black_borders) + img.resizeImage(options.upscale, options.stretch, options.black_borders, isSplit, toRight) img.quantizeImage() @@ -272,11 +272,17 @@ def dirImgProcess(path): if split is not None: if options.verbose: print "Splitted " + afile + if options.righttoleft: + toRight1 = False; + toRight2 = True; + else: + toRight1 = True; + toRight2 = False; img0 = image.ComicPage(split[0], options.profile) - applyImgOptimization(img0) + applyImgOptimization(img0, True, toRight1) img0.saveToDir(dirpath) img1 = image.ComicPage(split[1], options.profile) - applyImgOptimization(img1) + applyImgOptimization(img1, True, toRight2) img1.saveToDir(dirpath) else: applyImgOptimization(img) diff --git a/kcc/image.py b/kcc/image.py index 83fac9c..f4ac736 100755 --- a/kcc/image.py +++ b/kcc/image.py @@ -129,7 +129,7 @@ class ComicPage: palImg.putpalette(self.palette) self.image = self.image.quantize(palette=palImg) - def resizeImage(self, upscale=False, stretch=False, black_borders=False): + def resizeImage(self, upscale=False, stretch=False, black_borders=False, isSplit=False, toRight=False): method = Image.ANTIALIAS if black_borders: fill = 'black' @@ -137,10 +137,20 @@ class ComicPage: fill = 'white' if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]: if not upscale: - # do not upscale but center image in a device-sized image - borderw = (self.size[0] - self.image.size[0]) / 2 - borderh = (self.size[1] - self.image.size[1]) / 2 - self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=fill) + if isSplit: + borderw = (self.size[0] - self.image.size[0]) + borderh = (self.size[1] - self.image.size[1]) / 2 + self.image = ImageOps.expand(self.image, border=(0, borderh), fill=fill) + tempImg = Image.new(self.image.mode, (self.image.size[0] + borderw, self.image.size[1]), fill) + if toRight: + tempImg.paste(self.image, (borderw, 0)) + else: + tempImg.paste(self.image, (0, 0)) + self.image = tempImg + else: + borderw = (self.size[0] - self.image.size[0]) / 2 + borderh = (self.size[1] - self.image.size[1]) / 2 + self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=fill) return self.image else: method = Image.NEAREST From 0398d7bf939acbe0f63620746bc972f8b47458bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Mon, 4 Mar 2013 16:14:11 +0100 Subject: [PATCH 3/9] Don't create blank-page records for older Kindle. Kindle without Landscape mode show blank-page records incorrectly. --- kcc/comic2ebook.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index 514575c..827b5af 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -196,7 +196,7 @@ def buildOPF(profile, dstdir, title, filelist, cover=None, righttoleft=False): f.write("\n\n") for entry in reflist: if entry.endswith("-1"): - if (righttoleft and facing == 'left') or (not righttoleft and facing == 'right'): + if ((righttoleft and facing == 'left') or (not righttoleft and facing == 'right')) and (options.profile == 'K4' or options.profile == 'KHD'): f.write("\n") f.write("\n") elif entry.endswith("-2"): From 8802c24ad04a28ebc2ab5d0a3ffba1304d47b097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Mon, 4 Mar 2013 16:21:12 +0100 Subject: [PATCH 4/9] Don't create blank-page records for older Kindle. --- kcc/comic2ebook.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index 827b5af..bdbd6f6 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -192,7 +192,8 @@ def buildOPF(profile, dstdir, title, filelist, cover=None, righttoleft=False): mt = 'image/jpeg' f.write("\n") - f.write("\n") + if options.profile == 'K4' or options.profile == 'KHD': + f.write("\n") f.write("\n\n") for entry in reflist: if entry.endswith("-1"): @@ -321,7 +322,8 @@ def genEpubStruct(path): alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)] filelist.sort(key=lambda name: (alphanum_key(name[0].lower()), alphanum_key(name[1].lower()))) buildOPF(options.profile, path, options.title, filelist, cover, options.righttoleft) - filelist.append(buildBlankHTML(os.path.join(path, 'OEBPS', 'Text'))) + if options.profile == 'K4' or options.profile == 'KHD': + filelist.append(buildBlankHTML(os.path.join(path, 'OEBPS', 'Text'))) def getWorkFolder(afile): From 193ad9382c861f3f23556dc0cf0d049b53c4afdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Mon, 4 Mar 2013 17:05:16 +0100 Subject: [PATCH 5/9] Disabled new resizeImage function for older Kindle. --- kcc/comic2ebook.py | 2 +- kcc/image.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index bdbd6f6..ade53ec 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -254,7 +254,7 @@ def applyImgOptimization(img, isSplit=False, toRight=False): img.cropWhiteSpace(10.0) if options.cutpagenumbers: img.cutPageNumber() - img.resizeImage(options.upscale, options.stretch, options.black_borders, isSplit, toRight) + img.resizeImage(options.upscale, options.stretch, options.black_borders, isSplit, toRight, options.profile) img.quantizeImage() diff --git a/kcc/image.py b/kcc/image.py index f4ac736..c13a112 100755 --- a/kcc/image.py +++ b/kcc/image.py @@ -129,7 +129,7 @@ class ComicPage: palImg.putpalette(self.palette) self.image = self.image.quantize(palette=palImg) - def resizeImage(self, upscale=False, stretch=False, black_borders=False, isSplit=False, toRight=False): + def resizeImage(self, upscale=False, stretch=False, black_borders=False, isSplit=False, toRight=False, profile="KHD"): method = Image.ANTIALIAS if black_borders: fill = 'black' @@ -137,7 +137,7 @@ class ComicPage: fill = 'white' if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]: if not upscale: - if isSplit: + if isSplit and (profile == 'K4' or profile == 'KHD'): borderw = (self.size[0] - self.image.size[0]) borderh = (self.size[1] - self.image.size[1]) / 2 self.image = ImageOps.expand(self.image, border=(0, borderh), fill=fill) From c7f38a574f3d1cc2d65c3829fd62cca28318eabb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Mon, 4 Mar 2013 17:24:11 +0100 Subject: [PATCH 6/9] Fixed Landscape mode with upscaling enabled. --- kcc/image.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kcc/image.py b/kcc/image.py index c13a112..1cc186a 100755 --- a/kcc/image.py +++ b/kcc/image.py @@ -162,6 +162,8 @@ class ComicPage: 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] + if isSplit and (profile == 'K4' or profile == 'KHD'): + diff = 2 self.image = ImageOps.expand(self.image, border=(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] From e92ee816172eae47b75ce829c1a5172cc2544cf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jastrz=C4=99bski?= Date: Mon, 4 Mar 2013 19:52:38 +0100 Subject: [PATCH 7/9] Fixed single empty page on end of book. --- kcc/comic2ebook.py | 7 +++++-- kcc/image.py | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index ade53ec..fd66a23 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -192,7 +192,7 @@ def buildOPF(profile, dstdir, title, filelist, cover=None, righttoleft=False): mt = 'image/jpeg' f.write("\n") - if options.profile == 'K4' or options.profile == 'KHD': + if (options.profile == 'K4' or options.profile == 'KHD') and splittedSomething: f.write("\n") f.write("\n\n") for entry in reflist: @@ -260,6 +260,8 @@ def applyImgOptimization(img, isSplit=False, toRight=False): def dirImgProcess(path): global options + global splittedSomething + splittedSomething = False for (dirpath, dirnames, filenames) in os.walk(path): for afile in filenames: @@ -271,6 +273,7 @@ def dirImgProcess(path): img = image.ComicPage(os.path.join(dirpath, afile), options.profile) split = img.splitPage(dirpath, options.righttoleft, options.rotate) if split is not None: + splittedSomething = True if options.verbose: print "Splitted " + afile if options.righttoleft: @@ -322,7 +325,7 @@ def genEpubStruct(path): alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)] filelist.sort(key=lambda name: (alphanum_key(name[0].lower()), alphanum_key(name[1].lower()))) buildOPF(options.profile, path, options.title, filelist, cover, options.righttoleft) - if options.profile == 'K4' or options.profile == 'KHD': + if (options.profile == 'K4' or options.profile == 'KHD') and splittedSomething: filelist.append(buildBlankHTML(os.path.join(path, 'OEBPS', 'Text'))) diff --git a/kcc/image.py b/kcc/image.py index 1cc186a..55e9086 100755 --- a/kcc/image.py +++ b/kcc/image.py @@ -163,7 +163,7 @@ class ComicPage: if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev: diff = int(self.image.size[1] * ratioDev) - self.image.size[0] if isSplit and (profile == 'K4' or profile == 'KHD'): - diff = 2 + diff = 2 self.image = ImageOps.expand(self.image, border=(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] From 3c187889d1fee2243e43d5df9b9abb90907f536f Mon Sep 17 00:00:00 2001 From: Ciro Mattia Gonano Date: Tue, 5 Mar 2013 11:50:33 +0100 Subject: [PATCH 8/9] Image has already-set profile, so use the inited one --- kcc/comic2ebook.py | 2 +- kcc/image.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index fd66a23..619b026 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -254,7 +254,7 @@ def applyImgOptimization(img, isSplit=False, toRight=False): img.cropWhiteSpace(10.0) if options.cutpagenumbers: img.cutPageNumber() - img.resizeImage(options.upscale, options.stretch, options.black_borders, isSplit, toRight, options.profile) + img.resizeImage(options.upscale, options.stretch, options.black_borders, isSplit, toRight) img.quantizeImage() diff --git a/kcc/image.py b/kcc/image.py index 55e9086..6f52471 100755 --- a/kcc/image.py +++ b/kcc/image.py @@ -100,6 +100,7 @@ class ProfileData: class ComicPage: def __init__(self, source, device): try: + self.profile = device self.profile_label, self.size, self.palette = ProfileData.Profiles[device] except KeyError: raise RuntimeError('Unexpected output device %s' % device) @@ -129,7 +130,7 @@ class ComicPage: palImg.putpalette(self.palette) self.image = self.image.quantize(palette=palImg) - def resizeImage(self, upscale=False, stretch=False, black_borders=False, isSplit=False, toRight=False, profile="KHD"): + def resizeImage(self, upscale=False, stretch=False, black_borders=False, isSplit=False, toRight=False): method = Image.ANTIALIAS if black_borders: fill = 'black' @@ -137,7 +138,7 @@ class ComicPage: fill = 'white' if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]: if not upscale: - if isSplit and (profile == 'K4' or profile == 'KHD'): + if isSplit and (self.profile == 'K4' or self.profile == 'KHD'): borderw = (self.size[0] - self.image.size[0]) borderh = (self.size[1] - self.image.size[1]) / 2 self.image = ImageOps.expand(self.image, border=(0, borderh), fill=fill) @@ -162,7 +163,7 @@ class ComicPage: 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] - if isSplit and (profile == 'K4' or profile == 'KHD'): + if isSplit and (self.profile == 'K4' or self.profile == 'KHD'): diff = 2 self.image = ImageOps.expand(self.image, border=(diff / 2, 0), fill=fill) elif (float(self.image.size[0]) / float(self.image.size[1])) > ratioDev: From cc3237d05119e3ef7126efb18042af31f630baa2 Mon Sep 17 00:00:00 2001 From: Ciro Mattia Gonano Date: Tue, 5 Mar 2013 11:54:23 +0100 Subject: [PATCH 9/9] Formatting and PEP-8 codestyle --- kcc/comic2ebook.py | 72 ++++++++++++++++++++++++---------------------- kcc/image.py | 2 +- setup.py | 2 +- 3 files changed, 39 insertions(+), 37 deletions(-) diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index 619b026..ab30137 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -86,21 +86,22 @@ def buildHTML(path, imgfile): f.close() return path, imgfile + def buildBlankHTML(path): - f = open(os.path.join(path, 'blank.html'), "w") - f.writelines(["\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "" - ]) - f.close() - return path + f = open(os.path.join(path, 'blank.html'), "w") + f.writelines(["\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + ""]) + f.close() + return path + def buildNCX(dstdir, title, chapters): ncxfile = os.path.join(dstdir, 'OEBPS', 'toc.ncx') @@ -196,22 +197,23 @@ def buildOPF(profile, dstdir, title, filelist, cover=None, righttoleft=False): f.write("\n") f.write("\n\n") for entry in reflist: - if entry.endswith("-1"): - if ((righttoleft and facing == 'left') or (not righttoleft and facing == 'right')) and (options.profile == 'K4' or options.profile == 'KHD'): - f.write("\n") - f.write("\n") - elif entry.endswith("-2"): - f.write("\n") - if righttoleft: - facing = "right" - else: - facing = "left" - else: - f.write("\n") - if facing == 'right': - facing = 'left' - else: - facing = 'right' + if entry.endswith("-1"): + if (righttoleft and facing == 'left') or (not righttoleft and facing == 'right') and \ + (options.profile == 'K4' or options.profile == 'KHD'): + f.write("\n") + f.write("\n") + elif entry.endswith("-2"): + f.write("\n") + if righttoleft: + facing = "right" + else: + facing = "left" + else: + f.write("\n") + if facing == 'right': + facing = 'left' + else: + facing = 'right' f.write("\n\n\n\n") f.close() # finish with standard ePub folders @@ -277,11 +279,11 @@ def dirImgProcess(path): if options.verbose: print "Splitted " + afile if options.righttoleft: - toRight1 = False; - toRight2 = True; + toRight1 = False + toRight2 = True else: - toRight1 = True; - toRight2 = False; + toRight1 = True + toRight2 = False img0 = image.ComicPage(split[0], options.profile) applyImgOptimization(img0, True, toRight1) img0.saveToDir(dirpath) @@ -326,7 +328,7 @@ def genEpubStruct(path): filelist.sort(key=lambda name: (alphanum_key(name[0].lower()), alphanum_key(name[1].lower()))) buildOPF(options.profile, path, options.title, filelist, cover, options.righttoleft) if (options.profile == 'K4' or options.profile == 'KHD') and splittedSomething: - filelist.append(buildBlankHTML(os.path.join(path, 'OEBPS', 'Text'))) + filelist.append(buildBlankHTML(os.path.join(path, 'OEBPS', 'Text'))) def getWorkFolder(afile): diff --git a/kcc/image.py b/kcc/image.py index 6f52471..f3080ed 100755 --- a/kcc/image.py +++ b/kcc/image.py @@ -85,7 +85,7 @@ class ProfileData: 'KDX': ("Kindle DX", (824, 1200), Palette15), 'KDXG': ("Kindle DXG", (824, 1200), Palette16) } - + ProfileLabels = { "Kindle": 'K1', "Kindle 2": 'K2', diff --git a/setup.py b/setup.py index 0fd4b00..7ad2dec 100644 --- a/setup.py +++ b/setup.py @@ -57,7 +57,7 @@ setup( version=VERSION, author="Ciro Mattia Gonano", author_email="ciromattia@gmail.com", - description=("A tool to convert comics (CBR/CBZ/PDFs/image folders) to Mobipocket."), + description="A tool to convert comics (CBR/CBZ/PDFs/image folders) to Mobipocket.", license = "ISC License (ISCL)", keywords = "kindle comic mobipocket mobi cbz cbr manga", url = "http://github.com/ciromattia/kcc",