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