diff --git a/kcc/KCC_gui.py b/kcc/KCC_gui.py index d00f4dc..eef3ce9 100644 --- a/kcc/KCC_gui.py +++ b/kcc/KCC_gui.py @@ -205,6 +205,30 @@ class VersionThread(QtCore.QThread): 'Changelog)', 'warning') +class ProgressThread(QtCore.QThread): + def __init__(self): + QtCore.QThread.__init__(self) + self.running = False + self.content = None + self.progress = 0 + + def __del__(self): + self.wait() + + def run(self): + self.running = True + while self.running: + sleep(1) + if self.content: + self.emit(QtCore.SIGNAL("addMessage"), self.content + self.progress * '.', 'info', True) + self.progress += 1 + if self.progress == 4: + self.progress = 0 + + def stop(self): + self.running = False + + class WorkerSignals(QtCore.QObject): result = QtCore.pyqtSignal(list) @@ -296,6 +320,8 @@ class WorkerThread(QtCore.QThread): self.conversionAlive = GUIMain.conversionAlive def clean(self): + GUIMain.progress.content = '' + GUIMain.progress.stop() GUIMain.needClean = True self.emit(QtCore.SIGNAL("hideProgressBar")) self.emit(QtCore.SIGNAL("addMessage"), 'Conversion interrupted.', 'error') @@ -359,9 +385,11 @@ class WorkerThread(QtCore.QThread): self.errors = False self.emit(QtCore.SIGNAL("addMessage"), 'Source: ' + job, 'info') if str(GUI.FormatBox.currentText()) == 'CBZ': - self.emit(QtCore.SIGNAL("addMessage"), 'Creating CBZ file...', 'info') + self.emit(QtCore.SIGNAL("addMessage"), 'Creating CBZ files', 'info') + GUIMain.progress.content = 'Creating CBZ files' else: - self.emit(QtCore.SIGNAL("addMessage"), 'Creating EPUB file...', 'info') + self.emit(QtCore.SIGNAL("addMessage"), 'Creating EPUB files', 'info') + GUIMain.progress.content = 'Creating EPUB files' jobargv = list(argv) jobargv.append(job) try: @@ -372,10 +400,12 @@ class WorkerThread(QtCore.QThread): self.clean() return else: + GUIMain.progress.content = '' self.errors = True self.emit(QtCore.SIGNAL("addMessage"), str(warn), 'warning') self.emit(QtCore.SIGNAL("addMessage"), 'Failed to create output file!', 'warning') except Exception as err: + GUIMain.progress.content = '' self.errors = True type_, value_, traceback_ = sys.exc_info() self.emit(QtCore.SIGNAL("showDialog"), "Error during conversion %s:\n\n%s\n\nTraceback:\n%s" @@ -388,15 +418,17 @@ class WorkerThread(QtCore.QThread): self.clean() return if not self.errors: + GUIMain.progress.content = '' if str(GUI.FormatBox.currentText()) == 'CBZ': - self.emit(QtCore.SIGNAL("addMessage"), 'Creating CBZ file... Done!', 'info', True) + self.emit(QtCore.SIGNAL("addMessage"), 'Creating CBZ files... Done!', 'info', True) else: - self.emit(QtCore.SIGNAL("addMessage"), 'Creating EPUB file... Done!', 'info', True) + self.emit(QtCore.SIGNAL("addMessage"), 'Creating EPUB files... Done!', 'info', True) if str(GUI.FormatBox.currentText()) == 'MOBI': self.emit(QtCore.SIGNAL("progressBarTick"), 'status', 'Creating MOBI files') self.emit(QtCore.SIGNAL("progressBarTick"), len(outputPath)*2+1) self.emit(QtCore.SIGNAL("progressBarTick")) - self.emit(QtCore.SIGNAL("addMessage"), 'Creating MOBI file...', 'info') + self.emit(QtCore.SIGNAL("addMessage"), 'Creating MOBI files', 'info') + GUIMain.progress.content = 'Creating MOBI files' self.workerOutput = [] # Number of KindleGen threads depends on the size of RAM self.pool.setMaxThreadCount(self.threadNumber) @@ -420,8 +452,10 @@ class WorkerThread(QtCore.QThread): self.clean() return if self.kindlegenErrorCode[0] == 0: - self.emit(QtCore.SIGNAL("addMessage"), 'Creating MOBI file... Done!', 'info', True) - self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI file...', 'info') + GUIMain.progress.content = '' + self.emit(QtCore.SIGNAL("addMessage"), 'Creating MOBI files... Done!', 'info', True) + self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI files', 'info') + GUIMain.progress.content = 'Cleaning MOBI files' self.workerOutput = [] # Multithreading KindleUnpack in current form is a waste of resources. # Unless we higly optimise KindleUnpack or drop 32bit support this will not change. @@ -438,13 +472,15 @@ class WorkerThread(QtCore.QThread): break if not self.errors: for item in outputPath: + GUIMain.progress.content = '' mobiPath = item.replace('.epub', '.mobi') os.remove(mobiPath + '_toclean') GUIMain.completedWork[os.path.basename(mobiPath).encode('utf-8')] = \ mobiPath.encode('utf-8') - self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI file... Done!', 'info', + self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI files... Done!', 'info', True) else: + GUIMain.progress.content = '' for item in outputPath: mobiPath = item.replace('.epub', '.mobi') if os.path.exists(mobiPath): @@ -453,6 +489,7 @@ class WorkerThread(QtCore.QThread): os.remove(mobiPath + '_toclean') self.emit(QtCore.SIGNAL("addMessage"), 'KindleUnpack failed to clean MOBI file!', 'error') else: + GUIMain.progress.content = '' epubSize = (os.path.getsize(self.kindlegenErrorCode[2]))/1024/1024 for item in outputPath: if os.path.exists(item): @@ -471,6 +508,8 @@ class WorkerThread(QtCore.QThread): else: for item in outputPath: GUIMain.completedWork[os.path.basename(item).encode('utf-8')] = item.encode('utf-8') + GUIMain.progress.content = '' + GUIMain.progress.stop() self.emit(QtCore.SIGNAL("hideProgressBar")) GUIMain.needClean = True self.emit(QtCore.SIGNAL("addMessage"), 'All jobs completed.', 'info') @@ -769,6 +808,7 @@ class Ui_KCC(object): self.conversionAlive = False self.worker.sync() else: + self.progress.start() if self.needClean: self.needClean = False GUI.JobList.clear() @@ -868,6 +908,7 @@ class Ui_KCC(object): self.worker = WorkerThread() self.versionCheck = VersionThread() self.contentServer = WebServerThread() + self.progress = ProgressThread() self.conversionAlive = False self.needClean = True self.QualityBoxDisabled = False @@ -941,6 +982,7 @@ class Ui_KCC(object): KCC.connect(self.worker, QtCore.SIGNAL("hideProgressBar"), self.hideProgressBar) KCC.connect(self.versionCheck, QtCore.SIGNAL("addMessage"), self.addMessage) KCC.connect(self.contentServer, QtCore.SIGNAL("addMessage"), self.addMessage) + KCC.connect(self.progress, QtCore.SIGNAL("addMessage"), self.addMessage) KCC.closeEvent = self.saveSettings for f in formats: diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py index 2ee8155..b33156d 100755 --- a/kcc/comic2ebook.py +++ b/kcc/comic2ebook.py @@ -296,7 +296,8 @@ def getImageFileName(imgfile): def applyImgOptimization(img, opt, overrideQuality=5): - img.getImageFill(opt.webtoon) + if not img.fill: + img.getImageFill(opt.webtoon) if not opt.webtoon: img.cropWhiteSpace(10.0) if opt.cutpagenumbers and not opt.webtoon: @@ -377,17 +378,17 @@ def fileImgProcess(work): applyImgOptimization(img1, opt) img1.saveToDir(dirpath, opt.forcepng, opt.forcecolor, wipe) if opt.quality == 2: - img3 = image.ComicPage(split[0], opt.profileData) + img3 = image.ComicPage(split[0], opt.profileData, img0.fill) applyImgOptimization(img3, opt, 0) img3.saveToDir(dirpath, opt.forcepng, opt.forcecolor, True) - img4 = image.ComicPage(split[1], opt.profileData) + img4 = image.ComicPage(split[1], opt.profileData, img1.fill) applyImgOptimization(img4, opt, 0) img4.saveToDir(dirpath, opt.forcepng, opt.forcecolor, True) else: applyImgOptimization(img, opt) img.saveToDir(dirpath, opt.forcepng, opt.forcecolor, wipe) if opt.quality == 2: - img2 = image.ComicPage(os.path.join(dirpath, afile), opt.profileData) + img2 = image.ComicPage(os.path.join(dirpath, afile), opt.profileData, img.fill) if img.rotated: img2.image = img2.image.rotate(90) img2.rotated = True diff --git a/kcc/image.py b/kcc/image.py index 3a3ed21..96f8396 100755 --- a/kcc/image.py +++ b/kcc/image.py @@ -142,7 +142,7 @@ class ProfileData: class ComicPage: - def __init__(self, source, device): + def __init__(self, source, device, fill=None): try: self.profile_label, self.size, self.palette, self.gamma, self.panelviewsize = device except KeyError: @@ -172,7 +172,10 @@ class ComicPage: self.border = None self.noHPV = None self.noVPV = None - self.fill = None + if fill: + self.fill = fill + else: + self.fill = None def saveToDir(self, targetdir, forcepng, color, wipe): try: @@ -428,7 +431,7 @@ class ComicPage: self.image = self.image.crop((0, 0, widthImg - diff, heightImg)) return self.image - def getImageHistogram(self, image): + def getImageHistogram(self, image, new=True): histogram = image.histogram() RBGW = [] pixelCount = 0 @@ -437,37 +440,73 @@ class ComicPage: RBGW.append(histogram[i] + histogram[256 + i] + histogram[512 + i]) white = 0 black = 0 - for i in range(245, 256): + for i in range(251, 256): white += RBGW[i] - for i in range(11): + for i in range(5): black += RBGW[i] - if black > white and black > pixelCount*0.5: - return True + if new: + if black > 0 and white == 0: + return 1 + elif white > 0 and black == 0: + return -1 + else: + return False else: - return False + if black > white and black > pixelCount*0.5: + return True + else: + return False def getImageFill(self, isWebToon): - fill = 0 - if isWebToon or self.rotated: - fill += self.getImageHistogram(self.image.crop((0, 0, self.image.size[0], 5))) + if isWebToon: + fill = 0 + fill += self.getImageHistogram(self.image.crop((0, 0, self.image.size[0], 5)), False) fill += self.getImageHistogram(self.image.crop((0, self.image.size[1]-5, self.image.size[0], - self.image.size[1]))) - else: - fill += self.getImageHistogram(self.image.crop((0, 0, 5, self.image.size[1]))) - fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, 0, self.image.size[0], - self.image.size[1]))) - if fill == 2: - self.fill = 'black' - elif fill == 0: - self.fill = 'white' + self.image.size[1])), False) + if fill == 2: + self.fill = 'black' + elif fill == 0: + self.fill = 'white' + else: + fill = 0 + fill += self.getImageHistogram(self.image.crop((0, 0, 5, 5)), False) + fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, 0, self.image.size[0], 5)), False) + fill += self.getImageHistogram(self.image.crop((0, self.image.size[1]-5, 5, self.image.size[1])), False) + fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, self.image.size[1]-5, + self.image.size[0], self.image.size[1])), False) + if fill > 1: + self.fill = 'black' + else: + self.fill = 'white' else: fill = 0 - fill += self.getImageHistogram(self.image.crop((0, 0, 5, 5))) - fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, 0, self.image.size[0], 5))) - fill += self.getImageHistogram(self.image.crop((0, self.image.size[1]-5, 5, self.image.size[1]))) - fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, self.image.size[1]-5, - self.image.size[0], self.image.size[1]))) - if fill > 1: + # Search fom horizontal solid lines + startY = 0 + stopY = 3 + searching = True + while stopY <= self.image.size[1]: + checkSolid = self.getImageHistogram(self.image.crop((0, startY, self.image.size[0], stopY))) + if checkSolid: + fill += checkSolid + startY = stopY + 1 + stopY = startY + 3 + if stopY > self.image.size[1] and searching: + stopY = self.image.size[1] + searching = False + # Search fom vertical solid lines + startX = 0 + stopX = 3 + searching = True + while stopX <= self.image.size[0]: + checkSolid = self.getImageHistogram(self.image.crop((startX, 0, stopX, self.image.size[1]))) + if checkSolid: + fill += checkSolid + startX = stopX + 1 + stopX = startX + 3 + if stopX > self.image.size[0] and searching: + stopX = self.image.size[0] + searching = False + if fill > 0: self.fill = 'black' else: self.fill = 'white' \ No newline at end of file