diff --git a/kcc/KCC_gui.py b/kcc/KCC_gui.py
index 0f53788..fe5954c 100644
--- a/kcc/KCC_gui.py
+++ b/kcc/KCC_gui.py
@@ -1335,14 +1335,10 @@ class KCCGUI_MetaEditor(KCC_MetaEditor_ui.Ui_MetaEditorDialog):
self.EditorFrame.setEnabled(True)
self.OKButton.setEnabled(True)
self.StatusLabel.setText('Separate authors with a comma.')
- self.SeriesLine.setText(self.parser.data['Series'])
- self.VolumeLine.setText(self.parser.data['Volume'])
- self.NumberLine.setText(self.parser.data['Number'])
- self.WriterLine.setText(', '.join(self.parser.data['Writers']))
- self.PencillerLine.setText(', '.join(self.parser.data['Pencillers']))
- self.InkerLine.setText(', '.join(self.parser.data['Inkers']))
- self.ColoristLine.setText(', '.join(self.parser.data['Colorists']))
- self.MUidLine.setText(self.parser.data['MUid'])
+ for field in (self.SeriesLine, self.VolumeLine, self.NumberLine, self.MUidLine):
+ field.setText(self.parser.data[field.objectName()[:-4]])
+ for field in (self.WriterLine, self.PencillerLine, self.InkerLine, self.ColoristLine):
+ field.setText(', '.join(self.parser.data[field.objectName()[:-4] + 's']))
def saveData(self):
for field in (self.VolumeLine, self.NumberLine, self.MUidLine):
diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py
index eadaf4f..e72d911 100755
--- a/kcc/comic2ebook.py
+++ b/kcc/comic2ebook.py
@@ -75,6 +75,7 @@ def main(argv=None):
def buildHTML(path, imgfile, imgfilepath, forcePV=False):
imgfilepath = md5Checksum(imgfilepath)
filename = getImageFileName(imgfile)
+ additionalStyle = ''
if options.imgproc:
if "Rotated" in options.imgIndex[imgfilepath]:
rotatedPage = True
@@ -92,6 +93,8 @@ def buildHTML(path, imgfile, imgfilepath, forcePV=False):
noVerticalPV = True
else:
noVerticalPV = False
+ if "BlackFill" in options.imgIndex[imgfilepath]:
+ additionalStyle = ' style="background-color:#000000" '
else:
rotatedPage = False
noPV = False
@@ -125,7 +128,7 @@ def buildHTML(path, imgfile, imgfilepath, forcePV=False):
"\n",
"\n",
- "
\n",
+ "\n",
"\n",
"
\n"
@@ -169,7 +172,7 @@ def buildHTML(path, imgfile, imgfilepath, forcePV=False):
f.writelines(["
\n"])
- if options.quality == 2:
+ if options.quality == 2 and not forcePV:
imgfilepv = imgfile.split(".")
imgfilepv[0] += "-hq"
imgfilepv = ".".join(imgfilepv)
@@ -433,6 +436,7 @@ def buildEPUB(path, chapterNames, tomeNumber):
cover = os.path.join(os.path.join(path, 'OEBPS', 'Images'),
'cover' + getImageFileName(filelist[-1][1])[1])
image.Cover(os.path.join(filelist[-1][0], filelist[-1][1]), cover, options, tomeNumber)
+ # Hack that force Panel View on at last one page
if lastfile and not options.panelviewused and 'Ko' not in options.profile \
and options.profile not in ['K1', 'K2', 'KDX', 'OTHER']:
filelist[-1] = buildHTML(lastfile[0], lastfile[1], lastfile[2], True)
@@ -444,24 +448,17 @@ def buildEPUB(path, chapterNames, tomeNumber):
buildOPF(path, options.title, filelist, cover)
-def imgOptimization(img, opt, hqImage=None):
+def imgOptimization(img, opt):
if not img.fill:
img.getImageFill()
if not opt.webtoon:
img.cropWhiteSpace()
if opt.cutpagenumbers and not opt.webtoon:
img.cutPageNumber()
- img.optimizeImage()
- if hqImage:
- img.resizeImage(0)
- img.calculateBorder(hqImage, True)
- else:
- img.resizeImage()
- if opt.panelview:
- if opt.quality == 0:
- img.calculateBorder(img)
- elif opt.quality == 1:
- img.calculateBorder(img, True)
+ img.autocontrastImage()
+ img.resizeImage()
+ if not img.second and opt.panelview:
+ img.calculateBorder()
if opt.forcepng and not opt.forcecolor:
img.quantizeImage()
@@ -523,10 +520,6 @@ def imgFileProcessing(work):
opt = work[2]
output = []
img = image.ComicPage(os.path.join(dirpath, afile), opt)
- if opt.quality == 2:
- wipe = False
- else:
- wipe = True
if opt.nosplitrotate:
splitter = None
else:
@@ -534,36 +527,30 @@ def imgFileProcessing(work):
if splitter is not None:
img0 = image.ComicPage(splitter[0], opt)
imgOptimization(img0, opt)
- output.append(img0.saveToDir(dirpath))
+ if not img0.noHQ:
+ output.append(img0.saveToDir(dirpath))
img1 = image.ComicPage(splitter[1], opt)
imgOptimization(img1, opt)
- output.append(img1.saveToDir(dirpath))
- if wipe:
- output.append(img0.origFileName)
- output.append(img1.origFileName)
+ if not img1.noHQ:
+ output.append(img1.saveToDir(dirpath))
+ output.extend([img.origFileName, img0.origFileName, img1.origFileName])
if opt.quality == 2:
- img0b = image.ComicPage(splitter[0], opt, img0.fill)
- imgOptimization(img0b, opt, img0)
+ output.extend([img0.origFileName, img1.origFileName])
+ img0b = image.ComicPage(splitter[0], opt, img0)
+ imgOptimization(img0b, opt)
output.append(img0b.saveToDir(dirpath))
- img1b = image.ComicPage(splitter[1], opt, img1.fill)
- imgOptimization(img1b, opt, img1)
+ img1b = image.ComicPage(splitter[1], opt, img1)
+ imgOptimization(img1b, opt)
output.append(img1b.saveToDir(dirpath))
- output.append(img0.origFileName)
- output.append(img1.origFileName)
- output.append(img.origFileName)
else:
+ output.append(img.origFileName)
imgOptimization(img, opt)
- output.append(img.saveToDir(dirpath))
- if wipe:
- output.append(img.origFileName)
+ if not img.noHQ:
+ output.append(img.saveToDir(dirpath))
if opt.quality == 2:
- img2 = image.ComicPage(os.path.join(dirpath, afile), opt, img.fill)
- if img.rotated:
- img2.image = img2.image.rotate(90, Image.BICUBIC, True)
- img2.rotated = True
- imgOptimization(img2, opt, img)
+ img2 = image.ComicPage(os.path.join(dirpath, afile), opt, img)
+ imgOptimization(img2, opt)
output.append(img2.saveToDir(dirpath))
- output.append(img.origFileName)
return output
except Exception:
return str(sys.exc_info()[1])
@@ -575,7 +562,7 @@ def getWorkFolder(afile):
if os.path.isdir(afile):
workdir = mkdtemp('', 'KCC-TMP-')
try:
- os.rmdir(workdir) # needed for copytree() fails if dst already exists
+ os.rmdir(workdir)
fullPath = os.path.join(workdir, 'OEBPS', 'Images')
if len(fullPath) > 240:
raise UserWarning("Path is too long.")
@@ -906,20 +893,20 @@ def detectMargins(path):
yu = flag[2]
xr = flag[3]
yd = flag[4]
- if xl != "0":
- xl = "-" + str(float(xl)/100) + "%"
+ if xl != "0.0":
+ xl = "-" + xl + "%"
else:
xl = "0%"
- if xr != "0":
- xr = "-" + str(float(xr)/100) + "%"
+ if xr != "0.0":
+ xr = "-" + xr + "%"
else:
xr = "0%"
- if yu != "0":
- yu = "-" + str(float(yu)/100) + "%"
+ if yu != "0.0":
+ yu = "-" + yu + "%"
else:
yu = "0%"
- if yd != "0":
- yd = "-" + str(float(yd)/100) + "%"
+ if yd != "0.0":
+ yd = "-" + yd + "%"
else:
yd = "0%"
return xl, yu, xr, yd
@@ -1123,10 +1110,7 @@ def makeBook(source, qtGUI=None):
getComicInfo(os.path.join(path, "OEBPS", "Images"), source)
detectCorruption(os.path.join(path, "OEBPS", "Images"), source)
if options.webtoon:
- if options.customheight > 0:
- comic2panel.main(['-y ' + str(options.customheight), '-i', '-m', path], qtGUI)
- else:
- comic2panel.main(['-y ' + str(image.ProfileData.Profiles[options.profile][1][1]), '-i', '-m', path], qtGUI)
+ comic2panel.main(['-y ' + str(image.ProfileData.Profiles[options.profile][1][1]), '-i', '-m', path], qtGUI)
if options.imgproc:
print("\nProcessing images...")
if GUI:
diff --git a/kcc/image.py b/kcc/image.py
index 8ba8f09..d830e79 100755
--- a/kcc/image.py
+++ b/kcc/image.py
@@ -98,7 +98,7 @@ class ProfileData:
class ComicPage:
- def __init__(self, source, options, fill=None):
+ def __init__(self, source, options, original=None):
try:
self.profile_label, self.size, self.palette, self.gamma, self.panelviewsize = options.profileData
except KeyError:
@@ -107,58 +107,67 @@ class ComicPage:
self.filename = os.path.basename(self.origFileName)
self.image = Image.open(source)
self.image = self.image.convert('RGB')
- self.rotated = None
- self.border = None
- self.noHPV = None
- self.noVPV = None
- self.noPV = None
- self.purge = False
- self.hq = False
self.opt = options
- if fill:
- self.fill = fill
+ if original:
+ self.second = True
+ self.rotated = original.rotated
+ self.border = original.border
+ self.noHPV = original.noHPV
+ self.noVPV = original.noVPV
+ self.noPV = original.noPV
+ self.noHQ = original.noHQ
+ self.fill = original.fill
+ self.color = original.color
+ if self.rotated:
+ self.image = self.image.rotate(90, Image.BICUBIC, True)
+ self.opt.quality = 0
else:
+ self.second = False
+ self.rotated = None
+ self.border = None
+ self.noHPV = None
+ self.noVPV = None
+ self.noPV = None
self.fill = None
- if options.webtoon:
- self.color = True
- else:
- self.color = self.isImageColor()
+ self.noHQ = False
+ if options.webtoon:
+ self.color = True
+ else:
+ self.color = self.isImageColor()
def saveToDir(self, targetdir):
try:
- if not self.purge:
- flags = []
- filename = os.path.join(targetdir, os.path.splitext(self.filename)[0]) + '-KCC'
- if not self.opt.forcecolor and not self.opt.forcepng:
- self.image = self.image.convert('L')
- if self.rotated:
- flags.append('Rotated')
- if self.hq:
- flags.append('HighQuality')
- filename += '-HQ'
- if self.noPV:
- flags.append('NoPanelView')
- else:
- if self.noHPV:
- flags.append('NoHorizontalPanelView')
- if self.noVPV:
- flags.append('NoVerticalPanelView')
- if self.border:
- flags.append('Margins-' + str(self.border[0]) + '-' + str(self.border[1]) + '-'
- + str(self.border[2]) + '-' + str(self.border[3]))
- if self.opt.forcepng:
- filename += '.png'
- self.image.save(filename, 'PNG', optimize=1)
- else:
- filename += '.jpg'
- self.image.save(filename, 'JPEG', optimize=1, quality=80)
- return [md5Checksum(filename), flags]
+ flags = []
+ filename = os.path.join(targetdir, os.path.splitext(self.filename)[0]) + '-KCC'
+ if not self.opt.forcecolor and not self.opt.forcepng:
+ self.image = self.image.convert('L')
+ if self.rotated:
+ flags.append('Rotated')
+ if self.noPV:
+ flags.append('NoPanelView')
else:
- return None
+ if self.noHPV:
+ flags.append('NoHorizontalPanelView')
+ if self.noVPV:
+ flags.append('NoVerticalPanelView')
+ if self.border:
+ flags.append('Margins-' + str(self.border[0]) + '-' + str(self.border[1]) + '-'
+ + str(self.border[2]) + '-' + str(self.border[3]))
+ if self.fill != 'white':
+ flags.append('BlackFill')
+ if self.opt.quality == 2:
+ filename += '-HQ'
+ if self.opt.forcepng:
+ filename += '.png'
+ self.image.save(filename, 'PNG', optimize=1)
+ else:
+ filename += '.jpg'
+ self.image.save(filename, 'JPEG', optimize=1, quality=80)
+ return [md5Checksum(filename), flags]
except IOError as e:
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
- def optimizeImage(self):
+ def autocontrastImage(self):
gamma = self.opt.gamma
if gamma < 0.1:
gamma = self.gamma
@@ -180,80 +189,65 @@ class ComicPage:
# Quantize is deprecated but new function call it internally anyway...
self.image = self.image.quantize(palette=palImg)
- def calculateBorderPercent(self, x, img, isWidth):
- if isWidth:
- return int(round(float(x)/float(img.image.size[0]), 4) * 10000 * 1.5)
- else:
- return int(round(float(x)/float(img.image.size[1]), 4) * 10000 * 1.5)
-
- def calculateBorder(self, sourceImage, isHQ=False):
- if (isHQ and sourceImage.purge) or self.noPV:
- self.border = [0, 0, 0, 0]
- self.noPV = True
+ def calculateBorder(self):
+ if self.noPV:
+ self.border = [0.0, 0.0, 0.0, 0.0]
return
if self.fill == 'white':
- # Only already saved files can have P mode. So we can break color quantization.
- if sourceImage.image.mode == 'P':
- sourceImage.image = sourceImage.image.convert('RGB')
- border = ImageChops.invert(sourceImage.image).getbbox()
+ border = ImageChops.invert(self.image).getbbox()
else:
- border = sourceImage.image.getbbox()
+ border = self.image.getbbox()
+ if self.opt.quality == 2:
+ multiplier = 1.0
+ else:
+ multiplier = 1.5
if border is not None:
- if isHQ:
- multiplier = 1.0
- else:
- multiplier = 1.5
- self.border = [self.calculateBorderPercent(border[0], sourceImage, True),
- self.calculateBorderPercent(border[1], sourceImage, False),
- self.calculateBorderPercent((sourceImage.image.size[0] - border[2]), sourceImage, True),
- self.calculateBorderPercent((sourceImage.image.size[1] - border[3]), sourceImage, False)]
- if int((border[2] - border[0]) * multiplier) < self.size[0]:
+ self.border = [round(float(border[0])/float(self.image.size[0])*150, 3),
+ round(float(border[1])/float(self.image.size[1])*150, 3),
+ round(float(self.image.size[0]-border[2])/float(self.image.size[0])*150, 3),
+ round(float(self.image.size[1]-border[3])/float(self.image.size[1])*150, 3)]
+ if int((border[2] - border[0]) * multiplier) < self.size[0] + 10:
self.noHPV = True
- if int((border[3] - border[1]) * multiplier) < self.size[1]:
+ if int((border[3] - border[1]) * multiplier) < self.size[1] + 10:
self.noVPV = True
else:
- self.border = [0, 0, 0, 0]
+ self.border = [0.0, 0.0, 0.0, 0.0]
self.noHPV = True
self.noVPV = True
- def resizeImage(self, qualityMode=None):
- upscale = self.opt.upscale
- stretch = self.opt.stretch
- bordersColor = self.opt.bordersColor
- if qualityMode is None:
- qualityMode = self.opt.quality
- if bordersColor:
- fill = bordersColor
+ def resizeImage(self):
+ if self.opt.bordersColor:
+ fill = self.opt.bordersColor
else:
fill = self.fill
# Set target size
- if qualityMode == 0:
+ if self.opt.quality == 0:
size = (self.size[0], self.size[1])
- elif qualityMode == 1 and not stretch and not upscale and self.image.size[0] <=\
+ elif self.opt.quality == 1 and not self.opt.stretch and not self.opt.upscale and self.image.size[0] <=\
self.size[0] and self.image.size[1] <= self.size[1]:
size = (self.size[0], self.size[1])
- elif qualityMode == 1:
+ elif self.opt.quality == 1:
# Forcing upscale to make sure that margins will be not too big
- if not stretch:
- upscale = True
+ if not self.opt.stretch:
+ self.opt.upscale = True
size = (self.panelviewsize[0], self.panelviewsize[1])
- elif qualityMode == 2 and not stretch and not upscale and self.image.size[0] <=\
+ elif self.opt.quality == 2 and not self.opt.stretch and not self.opt.upscale and self.image.size[0] <=\
self.size[0] and self.image.size[1] <= self.size[1]:
- self.purge = True
- return self.image
+ # HQ version will not be needed
+ self.noHQ = True
+ return
else:
- self.hq = True
size = (self.panelviewsize[0], self.panelviewsize[1])
# If stretching is on - Resize without other considerations
- if stretch:
+ if self.opt.stretch:
if self.image.size[0] <= size[0] and self.image.size[1] <= size[1]:
method = Image.BICUBIC
else:
method = Image.LANCZOS
self.image = self.image.resize(size, method)
- return self.image
+ return
# If image is smaller than target resolution and upscale is off - Just expand it by adding margins
- if self.image.size[0] <= size[0] and self.image.size[1] <= size[1] and not upscale:
+ if self.image.size[0] <= size[0] and self.image.size[1] <= size[1] and not self.opt.upscale:
borderw = int((size[0] - self.image.size[0]) / 2)
borderh = int((size[1] - self.image.size[1]) / 2)
# PV is disabled when source image is smaller than device screen and upscale is off
@@ -263,7 +257,7 @@ class ComicPage:
# Border can't be float so sometimes image might be 1px too small/large
if self.image.size[0] != size[0] or self.image.size[1] != size[1]:
self.image = ImageOps.fit(self.image, size, method=Image.BICUBIC, centering=(0.5, 0.5))
- return self.image
+ return
# Otherwise - Upscale/Downscale
ratioDev = float(size[0]) / float(size[1])
if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev:
@@ -277,7 +271,7 @@ class ComicPage:
else:
method = Image.LANCZOS
self.image = ImageOps.fit(self.image, size, method=method, centering=(0.5, 0.5))
- return self.image
+ return
def splitPage(self, targetdir):
width, height = self.image.size
@@ -370,7 +364,6 @@ class ComicPage:
else:
diff = pageNumberCut1
self.image = self.image.crop((0, 0, widthImg, heightImg - diff))
- return self.image
def cropWhiteSpace(self):
if ImageChops.invert(self.image).getbbox() is not None:
@@ -406,7 +399,6 @@ class ComicPage:
diff += delta
diff -= delta
self.image = self.image.crop((0, 0, widthImg - diff, heightImg))
- return self.image
def getImageHistogram(self, image):
histogram = image.histogram()
diff --git a/kcc/metadata.py b/kcc/metadata.py
index d17b877..8070d52 100644
--- a/kcc/metadata.py
+++ b/kcc/metadata.py
@@ -69,7 +69,7 @@ class MetadataParser:
stdout=PIPE, stderr=STDOUT, shell=True)
extracted = False
for line in output.stdout:
- if b"Everything is Ok" in line:
+ if b"Everything is Ok" in line or b"No files to process" in line:
extracted = True
if not extracted:
rmtree(workdir)
diff --git a/kcc/shared.py b/kcc/shared.py
index 4558fa1..f31bb25 100644
--- a/kcc/shared.py
+++ b/kcc/shared.py
@@ -20,11 +20,14 @@ import os
from hashlib import md5
from html.parser import HTMLParser
from distutils.version import StrictVersion
-from scandir import walk
from time import sleep
from shutil import rmtree, move
from tempfile import mkdtemp
from zipfile import ZipFile, ZIP_DEFLATED
+try:
+ from scandir import walk
+except ImportError:
+ walk = None
class HTMLStripper(HTMLParser):