diff --git a/README.md b/README.md
index e067265..3664ee2 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# KCC
+# KCC
`KCC` (a.k.a. `KindleComicConverter`) is a Python app to convert comic files or folders to ePub or Panel View MOBI.
It was initally developed for Kindle but since v2.2 it outputs valid ePub 2.0 so _**despite its name, KCC is
@@ -16,9 +16,14 @@ _kc2_ in no way is a replacement for **KCC** so you can be quite confident we'll
You can find the latest released binary at the following links:
- OS X: [https://dl.dropbox.com/u/16806101/KindleComicConverter_osx_2.9.zip](https://dl.dropbox.com/u/16806101/KindleComicConverter_osx_2.9.zip)
- Win64: [https://dl.dropbox.com/u/16806101/KindleComicConverter_win-amd64_2.9.zip](https://dl.dropbox.com/u/16806101/KindleComicConverter_win-amd64_2.9.zip)
-- Win32: [http://pawelj.vulturis.eu/Shared/KindleComicConverter_win-x86_2.9.zip](http://pawelj.vulturis.eu/Shared/KindleComicConverter_win-x86_2.9.zip) *(thanks to [AcidWeb](https://github.com/AcidWeb))*
+- Win32: [http://pawelj.vulturis.eu/Shared/KindleComicConverter_win-x86_2.9.zip](http://pawelj.vulturis.eu/Shared/KindleComicConverter_win-x86_2.9.zip)
- Linux: Just download sourcecode and launch `python kcc.py` *(Provided you have Python and Pillow installed)*
+## AWKCC .NET GUI
+
+
+[All-in-one package for Windows users](http://www.mobileread.com/forums/showpost.php?p=2444957&postcount=3)
+
## INPUT FORMATS
`kcc` can understand and convert, at the moment, the following file types:
- PNG, JPG, GIF, TIFF, BMP
@@ -53,7 +58,7 @@ Options:
--version show program's version number and exit
-h, --help show this help message and exit
-p PROFILE, --profile=PROFILE
- Device profile (Choose one among K1, K2, K3, K4NT, K4T, KDX, KDXG or KHD) [Default=KHD]
+ Device profile (Choose one among K1, K2, K3, K4NT, K4T, KDX, KDXG, KHD, KF, KFHD, KFHD8) [Default=KHD]
-t TITLE, --title=TITLE
Comic title [Default=filename]
-m, --manga-style Manga style (Right-to-left reading and splitting) [Default=False]
@@ -88,55 +93,92 @@ The app relies and includes the following scripts/binaries:
- `magic.py` from [python-magic](https://github.com/ahupp/python-magic) library
## CHANGELOG
- - 1.00: Initial version
- - 1.10: Added support for CBZ/CBR files in comic2ebook.py
- - 1.11: Added support for CBZ/CBR files in KindleComicConverter
- - 1.20: Comic optimizations! Split pages not target-oriented (landscape with portrait target or portrait
- with landscape target), add palette and other image optimizations from Mangle.
- WARNING: PIL is required for all image mangling!
- - 1.30: Fixed an issue in OPF generation for device resolution
- Reworked options system (call with -h option to get the inline help)
- - 1.40: Added some options for controlling image optimization
- Further optimization (ImageOps, page numbering cut, autocontrast)
- - 1.41: Fixed a serious bug on resizing when img ratio was bigger than device one
- - 1.50: Added subfolder support for multiple chapters.
- - 2.0: GUI! AppleScript is gone and Tk is used to provide cross-platform GUI support.
- - 2.1: Added basic error reporting
- - 2.2: Added (valid!) ePub 2.0 output
- Rename .zip files to .cbz to avoid overwriting
- - 2.3: Fixed win32 ePub generation, folder handling, filenames with spaces and subfolders
- - 2.4: Use temporary directory as workdir (fixes converting from external volumes and zipfiles renaming)
- Fixed "add folders" from GUI.
- - 2.5: Added --black-borders option to set added borders black when page's ratio is not the device's one (#11).
- Fixes epub containing zipped itself (#10)
- - 2.6: Added --rotate option to rotate landscape images instead of splitting them (#16, #24)
- Added --output option to customize ePub output dir/file (#22)
- Add rendition:layout and rendition:orientation ePub meta tags (supported by new kindlegen 2.8)
- Fixed natural sorting for files (#18)
- - 2.7: Lots of GUI improvements (#27, #13)
- Added gamma support within --gamma option (defaults to profile-specified gamma) (#26, #27)
- Added --nodithering option to prevent dithering optimizations (#27)
- Epub margins support (#30)
- Fixed no file added if file has no spaces on Windows (#25)
- Gracefully exit if unrar missing (#15)
- Do not call kindlegen if source epub is bigger than 320MB (#17)
- Get filetype from magic number (#14)
- PDF conversion works again
- - 2.8: updated rarfile library
- Panel View support + HQ support (#36) - new option: --nopanelviewhq
- Split profiles for K4NT and K4T
- Rewrite of Landscape Mode support (huge readability improvement for KPW)
- Upscale use now BILINEAR method
- Added generic CSS file
- Optimized archive extraction for zip/rar files (#40)
- - 2.9: Added support for generating a plain CBZ (skipping all the EPUB/Mobi generation) (#45)
- Prevent output file overwriting the source one: if a duplicate name is detected, append _kcc to the name
- Rarfile library updated to 2.6
- Added GIF, TIFF and BMP to supported formats (#42)
- Filenames slugifications (#28, #31, #9, #8)
- - 2.10: Kindle Fire support (color ePub/Mobi)
- Panel View support for horizontal content
+####1.00
+* Initial version
+####1.10
+* Added support for CBZ/CBR files in comic2ebook.py
+
+####1.11
+* Added support for CBZ/CBR files in KindleComicConverter
+
+####1.20
+* Comic optimizations! Split pages not target-oriented (landscape with portrait target or portrait with landscape target), add palette and other image optimizations from Mangle. WARNING: PIL is required for all image mangling!
+
+####1.30
+* Fixed an issue in OPF generation for device resolution
+* Reworked options system (call with -h option to get the inline help)
+
+####1.40
+* Added some options for controlling image optimization
+* Further optimization (ImageOps, page numbering cut, autocontrast)
+
+####1.41
+* Fixed a serious bug on resizing when img ratio was bigger than device one
+
+####1.50
+* Added subfolder support for multiple chapters.
+
+####2.0
+* GUI! AppleScript is gone and Tk is used to provide cross-platform GUI support.
+
+####2.1
+* Added basic error reporting
+
+#### 2.2:
+* Added (valid!) ePub 2.0 output
+* Rename .zip files to .cbz to avoid overwriting
+
+####2.3
+* Fixed win32 ePub generation, folder handling, filenames with spaces and subfolders
+
+####2.4
+* Use temporary directory as workdir (fixes converting from external volumes and zipfiles renaming)
+* Fixed "add folders" from GUI.
+
+####2.5
+* Added --black-borders option to set added borders black when page's ratio is not the device's one (#11).
+* Fixes epub containing zipped itself (#10)
+
+####2.6
+* Added --rotate option to rotate landscape images instead of splitting them (#16, #24)
+* Added --output option to customize ePub output dir/file (#22)
+* Add rendition:layout and rendition:orientation ePub meta tags (supported by new kindlegen 2.8)
+* Fixed natural sorting for files (#18)
+
+####2.7
+* Lots of GUI improvements (#27, #13)
+* Added gamma support within --gamma option (defaults to profile-specified gamma) (#26, #27)
+* Added --nodithering option to prevent dithering optimizations (#27)
+* Epub margins support (#30)
+* Fixed no file added if file has no spaces on Windows (#25)
+* Gracefully exit if unrar missing (#15)
+* Do not call kindlegen if source epub is bigger than 320MB (#17)
+* Get filetype from magic number (#14)
+* PDF conversion works again
+
+####2.8
+* Updated rarfile library
+* Panel View support + HQ support (#36) - new option: --nopanelviewhq
+* Split profiles for K4NT and K4T
+* Rewrite of Landscape Mode support (huge readability improvement for KPW)
+* Upscale use now BILINEAR method
+* Added generic CSS file
+* Optimized archive extraction for zip/rar files (#40)
+
+####2.9
+* Added support for generating a plain CBZ (skipping all the EPUB/Mobi generation) (#45)
+* Prevent output file overwriting the source one: if a duplicate name is detected, append _kcc to the name
+* Rarfile library updated to 2.6
+* Added GIF, TIFF and BMP to supported formats (#42)
+* Filenames slugifications (#28, #31, #9, #8)
+
+####2.10:
+* Multiprocessing support
+* Kindle Fire support (color ePub/Mobi)
+* Panel View support for horizontal content
+* Fixed panel order for horizontal pages when --rotate is enabled
+* Disabled cropping and page number cutting for blank pages
## COPYRIGHT
diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py
index b92ed22..4db695d 100755
--- a/kcc/comic2ebook.py
+++ b/kcc/comic2ebook.py
@@ -32,6 +32,7 @@ from shutil import copytree
from shutil import rmtree
from shutil import make_archive
from optparse import OptionParser
+from multiprocessing import Pool
import image
import cbxarchive
import pdfjpgextract
@@ -40,6 +41,11 @@ import pdfjpgextract
def buildHTML(path, imgfile):
filename = getImageFileName(imgfile)
if filename is not None:
+ # All files marked with this sufix need horizontal Panel View.
+ if "_rotated" in str(filename):
+ rotate = True
+ else:
+ rotate = False
htmlpath = ''
postfix = ''
backref = 1
@@ -70,7 +76,7 @@ def buildHTML(path, imgfile):
imgfile, "\" class=\"singlePage\"/>\n"
])
if options.panelview:
- if options.panelviewhorizontal:
+ if rotate:
if options.righttoleft:
f.writelines(["
\n",
@@ -250,7 +256,7 @@ def buildOPF(profile, dstdir, title, filelist, cover=None):
f.write("\n\n")
splitCountUsed = 1
for entry in reflist:
- if entry.endswith("-1"):
+ if entry.endswith("-000001") or entry.endswith("-1"):
# noinspection PyRedundantParentheses
if ((options.righttoleft and facing == 'left') or (not options.righttoleft and facing == 'right')) and\
options.landscapemode:
@@ -260,7 +266,7 @@ def buildOPF(profile, dstdir, title, filelist, cover=None):
f.write("\n")
else:
f.write("\n")
- elif entry.endswith("-2"):
+ elif entry.endswith("-000002") or entry.endswith("-2"):
if options.landscapemode:
f.write("\n")
else:
@@ -309,16 +315,7 @@ def getImageFileName(imgfile):
return filename
-def isInFilelist(filename, filelist):
- filename = os.path.splitext(filename)
- seen = False
- for item in filelist:
- if filename[0] == item[0]:
- seen = True
- return seen
-
-
-def applyImgOptimization(img, isSplit=False, toRight=False):
+def applyImgOptimization(img, isSplit, toRight, options):
img.cropWhiteSpace(10.0)
if options.cutpagenumbers:
img.cutPageNumber()
@@ -331,51 +328,62 @@ def applyImgOptimization(img, isSplit=False, toRight=False):
def dirImgProcess(path):
global options, splitCount
- if options.righttoleft:
- facing = "right"
- else:
- facing = "left"
-
+ work = []
+ pagenumber = 0
+ pagenumbermodifier = 0
+ pool = Pool()
for (dirpath, dirnames, filenames) in os.walk(path):
for afile in filenames:
if getImageFileName(afile) is not None:
- if options.verbose:
- print "Optimizing " + afile + " for " + options.profile
- else:
- print ".",
- img = image.ComicPage(os.path.join(dirpath, afile), options.profile)
- if options.nosplitrotate:
- split = None
- else:
- split = img.splitPage(dirpath, options.righttoleft, options.rotate)
- if split is not None:
- if options.verbose:
- print "Splitted " + afile
- if options.righttoleft:
- toRight1 = False
- toRight2 = True
- if facing == "left":
- splitCount += 1
- facing = "right"
- else:
- toRight1 = True
- toRight2 = False
- if facing == "right":
- splitCount += 1
- facing = "left"
- img0 = image.ComicPage(split[0], options.profile)
- applyImgOptimization(img0, True, toRight1)
- img0.saveToDir(dirpath, options.forcepng, options.forcecolor)
- img1 = image.ComicPage(split[1], options.profile)
- applyImgOptimization(img1, True, toRight2)
- img1.saveToDir(dirpath, options.forcepng, options.forcecolor)
- else:
- if facing == "right":
- facing = "left"
- else:
- facing = "right"
- applyImgOptimization(img)
- img.saveToDir(dirpath, options.forcepng, options.forcecolor)
+ pagenumber += 1
+ work.append([afile, dirpath, pagenumber, options])
+ splitpages = pool.map(fileImgProcess, work)
+ pool.close()
+ pool.join()
+ splitpages = filter(None, splitpages)
+ splitpages.sort()
+ for page in splitpages:
+ if (page + pagenumbermodifier) % 2 == 0:
+ splitCount += 1
+ pagenumbermodifier += 1
+ pagenumbermodifier += 1
+
+
+def fileImgProcess(work):
+ afile = work[0]
+ dirpath = work[1]
+ pagenumber = work[2]
+ options = work[3]
+ output = None
+ if options.verbose:
+ print "Optimizing " + afile + " for " + options.profile
+ else:
+ print ".",
+ img = image.ComicPage(os.path.join(dirpath, afile), options.profile)
+ if options.nosplitrotate:
+ split = None
+ else:
+ split = img.splitPage(dirpath, options.righttoleft, options.rotate)
+ if split is not None and split is not "R":
+ if options.verbose:
+ print "Splitted " + afile
+ if options.righttoleft:
+ toRight1 = False
+ toRight2 = True
+ else:
+ toRight1 = True
+ toRight2 = False
+ output = pagenumber
+ img0 = image.ComicPage(split[0], options.profile)
+ applyImgOptimization(img0, True, toRight1, options)
+ img0.saveToDir(dirpath, options.forcepng, options.forcecolor)
+ img1 = image.ComicPage(split[1], options.profile)
+ applyImgOptimization(img1, True, toRight2, options)
+ img1.saveToDir(dirpath, options.forcepng, options.forcecolor)
+ else:
+ applyImgOptimization(img, False, False, options)
+ img.saveToDir(dirpath, options.forcepng, options.forcecolor, split)
+ return output
def genEpubStruct(path):
@@ -387,8 +395,8 @@ def genEpubStruct(path):
sanitizeTree(os.path.join(path, 'OEBPS', 'Images'))
os.mkdir(os.path.join(path, 'OEBPS', 'Text'))
f = open(os.path.join(path, 'OEBPS', 'Text', 'style.css'), 'w')
- #DON'T COMPRESS CSS. KINDLE WILL FAIL TO PARSE IT.
- #Generic Panel View support + Margins fix for Non-Kindle devices.
+ # 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",
@@ -511,13 +519,6 @@ def genEpubStruct(path):
for afile in filenames:
filename = getImageFileName(afile)
if filename is not None:
- if "credit" in afile.lower():
- os.rename(os.path.join(dirpath, afile), os.path.join(dirpath, 'ZZZ999_' + afile))
- afile = 'ZZZ999_' + afile
- if "+" in afile.lower() or "#" in afile.lower():
- newfilename = afile.replace('+', '_').replace('#', '_')
- os.rename(os.path.join(dirpath, afile), os.path.join(dirpath, newfilename))
- afile = newfilename
filelist.append(buildHTML(dirpath, afile))
if not chapter:
chapterlist.append((dirpath.replace('Images', 'Text'), filelist[-1][1]))
@@ -598,11 +599,11 @@ def sanitizeTree(filetree):
def Copyright():
print ('comic2ebook v%(__version__)s. '
- 'Written 2012 by Ciro Mattia Gonano.' % globals())
+ 'Written 2013 by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals())
def Usage():
- print "Generates HTML, NCX and OPF for a Comic ebook from a bunch of images."
+ print "Generates EPUB/CBZ comic ebook from a bunch of images."
parser.print_help()
@@ -621,8 +622,6 @@ def main(argv=None):
help="Outputs a CBZ archive and does not generate EPUB")
parser.add_option("--nopanelviewhq", action="store_true", dest="nopanelviewhq", default=False,
help="Disable high quality Panel View [Default=False]")
- parser.add_option("--panelviewhorizontal", action="store_true", dest="panelviewhorizontal", default=False,
- help="Enable horizontal Panel View [Default=False]")
parser.add_option("--noprocessing", action="store_false", dest="imgproc", default=True,
help="Do not apply image preprocessing (Page splitting and optimizations) [Default=True]")
parser.add_option("--forcepng", action="store_true", dest="forcepng", default=False,
@@ -696,25 +695,33 @@ def getOutputFilename(srcpath, wantedname, ext):
def checkOptions():
global options
+ # Landscape mode is only supported by Kindle Touch and Paperwhite.
if options.profile == 'K4T' or options.profile == 'KHD':
options.landscapemode = True
else:
options.landscapemode = False
+ # Older Kindle don't support Virtual Panel View. We providing them configuration that will fake that feature.
if options.profile == 'K3' or options.profile == 'K4NT':
- #Real Panel View
+ # Real Panel View
options.panelview = True
else:
- #Virtual Panel View
+ # Virtual Panel View
options.panelview = False
+ # Older Kindle don't need higher resolution files due lack of Panel View.
+ # Kindle Fire family have very high resolution. Bigger images are not needed.
if options.profile == 'K1' or options.profile == 'K2' or options.profile == 'KDX' or options.profile == 'KDXG'\
or options.profile == 'KF' or options.profile == 'KFHD' or options.profile == 'KFHD8':
options.nopanelviewhq = True
+ # Disabling grayscale conversion for Kindle Fire family.
+ # Forcing JPEG output. For now code can't provide color PNG files.
if options.profile == 'KF' or options.profile == 'KFHD' or options.profile == 'KFHD8':
options.forcecolor = True
options.forcepng = False
else:
options.forcecolor = False
- if options.panelviewhorizontal:
+ # Mixing vertical and horizontal pages require real Panel View.
+ # Landscape mode don't work correcly without Virtual Panel View.
+ if options.rotate:
options.panelview = True
options.landscapemode = False
@@ -723,6 +730,7 @@ def getEpubPath():
global epub_path
return epub_path
+
if __name__ == "__main__":
Copyright()
main(sys.argv[1:])
diff --git a/kcc/image.py b/kcc/image.py
index 2b2da34..4ce1a1e 100755
--- a/kcc/image.py
+++ b/kcc/image.py
@@ -20,7 +20,7 @@ __copyright__ = '2012-2013, Ciro Mattia Gonano '
__docformat__ = 'restructuredtext en'
import os
-from PIL import Image, ImageOps, ImageStat
+from PIL import Image, ImageOps, ImageStat, ImageChops
class ImageFlags:
@@ -119,16 +119,21 @@ class ComicPage:
raise RuntimeError('Cannot read image file %s' % source)
self.image = self.image.convert('RGB')
- def saveToDir(self, targetdir, forcepng, color=False):
+ def saveToDir(self, targetdir, forcepng, color, sufix=None):
filename = os.path.basename(self.origFileName)
try:
if not color:
self.image = self.image.convert('L') # convert to grayscale
+ # Sufix is used to recognise which files need horizontal Panel View.
+ if sufix == "R":
+ sufix = "_rotated"
+ else:
+ sufix = ""
os.remove(os.path.join(targetdir, filename))
if forcepng:
- self.image.save(os.path.join(targetdir, os.path.splitext(filename)[0] + ".png"), "PNG")
+ self.image.save(os.path.join(targetdir, os.path.splitext(filename)[0] + sufix + ".png"), "PNG")
else:
- self.image.save(os.path.join(targetdir, os.path.splitext(filename)[0] + ".jpg"), "JPEG")
+ self.image.save(os.path.join(targetdir, os.path.splitext(filename)[0] + sufix + ".jpg"), "JPEG")
except IOError as e:
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
@@ -202,7 +207,7 @@ class ComicPage:
if (width > height) != (dstwidth > dstheight):
if rotate:
self.image = self.image.rotate(90)
- return None
+ return "R"
else:
if width > height:
# source is landscape, so split by the width
@@ -232,95 +237,97 @@ class ComicPage:
return None
def cutPageNumber(self):
- widthImg, heightImg = self.image.size
- delta = 2
- diff = delta
- fixedThreshold = 5
- if ImageStat.Stat(self.image).var[0] < 2 * fixedThreshold:
- return self.image
- while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] < fixedThreshold\
- and diff < heightImg:
- diff += delta
- diff -= delta
- pageNumberCut1 = diff
- if diff < delta:
+ if ImageChops.invert(self.image).getbbox() is not None:
+ widthImg, heightImg = self.image.size
+ delta = 2
diff = delta
- oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0]
- diff += delta
- while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] - oldStat > 0\
- and diff < heightImg / 4:
+ fixedThreshold = 5
+ if ImageStat.Stat(self.image).var[0] < 2 * fixedThreshold:
+ return self.image
+ while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] < fixedThreshold\
+ and diff < heightImg:
+ diff += delta
+ diff -= delta
+ pageNumberCut1 = diff
+ if diff < delta:
+ diff = delta
oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0]
diff += delta
- diff -= delta
- pageNumberCut2 = diff
- diff += delta
- oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg - pageNumberCut2))).var[0]
- while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg - pageNumberCut2))).var[0]\
- < fixedThreshold + oldStat and diff < heightImg / 4:
+ while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] - oldStat > 0\
+ and diff < heightImg / 4:
+ oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0]
+ diff += delta
+ diff -= delta
+ pageNumberCut2 = diff
diff += delta
- diff -= delta
- pageNumberCut3 = diff
- delta = 5
- diff = delta
- while ImageStat.Stat(self.image.crop((0, heightImg - pageNumberCut2, diff, heightImg))).var[0] < fixedThreshold\
- and diff < widthImg:
- diff += delta
- diff -= delta
- pageNumberX1 = diff
- diff = delta
- while ImageStat.Stat(self.image.crop((widthImg - diff, heightImg - pageNumberCut2,
- widthImg, heightImg))).var[0] < fixedThreshold and diff < widthImg:
- diff += delta
- diff -= delta
- pageNumberX2 = widthImg - diff
- if pageNumberCut3 - pageNumberCut1 > 2 * delta\
- and float(pageNumberX2 - pageNumberX1) / float(pageNumberCut2 - pageNumberCut1) <= 9.0\
- and ImageStat.Stat(self.image.crop((0, heightImg - pageNumberCut3, widthImg, heightImg))).var[0]\
- / ImageStat.Stat(self.image).var[0] < 0.1\
- and pageNumberCut3 < heightImg / 4 - delta:
- diff = pageNumberCut3
- else:
- diff = pageNumberCut1
- self.image = self.image.crop((0, 0, widthImg, heightImg - diff))
+ oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg - pageNumberCut2))).var[0]
+ while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg - pageNumberCut2))).var[0]\
+ < fixedThreshold + oldStat and diff < heightImg / 4:
+ diff += delta
+ diff -= delta
+ pageNumberCut3 = diff
+ delta = 5
+ diff = delta
+ while ImageStat.Stat(self.image.crop((0, heightImg - pageNumberCut2, diff, heightImg))).var[0] < fixedThreshold\
+ and diff < widthImg:
+ diff += delta
+ diff -= delta
+ pageNumberX1 = diff
+ diff = delta
+ while ImageStat.Stat(self.image.crop((widthImg - diff, heightImg - pageNumberCut2,
+ widthImg, heightImg))).var[0] < fixedThreshold and diff < widthImg:
+ diff += delta
+ diff -= delta
+ pageNumberX2 = widthImg - diff
+ if pageNumberCut3 - pageNumberCut1 > 2 * delta\
+ and float(pageNumberX2 - pageNumberX1) / float(pageNumberCut2 - pageNumberCut1) <= 9.0\
+ and ImageStat.Stat(self.image.crop((0, heightImg - pageNumberCut3, widthImg, heightImg))).var[0]\
+ / ImageStat.Stat(self.image).var[0] < 0.1\
+ and pageNumberCut3 < heightImg / 4 - delta:
+ diff = pageNumberCut3
+ else:
+ diff = pageNumberCut1
+ self.image = self.image.crop((0, 0, widthImg, heightImg - diff))
return self.image
def cropWhiteSpace(self, threshold):
- widthImg, heightImg = self.image.size
- delta = 10
- diff = delta
- # top
- while ImageStat.Stat(self.image.crop((0, 0, widthImg, diff))).var[0] < threshold and diff < heightImg:
- diff += delta
- diff -= delta
- # print "Top crop: %s"%diff
- self.image = self.image.crop((0, diff, widthImg, heightImg))
- widthImg, heightImg = self.image.size
- diff = delta
- # left
- while ImageStat.Stat(self.image.crop((0, 0, diff, heightImg))).var[0] < threshold and diff < widthImg:
- diff += delta
- diff -= delta
- # print "Left crop: %s"%diff
- self.image = self.image.crop((diff, 0, widthImg, heightImg))
- widthImg, heightImg = self.image.size
- diff = delta
- # down
- while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] < threshold\
- and diff < heightImg:
- diff += delta
- diff -= delta
- # print "Down crop: %s"%diff
- self.image = self.image.crop((0, 0, widthImg, heightImg - diff))
- widthImg, heightImg = self.image.size
- diff = delta
- # right
- while ImageStat.Stat(self.image.crop((widthImg - diff, 0, widthImg, heightImg))).var[0] < threshold\
- and diff < widthImg:
- diff += delta
- diff -= delta
- # print "Right crop: %s"%diff
- self.image = self.image.crop((0, 0, widthImg - diff, heightImg))
- # print "New size: %sx%s"%(self.image.size[0],self.image.size[1])
+ if ImageChops.invert(self.image).getbbox() is not None:
+ widthImg, heightImg = self.image.size
+ delta = 10
+ diff = delta
+ # top
+ while ImageStat.Stat(self.image.crop((0, 0, widthImg, diff))).var[0] < threshold and diff < heightImg:
+ diff += delta
+ diff -= delta
+ # print "Top crop: %s"%diff
+ self.image = self.image.crop((0, diff, widthImg, heightImg))
+ widthImg, heightImg = self.image.size
+ diff = delta
+ # left
+ while ImageStat.Stat(self.image.crop((0, 0, diff, heightImg))).var[0] < threshold and diff < widthImg:
+ diff += delta
+ diff -= delta
+ # print "Left crop: %s"%diff
+ self.image = self.image.crop((diff, 0, widthImg, heightImg))
+ widthImg, heightImg = self.image.size
+ diff = delta
+ # down
+ while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] < threshold\
+ and diff < heightImg:
+ diff += delta
+ diff -= delta
+ # print "Down crop: %s"%diff
+ self.image = self.image.crop((0, 0, widthImg, heightImg - diff))
+ widthImg, heightImg = self.image.size
+ diff = delta
+ # right
+ while ImageStat.Stat(self.image.crop((widthImg - diff, 0, widthImg, heightImg))).var[0] < threshold\
+ and diff < widthImg:
+ diff += delta
+ diff -= delta
+ # print "Right crop: %s"%diff
+ self.image = self.image.crop((0, 0, widthImg - diff, heightImg))
+ # print "New size: %sx%s"%(self.image.size[0],self.image.size[1])
return self.image
# def addProgressbar(self, file_number, files_totalnumber, size, howoften):