mirror of
https://github.com/ciromattia/kcc
synced 2025-12-15 10:46:40 +00:00
Mainly adhere to PEP 8 code style (http://www.python.org/dev/peps/pep-0008/)
Add some commented code for working on Panel view enhancement and natural sorting.
This commit is contained in:
@@ -14,22 +14,23 @@
|
|||||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
# PERFORMANCE OF THIS SOFTWARE.
|
# PERFORMANCE OF THIS SOFTWARE.
|
||||||
#
|
#
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>'
|
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
class CBxArchive:
|
class CBxArchive:
|
||||||
def __init__(self, origFileName):
|
def __init__(self, origFileName):
|
||||||
self.cbxexts = ['.zip','.cbz','.rar','.cbr']
|
self.cbxexts = ['.zip', '.cbz', '.rar', '.cbr']
|
||||||
self.origFileName = origFileName
|
self.origFileName = origFileName
|
||||||
self.filename = os.path.splitext(origFileName)
|
self.filename = os.path.splitext(origFileName)
|
||||||
|
|
||||||
def isCbxFile(self):
|
def isCbxFile(self):
|
||||||
return self.filename[1].lower() in self.cbxexts
|
return self.filename[1].lower() in self.cbxexts
|
||||||
|
|
||||||
def extractCBZ(self,targetdir):
|
def extractCBZ(self, targetdir):
|
||||||
try:
|
try:
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -40,13 +41,13 @@ class CBxArchive:
|
|||||||
pass # skip MacOS special files
|
pass # skip MacOS special files
|
||||||
elif f.endswith('/'):
|
elif f.endswith('/'):
|
||||||
try:
|
try:
|
||||||
os.makedirs(os.path.join(targetdir,f))
|
os.makedirs(os.path.join(targetdir, f))
|
||||||
except:
|
except:
|
||||||
pass #the dir exists so we are going to extract the images only.
|
pass # the dir exists so we are going to extract the images only.
|
||||||
else:
|
else:
|
||||||
cbzFile.extract(f, targetdir)
|
cbzFile.extract(f, targetdir)
|
||||||
|
|
||||||
def extractCBR(self,targetdir):
|
def extractCBR(self, targetdir):
|
||||||
try:
|
try:
|
||||||
import rarfile
|
import rarfile
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -55,24 +56,24 @@ class CBxArchive:
|
|||||||
cbrFile = rarfile.RarFile(self.origFileName)
|
cbrFile = rarfile.RarFile(self.origFileName)
|
||||||
for f in cbrFile.namelist():
|
for f in cbrFile.namelist():
|
||||||
if f.startswith('__MACOSX') or f.endswith('.DS_Store'):
|
if f.startswith('__MACOSX') or f.endswith('.DS_Store'):
|
||||||
pass # skip MacOS special files
|
pass # skip MacOS special files
|
||||||
elif f.endswith('/'):
|
elif f.endswith('/'):
|
||||||
try:
|
try:
|
||||||
os.makedirs(os.path.join(targetdir,f))
|
os.makedirs(os.path.join(targetdir,f))
|
||||||
except:
|
except:
|
||||||
pass #the dir exists so we are going to extract the images only.
|
pass # the dir exists so we are going to extract the images only.
|
||||||
else:
|
else:
|
||||||
cbrFile.extract(f, targetdir)
|
cbrFile.extract(f, targetdir)
|
||||||
|
|
||||||
def extract(self,targetdir):
|
def extract(self, targetdir):
|
||||||
if '.cbr' == self.filename[1].lower() or '.rar' == self.filename[1].lower():
|
if '.cbr' == self.filename[1].lower() or '.rar' == self.filename[1].lower():
|
||||||
self.extractCBR(targetdir)
|
self.extractCBR(targetdir)
|
||||||
elif '.cbz' == self.filename[1].lower() or '.zip' == self.filename[1].lower():
|
elif '.cbz' == self.filename[1].lower() or '.zip' == self.filename[1].lower():
|
||||||
self.extractCBZ(targetdir)
|
self.extractCBZ(targetdir)
|
||||||
dir = os.listdir(targetdir)
|
adir = os.listdir(targetdir)
|
||||||
if len(dir) == 1 and os.path.isdir(os.path.join(targetdir,dir[0])):
|
if len(adir) == 1 and os.path.isdir(os.path.join(targetdir, adir[0])):
|
||||||
import shutil
|
import shutil
|
||||||
for f in os.listdir(os.path.join(targetdir,dir[0])):
|
for f in os.listdir(os.path.join(targetdir, adir[0])):
|
||||||
shutil.move(os.path.join(targetdir,dir[0],f),targetdir)
|
shutil.move(os.path.join(targetdir, adir[0], f), targetdir)
|
||||||
os.rmdir(os.path.join(targetdir,dir[0]))
|
os.rmdir(os.path.join(targetdir, adir[0]))
|
||||||
return targetdir
|
return targetdir
|
||||||
|
|||||||
91
kcc/gui.py
91
kcc/gui.py
@@ -16,16 +16,22 @@
|
|||||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
# PERFORMANCE OF THIS SOFTWARE.
|
# PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>'
|
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
from Tkinter import *
|
from Tkinter import *
|
||||||
import tkFileDialog, tkMessageBox, ttk
|
import tkFileDialog
|
||||||
import comic2ebook, kindlestrip
|
import tkMessageBox
|
||||||
|
import ttk
|
||||||
|
import comic2ebook
|
||||||
|
import kindlestrip
|
||||||
from image import ProfileData
|
from image import ProfileData
|
||||||
from subprocess import call, Popen, PIPE, STDOUT
|
from subprocess import call
|
||||||
import os, shutil, stat
|
import os
|
||||||
|
import shutil
|
||||||
|
import stat
|
||||||
|
|
||||||
|
|
||||||
class MainWindow:
|
class MainWindow:
|
||||||
|
|
||||||
@@ -34,9 +40,9 @@ 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 a file...", 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)
|
||||||
@@ -58,58 +64,58 @@ class MainWindow:
|
|||||||
def refresh_list(self):
|
def refresh_list(self):
|
||||||
self.filelocation.config(state=NORMAL)
|
self.filelocation.config(state=NORMAL)
|
||||||
self.filelocation.delete(0, END)
|
self.filelocation.delete(0, END)
|
||||||
for file in self.filelist:
|
for afile in self.filelist:
|
||||||
self.filelocation.insert(END, file)
|
self.filelocation.insert(END, afile)
|
||||||
self.filelocation.config(state=DISABLED)
|
self.filelocation.config(state=DISABLED)
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
self.filelocation = Listbox(self.master)
|
self.filelocation = Listbox(self.master)
|
||||||
self.filelocation.grid(row=0,columnspan=4,sticky=W+E+N+S)
|
self.filelocation.grid(row=0, columnspan=4, sticky=W + E + N + S)
|
||||||
self.refresh_list()
|
self.refresh_list()
|
||||||
|
|
||||||
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=1, column=3)
|
||||||
|
|
||||||
self.options = {
|
self.options = {
|
||||||
'epub_only':IntVar(None,0),
|
'epub_only': IntVar(None, 0),
|
||||||
'image_preprocess':IntVar(None,1),
|
'image_preprocess': IntVar(None, 1),
|
||||||
'cut_page_numbers':IntVar(None,1),
|
'cut_page_numbers': IntVar(None, 1),
|
||||||
'mangastyle':IntVar(None,0),
|
'mangastyle': IntVar(None, 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 (does not call 'kindlegen')",
|
||||||
'image_preprocess':"Apply image optimizations",
|
'image_preprocess': "Apply image optimizations",
|
||||||
'cut_page_numbers':"Cut page numbers",
|
'cut_page_numbers': "Cut page numbers",
|
||||||
'mangastyle':"Split manga-style (right-to-left reading)",
|
'mangastyle': "Split manga-style (right-to-left reading)",
|
||||||
'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:
|
||||||
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(column=3, sticky='w')
|
||||||
self.progressbar = ttk.Progressbar(orient=HORIZONTAL, length=200, mode='determinate')
|
self.progressbar = ttk.Progressbar(orient=HORIZONTAL, length=200, mode='determinate')
|
||||||
|
|
||||||
self.submit = Button(self.master, text="Execute!", command=self.start_conversion, fg="red")
|
self.submit = Button(self.master, text="Execute!", command=self.start_conversion, fg="red")
|
||||||
self.submit.grid(column=3)
|
self.submit.grid(column=3)
|
||||||
self.progressbar.grid(column=0,columnspan=4,sticky=W+E+N+S)
|
self.progressbar.grid(column=0, columnspan=4, sticky=W + E + N + S)
|
||||||
|
|
||||||
# self.debug = Listbox(self.master)
|
self.notelabel = Label(self.master,
|
||||||
# self.debug.grid(row=9,columnspan=4,sticky=W+E+N+S)
|
text="GUI can seem frozen while converting, kindly wait until some message appears!")
|
||||||
# self.debug.insert(END, os.environ['PATH'])
|
self.notelabel.grid(column=0, columnspan=4, sticky=W + E + N + S)
|
||||||
|
|
||||||
def start_conversion(self):
|
def start_conversion(self):
|
||||||
self.progressbar.start()
|
self.progressbar.start()
|
||||||
@@ -120,9 +126,8 @@ class MainWindow:
|
|||||||
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 file selected', "You should really select some files to convert...")
|
||||||
return
|
return
|
||||||
tkMessageBox.showinfo('Starting conversion', "KCC will now start converting files. GUI can seem frozen, kindly wait until some message appears!")
|
|
||||||
profilekey = ProfileData.ProfileLabels[self.profile.get()]
|
profilekey = ProfileData.ProfileLabels[self.profile.get()]
|
||||||
argv = ["-p",profilekey]
|
argv = ["-p", profilekey]
|
||||||
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['cut_page_numbers'].get() == 0:
|
if self.options['cut_page_numbers'].get() == 0:
|
||||||
@@ -138,8 +143,8 @@ class MainWindow:
|
|||||||
errors = False
|
errors = False
|
||||||
for entry in self.filelist:
|
for entry in self.filelist:
|
||||||
self.master.update()
|
self.master.update()
|
||||||
|
subargv = list(argv)
|
||||||
try:
|
try:
|
||||||
subargv = list(argv)
|
|
||||||
subargv.append(entry)
|
subargv.append(entry)
|
||||||
epub_path = comic2ebook.main(subargv)
|
epub_path = comic2ebook.main(subargv)
|
||||||
except Exception, err:
|
except Exception, err:
|
||||||
@@ -147,7 +152,7 @@ class MainWindow:
|
|||||||
errors = True
|
errors = True
|
||||||
continue
|
continue
|
||||||
if self.options['epub_only'] == 1:
|
if self.options['epub_only'] == 1:
|
||||||
continue;
|
continue
|
||||||
try:
|
try:
|
||||||
retcode = call("kindlegen \"" + epub_path + "\"", shell=True)
|
retcode = call("kindlegen \"" + epub_path + "\"", shell=True)
|
||||||
if retcode < 0:
|
if retcode < 0:
|
||||||
@@ -158,9 +163,9 @@ class MainWindow:
|
|||||||
tkMessageBox.showerror('Error kindlegen', "Error on file %s:\n%s" % (epub_path, e))
|
tkMessageBox.showerror('Error kindlegen', "Error on file %s:\n%s" % (epub_path, e))
|
||||||
errors = True
|
errors = True
|
||||||
continue
|
continue
|
||||||
|
mobifile = epub_path.replace('.epub', '.mobi')
|
||||||
try:
|
try:
|
||||||
mobifile = epub_path.replace('.epub','.mobi')
|
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')
|
||||||
except Exception, err:
|
except Exception, err:
|
||||||
@@ -178,7 +183,7 @@ class MainWindow:
|
|||||||
"Conversion successfully done!"
|
"Conversion successfully done!"
|
||||||
)
|
)
|
||||||
|
|
||||||
def remove_readonly(self, fn, path, excinfo):
|
def remove_readonly(self, fn, path):
|
||||||
if fn is os.rmdir:
|
if fn is os.rmdir:
|
||||||
os.chmod(path, stat.S_IWRITE)
|
os.chmod(path, stat.S_IWRITE)
|
||||||
os.rmdir(path)
|
os.rmdir(path)
|
||||||
@@ -191,5 +196,3 @@ class MainWindow:
|
|||||||
self.master = master
|
self.master = master
|
||||||
self.master.title(title)
|
self.master.title(title)
|
||||||
self.initialize()
|
self.initialize()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
154
kcc/image.py
154
kcc/image.py
@@ -15,13 +15,14 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>'
|
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from PIL import Image, ImageOps, ImageDraw, ImageStat
|
from PIL import Image, ImageOps, ImageDraw, ImageStat
|
||||||
|
|
||||||
|
|
||||||
class ImageFlags:
|
class ImageFlags:
|
||||||
Orient = 1 << 0
|
Orient = 1 << 0
|
||||||
Resize = 1 << 1
|
Resize = 1 << 1
|
||||||
@@ -86,17 +87,18 @@ class ProfileData:
|
|||||||
}
|
}
|
||||||
|
|
||||||
ProfileLabels = {
|
ProfileLabels = {
|
||||||
"Kindle" : 'K1',
|
"Kindle": 'K1',
|
||||||
"Kindle 2" : 'K2',
|
"Kindle 2": 'K2',
|
||||||
"Kindle 3/Keyboard" : 'K3',
|
"Kindle 3/Keyboard": 'K3',
|
||||||
"Kindle 4/NT/Touch" : 'K4',
|
"Kindle 4/NT/Touch": 'K4',
|
||||||
"Kindle Paperwhite" : 'KHD',
|
"Kindle Paperwhite": 'KHD',
|
||||||
"Kindle DX" : 'KDX',
|
"Kindle DX": 'KDX',
|
||||||
"Kindle DXG" : 'KDXG'
|
"Kindle DXG": 'KDXG'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ComicPage:
|
class ComicPage:
|
||||||
def __init__(self,source,device):
|
def __init__(self, source, device):
|
||||||
try:
|
try:
|
||||||
self.profile_label, self.size, self.palette = ProfileData.Profiles[device]
|
self.profile_label, self.size, self.palette = ProfileData.Profiles[device]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@@ -108,13 +110,13 @@ 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):
|
||||||
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")
|
self.image.save(os.path.join(targetdir, filename), "JPEG")
|
||||||
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):
|
||||||
self.image = ImageOps.autocontrast(self.image)
|
self.image = ImageOps.autocontrast(self.image)
|
||||||
@@ -122,12 +124,12 @@ class ComicPage:
|
|||||||
def quantizeImage(self):
|
def quantizeImage(self):
|
||||||
colors = len(self.palette) / 3
|
colors = len(self.palette) / 3
|
||||||
if colors < 256:
|
if colors < 256:
|
||||||
self.palette = self.palette + self.palette[:3] * (256 - colors)
|
self.palette += self.palette[:3] * (256 - colors)
|
||||||
palImg = Image.new('P', (1, 1))
|
palImg = Image.new('P', (1, 1))
|
||||||
palImg.putpalette(self.palette)
|
palImg.putpalette(self.palette)
|
||||||
self.image = self.image.quantize(palette=palImg)
|
self.image = self.image.quantize(palette=palImg)
|
||||||
|
|
||||||
def resizeImage(self,upscale=False, stretch=False, black_borders=False):
|
def resizeImage(self, upscale=False, stretch=False, black_borders=False):
|
||||||
method = Image.ANTIALIAS
|
method = Image.ANTIALIAS
|
||||||
if black_borders:
|
if black_borders:
|
||||||
fill = 'black'
|
fill = 'black'
|
||||||
@@ -138,23 +140,23 @@ class ComicPage:
|
|||||||
# do not upscale but center image in a device-sized image
|
# do not upscale but center image in a device-sized image
|
||||||
borderw = (self.size[0] - self.image.size[0]) / 2
|
borderw = (self.size[0] - self.image.size[0]) / 2
|
||||||
borderh = (self.size[1] - self.image.size[1]) / 2
|
borderh = (self.size[1] - self.image.size[1]) / 2
|
||||||
self.image = ImageOps.expand(self.image, border=(borderw,borderh), fill=fill)
|
self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=fill)
|
||||||
return self.image
|
return self.image
|
||||||
else:
|
else:
|
||||||
method = Image.NEAREST
|
method = Image.NEAREST
|
||||||
|
|
||||||
if stretch: # if stretching call directly resize() without other considerations.
|
if stretch: # if stretching call directly resize() without other considerations.
|
||||||
self.image = self.image.resize(self.size,method)
|
self.image = self.image.resize(self.size, method)
|
||||||
return self.image
|
return self.image
|
||||||
|
|
||||||
ratioDev = float(self.size[0]) / float(self.size[1])
|
ratioDev = float(self.size[0]) / float(self.size[1])
|
||||||
if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev:
|
if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev:
|
||||||
diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
|
diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
|
||||||
self.image = ImageOps.expand(self.image, border=(diff/2,0), fill=fill)
|
self.image = ImageOps.expand(self.image, border=(diff / 2, 0), fill=fill)
|
||||||
elif (float(self.image.size[0]) / float(self.image.size[1])) > ratioDev:
|
elif (float(self.image.size[0]) / float(self.image.size[1])) > ratioDev:
|
||||||
diff = int(self.image.size[0] / ratioDev) - self.image.size[1]
|
diff = int(self.image.size[0] / ratioDev) - self.image.size[1]
|
||||||
self.image = ImageOps.expand(self.image, border=(0,diff/2), fill=fill)
|
self.image = ImageOps.expand(self.image, border=(0, diff / 2), fill=fill)
|
||||||
self.image = ImageOps.fit(self.image, self.size, method = method, centering = (0.5,0.5))
|
self.image = ImageOps.fit(self.image, self.size, method=method, centering=(0.5, 0.5))
|
||||||
return self.image
|
return self.image
|
||||||
|
|
||||||
def splitPage(self, targetdir, righttoleft=False):
|
def splitPage(self, targetdir, righttoleft=False):
|
||||||
@@ -165,12 +167,12 @@ class ComicPage:
|
|||||||
if (width > height) != (dstwidth > dstheight):
|
if (width > height) != (dstwidth > dstheight):
|
||||||
if width > height:
|
if width > height:
|
||||||
# source is landscape, so split by the width
|
# source is landscape, so split by the width
|
||||||
leftbox = (0, 0, width/2, height)
|
leftbox = (0, 0, width / 2, height)
|
||||||
rightbox = (width/2, 0, width, height)
|
rightbox = (width / 2, 0, width, height)
|
||||||
else:
|
else:
|
||||||
# source is portrait and target is landscape, so split by the height
|
# source is portrait and target is landscape, so split by the height
|
||||||
leftbox = (0, 0, width, height/2)
|
leftbox = (0, 0, width, height / 2)
|
||||||
rightbox = (0, height/2, width, height)
|
rightbox = (0, height / 2, width, height)
|
||||||
filename = os.path.splitext(os.path.basename(self.origFileName))
|
filename = os.path.splitext(os.path.basename(self.origFileName))
|
||||||
fileone = targetdir + '/' + filename[0] + '-1' + filename[1]
|
fileone = targetdir + '/' + filename[0] + '-1' + filename[1]
|
||||||
filetwo = targetdir + '/' + filename[0] + '-2' + filename[1]
|
filetwo = targetdir + '/' + filename[0] + '-2' + filename[1]
|
||||||
@@ -185,8 +187,8 @@ class ComicPage:
|
|||||||
pagetwo.save(filetwo)
|
pagetwo.save(filetwo)
|
||||||
os.remove(self.origFileName)
|
os.remove(self.origFileName)
|
||||||
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))
|
||||||
return fileone,filetwo
|
return fileone, filetwo
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -213,56 +215,57 @@ class ComicPage:
|
|||||||
draw.rectangle([corner1, corner2], outline=foreground)
|
draw.rectangle([corner1, corner2], outline=foreground)
|
||||||
self.image = imageBg
|
self.image = imageBg
|
||||||
|
|
||||||
|
|
||||||
def cutPageNumber(self):
|
def cutPageNumber(self):
|
||||||
widthImg, heightImg = self.image.size
|
widthImg, heightImg = self.image.size
|
||||||
delta = 2
|
delta = 2
|
||||||
diff = delta
|
diff = delta
|
||||||
fixedThreshold = 5
|
fixedThreshold = 5
|
||||||
if ImageStat.Stat(self.image).var[0] < 2*fixedThreshold:
|
if ImageStat.Stat(self.image).var[0] < 2 * fixedThreshold:
|
||||||
return self.image
|
return self.image
|
||||||
while ImageStat.Stat(self.image.crop((0,heightImg-diff,widthImg,heightImg))).var[0] < fixedThreshold\
|
while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] < fixedThreshold\
|
||||||
and diff < heightImg:
|
and diff < heightImg:
|
||||||
diff += delta
|
diff += delta
|
||||||
diff -= delta
|
diff -= delta
|
||||||
pageNumberCut1 = diff
|
pageNumberCut1 = diff
|
||||||
if diff<delta:
|
if diff < delta:
|
||||||
diff=delta
|
diff = delta
|
||||||
oldStat=ImageStat.Stat(self.image.crop((0,heightImg-diff,widthImg,heightImg))).var[0]
|
oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0]
|
||||||
diff += delta
|
diff += delta
|
||||||
while ImageStat.Stat(self.image.crop((0,heightImg-diff,widthImg,heightImg))).var[0] - oldStat > 0\
|
while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] - oldStat > 0\
|
||||||
and diff < heightImg/4:
|
and diff < heightImg / 4:
|
||||||
oldStat=ImageStat.Stat(self.image.crop((0,heightImg-diff,widthImg,heightImg))).var[0]
|
oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0]
|
||||||
diff += delta
|
diff += delta
|
||||||
diff -= delta
|
diff -= delta
|
||||||
pageNumberCut2 = diff
|
pageNumberCut2 = diff
|
||||||
diff += delta
|
diff += delta
|
||||||
oldStat=ImageStat.Stat(self.image.crop((0,heightImg-diff,widthImg,heightImg-pageNumberCut2))).var[0]
|
oldStat = ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg - pageNumberCut2))).var[0]
|
||||||
while ImageStat.Stat(self.image.crop((0,heightImg-diff,widthImg,heightImg-pageNumberCut2))).var[0] < fixedThreshold+oldStat\
|
while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg - pageNumberCut2))).var[0]\
|
||||||
and diff < heightImg/4:
|
< fixedThreshold + oldStat and diff < heightImg / 4:
|
||||||
diff += delta
|
diff += delta
|
||||||
diff -= delta
|
diff -= delta
|
||||||
pageNumberCut3 = diff
|
pageNumberCut3 = diff
|
||||||
delta = 5
|
delta = 5
|
||||||
diff = delta
|
diff = delta
|
||||||
while ImageStat.Stat(self.image.crop((0,heightImg-pageNumberCut2,diff,heightImg))).var[0] < fixedThreshold and diff < widthImg:
|
while ImageStat.Stat(self.image.crop((0, heightImg - pageNumberCut2, diff, heightImg))).var[0] < fixedThreshold\
|
||||||
|
and diff < widthImg:
|
||||||
diff += delta
|
diff += delta
|
||||||
diff -= delta
|
diff -= delta
|
||||||
pageNumberX1 = diff
|
pageNumberX1 = diff
|
||||||
diff = delta
|
diff = delta
|
||||||
while ImageStat.Stat(self.image.crop((widthImg-diff,heightImg-pageNumberCut2,widthImg,heightImg))).var[0] < fixedThreshold and diff < widthImg:
|
while ImageStat.Stat(self.image.crop((widthImg - diff, heightImg - pageNumberCut2,
|
||||||
|
widthImg, heightImg))).var[0] < fixedThreshold and diff < widthImg:
|
||||||
diff += delta
|
diff += delta
|
||||||
diff -= delta
|
diff -= delta
|
||||||
pageNumberX2=widthImg-diff
|
pageNumberX2 = widthImg - diff
|
||||||
|
if pageNumberCut3 - pageNumberCut1 > 2 * delta\
|
||||||
if pageNumberCut3-pageNumberCut1 > 2*delta\
|
and float(pageNumberX2 - pageNumberX1) / float(pageNumberCut2 - pageNumberCut1) <= 9.0\
|
||||||
and float(pageNumberX2-pageNumberX1)/float(pageNumberCut2-pageNumberCut1) <= 9.0\
|
and ImageStat.Stat(self.image.crop((0, heightImg - pageNumberCut3, widthImg, heightImg))).var[0]\
|
||||||
and ImageStat.Stat(self.image.crop((0,heightImg-pageNumberCut3,widthImg,heightImg))).var[0] / ImageStat.Stat(self.image).var[0] < 0.1\
|
/ ImageStat.Stat(self.image).var[0] < 0.1\
|
||||||
and pageNumberCut3 < heightImg/4-delta:
|
and pageNumberCut3 < heightImg / 4 - delta:
|
||||||
diff=pageNumberCut3
|
diff = pageNumberCut3
|
||||||
else:
|
else:
|
||||||
diff=pageNumberCut1
|
diff = pageNumberCut1
|
||||||
self.image = self.image.crop((0,0,widthImg,heightImg-diff))
|
self.image = self.image.crop((0, 0, widthImg, heightImg - diff))
|
||||||
return self.image
|
return self.image
|
||||||
|
|
||||||
def cropWhiteSpace(self, threshold):
|
def cropWhiteSpace(self, threshold):
|
||||||
@@ -270,68 +273,71 @@ class ComicPage:
|
|||||||
delta = 10
|
delta = 10
|
||||||
diff = delta
|
diff = delta
|
||||||
# top
|
# top
|
||||||
while ImageStat.Stat(self.image.crop((0,0,widthImg,diff))).var[0] < threshold and diff < heightImg:
|
while ImageStat.Stat(self.image.crop((0, 0, widthImg, diff))).var[0] < threshold and diff < heightImg:
|
||||||
diff += delta
|
diff += delta
|
||||||
diff -= delta
|
diff -= delta
|
||||||
# print "Top crop: %s"%diff
|
# print "Top crop: %s"%diff
|
||||||
self.image = self.image.crop((0,diff,widthImg,heightImg))
|
self.image = self.image.crop((0, diff, widthImg, heightImg))
|
||||||
widthImg, heightImg = self.image.size
|
widthImg, heightImg = self.image.size
|
||||||
diff = delta
|
diff = delta
|
||||||
# left
|
# left
|
||||||
while ImageStat.Stat(self.image.crop((0,0,diff,heightImg))).var[0] < threshold and diff < widthImg:
|
while ImageStat.Stat(self.image.crop((0, 0, diff, heightImg))).var[0] < threshold and diff < widthImg:
|
||||||
diff += delta
|
diff += delta
|
||||||
diff -= delta
|
diff -= delta
|
||||||
# print "Left crop: %s"%diff
|
# print "Left crop: %s"%diff
|
||||||
self.image = self.image.crop((diff,0,widthImg,heightImg))
|
self.image = self.image.crop((diff, 0, widthImg, heightImg))
|
||||||
widthImg, heightImg = self.image.size
|
widthImg, heightImg = self.image.size
|
||||||
diff = delta
|
diff = delta
|
||||||
# down
|
# down
|
||||||
while ImageStat.Stat(self.image.crop((0,heightImg-diff,widthImg,heightImg))).var[0] < threshold\
|
while ImageStat.Stat(self.image.crop((0, heightImg - diff, widthImg, heightImg))).var[0] < threshold\
|
||||||
and diff < heightImg:
|
and diff < heightImg:
|
||||||
diff += delta
|
diff += delta
|
||||||
diff -= delta
|
diff -= delta
|
||||||
# print "Down crop: %s"%diff
|
# print "Down crop: %s"%diff
|
||||||
self.image = self.image.crop((0,0,widthImg,heightImg-diff))
|
self.image = self.image.crop((0, 0, widthImg, heightImg - diff))
|
||||||
widthImg, heightImg = self.image.size
|
widthImg, heightImg = self.image.size
|
||||||
diff = delta
|
diff = delta
|
||||||
# right
|
# right
|
||||||
while ImageStat.Stat(self.image.crop((widthImg-diff,0,widthImg,heightImg))).var[0] < threshold\
|
while ImageStat.Stat(self.image.crop((widthImg - diff, 0, widthImg, heightImg))).var[0] < threshold\
|
||||||
and diff < widthImg:
|
and diff < widthImg:
|
||||||
diff += delta
|
diff += delta
|
||||||
diff -= delta
|
diff -= delta
|
||||||
# print "Right crop: %s"%diff
|
# print "Right crop: %s"%diff
|
||||||
self.image = self.image.crop((0,0 ,widthImg-diff,heightImg))
|
self.image = self.image.crop((0, 0, widthImg - diff, heightImg))
|
||||||
# print "New size: %sx%s"%(self.image.size[0],self.image.size[1])
|
# print "New size: %sx%s"%(self.image.size[0],self.image.size[1])
|
||||||
return self.image
|
return self.image
|
||||||
|
|
||||||
def addProgressbar(self, file_number, files_totalnumber, size, howoften):
|
def addProgressbar(self, file_number, files_totalnumber, size, howoften):
|
||||||
if file_number//howoften!=float(file_number)/howoften:
|
if file_number // howoften != float(file_number) / howoften:
|
||||||
return self.image
|
return self.image
|
||||||
white = (255,255,255)
|
white = (255, 255, 255)
|
||||||
black = (0,0,0)
|
black = (0, 0, 0)
|
||||||
widthDev, heightDev = size
|
widthDev, heightDev = size
|
||||||
widthImg, heightImg = self.image.size
|
widthImg, heightImg = self.image.size
|
||||||
pastePt = (
|
pastePt = (
|
||||||
max(0, (widthDev - widthImg) / 2),
|
max(0, (widthDev - widthImg) / 2),
|
||||||
max(0, (heightDev - heightImg) / 2)
|
max(0, (heightDev - heightImg) / 2)
|
||||||
)
|
)
|
||||||
imageBg = Image.new('RGB',size,white)
|
imageBg = Image.new('RGB', size, white)
|
||||||
imageBg.paste(self.image, pastePt)
|
imageBg.paste(self.image, pastePt)
|
||||||
self.image = imageBg
|
self.image = imageBg
|
||||||
widthImg, heightImg = self.image.size
|
widthImg, heightImg = self.image.size
|
||||||
draw = ImageDraw.Draw(self.image)
|
draw = ImageDraw.Draw(self.image)
|
||||||
#Black rectangle
|
#Black rectangle
|
||||||
draw.rectangle([(0,heightImg-3), (widthImg,heightImg)], outline=black, fill=black)
|
draw.rectangle([(0, heightImg - 3), (widthImg, heightImg)], outline=black, fill=black)
|
||||||
#White rectangle
|
#White rectangle
|
||||||
draw.rectangle([(widthImg*file_number/files_totalnumber,heightImg-3), (widthImg-1,heightImg)], outline=black, fill=white)
|
draw.rectangle([(widthImg * file_number / files_totalnumber, heightImg - 3), (widthImg - 1, heightImg)],
|
||||||
|
outline=black, fill=white)
|
||||||
#Making notches
|
#Making notches
|
||||||
for i in range(1,10):
|
for i in range(1, 10):
|
||||||
if i <= (10*file_number/files_totalnumber):
|
if i <= (10 * file_number / files_totalnumber):
|
||||||
notch_colour=white #White
|
notch_colour = white # White
|
||||||
else:
|
else:
|
||||||
notch_colour=black #Black
|
notch_colour = black # Black
|
||||||
draw.line([(widthImg*float(i)/10,heightImg-3), (widthImg*float(i)/10,heightImg)],fill=notch_colour)
|
draw.line([(widthImg * float(i) / 10, heightImg - 3), (widthImg * float(i) / 10, heightImg)],
|
||||||
|
fill=notch_colour)
|
||||||
#The 50%
|
#The 50%
|
||||||
if i==5:
|
if i == 5:
|
||||||
draw.rectangle([(widthImg/2-1,heightImg-5), (widthImg/2+1,heightImg)],outline=black,fill=notch_colour)
|
draw.rectangle([(widthImg / 2 - 1, heightImg - 5), (widthImg / 2 + 1, heightImg)],
|
||||||
|
outline=black, fill=notch_colour)
|
||||||
return self.image
|
return self.image
|
||||||
|
|||||||
Reference in New Issue
Block a user