mirror of
https://github.com/ciromattia/kcc
synced 2025-12-13 17:56:30 +00:00
@@ -127,7 +127,7 @@ def buildNCX(dstdir, title, chapters):
|
|||||||
def buildOPF(profile, dstdir, title, filelist, cover=None, righttoleft=False):
|
def buildOPF(profile, dstdir, title, filelist, cover=None, righttoleft=False):
|
||||||
opffile = os.path.join(dstdir, 'OEBPS', 'content.opf')
|
opffile = os.path.join(dstdir, 'OEBPS', 'content.opf')
|
||||||
# read the first file resolution
|
# 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])
|
imgres = str(deviceres[0]) + "x" + str(deviceres[1])
|
||||||
if righttoleft:
|
if righttoleft:
|
||||||
writingmode = "horizontal-rl"
|
writingmode = "horizontal-rl"
|
||||||
@@ -252,11 +252,12 @@ def isInFilelist(filename, filelist):
|
|||||||
|
|
||||||
|
|
||||||
def applyImgOptimization(img, isSplit=False, toRight=False):
|
def applyImgOptimization(img, isSplit=False, toRight=False):
|
||||||
img.optimizeImage()
|
img.optimizeImage(options.gamma)
|
||||||
img.cropWhiteSpace(10.0)
|
img.cropWhiteSpace(10.0)
|
||||||
if options.cutpagenumbers:
|
if options.cutpagenumbers:
|
||||||
img.cutPageNumber()
|
img.cutPageNumber()
|
||||||
img.resizeImage(options.upscale, options.stretch, options.black_borders, isSplit, toRight)
|
img.resizeImage(options.upscale, options.stretch, options.black_borders, isSplit, toRight)
|
||||||
|
if not options.notquantize:
|
||||||
img.quantizeImage()
|
img.quantizeImage()
|
||||||
|
|
||||||
|
|
||||||
@@ -277,6 +278,9 @@ def dirImgProcess(path):
|
|||||||
else:
|
else:
|
||||||
print ".",
|
print ".",
|
||||||
img = image.ComicPage(os.path.join(dirpath, afile), options.profile)
|
img = image.ComicPage(os.path.join(dirpath, afile), options.profile)
|
||||||
|
if options.nosplitrotate:
|
||||||
|
split = None
|
||||||
|
else:
|
||||||
split = img.splitPage(dirpath, options.righttoleft, options.rotate)
|
split = img.splitPage(dirpath, options.righttoleft, options.rotate)
|
||||||
if split is not None:
|
if split is not None:
|
||||||
if options.verbose:
|
if options.verbose:
|
||||||
@@ -297,17 +301,17 @@ def dirImgProcess(path):
|
|||||||
facing = "left"
|
facing = "left"
|
||||||
img0 = image.ComicPage(split[0], options.profile)
|
img0 = image.ComicPage(split[0], options.profile)
|
||||||
applyImgOptimization(img0, True, toRight1)
|
applyImgOptimization(img0, True, toRight1)
|
||||||
img0.saveToDir(dirpath)
|
img0.saveToDir(dirpath, options.notquantize)
|
||||||
img1 = image.ComicPage(split[1], options.profile)
|
img1 = image.ComicPage(split[1], options.profile)
|
||||||
applyImgOptimization(img1, True, toRight2)
|
applyImgOptimization(img1, True, toRight2)
|
||||||
img1.saveToDir(dirpath)
|
img1.saveToDir(dirpath, options.notquantize)
|
||||||
else:
|
else:
|
||||||
if facing == "right":
|
if facing == "right":
|
||||||
facing = "left"
|
facing = "left"
|
||||||
else:
|
else:
|
||||||
facing = "right"
|
facing = "right"
|
||||||
applyImgOptimization(img)
|
applyImgOptimization(img)
|
||||||
img.saveToDir(dirpath)
|
img.saveToDir(dirpath, options.notquantize)
|
||||||
|
|
||||||
|
|
||||||
def genEpubStruct(path):
|
def genEpubStruct(path):
|
||||||
@@ -396,6 +400,10 @@ def main(argv=None):
|
|||||||
help="Verbose output [default=False]")
|
help="Verbose output [default=False]")
|
||||||
parser.add_option("--no-image-processing", action="store_false", dest="imgproc", default=True,
|
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]")
|
help="Do not apply image preprocessing (page splitting and optimizations) [default=True]")
|
||||||
|
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,
|
parser.add_option("--upscale-images", action="store_true", dest="upscale", default=False,
|
||||||
help="Resize images smaller than device's resolution [default=False]")
|
help="Resize images smaller than device's resolution [default=False]")
|
||||||
parser.add_option("--stretch-images", action="store_true", dest="stretch", default=False,
|
parser.add_option("--stretch-images", action="store_true", dest="stretch", default=False,
|
||||||
@@ -405,6 +413,8 @@ def main(argv=None):
|
|||||||
+ "is not like the device's one [default=False]")
|
+ "is not like the device's one [default=False]")
|
||||||
parser.add_option("--no-cut-page-numbers", action="store_false", dest="cutpagenumbers", default=True,
|
parser.add_option("--no-cut-page-numbers", action="store_false", dest="cutpagenumbers", default=True,
|
||||||
help="Do not try to cut page numbering on images [default=True]")
|
help="Do not try to cut page numbering on images [default=True]")
|
||||||
|
parser.add_option("--nosplitrotate", action="store_true", dest="nosplitrotate", default=False,
|
||||||
|
help="Disable splitting and rotation [default=False]")
|
||||||
parser.add_option("--rotate", action="store_true", dest="rotate", default=False,
|
parser.add_option("--rotate", action="store_true", dest="rotate", default=False,
|
||||||
help="Rotate landscape pages instead of splitting them [default=False]")
|
help="Rotate landscape pages instead of splitting them [default=False]")
|
||||||
parser.add_option("-o", "--output", action="store", dest="output", default=None,
|
parser.add_option("-o", "--output", action="store", dest="output", default=None,
|
||||||
|
|||||||
88
kcc/gui.py
88
kcc/gui.py
@@ -41,24 +41,19 @@ class MainWindow:
|
|||||||
self.refresh_list()
|
self.refresh_list()
|
||||||
|
|
||||||
def open_files(self):
|
def open_files(self):
|
||||||
filetypes = [('all files', '.*'), ('Comic files', ('*.cbr', '*.cbz', '*.zip', '*.rar', '*.pdf'))]
|
filetypes = [('All files', '.*'), ('Comic files', ('*.cbr', '*.cbz', '*.zip', '*.rar', '*.pdf'))]
|
||||||
f = tkFileDialog.askopenfilenames(title="Choose a file...", filetypes=filetypes)
|
f = tkFileDialog.askopenfilenames(title="Choose files", filetypes=filetypes)
|
||||||
if not isinstance(f, tuple):
|
if not isinstance(f, tuple):
|
||||||
try:
|
try:
|
||||||
import re
|
import re
|
||||||
f = re.findall('\{(.*?)\}', f)
|
f = re.findall('\{(.*?)\}', f)
|
||||||
except:
|
except:
|
||||||
import tkMessageBox
|
|
||||||
tkMessageBox.showerror(
|
|
||||||
"Open file",
|
|
||||||
"askopenfilename() returned other than a tuple and no regex module could be found"
|
|
||||||
)
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
self.filelist.extend(f)
|
self.filelist.extend(f)
|
||||||
self.refresh_list()
|
self.refresh_list()
|
||||||
|
|
||||||
def open_folder(self):
|
def open_folder(self):
|
||||||
f = tkFileDialog.askdirectory(title="Choose a folder...")
|
f = tkFileDialog.askdirectory(title="Choose folder:")
|
||||||
self.filelist.extend([f])
|
self.filelist.extend([f])
|
||||||
self.refresh_list()
|
self.refresh_list()
|
||||||
|
|
||||||
@@ -76,63 +71,86 @@ class MainWindow:
|
|||||||
|
|
||||||
self.clear_file = Button(self.master, text="Clear files", command=self.clear_files)
|
self.clear_file = Button(self.master, text="Clear files", command=self.clear_files)
|
||||||
self.clear_file.grid(row=4, column=0, rowspan=3)
|
self.clear_file.grid(row=4, column=0, rowspan=3)
|
||||||
self.open_file = Button(self.master, text="Add files...", command=self.open_files)
|
self.open_file = Button(self.master, text="Add files", command=self.open_files)
|
||||||
self.open_file.grid(row=4, column=1, rowspan=3)
|
self.open_file.grid(row=4, column=1, rowspan=3)
|
||||||
self.open_folder = Button(self.master, text="Add folder...", command=self.open_folder)
|
self.open_folder = Button(self.master, text="Add folder", command=self.open_folder)
|
||||||
self.open_folder.grid(row=4, column=2, rowspan=3)
|
self.open_folder.grid(row=4, column=2, rowspan=3)
|
||||||
|
|
||||||
self.profile = StringVar()
|
self.profile = StringVar()
|
||||||
profiles = sorted(ProfileData.ProfileLabels.iterkeys())
|
profiles = sorted(ProfileData.ProfileLabels.iterkeys())
|
||||||
self.profile.set(profiles[-1])
|
self.profile.set(profiles[-1])
|
||||||
w = apply(OptionMenu, (self.master, self.profile) + tuple(profiles))
|
w = apply(OptionMenu, (self.master, self.profile) + tuple(profiles))
|
||||||
w.grid(row=1, column=3)
|
w.grid(row=4, column=3, sticky=W + E + N + S)
|
||||||
|
|
||||||
self.options = {
|
self.options = {
|
||||||
'epub_only': IntVar(None, 0),
|
'epub_only': IntVar(None, 0),
|
||||||
'image_preprocess': IntVar(None, 1),
|
'image_preprocess': IntVar(None, 1),
|
||||||
|
'notquantize': IntVar(None, 0),
|
||||||
|
'nosplitrotate': IntVar(None, 0),
|
||||||
'rotate': IntVar(None, 0),
|
'rotate': IntVar(None, 0),
|
||||||
'cut_page_numbers': IntVar(None, 1),
|
'cut_page_numbers': IntVar(None, 1),
|
||||||
'mangastyle': IntVar(None, 0),
|
'mangastyle': IntVar(None, 0),
|
||||||
|
'image_gamma': DoubleVar(None, 0.0),
|
||||||
'image_upscale': IntVar(None, 0),
|
'image_upscale': IntVar(None, 0),
|
||||||
'image_stretch': IntVar(None, 0),
|
'image_stretch': IntVar(None, 0),
|
||||||
'black_borders': IntVar(None, 0)
|
'black_borders': IntVar(None, 0)
|
||||||
}
|
}
|
||||||
self.optionlabels = {
|
self.optionlabels = {
|
||||||
'epub_only': "Generate ePub only (does not call 'kindlegen')",
|
'epub_only': "Generate EPUB only",
|
||||||
'image_preprocess': "Apply image optimizations",
|
'image_preprocess': "Apply image optimizations",
|
||||||
|
'notquantize': "Disable image quantization",
|
||||||
|
'nosplitrotate': "Disable splitting and rotation",
|
||||||
'rotate': "Rotate landscape images instead of splitting them",
|
'rotate': "Rotate landscape images instead of splitting them",
|
||||||
'cut_page_numbers': "Cut page numbers",
|
'cut_page_numbers': "Cut page numbers",
|
||||||
'mangastyle': "Manga-style (right-to-left reading, applies to reading and splitting)",
|
'mangastyle': "Manga mode",
|
||||||
|
'image_gamma': "Custom gamma\n(if 0.0 the default gamma for the profile will be used)",
|
||||||
'image_upscale': "Allow image upscaling",
|
'image_upscale': "Allow image upscaling",
|
||||||
'image_stretch': "Stretch images",
|
'image_stretch': "Stretch images",
|
||||||
'black_borders': "Use black borders"
|
'black_borders': "Use black borders"
|
||||||
}
|
}
|
||||||
for key in self.options:
|
for key in self.options:
|
||||||
|
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 = Checkbutton(self.master, text=self.optionlabels[key], variable=self.options[key])
|
||||||
aCheckButton.grid(column=3, sticky='w')
|
aCheckButton.grid(columnspan=4, sticky=W + N + S)
|
||||||
self.progressbar = ttk.Progressbar(orient=HORIZONTAL, length=200, mode='determinate')
|
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)
|
||||||
|
|
||||||
self.submit = Button(self.master, text="Execute!", command=self.start_conversion, fg="red")
|
self.submit = Button(self.master, text="CONVERT", command=self.start_conversion, fg="red")
|
||||||
self.submit.grid(column=3)
|
self.submit.grid(columnspan=4, sticky=W + E + N + S)
|
||||||
self.progressbar.grid(column=0, columnspan=4, sticky=W + E + N + S)
|
aLabel = Label(self.master, text="file progress", justify=RIGHT)
|
||||||
|
aLabel.grid(column=0, sticky=E)
|
||||||
self.notelabel = Label(self.master,
|
self.progress_file = ttk.Progressbar(orient=HORIZONTAL, length=200, mode='determinate', maximum=4)
|
||||||
text="GUI can seem frozen while converting, kindly wait until some message appears!")
|
self.progress_file.grid(column=1, columnspan=3, row=(self.master.grid_size()[1] - 1), sticky=W + E + N + S)
|
||||||
self.notelabel.grid(column=0, columnspan=4, 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):
|
def start_conversion(self):
|
||||||
self.progressbar.start()
|
self.submit['state'] = DISABLED
|
||||||
|
self.master.update()
|
||||||
self.convert()
|
self.convert()
|
||||||
self.progressbar.stop()
|
self.submit['state'] = NORMAL
|
||||||
|
self.master.update()
|
||||||
|
|
||||||
def convert(self):
|
def convert(self):
|
||||||
if len(self.filelist) < 1:
|
if len(self.filelist) < 1:
|
||||||
tkMessageBox.showwarning('No file selected', "You should really select some files to convert...")
|
tkMessageBox.showwarning('No files selected!', "Please choose files to convert.")
|
||||||
return
|
return
|
||||||
profilekey = ProfileData.ProfileLabels[self.profile.get()]
|
profilekey = ProfileData.ProfileLabels[self.profile.get()]
|
||||||
argv = ["-p", profilekey]
|
argv = ["-p", profilekey]
|
||||||
|
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:
|
if self.options['image_preprocess'].get() == 0:
|
||||||
argv.append("--no-image-processing")
|
argv.append("--no-image-processing")
|
||||||
|
if self.options['notquantize'].get() == 1:
|
||||||
|
argv.append("--nodithering")
|
||||||
|
if self.options['nosplitrotate'].get() == 1:
|
||||||
|
argv.append("--nosplitrotate")
|
||||||
if self.options['rotate'].get() == 1:
|
if self.options['rotate'].get() == 1:
|
||||||
argv.append("--rotate")
|
argv.append("--rotate")
|
||||||
if self.options['cut_page_numbers'].get() == 0:
|
if self.options['cut_page_numbers'].get() == 0:
|
||||||
@@ -146,12 +164,20 @@ class MainWindow:
|
|||||||
if self.options['black_borders'].get() == 1:
|
if self.options['black_borders'].get() == 1:
|
||||||
argv.append("--black-borders")
|
argv.append("--black-borders")
|
||||||
errors = False
|
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:
|
for entry in self.filelist:
|
||||||
|
filenum += 1
|
||||||
|
self.progress_file['value'] = 1
|
||||||
self.master.update()
|
self.master.update()
|
||||||
subargv = list(argv)
|
subargv = list(argv)
|
||||||
try:
|
try:
|
||||||
subargv.append(entry)
|
subargv.append(entry)
|
||||||
epub_path = comic2ebook.main(subargv)
|
epub_path = comic2ebook.main(subargv)
|
||||||
|
self.progress_file['value'] = 2
|
||||||
|
self.master.update()
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
type_, value_, traceback_ = sys.exc_info()
|
type_, value_, traceback_ = sys.exc_info()
|
||||||
tkMessageBox.showerror('KCC Error', "Error on file %s:\n%s\nTraceback:\n%s" %
|
tkMessageBox.showerror('KCC Error', "Error on file %s:\n%s\nTraceback:\n%s" %
|
||||||
@@ -166,8 +192,10 @@ class MainWindow:
|
|||||||
print >>sys.stderr, "Child was terminated by signal", -retcode
|
print >>sys.stderr, "Child was terminated by signal", -retcode
|
||||||
else:
|
else:
|
||||||
print >>sys.stderr, "Child returned", retcode
|
print >>sys.stderr, "Child returned", retcode
|
||||||
|
self.progress_file['value'] = 3
|
||||||
|
self.master.update()
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
tkMessageBox.showerror('Error kindlegen', "Error on file %s:\n%s" % (epub_path, e))
|
tkMessageBox.showerror('KindleGen Error', "Error on file %s:\n%s" % (epub_path, e))
|
||||||
errors = True
|
errors = True
|
||||||
continue
|
continue
|
||||||
mobifile = epub_path.replace('.epub', '.mobi')
|
mobifile = epub_path.replace('.epub', '.mobi')
|
||||||
@@ -175,19 +203,23 @@ class MainWindow:
|
|||||||
shutil.move(mobifile, mobifile + '_tostrip')
|
shutil.move(mobifile, mobifile + '_tostrip')
|
||||||
kindlestrip.main((mobifile + '_tostrip', mobifile))
|
kindlestrip.main((mobifile + '_tostrip', mobifile))
|
||||||
os.remove(mobifile + '_tostrip')
|
os.remove(mobifile + '_tostrip')
|
||||||
|
self.progress_file['value'] = 4
|
||||||
|
self.master.update()
|
||||||
except Exception, err:
|
except Exception, err:
|
||||||
tkMessageBox.showerror('Error', "Error on file %s:\n%s" % (mobifile, str(err)))
|
tkMessageBox.showerror('Error', "Error on file %s:\n%s" % (mobifile, str(err)))
|
||||||
errors = True
|
errors = True
|
||||||
continue
|
continue
|
||||||
|
self.progress_overall['value'] = filenum
|
||||||
|
self.master.update()
|
||||||
if errors:
|
if errors:
|
||||||
tkMessageBox.showinfo(
|
tkMessageBox.showinfo(
|
||||||
"Done",
|
"Done",
|
||||||
"Conversion finished (some errors have been reported)"
|
"Conversion failed. Errors have been reported."
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
tkMessageBox.showinfo(
|
tkMessageBox.showinfo(
|
||||||
"Done",
|
"Done",
|
||||||
"Conversion successfully done!"
|
"Conversion successful!"
|
||||||
)
|
)
|
||||||
|
|
||||||
def remove_readonly(self, fn, path):
|
def remove_readonly(self, fn, path):
|
||||||
|
|||||||
31
kcc/image.py
31
kcc/image.py
@@ -77,13 +77,13 @@ class ProfileData:
|
|||||||
]
|
]
|
||||||
|
|
||||||
Profiles = {
|
Profiles = {
|
||||||
'K1': ("Kindle", (600, 800), Palette4),
|
'K1': ("Kindle", (600, 800), Palette4, 1.8),
|
||||||
'K2': ("Kindle 2", (600, 800), Palette15),
|
'K2': ("Kindle 2", (600, 800), Palette15, 1.8),
|
||||||
'K3': ("Kindle 3/Keyboard", (600, 800), Palette16),
|
'K3': ("Kindle 3/Keyboard", (600, 800), Palette16, 1.8),
|
||||||
'K4': ("Kindle 4/NT/Touch", (600, 800), Palette16),
|
'K4': ("Kindle 4/NT/Touch", (600, 800), Palette16, 1.8),
|
||||||
'KHD': ("Kindle Paperwhite", (758, 1024), Palette16),
|
'KHD': ("Kindle Paperwhite", (758, 1024), Palette16, 1.8),
|
||||||
'KDX': ("Kindle DX", (824, 1200), Palette15),
|
'KDX': ("Kindle DX", (824, 1200), Palette15, 1.8),
|
||||||
'KDXG': ("Kindle DXG", (824, 1200), Palette16)
|
'KDXG': ("Kindle DXG", (824, 1200), Palette16, 1.8)
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfileLabels = {
|
ProfileLabels = {
|
||||||
@@ -101,7 +101,7 @@ class ComicPage:
|
|||||||
def __init__(self, source, device):
|
def __init__(self, source, device):
|
||||||
try:
|
try:
|
||||||
self.profile = device
|
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:
|
except KeyError:
|
||||||
raise RuntimeError('Unexpected output device %s' % device)
|
raise RuntimeError('Unexpected output device %s' % device)
|
||||||
try:
|
try:
|
||||||
@@ -111,16 +111,25 @@ class ComicPage:
|
|||||||
raise RuntimeError('Cannot read image file %s' % source)
|
raise RuntimeError('Cannot read image file %s' % source)
|
||||||
self.image = self.image.convert('RGB')
|
self.image = self.image.convert('RGB')
|
||||||
|
|
||||||
def saveToDir(self, targetdir):
|
def saveToDir(self, targetdir, notquantize):
|
||||||
filename = os.path.basename(self.origFileName)
|
filename = os.path.basename(self.origFileName)
|
||||||
try:
|
try:
|
||||||
self.image = self.image.convert('L') # convert to grayscale
|
self.image = self.image.convert('L') # convert to grayscale
|
||||||
self.image.save(os.path.join(targetdir, filename), "JPEG")
|
os.remove(os.path.join(targetdir, filename))
|
||||||
|
if notquantize:
|
||||||
|
self.image.save(os.path.join(targetdir, os.path.splitext(filename)[0] + ".jpg"), "JPEG")
|
||||||
|
else:
|
||||||
|
self.image.save(os.path.join(targetdir, os.path.splitext(filename)[0] + ".png"), "PNG")
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
|
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
|
||||||
|
|
||||||
def optimizeImage(self):
|
def optimizeImage(self, gamma):
|
||||||
|
if gamma < 0.1:
|
||||||
|
gamma = self.gamma
|
||||||
|
if gamma == 1.0:
|
||||||
self.image = ImageOps.autocontrast(self.image)
|
self.image = ImageOps.autocontrast(self.image)
|
||||||
|
else:
|
||||||
|
self.image = ImageOps.autocontrast(Image.eval(self.image, lambda a: 255 * (a / 255.) ** gamma))
|
||||||
|
|
||||||
def quantizeImage(self):
|
def quantizeImage(self):
|
||||||
colors = len(self.palette) / 3
|
colors = len(self.palette) / 3
|
||||||
|
|||||||
4
setup.py
4
setup.py
@@ -5,7 +5,7 @@ Will automatically ensure that all build prerequisites are available
|
|||||||
via ez_setup
|
via ez_setup
|
||||||
|
|
||||||
Usage (Mac OS X):
|
Usage (Mac OS X):
|
||||||
python setup.py build
|
python setup.py py2app
|
||||||
|
|
||||||
Usage (Windows):
|
Usage (Windows):
|
||||||
python setup.py build
|
python setup.py build
|
||||||
@@ -71,7 +71,7 @@ setup(
|
|||||||
'Intended Audience :: End Users/Desktop',
|
'Intended Audience :: End Users/Desktop',
|
||||||
'Operating System :: OS Independent',
|
'Operating System :: OS Independent',
|
||||||
'Programming Language :: Python',
|
'Programming Language :: Python',
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 2.7',
|
||||||
'Topic :: Multimedia :: Graphics :: Graphics Conversion',
|
'Topic :: Multimedia :: Graphics :: Graphics Conversion',
|
||||||
'Topic :: Utilities'
|
'Topic :: Utilities'
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user