mirror of
https://github.com/ciromattia/kcc
synced 2025-12-13 01:36:27 +00:00
Merge branch 'master'
This commit is contained in:
@@ -129,7 +129,7 @@ def buildNCX(dstdir, title, chapters):
|
||||
def buildOPF(profile, dstdir, title, filelist, cover=None, righttoleft=False):
|
||||
opffile = os.path.join(dstdir, 'OEBPS', 'content.opf')
|
||||
# read the first file resolution
|
||||
profilelabel, deviceres, palette = image.ProfileData.Profiles[profile]
|
||||
profilelabel, deviceres, palette, gamma = image.ProfileData.Profiles[profile]
|
||||
imgres = str(deviceres[0]) + "x" + str(deviceres[1])
|
||||
if righttoleft:
|
||||
writingmode = "horizontal-rl"
|
||||
@@ -260,7 +260,7 @@ def applyImgOptimization(img, isSplit=False, toRight=False):
|
||||
img.cutPageNumber()
|
||||
img.resizeImage(options.upscale, options.stretch, options.black_borders, isSplit, toRight)
|
||||
if not options.notquantize:
|
||||
img.quantizeImage()
|
||||
img.quantizeImage()
|
||||
|
||||
|
||||
def dirImgProcess(path):
|
||||
@@ -430,8 +430,8 @@ def main(argv=None):
|
||||
help="Verbose output [default=False]")
|
||||
parser.add_option("--no-image-processing", action="store_false", dest="imgproc", default=True,
|
||||
help="Do not apply image preprocessing (page splitting and optimizations) [default=True]")
|
||||
parser.add_option("--gamma", type="float", dest="gamma", default=2.2,
|
||||
help="Apply gamma correction to linearize the image [default=2.2]")
|
||||
parser.add_option("--gamma", type="float", dest="gamma", default="0.0",
|
||||
help="Apply gamma correction to linearize the image [default=auto]")
|
||||
parser.add_option("--nodithering", action="store_true", dest="notquantize", default=False,
|
||||
help="Disable image quantization [default=False]")
|
||||
parser.add_option("--upscale-images", action="store_true", dest="upscale", default=False,
|
||||
|
||||
52
kcc/gui.py
52
kcc/gui.py
@@ -31,6 +31,7 @@ from subprocess import call
|
||||
import os
|
||||
import shutil
|
||||
import stat
|
||||
import traceback
|
||||
|
||||
|
||||
class MainWindow:
|
||||
@@ -89,7 +90,7 @@ class MainWindow:
|
||||
'rotate': IntVar(None, 0),
|
||||
'cut_page_numbers': IntVar(None, 1),
|
||||
'mangastyle': IntVar(None, 0),
|
||||
'image_gamma': DoubleVar(None, 2.2),
|
||||
'image_gamma': DoubleVar(None, 0.0),
|
||||
'image_upscale': IntVar(None, 0),
|
||||
'image_stretch': IntVar(None, 0),
|
||||
'black_borders': IntVar(None, 0)
|
||||
@@ -102,26 +103,38 @@ class MainWindow:
|
||||
'rotate': "Rotate landscape images instead of splitting them",
|
||||
'cut_page_numbers': "Cut page numbers",
|
||||
'mangastyle': "Manga mode",
|
||||
'image_gamma': "Gamma",
|
||||
'image_gamma': "Custom gamma\n(if 0.0 the default gamma for the profile will be used)",
|
||||
'image_upscale': "Allow image upscaling",
|
||||
'image_stretch': "Stretch images",
|
||||
'black_borders': "Use black borders"
|
||||
}
|
||||
for key in self.options:
|
||||
if isinstance( self.options[key], IntVar ) or isinstance( self.options[key], BooleanVar ):
|
||||
if isinstance(self.options[key], IntVar) or isinstance(self.options[key], BooleanVar):
|
||||
aCheckButton = Checkbutton(self.master, text=self.optionlabels[key], variable=self.options[key])
|
||||
aCheckButton.grid(columnspan=4, sticky=W + N + S)
|
||||
elif isinstance( self.options[key], DoubleVar ):
|
||||
aLabel = Label(self.master, text=self.optionlabels[key])
|
||||
aLabel.grid(column=2, sticky=W + N + S)
|
||||
elif isinstance(self.options[key], DoubleVar):
|
||||
aLabel = Label(self.master, text=self.optionlabels[key], justify=RIGHT)
|
||||
aLabel.grid(column=0, columnspan=3, sticky=W + N + S)
|
||||
aEntry = Entry(self.master, textvariable=self.options[key])
|
||||
aEntry.grid(column=3, row=(self.master.grid_size()[1]-1), sticky=W + N + S)
|
||||
aEntry.grid(column=3, row=(self.master.grid_size()[1] - 1), sticky=W + N + S)
|
||||
|
||||
self.submit = Button(self.master, text="CONVERT", command=self.start_conversion, fg="red")
|
||||
self.submit.grid(columnspan=4, sticky=W + E + N + S)
|
||||
aLabel = Label(self.master, text="file progress", justify=RIGHT)
|
||||
aLabel.grid(column=0, sticky=E)
|
||||
self.progress_file = ttk.Progressbar(orient=HORIZONTAL, length=200, mode='determinate', maximum=4)
|
||||
self.progress_file.grid(column=1, columnspan=3, row=(self.master.grid_size()[1] - 1), sticky=W + E + N + S)
|
||||
aLabel = Label(self.master, text="overall progress", justify=RIGHT)
|
||||
aLabel.grid(column=0, sticky=E)
|
||||
self.progress_overall = ttk.Progressbar(orient=HORIZONTAL, length=200, mode='determinate')
|
||||
self.progress_overall.grid(column=1, columnspan=3, row=(self.master.grid_size()[1] - 1), sticky=W + E + N + S)
|
||||
|
||||
def start_conversion(self):
|
||||
self.submit['state'] = DISABLED
|
||||
self.master.update()
|
||||
self.convert()
|
||||
self.submit['state'] = NORMAL
|
||||
self.master.update()
|
||||
|
||||
def convert(self):
|
||||
if len(self.filelist) < 1:
|
||||
@@ -129,8 +142,9 @@ class MainWindow:
|
||||
return
|
||||
profilekey = ProfileData.ProfileLabels[self.profile.get()]
|
||||
argv = ["-p", profilekey]
|
||||
argv.append("--gamma")
|
||||
argv.append(self.options['image_gamma'].get())
|
||||
if self.options['image_gamma'].get() != 0.0:
|
||||
argv.append("--gamma")
|
||||
argv.append(self.options['image_gamma'].get())
|
||||
if self.options['image_preprocess'].get() == 0:
|
||||
argv.append("--no-image-processing")
|
||||
if self.options['notquantize'].get() == 1:
|
||||
@@ -150,14 +164,24 @@ class MainWindow:
|
||||
if self.options['black_borders'].get() == 1:
|
||||
argv.append("--black-borders")
|
||||
errors = False
|
||||
left_files = len(self.filelist)
|
||||
filenum = 0
|
||||
self.progress_overall['value'] = 0
|
||||
self.progress_overall['maximum'] = left_files
|
||||
for entry in self.filelist:
|
||||
filenum += 1
|
||||
self.progress_file['value'] = 1
|
||||
self.master.update()
|
||||
subargv = list(argv)
|
||||
try:
|
||||
subargv.append(entry)
|
||||
epub_path = comic2ebook.main(subargv)
|
||||
except Exception, err:
|
||||
tkMessageBox.showerror('KCC Error', "Error on file %s:\n%s" % (subargv[-1], str(err)))
|
||||
self.progress_file['value'] = 2
|
||||
self.master.update()
|
||||
except Exception as err:
|
||||
type_, value_, traceback_ = sys.exc_info()
|
||||
tkMessageBox.showerror('KCC Error', "Error on file %s:\n%s\nTraceback:\n%s" %
|
||||
(subargv[-1], str(err), traceback.format_tb(traceback_)))
|
||||
errors = True
|
||||
continue
|
||||
if self.options['epub_only'] == 1:
|
||||
@@ -168,6 +192,8 @@ class MainWindow:
|
||||
print >>sys.stderr, "Child was terminated by signal", -retcode
|
||||
else:
|
||||
print >>sys.stderr, "Child returned", retcode
|
||||
self.progress_file['value'] = 3
|
||||
self.master.update()
|
||||
except OSError as e:
|
||||
tkMessageBox.showerror('KindleGen Error', "Error on file %s:\n%s" % (epub_path, e))
|
||||
errors = True
|
||||
@@ -177,10 +203,14 @@ class MainWindow:
|
||||
shutil.move(mobifile, mobifile + '_tostrip')
|
||||
kindlestrip.main((mobifile + '_tostrip', mobifile))
|
||||
os.remove(mobifile + '_tostrip')
|
||||
self.progress_file['value'] = 4
|
||||
self.master.update()
|
||||
except Exception, err:
|
||||
tkMessageBox.showerror('Error', "Error on file %s:\n%s" % (mobifile, str(err)))
|
||||
errors = True
|
||||
continue
|
||||
self.progress_overall['value'] = filenum
|
||||
self.master.update()
|
||||
if errors:
|
||||
tkMessageBox.showinfo(
|
||||
"Done",
|
||||
|
||||
26
kcc/image.py
26
kcc/image.py
@@ -77,13 +77,13 @@ class ProfileData:
|
||||
]
|
||||
|
||||
Profiles = {
|
||||
'K1': ("Kindle", (600, 800), Palette4),
|
||||
'K2': ("Kindle 2", (600, 800), Palette15),
|
||||
'K3': ("Kindle 3/Keyboard", (600, 800), Palette16),
|
||||
'K4': ("Kindle 4/NT/Touch", (600, 800), Palette16),
|
||||
'KHD': ("Kindle Paperwhite", (758, 1024), Palette16),
|
||||
'KDX': ("Kindle DX", (824, 1200), Palette15),
|
||||
'KDXG': ("Kindle DXG", (824, 1200), Palette16)
|
||||
'K1': ("Kindle", (600, 800), Palette4, 1.8),
|
||||
'K2': ("Kindle 2", (600, 800), Palette15, 1.8),
|
||||
'K3': ("Kindle 3/Keyboard", (600, 800), Palette16, 1.8),
|
||||
'K4': ("Kindle 4/NT/Touch", (600, 800), Palette16, 1.8),
|
||||
'KHD': ("Kindle Paperwhite", (758, 1024), Palette16, 1.8),
|
||||
'KDX': ("Kindle DX", (824, 1200), Palette15, 1.8),
|
||||
'KDXG': ("Kindle DXG", (824, 1200), Palette16, 1.8)
|
||||
}
|
||||
|
||||
ProfileLabels = {
|
||||
@@ -101,7 +101,7 @@ class ComicPage:
|
||||
def __init__(self, source, device):
|
||||
try:
|
||||
self.profile = device
|
||||
self.profile_label, self.size, self.palette = ProfileData.Profiles[device]
|
||||
self.profile_label, self.size, self.palette, self.gamma = ProfileData.Profiles[device]
|
||||
except KeyError:
|
||||
raise RuntimeError('Unexpected output device %s' % device)
|
||||
try:
|
||||
@@ -115,7 +115,7 @@ class ComicPage:
|
||||
filename = os.path.basename(self.origFileName)
|
||||
try:
|
||||
self.image = self.image.convert('L') # convert to grayscale
|
||||
os.remove(os.path.join(targetdir,filename))
|
||||
os.remove(os.path.join(targetdir, filename))
|
||||
if notquantize:
|
||||
self.image.save(os.path.join(targetdir, os.path.splitext(filename)[0] + ".jpg"), "JPEG")
|
||||
else:
|
||||
@@ -124,8 +124,12 @@ class ComicPage:
|
||||
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
|
||||
|
||||
def optimizeImage(self, gamma):
|
||||
self.image = ImageOps.autocontrast(Image.eval(self.image, lambda a: 255*(a/255.)**gamma))
|
||||
|
||||
if gamma < 0.1:
|
||||
gamma = self.gamma
|
||||
if gamma == 1.0:
|
||||
self.image = ImageOps.autocontrast(self.image)
|
||||
else:
|
||||
self.image = ImageOps.autocontrast(Image.eval(self.image, lambda a: 255 * (a / 255.) ** gamma))
|
||||
|
||||
def quantizeImage(self):
|
||||
colors = len(self.palette) / 3
|
||||
|
||||
@@ -70,3 +70,4 @@ class PdfJpgExtract:
|
||||
|
||||
njpg += 1
|
||||
i = iend
|
||||
return self.path
|
||||
|
||||
Reference in New Issue
Block a user