about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCiro Mattia Gonano <ciromattia@gmail.com>2013-01-29 15:01:36 +0100
committerCiro Mattia Gonano <ciromattia@gmail.com>2013-01-29 15:01:36 +0100
commitd136f8cc3a8eeca5aa5a7f3ea642447ebbb5fa75 (patch)
treee9eab8bcb5af23eba1f5c4b891b77c9ef937daf0
parentFormatting (diff)
downloadkcc-d136f8cc3a8eeca5aa5a7f3ea642447ebbb5fa75.tar.gz
kcc-d136f8cc3a8eeca5aa5a7f3ea642447ebbb5fa75.tar.bz2
kcc-d136f8cc3a8eeca5aa5a7f3ea642447ebbb5fa75.zip
Use temporary directory as workdir (fixes converting from external volumes and zipfiles renaming)
Fixed "add folders" from GUI.
-rw-r--r--README.md10
-rw-r--r--kcc.py2
-rw-r--r--kcc/cbxarchive.py46
-rwxr-xr-xkcc/comic2ebook.py74
-rw-r--r--kcc/gui.py6
-rwxr-xr-xkcc/image.py20
6 files changed, 65 insertions, 93 deletions
diff --git a/README.md b/README.md
index 3c94ccc..657efad 100644
--- a/README.md
+++ b/README.md
@@ -12,8 +12,8 @@ It also optimizes comic images by:
 
 ## BINARY RELEASES
 You can find the latest released binary at the following links:  
-- OS X: [https://dl.dropbox.com/u/16806101/KindleComicConverter_osx_2.3.zip](https://dl.dropbox.com/u/16806101/KindleComicConverter_osx_2.3.zip)
-- Win64: [https://dl.dropbox.com/u/16806101/KindleComicConverter_win-amd64_2.3.zip](https://dl.dropbox.com/u/16806101/KindleComicConverter_win-amd64_2.3.zip)
+- OS X: [https://dl.dropbox.com/u/16806101/KindleComicConverter_osx_2.4.zip](https://dl.dropbox.com/u/16806101/KindleComicConverter_osx_2.4.zip)
+- Win64: [https://dl.dropbox.com/u/16806101/KindleComicConverter_win-amd64_2.4.zip](https://dl.dropbox.com/u/16806101/KindleComicConverter_win-amd64_2.4.zip)
 - Linux: just download sourcecode and launch `python kcc.py` *(provided you have Python and Pillow installed)*
 
 ## INPUT FORMATS
@@ -40,6 +40,8 @@ As of v. 1.50, KCC supports subfolders!
 ### GUI
 
 Should be pretty self-explanatory, just keep in mind that it's still in development ;)
+While working it seems frozen, I'll try to fix the aesthetics later.
+Conversion being done, you should find an .epub and a .mobi files alongside the original input file (same directory)
 
 ### Standalone `comic2ebook.py` usage:
 
@@ -104,7 +106,9 @@ and installed in a directory reachable by your PATH (e.g. `/usr/local/bin/` or `
   - 2.1: Added basic error reporting
   - 2.2: Added (valid!) ePub 2.0 output
         Rename .zip files to .cbz to avoid overwriting
-  - 2.3: Fixed win32 ePub generation, folder handling, filenames with spaces and subfolders.
+  - 2.3: Fixed win32 ePub generation, folder handling, filenames with spaces and subfolders
+  - 2.4: Use temporary directory as workdir (fixes converting from external volumes and zipfiles renaming)
+        Fixed "add folders" from GUI.
 
 ## TODO
   - Add gracefully exit for CBR if no rarfile.py and no unrar executable are found
diff --git a/kcc.py b/kcc.py
index 9986586..af0955e 100644
--- a/kcc.py
+++ b/kcc.py
@@ -16,7 +16,7 @@
 # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 #
-__version__ = '2.3'
+__version__ = '2.4'
 __license__   = 'ISC'
 __copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>'
 __docformat__ = 'restructuredtext en'
diff --git a/kcc/cbxarchive.py b/kcc/cbxarchive.py
index 6b0e7ea..54d16b3 100644
--- a/kcc/cbxarchive.py
+++ b/kcc/cbxarchive.py
@@ -25,35 +25,28 @@ class CBxArchive:
         self.cbxexts = ['.zip','.cbz','.rar','.cbr']
         self.origFileName = origFileName
         self.filename = os.path.splitext(origFileName)
-        self.path = self.filename[0]
 
     def isCbxFile(self):
-        result = (self.filename[1].lower() in self.cbxexts)
-        if result == True:
-            return result
-        return False
+        return self.filename[1].lower() in self.cbxexts
 
-    def getPath(self):
-        return self.path
-
-    def extractCBZ(self):
+    def extractCBZ(self,targetdir):
         try:
             from zipfile import ZipFile
         except ImportError:
             self.cbzFile = None
         cbzFile = ZipFile(self.origFileName)
         for f in cbzFile.namelist():
-            if (f.startswith('__MACOSX') or f.endswith('.DS_Store')):
+            if f.startswith('__MACOSX') or f.endswith('.DS_Store'):
                 pass # skip MacOS special files
             elif f.endswith('/'):
                 try:
-                    os.makedirs(self.path+'/'+f)
+                    os.makedirs(os.path.join(targetdir,f))
                 except:
                     pass #the dir exists so we are going to extract the images only.
             else:
-                cbzFile.extract(f, self.path)
+                cbzFile.extract(f, targetdir)
 
-    def extractCBR(self):
+    def extractCBR(self,targetdir):
         try:
             import rarfile
         except ImportError:
@@ -61,24 +54,25 @@ class CBxArchive:
             return
         cbrFile = rarfile.RarFile(self.origFileName)
         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
             elif f.endswith('/'):
                 try:
-                    os.makedirs(self.path+'/'+f)
+                    os.makedirs(os.path.join(targetdir,f))
                 except:
                     pass #the dir exists so we are going to extract the images only.
             else:
-                cbrFile.extract(f, self.path)
+                cbrFile.extract(f, targetdir)
 
-    def extract(self):
-        if ('.cbr' == self.filename[1].lower() or '.rar' == self.filename[1].lower()):
-            self.extractCBR()
-        elif ('.cbz' == self.filename[1].lower() or '.zip' == self.filename[1].lower()):
-            self.extractCBZ()
-        dir = os.listdir(self.path)
-        if (len(dir) == 1):
+    def extract(self,targetdir):
+        if '.cbr' == self.filename[1].lower() or '.rar' == self.filename[1].lower():
+            self.extractCBR(targetdir)
+        elif '.cbz' == self.filename[1].lower() or '.zip' == self.filename[1].lower():
+            self.extractCBZ(targetdir)
+        dir = os.listdir(targetdir)
+        if len(dir) == 1 and os.path.isdir(os.path.join(targetdir,dir[0])):
             import shutil
-            for f in os.listdir(self.path + "/" + dir[0]):
-                shutil.move(self.path + "/" + dir[0] + "/" + f,self.path)
-            os.rmdir(self.path + "/" + dir[0])
+            for f in os.listdir(os.path.join(targetdir,dir[0])):
+                shutil.move(os.path.join(targetdir,dir[0],f),targetdir)
+            os.rmdir(os.path.join(targetdir,dir[0]))
+        return targetdir
diff --git a/kcc/comic2ebook.py b/kcc/comic2ebook.py
index bfe336e..c556512 100755
--- a/kcc/comic2ebook.py
+++ b/kcc/comic2ebook.py
@@ -16,39 +16,20 @@
 # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 #
-# Changelog
-#  1.00 - Initial version
-#  1.10 - Added support for CBZ/CBR files
-#  1.11 - Added support for ZIP/RAR extensions
-#  1.20 - Comic optimizations! Split pages not target-oriented (landscape
-#       with portrait target or portrait with landscape target), add palette
-#       and other image optimizations from Mangle.
-#       WARNING: PIL is required for all image mangling!
-#  1.30 - Fixed an issue in OPF generation for device resolution
-#       Reworked options system (call with -h option to get the inline help)
-#  1.40 - Added some options for controlling image optimization
-#       Further optimization (ImageOps, page numbering cut, autocontrast)
-#  1.41 - Fixed a serious bug on resizing when img ratio was bigger than device one
-#  1.50 - Support for subfolders
-#
-# Todo:
-#   - Add gracefully exit for CBR if no rarfile.py and no unrar
-#       executable are found
-#   - Improve error reporting
-
-__version__ = '2.3'
+__version__ = '2.4'
 __license__   = 'ISC'
 __copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>'
 __docformat__ = 'restructuredtext en'
 
-import os, sys
-from shutil import move,copyfile,make_archive,rmtree
+import os, sys, tempfile
+from shutil import move,copyfile,copytree,rmtree,make_archive
 from optparse import OptionParser
 import image, cbxarchive, pdfjpgextract
 
 def buildHTML(path,file):
     filename = getImageFileName(file)
     if filename is not None:
+        htmlpath = ''
         postfix = ''
         backref = 1
         head = path
@@ -203,9 +184,9 @@ def dirImgProcess(path):
                     if options.verbose:
                         print "Splitted " + file
                     img0 = image.ComicPage(split[0],options.profile)
-                    img1 = image.ComicPage(split[1],options.profile)
                     applyImgOptimization(img0)
                     img0.saveToDir(dirpath)
+                    img1 = image.ComicPage(split[1],options.profile)
                     applyImgOptimization(img1)
                     img1.saveToDir(dirpath)
                 else:
@@ -238,35 +219,31 @@ def genEpubStruct(path):
                 if cover is None:
                     cover = os.path.join(filelist[-1][0],'cover' + getImageFileName(filelist[-1][1])[1])
                     copyfile(os.path.join(filelist[-1][0],filelist[-1][1]), cover)
-    if options.title == 'defaulttitle':
-        options.title = os.path.basename(path)
     buildNCX(path,options.title,chapterlist)
     # ensure we're sorting files alphabetically
     filelist = sorted(filelist, key=lambda name: (name[0].lower(), name[1].lower()))
     buildOPF(options.profile,path,options.title,filelist,cover)
 
 def getWorkFolder(file):
+    workdir = tempfile.mkdtemp()
     fname = os.path.splitext(file)
-    if fname[1].lower() == '.pdf':
+    if os.path.isdir(file):
+        try:
+            import shutil
+            os.rmdir(workdir)   # needed for copytree() fails if dst already exists
+            copytree(file, workdir)
+            path = workdir
+        except OSError:
+            raise
+    elif fname[1].lower() == '.pdf':
         pdf = pdfjpgextract.PdfJpgExtract(file)
-        pdf.extract()
-        path = pdf.getPath()
+        path = pdf.extract(workdir)
     else:
-        if fname[1].lower() == '.zip':
-            move(file,fname[0] + '.cbz')
-            file = fname[0] + '.cbz'
         cbx = cbxarchive.CBxArchive(file)
         if cbx.isCbxFile():
-            cbx.extract()
-            path = cbx.getPath()
+            path = cbx.extract(workdir)
         else:
-            try:
-                import shutil
-                if not os.path.isdir(file + "_orig"):
-                    shutil.copytree(file, file + "_orig")
-                path = file
-            except OSError:
-                raise
+            raise TypeError
     move(path,path + "_temp")
     move(path + "_temp",os.path.join(path,'OEBPS','Images'))
     return path
@@ -304,18 +281,23 @@ def main(argv=None):
     if len(args) != 1:
         parser.print_help()
         return
-    path = args[0]
-    path = getWorkFolder(path)
+    path = getWorkFolder(args[0])
+    if options.title == 'defaulttitle':
+        options.title = os.path.splitext(os.path.basename(args[0]))[0]
     if options.imgproc:
         print "Processing images..."
         dirImgProcess(path + "/OEBPS/Images/")
     print "Creating ePub structure..."
     genEpubStruct(path)
     # actually zip the ePub
-    make_archive(path,'zip',path)
-    move(path + '.zip', path + '.epub')
+    if os.path.isdir(args[0]):
+        epubpath = args[0] + '.epub'
+    else:
+        epubpath = os.path.splitext(args[0])[0] + '.epub'
+    make_archive(os.path.join(path,'comic'),'zip',path)
+    move(os.path.join(path,'comic') + '.zip', epubpath)
     rmtree(path)
-    epub_path = path + '.epub'
+    return epubpath
 
 def getEpubPath():
     global epub_path
diff --git a/kcc/gui.py b/kcc/gui.py
index 0565a0f..e0daed3 100644
--- a/kcc/gui.py
+++ b/kcc/gui.py
@@ -51,7 +51,8 @@ class MainWindow:
         self.refresh_list()
 
     def open_folder(self):
-        self.filelist = tkFileDialog.askdirectory(title="Choose a folder...")
+        f = tkFileDialog.askdirectory(title="Choose a folder...")
+        self.filelist.extend([f])
         self.refresh_list()
 
     def refresh_list(self):
@@ -146,8 +147,7 @@ class MainWindow:
             try:
                 subargv = list(argv)
                 subargv.append(entry)
-                comic2ebook.main(subargv)
-                epub_path = comic2ebook.getEpubPath()
+                epub_path = comic2ebook.main(subargv)
             except Exception, err:
                 tkMessageBox.showerror('Error comic2ebook', "Error on file %s:\n%s" % (subargv[-1], str(err)))
                 errors = True
diff --git a/kcc/image.py b/kcc/image.py
index a55db41..6dd6f9c 100755
--- a/kcc/image.py
+++ b/kcc/image.py
@@ -110,10 +110,9 @@ class ComicPage:
 
     def saveToDir(self,targetdir):
         filename = os.path.basename(self.origFileName)
-        #print "Saving to " + targetdir + '/' + filename
         try:
             self.image = self.image.convert('L')    # convert to grayscale
-            self.image.save(targetdir + '/' + filename,"JPEG")
+            self.image.save(os.path.join(targetdir,filename),"JPEG")
         except IOError as e:
             raise RuntimeError('Cannot write image in directory %s: %s' %(targetdir,e))
 
@@ -133,11 +132,9 @@ class ComicPage:
         if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]:
             if not upscale:
                 # do not upscale but center image in a device-sized image
-                newImage = Image.new('RGB', (self.size[0], self.size[1]), (255,255,255))
-                newImage.paste(self.image, (
-                    (self.size[0] - self.image.size[0]) / 2,
-                    (self.size[1] - self.image.size[1]) / 2))
-                self.image = newImage
+                borderw = (self.size[0] - self.image.size[0]) / 2
+                borderh = (self.size[1] - self.image.size[1]) / 2
+                self.image = ImageOps.expand(self.image, border=(borderw,borderh), fill='white')
                 return self.image
             else:
                 method = Image.NEAREST
@@ -149,14 +146,10 @@ class ComicPage:
         ratioDev = float(self.size[0]) / float(self.size[1])
         if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev:
             diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
-            newImage = Image.new('RGB', (self.image.size[0] + diff, self.image.size[1]), (255,255,255))
-            newImage.paste(self.image, (diff / 2, 0, diff / 2 + self.image.size[0], self.image.size[1]))
-            self.image = newImage
+            self.image = ImageOps.expand(self.image, border=(diff/2,0), fill='white')
         elif (float(self.image.size[0]) / float(self.image.size[1])) > ratioDev:
             diff = int(self.image.size[0] / ratioDev) - self.image.size[1]
-            newImage = Image.new('RGB', (self.image.size[0], self.image.size[1] + diff), (255,255,255))
-            newImage.paste(self.image, (0, diff / 2, self.image.size[0], diff / 2 + self.image.size[1]))
-            self.image = newImage
+            self.image = ImageOps.expand(self.image, border=(0,diff/2), fill='white')
         self.image = ImageOps.fit(self.image, self.size, method = method, centering = (0.5,0.5))
         return self.image
 
@@ -338,4 +331,3 @@ class ComicPage:
             if i==5:
                 draw.rectangle([(widthImg/2-1,heightImg-5), (widthImg/2+1,heightImg)],outline=black,fill=notch_colour)
         return self.image
-