about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPaweł Jastrzębski <[email protected]>2017-03-17 11:11:00 +0100
committerGitHub <[email protected]>2017-03-17 11:11:00 +0100
commitc01ff83fce6e91a7ee417c113377996400770572 (patch)
treec76b5d0398d5085a7a57e63a688856f28c3cab1b
parentMerge pull request #224 from ciromattia/dev (diff)
parentUpdate README.md (diff)
downloadkcc-c01ff83fce6e91a7ee417c113377996400770572.tar.gz
kcc-c01ff83fce6e91a7ee417c113377996400770572.tar.bz2
kcc-c01ff83fce6e91a7ee417c113377996400770572.zip
Merge pull request #231 from ciromattia/dev
5.3.1
-rw-r--r--.gitignore1
-rw-r--r--MANIFEST.in1
-rw-r--r--README.md154
-rw-r--r--docker/Dockerfile7
-rwxr-xr-xkcc-c2e.py9
-rwxr-xr-xkcc-c2p.py9
-rw-r--r--kcc.iss2
-rwxr-xr-xkcc.py20
-rw-r--r--kindlecomicconverter/KCC_gui.py20
-rw-r--r--kindlecomicconverter/__init__.py2
-rw-r--r--kindlecomicconverter/cbxarchive.py24
-rwxr-xr-xkindlecomicconverter/comic2ebook.py106
-rw-r--r--kindlecomicconverter/comic2panel.py18
-rwxr-xr-xkindlecomicconverter/image.py14
-rw-r--r--kindlecomicconverter/shared.py67
-rw-r--r--kindlecomicconverter/startup.py53
-rw-r--r--other/osx/Info.plist6
-rw-r--r--requirements.txt5
-rwxr-xr-xsetup.py92
19 files changed, 279 insertions, 331 deletions
diff --git a/.gitignore b/.gitignore
index 9e0e197..d4fbd53 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,4 @@ setup.sh
 kindlecomicconverter/sentry.py
 build/
 .python-version
+KindleComicConverter.egg-info/
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..e938f6e
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1 @@
+exclude kindlecomicconverter/sentry.py
\ No newline at end of file
diff --git a/README.md b/README.md
index d1c8ea8..a06ad77 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,6 @@
-# KCC
+# KCC
+
+[![GitHub release](https://img.shields.io/github/release/ciromattia/kcc.svg)]() [![PyPI](https://img.shields.io/pypi/v/KindleComicConverter.svg)]() [![AUR](https://img.shields.io/aur/version/kcc.svg)]()
 
 **Kindle Comic Converter** is a Python app to convert comic/manga files or folders to EPUB, Panel View MOBI or E-Ink optimized CBZ.
 It was initially developed for Kindle but since version 4.6 it outputs valid EPUB 3.0 so _**despite its name, KCC is
@@ -17,11 +19,11 @@ If you can fix an open issue, fork & make a pull request.
 
 If you find **KCC** valuable you can consider donating to the authors:
 - Ciro Mattia Gonano:
- - [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=D8WNYNPBGDAS2)
- - [![Flattr this](http://api.flattr.com/button/flattr-badge-large.png)](http://flattr.com/thing/2260449/ciromattiakcc-on-GitHub)
+  - [![Donate PayPal](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=D8WNYNPBGDAS2)
+  - [![Donate Flattr](https://img.shields.io/badge/Donate-Flattr-green.svg)](http://flattr.com/thing/2260449/ciromattiakcc-on-GitHub)
 - Paweł Jastrzębski:
- - [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YTTJ4LK2JDHPS)
- - Bitcoin: 1W15wwqsfd7wbaZ6wvSJf1LW1bz6q5L8b
+  - [![Donate PayPal](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YTTJ4LK2JDHPS)
+  - [![Donate Bitcoin](https://img.shields.io/badge/Donate-Bitcoin-green.svg)](https://jastrzeb.ski/donate/)
 
 ## BINARY RELEASES
 You can find the latest released binary at the following links:
@@ -29,20 +31,25 @@ You can find the latest released binary at the following links:
 - **Linux (Glibc 2.19+):** [http://kcc.iosphe.re/Linux/](http://kcc.iosphe.re/Linux/)
 - **OS X (10.9+):** [http://kcc.iosphe.re/OSX/](http://kcc.iosphe.re/OSX/)
 
+## PYPI
+**KCC** is also available on PyPI.
+```
+pip install KindleComicConverter
+```
+
 ## DEPENDENCIES
 Following software is required to run Linux version of **KCC** and/or bare sources:
 - Python 3.3+
-- [PyQt](https://pypi.python.org/pypi/PyQt5) 5.6.0+
-- [Pillow](https://pypi.python.org/pypi/Pillow/) 3.2.0+
-- [psutil](https://pypi.python.org/pypi/psutil) 4.1.0+
-- [python-slugify](https://pypi.python.org/pypi/python-slugify) 1.2.0+
-- [raven](https://pypi.python.org/pypi/raven) 5.13.0+
-- [scandir](https://pypi.python.org/pypi/scandir) 1.2.0+ _(needed only when using Python 3.3 or 3.4)_
+- [PyQt5](https://pypi.python.org/pypi/PyQt5) 5.6.0+
+- [Pillow](https://pypi.python.org/pypi/Pillow/) 4.0.0+
+- [psutil](https://pypi.python.org/pypi/psutil) 5.0.0+
+- [python-slugify](https://pypi.python.org/pypi/python-slugify) 1.2.1+
+- [raven](https://pypi.python.org/pypi/raven) 6.0.0+
 
 On Debian based distributions these two commands should install all needed dependencies:
 ```
 sudo apt-get install python3 python3-dev python3-pip libpng-dev libjpeg-dev p7zip-full unrar
-sudo pip3 install --upgrade pillow python-slugify psutil scandir raven pyqt5
+sudo pip3 install --upgrade pillow python-slugify psutil pyqt5 raven
 ```
 
 ### Optional dependencies
@@ -163,35 +170,40 @@ The app relies and includes the following scripts:
 * [Kobo Aura ONE](http://kcc.iosphe.re/Samples/Ubunchu-KoAO.kepub.epub)
 
 ## CHANGELOG
-####5.3:
+#### 5.3.1:
+* Small increase of output quality
+* Improved error reporting
+* Internal changes and tweaks
+
+#### 5.3:
 * Vastly improved output compatibility for non-Kindle devices
 * Enabled old pinch zoom for Kindle devices
 * Re-enabled Panel View support for Kindle Keyboard
 * Partially re-enabled OS X file association mechanism
 * Fixed multiple smaller issues
 
-####5.2.1:
+#### 5.2.1:
 * Improved directory parsing
 * Tweaked margin detection algorithm
 * Improved error reporting
 
-####5.2:
+#### 5.2:
 * Added new Panel View options
 * Implemented new margin detection algorithm
 * Removed HQ Panel View mode
 * Fixed multiple smaller issues
 
-####5.1.3:
+#### 5.1.3:
 * Added Kobo Aura ONE profile
 * Fixed few small bugs
 
-####5.1.2:
+#### 5.1.2:
 * Fixed error reporting
 
-####5.1.1:
+#### 5.1.1:
 * Fixed multiple GUI bugs
 
-####5.1:
+#### 5.1:
 * GUI now can be resized and high DPI support was somewhat improved
 * Added profile for Kindle Oasis
 * Implemented new error reporting mechanism
@@ -199,55 +211,55 @@ The app relies and includes the following scripts:
 * Fixed permission issues on Windows
 * Fixed multiple smaller issues
 
-####5.0.1:
+#### 5.0.1:
 * Fixed Panel View placement issues
 * Decreased application startup time
 * Fixed multiple smaller issues
 
-####5.0:
+#### 5.0:
 * Major overhaul of internal mechanisms and GUI
 * Added cover upload feature
 * Tweaked Webtoon parsing mode
 * Fixed multiple smaller issues
 * Migrated build enviroment to PyInstaller
 
-####4.6.5:
+#### 4.6.5:
 * Fixed multiple Windows and OS X issues
 * Allowed Linux release to use older PyQT5 version
 
-####4.6.4:
+#### 4.6.4:
 * Fixed multiple Windows specific problems
 * Improved error handling
 * Improved color detection algorithm
 * New, slimmer OS X release
 
-####4.6.3:
+#### 4.6.3:
 * Implemented remote bug reporting
 * Minor bug fixes and GUI tweaks
 
-####4.6.2:
+#### 4.6.2:
 * Fixed critical MOBI header bug
 * Fixed metadata encoding error
 
-####4.6.1:
+#### 4.6.1:
 * Fixed KEPUB TOC generator
 * Added warning about too small input files
 * ComicRack Summary metadata field is now parsed
 * Small tweaks of KEPUB output
 
-####4.6:
+#### 4.6:
 * KEPUB is now default output for all Kobo profiles
 * EPUB output now produce fully valid EPUB 3.0.1
 * Added profile for Kindle Paperwhite 3
 * Dropped official support of all Kindle Fire models and Kindle for Android
 * Other minor tweaks
 
-####4.5.1:
+#### 4.5.1:
 * Added Kobo Glo HD profile
 * Fixed RAR/CBR parsing anomalies
 * Minor bug fixes and tweaks
 
-####4.5:
+#### 4.5:
 * Added simple ComicRack metadata editor
 * Re-enabled Manga Cover Database support
 * ComicRack bookmarks are now parsed
@@ -256,61 +268,61 @@ The app relies and includes the following scripts:
 * Fixed sorting anomalies
 * Improved conversion speed
 
-####4.4.1:
+#### 4.4.1:
 * Fixed problems with OSX GUI
 * Added one missing DLL to Windows installer
 
-####4.4:
+#### 4.4:
 * Improved speed and quality of conversion
 * Added RAR5 support
 * Dropped BMP and TIFF support
 * Fixed some WebToon mode bugs
 * Fixed CBR parsing on OSX
 
-####4.3.1:
+#### 4.3.1:
 * Fixed Kindle Voyage profile
 * Fixed some bugs in OS X release
 * CLI version now support multiple input files at once
 * Disabled MCB support
 * Other minor tweaks
 
-####4.3:
+#### 4.3:
 * Added profiles for Kindle Voyage and Kobo Aura H2O
 * Added missing features to CLI version
 * Other minor bug fixes
 
-####4.2.1:
+#### 4.2.1:
 * Improved margin color detection 
 * Fixed random crashes of MOBI processing step
 * Fixed resizing problems in high quality mode
 * Fixed some MCD support bugs
 * Default output format for Kindle DX is now CBZ
 
-####4.2:
+#### 4.2:
 * Added [Manga Cover Database](http://manga.joentjuh.nl/) support
 * Officially dropped Windows XP support
 * Fixed _Other_ profile
 * Fixed problems with page order on stock KOBO CBZ reader
 * Many other small bug fixes and tweaks
 
-####4.1:
+#### 4.1:
 * Thanks to code contributed by Kevin Hendricks speed of MOBI creation was greatly increased
 * Improved performance on Windows
 * Improved MOBI splitting and changed maximal size of output file
 * Fixed _No optimization_ mode
 * Multiple small tweaks nad minor bug fixes
 
-####4.0.2:
+#### 4.0.2:
 * Fixed some Windows and OSX specific bugs
 * Fixed problem with marigns when using HQ mode
 
-####4.0.1:
+#### 4.0.1:
 * Fixed file lock problems that plagued some Windows users
 * Fixed content server failing to start on Windows
 * Improved performance of WebToon splitter
 * Tweaked margin color detection
 
-####4.0:
+#### 4.0:
 * KCC now use Python 3.3 and Qt 5.2
 * Full UTF-8 awareness
 * CBZ output now support Manga mode
@@ -322,13 +334,13 @@ The app relies and includes the following scripts:
 * Fixed OSX file association support
 * Many extensive internal changes and tweaks
 
-####3.7.2:
+#### 3.7.2:
 * Fixed problems with HQ mode
 
-####3.7.1:
+#### 3.7.1:
 * Hotfixed Kobo profiles
 
-####3.7:
+#### 3.7:
 * Added profiles for KOBO devices
 * Improved Panel View support
 * Improved WebToon splitter
@@ -337,14 +349,14 @@ The app relies and includes the following scripts:
 * Fixed stretching option
 * GUI tweaks and minor bugfixes
 
-####3.6.2:
+#### 3.6.2:
 * Fixed previous PNG output fix
 * Fixed Panel View anomalies
 
-####3.6.1:
+#### 3.6.1:
 * Fixed PNG output
 
-####3.6:
+#### 3.6:
 * Increased quality of Panel View zoom
 * Creation of multipart MOBI output is now faster on machines with 4GB+ RAM
 * Automatic gamma correction now distinguishes color and grayscale images
@@ -355,13 +367,13 @@ The app relies and includes the following scripts:
 * Fixed Kindle Fire HDX 7" output
 * Increased target resolution for Kindle DX/DXG CBZ output
 
-####3.5:
+#### 3.5:
 * Added simple content server - Converted files can be now delivered wireless
 * Added proper Windows installer
 * Improved multiprocessing speed
 * GUI tweaks and minor bug fixes
 
-####3.4:
+#### 3.4:
 * Improved PNG output
 * Increased quality of upscaling
 * Added support of file association - KCC can now open CBZ, CBR, CB7, ZIP, RAR, 7Z and PDF files directly
@@ -370,7 +382,7 @@ The app relies and includes the following scripts:
 * Merged DX and DXG profiles
 * Many other minor bug fixes and GUI tweaks
 
-####3.3:
+#### 3.3:
 * Margins are now automatically omitted in Panel View mode
 * Margin color fill is now autodetected
 * Created MOBI files are not longer marked as _Personal_ on newer Kindle models
@@ -384,27 +396,27 @@ The app relies and includes the following scripts:
 * Windows release is now bundled with UnRAR and 7za
 * Small GUI tweaks
 
-####3.2:
+#### 3.2:
 * Too big EPUB files are now splitted before conversion to MOBI
 * Added experimental parser of manga webtoons
 * Improved error handling
 
-####3.2.1:
+#### 3.2.1:
 * Hotfixed crash occurring on OS with Russian locale
 
-####3.1:
+#### 3.1:
 * Added profile: Kindle for Android
 * Add file/directory dialogs now support multiselect
 * Many small fixes and tweaks
 
-####3.0:
+#### 3.0:
 * New QT GUI
 * Merge with AWKCC
 * Added ultra quality mode
 * Added support for custom width/height
 * Added option to disable color conversion
 
-####2.10:
+#### 2.10:
 * Multiprocessing support
 * Kindle Fire support (color EPUB/MOBI)
 * Panel View support for horizontal content
@@ -412,14 +424,14 @@ The app relies and includes the following scripts:
 * Disabled cropping and page number cutting for blank pages
 * Fixed some slugify issues with specific file naming conventions (#50, #51)
 
-####2.9
+#### 2.9
 * Added support for generating a plain CBZ (skipping all the EPUB/MOBI generation) (#45)  
 * Prevent output file overwriting the source one: if a duplicate name is detected, append _kcc to the name  
 * Rarfile library updated to 2.6  
 * Added GIF, TIFF and BMP to supported formats (#42)  
 * Filenames slugifications (#28, #31, #9, #8)
 
-####2.8
+#### 2.8
 * Updated rarfile library  
 * Panel View support + HQ support (#36) - new option: --nopanelviewhq
 * Split profiles for K4NT and K4T  
@@ -428,7 +440,7 @@ The app relies and includes the following scripts:
 * Added generic CSS file  
 * Optimized archive extraction for zip/rar files (#40)  
 
-####2.7
+#### 2.7
 * Lots of GUI improvements (#27, #13)  
 * Added gamma support within --gamma option (defaults to profile-specified gamma) (#26, #27)  
 * Added --nodithering option to prevent dithering optimizations (#27)  
@@ -439,57 +451,57 @@ The app relies and includes the following scripts:
 * Get filetype from magic number (#14)   
 * PDF conversion works again  
 
-####2.6
+#### 2.6
 * Added --rotate option to rotate landscape images instead of splitting them (#16, #24)  
 * Added --output option to customize EPUB output dir/file (#22)  
 * Add rendition:layout and rendition:orientation EPUB meta tags (supported by new kindlegen 2.8)  
 * Fixed natural sorting for files (#18)
 
-####2.5
+#### 2.5
 * Added --black-borders option to set added borders black when page's ratio is not the device's one (#11).  
 * Fixes EPUB containing zipped itself (#10)  
 
-####2.4
+#### 2.4
 * Use temporary directory as workdir (fixes converting from external volumes and zipfiles renaming)  
 * Fixed "add folders" from GUI.
 
-####2.3
+#### 2.3
 * Fixed win32 EPUB generation, folder handling, filenames with spaces and subfolders
 
-####2.2:
+#### 2.2:
 * Added (valid!) EPUB 2.0 output  
 * Rename .zip files to .cbz to avoid overwriting
 
-####2.1
+#### 2.1
 * Added basic error reporting
 
-####2.0
+#### 2.0
 * GUI! AppleScript is gone and Tk is used to provide cross-platform GUI support.
 
-####1.5
+#### 1.5
 * Added subfolder support for multiple chapters.
 
-####1.4.1
+#### 1.4.1
 * Fixed a serious bug on resizing when img ratio was bigger than device one
 
-####1.4
+#### 1.4
 * Added some options for controlling image optimization  
 * Further optimization (ImageOps, page numbering cut, autocontrast)
 
-####1.3
+#### 1.3
 * Fixed an issue in OPF generation for device resolution  
 * Reworked options system (call with -h option to get the inline help)
 
-####1.2
+#### 1.2
 * 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.1.1
+#### 1.1.1
 * Added support for CBZ/CBR files in Kindle Comic Converter
 
-####1.1
+#### 1.1
 * Added support for CBZ/CBR files in comic2ebook.py
 
-####1.0
+#### 1.0
 * Initial version
 
 ## PRIVACY
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 784bfac..89dd7e3 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -1,14 +1,11 @@
 # acidweb/kcc
-FROM debian:jessie
+FROM debian:stretch
 MAINTAINER Paweł Jastrzębski <[email protected]>
 
 ADD ./Build /Build
 
-RUN printf "deb http://httpredir.debian.org/debian stretch main" > /etc/apt/sources.list.d/stretch.list
-RUN printf "Package: *\nPin: release a=testing\nPin-Priority: 400\n" > /etc/apt/preferences.d/stretch.pref
 RUN apt-get update && apt-get -y dist-upgrade
-RUN apt-get -y install build-essential curl ruby ruby-dev libpng-dev libjpeg-dev
-RUN apt-get -y -t testing install python3 python3-dev python3-pyqt5
+RUN apt-get -y install build-essential curl ruby ruby-dev libpng-dev libjpeg-dev python3 python3-dev python3-pyqt5
 RUN curl https://bootstrap.pypa.io/get-pip.py | python3
 RUN apt-get clean -y && apt-get autoclean -y && apt-get autoremove -y && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
 
diff --git a/kcc-c2e.py b/kcc-c2e.py
index cb83188..c17deec 100755
--- a/kcc-c2e.py
+++ b/kcc-c2e.py
@@ -23,14 +23,9 @@ if sys.version_info[0] != 3:
     print('ERROR: This is Python 3 script!')
     exit(1)
 
-from kindlecomicconverter.shared import dependencyCheck
-dependencyCheck(2)
-
 from multiprocessing import freeze_support
-from kindlecomicconverter import __version__
-from kindlecomicconverter.comic2ebook import main
+from kindlecomicconverter.startup import startC2E
 
 if __name__ == "__main__":
     freeze_support()
-    print('comic2ebook v' + __version__ + ' - Written by Ciro Mattia Gonano and Pawel Jastrzebski.')
-    sys.exit(main(sys.argv[1:]))
+    startC2E()
diff --git a/kcc-c2p.py b/kcc-c2p.py
index bc6aa6b..f1fb915 100755
--- a/kcc-c2p.py
+++ b/kcc-c2p.py
@@ -23,14 +23,9 @@ if sys.version_info[0] != 3:
     print('ERROR: This is Python 3 script!')
     exit(1)
 
-from kindlecomicconverter.shared import dependencyCheck
-dependencyCheck(1)
-
 from multiprocessing import freeze_support
-from kindlecomicconverter import __version__
-from kindlecomicconverter.comic2panel import main
+from kindlecomicconverter.startup import startC2P
 
 if __name__ == "__main__":
     freeze_support()
-    print('comic2panel v' + __version__ + ' - Written by Ciro Mattia Gonano and Pawel Jastrzebski.')
-    sys.exit(main(sys.argv[1:]))
+    startC2P()
\ No newline at end of file
diff --git a/kcc.iss b/kcc.iss
index 7cd7685..7dea76f 100644
--- a/kcc.iss
+++ b/kcc.iss
@@ -1,5 +1,5 @@
 #define MyAppName "Kindle Comic Converter"
-#define MyAppVersion "5.3.0"
+#define MyAppVersion "5.3.1"
 #define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
 #define MyAppURL "http://kcc.iosphe.re/"
 #define MyAppExeName "KCC.exe"
diff --git a/kcc.py b/kcc.py
index a93e48f..445b0a3 100755
--- a/kcc.py
+++ b/kcc.py
@@ -63,24 +63,10 @@ if getattr(sys, 'frozen', False):
     except:
         pass
 
-from kindlecomicconverter.shared import dependencyCheck
-dependencyCheck(3)
-
 from multiprocessing import freeze_support
-from kindlecomicconverter import KCC_gui
+from kindlecomicconverter.startup import start
 
 if __name__ == "__main__":
     freeze_support()
-    os.environ['QT_AUTO_SCREEN_SCALE_FACTOR'] = "1"
-    KCCAplication = KCC_gui.QApplicationMessaging(sys.argv)
-    if KCCAplication.isRunning():
-        if len(sys.argv) > 1:
-            KCCAplication.sendMessage(sys.argv[1])
-        else:
-            KCCAplication.sendMessage('ARISE')
-    else:
-        KCCWindow = KCC_gui.QMainWindowKCC()
-        KCCUI = KCC_gui.KCCGUI(KCCAplication, KCCWindow)
-        if len(sys.argv) > 1:
-            KCCUI.handleMessage(sys.argv[1])
-        sys.exit(KCCAplication.exec_())
+    start()
+
diff --git a/kindlecomicconverter/KCC_gui.py b/kindlecomicconverter/KCC_gui.py
index 63f004c..5cf29d7 100644
--- a/kindlecomicconverter/KCC_gui.py
+++ b/kindlecomicconverter/KCC_gui.py
@@ -26,12 +26,12 @@ from shutil import move
 from subprocess import STDOUT, PIPE
 from PyQt5 import QtGui, QtCore, QtWidgets, QtNetwork
 from xml.dom.minidom import parse
+from xml.sax.saxutils import escape
 from psutil import Popen, Process
 from copy import copy
 from distutils.version import StrictVersion
-from xml.sax.saxutils import escape
 from raven import Client
-from .shared import md5Checksum, HTMLStripper, sanitizeTrace, saferRemove
+from .shared import md5Checksum, HTMLStripper, sanitizeTrace
 from . import __version__
 from . import comic2ebook
 from . import metadata
@@ -334,7 +334,7 @@ class WorkerThread(QtCore.QThread):
                 if 'outputPath' in locals():
                     for item in outputPath:
                         if os.path.exists(item):
-                            saferRemove(item)
+                            os.remove(item)
                 self.clean()
                 return
             if not self.errors:
@@ -361,9 +361,9 @@ class WorkerThread(QtCore.QThread):
                     if not self.conversionAlive:
                         for item in outputPath:
                             if os.path.exists(item):
-                                saferRemove(item)
+                                os.remove(item)
                             if os.path.exists(item.replace('.epub', '.mobi')):
-                                saferRemove(item.replace('.epub', '.mobi'))
+                                os.remove(item.replace('.epub', '.mobi'))
                         self.clean()
                         return
                     if self.kindlegenErrorCode[0] == 0:
@@ -384,7 +384,7 @@ class WorkerThread(QtCore.QThread):
                             for item in outputPath:
                                 GUI.progress.content = ''
                                 mobiPath = item.replace('.epub', '.mobi')
-                                saferRemove(mobiPath + '_toclean')
+                                os.remove(mobiPath + '_toclean')
                                 if GUI.targetDirectory and GUI.targetDirectory != os.path.dirname(mobiPath):
                                     try:
                                         move(mobiPath, GUI.targetDirectory)
@@ -402,9 +402,9 @@ class WorkerThread(QtCore.QThread):
                             for item in outputPath:
                                 mobiPath = item.replace('.epub', '.mobi')
                                 if os.path.exists(mobiPath):
-                                    saferRemove(mobiPath)
+                                    os.remove(mobiPath)
                                 if os.path.exists(mobiPath + '_toclean'):
-                                    saferRemove(mobiPath + '_toclean')
+                                    os.remove(mobiPath + '_toclean')
                             MW.addMessage.emit('Failed to process MOBI file!', 'error', False)
                             MW.addTrayMessage.emit('Failed to process MOBI file!', 'Critical')
                     else:
@@ -412,9 +412,9 @@ class WorkerThread(QtCore.QThread):
                         epubSize = (os.path.getsize(self.kindlegenErrorCode[2])) // 1024 // 1024
                         for item in outputPath:
                             if os.path.exists(item):
-                                saferRemove(item)
+                                os.remove(item)
                             if os.path.exists(item.replace('.epub', '.mobi')):
-                                saferRemove(item.replace('.epub', '.mobi'))
+                                os.remove(item.replace('.epub', '.mobi'))
                         MW.addMessage.emit('KindleGen failed to create MOBI!', 'error', False)
                         MW.addTrayMessage.emit('KindleGen failed to create MOBI!', 'Critical')
                         if self.kindlegenErrorCode[0] == 1 and self.kindlegenErrorCode[1] != '':
diff --git a/kindlecomicconverter/__init__.py b/kindlecomicconverter/__init__.py
index c966b7c..3622f15 100644
--- a/kindlecomicconverter/__init__.py
+++ b/kindlecomicconverter/__init__.py
@@ -1,4 +1,4 @@
-__version__ = '5.3.0'
+__version__ = '5.3.1'
 __license__ = 'ISC'
 __copyright__ = '2012-2017, Ciro Mattia Gonano <[email protected]>, Pawel Jastrzebski <[email protected]>'
 __docformat__ = 'restructuredtext en'
diff --git a/kindlecomicconverter/cbxarchive.py b/kindlecomicconverter/cbxarchive.py
index 726432b..7bd833f 100644
--- a/kindlecomicconverter/cbxarchive.py
+++ b/kindlecomicconverter/cbxarchive.py
@@ -22,12 +22,8 @@ from zipfile import is_zipfile, ZipFile
 from subprocess import STDOUT, PIPE
 from psutil import Popen
 from shutil import move, copy
-try:
-    from scandir import walk
-except ImportError:
-    walk = os.walk
 from . import rarfile
-from .shared import check7ZFile as is_7zfile, saferReplace, saferRemove
+from .shared import check7ZFile as is_7zfile
 
 
 class CBxArchive:
@@ -50,12 +46,12 @@ class CBxArchive:
         filelist = []
         for f in cbzFile.namelist():
             if f.startswith('__MACOSX') or f.endswith('.DS_Store') or f.endswith('humbs.db'):
-                pass    # skip MacOS special files
+                pass
             elif f.endswith('/'):
                 try:
                     os.makedirs(os.path.join(targetdir, f))
                 except Exception:
-                    pass  # the dir exists so we are going to extract the images only.
+                    pass
             else:
                 filelist.append(f)
         cbzFile.extractall(targetdir, filelist)
@@ -63,24 +59,18 @@ class CBxArchive:
     def extractCBR(self, targetdir):
         cbrFile = rarfile.RarFile(self.origFileName)
         cbrFile.extractall(targetdir)
-        for root, dirnames, filenames in walk(targetdir):
+        for root, _, filenames in os.walk(targetdir):
             for filename in filenames:
                 if filename.startswith('__MACOSX') or filename.endswith('.DS_Store') or filename.endswith('humbs.db'):
-                    saferRemove(os.path.join(root, filename))
+                    os.remove(os.path.join(root, filename))
 
     def extractCB7(self, targetdir):
-        # Workaround for some wide UTF-8 + Popen abnormalities
-        if sys.platform.startswith('darwin'):
-            copy(self.origFileName, os.path.join(os.path.dirname(self.origFileName), 'TMP_KCC_TMP'))
-            self.origFileName = os.path.join(os.path.dirname(self.origFileName), 'TMP_KCC_TMP')
         output = Popen('7za x "' + self.origFileName + '" -xr!__MACOSX -xr!.DS_Store -xr!thumbs.db -xr!Thumbs.db -o"' +
                        targetdir + '"', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
         extracted = False
         for line in output.stdout:
             if b"Everything is Ok" in line:
                 extracted = True
-        if sys.platform.startswith('darwin'):
-            saferRemove(self.origFileName)
         if not extracted:
             raise OSError
 
@@ -96,10 +86,6 @@ class CBxArchive:
             adir.remove('ComicInfo.xml')
         if len(adir) == 1 and os.path.isdir(os.path.join(targetdir, adir[0])):
             for f in os.listdir(os.path.join(targetdir, adir[0])):
-                # If directory names contain UTF-8 chars shutil.move can't clean up the mess alone
-                if os.path.isdir(os.path.join(targetdir, f)):
-                    saferReplace(os.path.join(targetdir, adir[0], f), os.path.join(targetdir, adir[0], f + '-A'))
-                    f += '-A'
                 move(os.path.join(targetdir, adir[0], f), targetdir)
             os.rmdir(os.path.join(targetdir, adir[0]))
         return targetdir
diff --git a/kindlecomicconverter/comic2ebook.py b/kindlecomicconverter/comic2ebook.py
index 404ca11..f5c6320 100755
--- a/kindlecomicconverter/comic2ebook.py
+++ b/kindlecomicconverter/comic2ebook.py
@@ -36,17 +36,13 @@ from uuid import uuid4
 from slugify import slugify as slugifyExt
 from PIL import Image
 from subprocess import STDOUT, PIPE
-from psutil import Popen, virtual_memory
+from psutil import Popen, virtual_memory, disk_usage
 from html import escape
 try:
     from PyQt5 import QtCore
 except ImportError:
     QtCore = None
-try:
-    from scandir import walk
-except ImportError:
-    walk = os.walk
-from .shared import md5Checksum, getImageFileName, walkSort, walkLevel, saferReplace, saferRemove, sanitizeTrace
+from .shared import md5Checksum, getImageFileName, walkSort, walkLevel, sanitizeTrace
 from . import comic2panel
 from . import image
 from . import cbxarchive
@@ -85,11 +81,11 @@ def buildHTML(path, imgfile, imgfilepath):
     imgfilepath = md5Checksum(imgfilepath)
     filename = getImageFileName(imgfile)
     deviceres = options.profileData[1]
-    if "Rotated" in options.imgIndex[imgfilepath]:
+    if "Rotated" in options.imgMetadata[imgfilepath]:
         rotatedPage = True
     else:
         rotatedPage = False
-    if "BlackFill" in options.imgIndex[imgfilepath]:
+    if "BlackBackground" in options.imgMetadata[imgfilepath]:
         additionalStyle = 'background-color:#000000;'
     else:
         additionalStyle = 'background-color:#FFFFFF;'
@@ -424,7 +420,7 @@ def buildEPUB(path, chapterNames, tomeNumber):
                   "display: none;\n",
                   "}\n"])
     f.close()
-    for (dirpath, dirnames, filenames) in walk(os.path.join(path, 'OEBPS', 'Images')):
+    for dirpath, dirnames, filenames in os.walk(os.path.join(path, 'OEBPS', 'Images')):
         chapter = False
         dirnames, filenames = walkSort(dirnames, filenames)
         for afile in filenames:
@@ -461,11 +457,11 @@ def imgDirectoryProcessing(path):
     global workerPool, workerOutput
     workerPool = Pool()
     workerOutput = []
-    options.imgIndex = {}
-    options.imgPurgeIndex = []
+    options.imgMetadata = {}
+    options.imgOld = []
     work = []
     pagenumber = 0
-    for (dirpath, dirnames, filenames) in walk(path):
+    for dirpath, _, filenames in os.walk(path):
         for afile in filenames:
             pagenumber += 1
             work.append([afile, dirpath, options])
@@ -482,9 +478,9 @@ def imgDirectoryProcessing(path):
         if len(workerOutput) > 0:
             rmtree(os.path.join(path, '..', '..'), True)
             raise RuntimeError("One of workers crashed. Cause: " + workerOutput[0][0], workerOutput[0][1])
-        for file in options.imgPurgeIndex:
+        for file in options.imgOld:
             if os.path.isfile(file):
-                saferRemove(file)
+                os.remove(file)
     else:
         rmtree(os.path.join(path, '..', '..'), True)
         raise UserWarning("Source directory is empty.")
@@ -497,8 +493,8 @@ def imgFileProcessingTick(output):
     else:
         for page in output:
             if page is not None:
-                options.imgIndex[page[0]] = page[1]
-                options.imgPurgeIndex.append(page[2])
+                options.imgMetadata[page[0]] = page[1]
+                options.imgOld.append(page[2])
     if GUI:
         GUI.progressBarTick.emit('tick')
         if not GUI.conversionAlive:
@@ -513,7 +509,7 @@ def imgFileProcessing(work):
         output = []
         workImg = image.ComicPageParser((dirpath, afile), opt)
         for i in workImg.payload:
-            img = image.ComicPage(i[0], i[1], i[2], i[3], i[4], opt)
+            img = image.ComicPage(opt, *i)
             if opt.cropping == 2 and not opt.webtoon:
                 img.cropPageNumber(opt.croppingp)
             if opt.cropping > 0 and not opt.webtoon:
@@ -530,6 +526,8 @@ def imgFileProcessing(work):
 
 def getWorkFolder(afile):
     if os.path.isdir(afile):
+        if disk_usage(gettempdir())[2] < getDirectorySize(afile) * 2.5:
+            raise UserWarning("Not enough disk space to perform conversion.")
         workdir = mkdtemp('', 'KCC-')
         try:
             os.rmdir(workdir)
@@ -540,24 +538,27 @@ def getWorkFolder(afile):
         except:
             rmtree(workdir, True)
             raise UserWarning("Failed to prepare a workspace.")
-    elif os.path.isfile(afile) and afile.lower().endswith('.pdf'):
-        pdf = pdfjpgextract.PdfJpgExtract(afile)
-        path, njpg = pdf.extract()
-        if njpg == 0:
-            rmtree(path, True)
-            raise UserWarning("Failed to extract images from PDF file.")
     elif os.path.isfile(afile):
-        workdir = mkdtemp('', 'KCC-')
-        cbx = cbxarchive.CBxArchive(afile)
-        if cbx.isCbxFile():
-            try:
-                path = cbx.extract(workdir)
-            except:
-                rmtree(workdir, True)
-                raise UserWarning("Failed to extract archive.")
+        if disk_usage(gettempdir())[2] < os.path.getsize(afile) * 2.5:
+            raise UserWarning("Not enough disk space to perform conversion.")
+        if afile.lower().endswith('.pdf'):
+            pdf = pdfjpgextract.PdfJpgExtract(afile)
+            path, njpg = pdf.extract()
+            if njpg == 0:
+                rmtree(path, True)
+                raise UserWarning("Failed to extract images from PDF file.")
         else:
-            rmtree(workdir, True)
-            raise UserWarning("Failed to detect archive format.")
+            workdir = mkdtemp('', 'KCC-')
+            cbx = cbxarchive.CBxArchive(afile)
+            if cbx.isCbxFile():
+                try:
+                    path = cbx.extract(workdir)
+                except:
+                    rmtree(workdir, True)
+                    raise UserWarning("Failed to extract archive.")
+            else:
+                rmtree(workdir, True)
+                raise UserWarning("Failed to detect archive format.")
     else:
         raise UserWarning("Failed to open source file/directory.")
     sanitizePermissions(path)
@@ -619,7 +620,7 @@ def getComicInfo(path, originalPath):
         try:
             xml = metadata.MetadataParser(xmlPath)
         except Exception:
-            saferRemove(xmlPath)
+            os.remove(xmlPath)
             return
         options.authors = []
         if defaultTitle:
@@ -644,7 +645,7 @@ def getComicInfo(path, originalPath):
             options.chapters = xml.data['Bookmarks']
         if xml.data['Summary']:
             options.summary = escape(xml.data['Summary'])
-        saferRemove(xmlPath)
+        os.remove(xmlPath)
 
 
 def getCoversFromMCB(mangaID):
@@ -663,7 +664,7 @@ def getCoversFromMCB(mangaID):
 
 def getDirectorySize(start_path='.'):
     total_size = 0
-    for dirpath, dirnames, filenames in walk(start_path):
+    for dirpath, _, filenames in os.walk(start_path):
         for f in filenames:
             fp = os.path.join(dirpath, f)
             total_size += os.path.getsize(fp)
@@ -688,7 +689,7 @@ def getPanelViewSize(deviceres, size):
 
 def sanitizeTree(filetree):
     chapterNames = {}
-    for root, dirs, files in walk(filetree, False):
+    for root, dirs, files in os.walk(filetree, False):
         for name in files:
             splitname = os.path.splitext(name)
             slugified = slugify(splitname[0])
@@ -698,7 +699,7 @@ def sanitizeTree(filetree):
             newKey = os.path.join(root, slugified + splitname[1])
             key = os.path.join(root, name)
             if key != newKey:
-                saferReplace(key, newKey)
+                os.replace(key, newKey)
         for name in dirs:
             tmpName = name
             slugified = slugify(name)
@@ -708,13 +709,13 @@ def sanitizeTree(filetree):
             newKey = os.path.join(root, slugified)
             key = os.path.join(root, name)
             if key != newKey:
-                saferReplace(key, newKey)
+                os.replace(key, newKey)
     return chapterNames
 
 
 def sanitizeTreeKobo(filetree):
     pageNumber = 0
-    for root, dirs, files in walk(filetree):
+    for root, dirs, files in os.walk(filetree):
         dirs, files = walkSort(dirs, files)
         for name in files:
             splitname = os.path.splitext(name)
@@ -726,11 +727,11 @@ def sanitizeTreeKobo(filetree):
             newKey = os.path.join(root, slugified + splitname[1])
             key = os.path.join(root, name)
             if key != newKey:
-                saferReplace(key, newKey)
+                os.replace(key, newKey)
 
 
 def sanitizePermissions(filetree):
-    for root, dirs, files in walk(filetree, False):
+    for root, dirs, files in os.walk(filetree, False):
         for name in files:
             os.chmod(os.path.join(root, name), S_IWRITE | S_IREAD)
         for name in dirs:
@@ -785,7 +786,7 @@ def splitProcess(path, mode):
                     move(os.path.join(root, name), os.path.join(currentTarget, name))
     else:
         firstTome = True
-        for root, dirs, files in walkLevel(path, 0):
+        for root, dirs, _ in walkLevel(path, 0):
             for name in dirs:
                 if not firstTome:
                     currentTarget, pathRoot = createNewTome()
@@ -799,9 +800,12 @@ def splitProcess(path, mode):
 def detectCorruption(tmpPath, orgPath):
     imageNumber = 0
     imageSmaller = 0
-    for root, dirs, files in walk(tmpPath, False):
+    alreadyProcessed = False
+    for root, _, files in os.walk(tmpPath, False):
         for name in files:
             if getImageFileName(name) is not None:
+                if not alreadyProcessed and getImageFileName(name)[0].endswith('-kcc'):
+                    alreadyProcessed = True
                 path = os.path.join(root, name)
                 pathOrg = orgPath + path.split('OEBPS' + os.path.sep + 'Images')[1]
                 if os.path.getsize(path) == 0:
@@ -822,7 +826,13 @@ def detectCorruption(tmpPath, orgPath):
                     else:
                         raise RuntimeError('Image file %s is corrupted.' % pathOrg)
             else:
-                saferRemove(os.path.join(root, name))
+                os.remove(os.path.join(root, name))
+    if alreadyProcessed:
+        print("WARNING: Source files are probably created by KCC. Second conversion will decrease quality.")
+        if GUI:
+            GUI.addMessage.emit('Source files are probably created by KCC. Second conversion will decrease quality.',
+                                'warning', False)
+            GUI.addMessage.emit('', '', False)
     if imageSmaller > imageNumber * 0.25 and not options.upscale and not options.stretch:
         print("WARNING: More than 25% of images are smaller than target device resolution. "
               "Consider enabling stretching or upscaling to improve readability.")
@@ -850,7 +860,7 @@ def makeZIP(zipFilename, baseDir, isEPUB=False):
     zipOutput = ZipFile(zipFilename, 'w', ZIP_DEFLATED)
     if isEPUB:
         zipOutput.writestr('mimetype', 'application/epub+zip', ZIP_STORED)
-    for dirpath, dirnames, filenames in walk(baseDir):
+    for dirpath, _, filenames in os.walk(baseDir):
         for name in filenames:
             path = os.path.normpath(os.path.join(dirpath, name))
             aPath = os.path.normpath(os.path.join(dirpath.replace(baseDir, ''), name))
@@ -1107,14 +1117,14 @@ def makeBook(source, qtGUI=None):
                 print('Error: Failed to tweak KindleGen output!')
                 return filepath
             else:
-                saferRemove(i.replace('.epub', '.mobi') + '_toclean')
+                os.remove(i.replace('.epub', '.mobi') + '_toclean')
             if k.path and k.coverSupport:
                 options.covers[filepath.index(i)][0].saveToKindle(k, options.covers[filepath.index(i)][1])
     return filepath
 
 
 def makeMOBIFix(item, uuid):
-    saferRemove(item)
+    os.remove(item)
     mobiPath = item.replace('.epub', '.mobi')
     move(mobiPath, mobiPath + '_toclean')
     try:
diff --git a/kindlecomicconverter/comic2panel.py b/kindlecomicconverter/comic2panel.py
index 522587c..e173575 100644
--- a/kindlecomicconverter/comic2panel.py
+++ b/kindlecomicconverter/comic2panel.py
@@ -24,15 +24,11 @@ from shutil import rmtree, copytree, move
 from optparse import OptionParser, OptionGroup
 from multiprocessing import Pool
 from PIL import Image, ImageStat, ImageOps
-from .shared import getImageFileName, walkLevel, walkSort, saferRemove, sanitizeTrace
+from .shared import getImageFileName, walkLevel, walkSort, sanitizeTrace
 try:
     from PyQt5 import QtCore
 except ImportError:
     QtCore = None
-try:
-    from scandir import walk
-except ImportError:
-    walk = os.walk
 
 
 def mergeDirectoryTick(output):
@@ -52,7 +48,7 @@ def mergeDirectory(work):
         imagesValid = []
         sizes = []
         targetHeight = 0
-        for root, dirs, files in walkLevel(directory, 0):
+        for root, _, files in walkLevel(directory, 0):
             for name in files:
                 if getImageFileName(name) is not None:
                     i = Image.open(os.path.join(root, name))
@@ -77,7 +73,7 @@ def mergeDirectory(work):
                     img = ImageOps.fit(img, (targetWidth, img.size[1]), method=Image.BICUBIC, centering=(0.5, 0.5))
                 result.paste(img, (0, y))
                 y += img.size[1]
-                saferRemove(i)
+                os.remove(i)
             savePath = os.path.split(imagesValid[0])
             result.save(os.path.join(savePath[0], os.path.splitext(savePath[1])[0] + '.png'), 'PNG')
     except Exception:
@@ -203,7 +199,7 @@ def splitImage(work):
                         targetHeight += panels[panel][2]
                     newPage.save(os.path.join(path, fileExpanded[0] + '-' + str(pageNumber) + '.png'), 'PNG')
                     pageNumber += 1
-            saferRemove(filePath)
+            os.remove(filePath)
     except Exception:
         return str(sys.exc_info()[1]), sanitizeTrace(sys.exc_info()[2])
 
@@ -250,7 +246,7 @@ def main(argv=None, qtGUI=None):
                 mergeWorkerOutput = []
                 mergeWorkerPool = Pool()
                 mergeWork.append([options.targetDir])
-                for root, dirs, files in walk(options.targetDir, False):
+                for root, dirs, files in os.walk(options.targetDir, False):
                     dirs, files = walkSort(dirs, files)
                     for directory in dirs:
                         directoryNumer += 1
@@ -269,13 +265,13 @@ def main(argv=None, qtGUI=None):
                     rmtree(options.targetDir, True)
                     raise RuntimeError("One of workers crashed. Cause: " + mergeWorkerOutput[0][0], mergeWorkerOutput[0][1])
             print("Splitting images...")
-            for root, dirs, files in walk(options.targetDir, False):
+            for root, _, files in os.walk(options.targetDir, False):
                 for name in files:
                     if getImageFileName(name) is not None:
                         pagenumber += 1
                         work.append([root, name, options])
                     else:
-                        saferRemove(os.path.join(root, name))
+                        os.remove(os.path.join(root, name))
             if GUI:
                 GUI.progressBarTick.emit('Splitting images')
                 GUI.progressBarTick.emit(str(pagenumber))
diff --git a/kindlecomicconverter/image.py b/kindlecomicconverter/image.py
index ecc08b9..5035a9e 100755
--- a/kindlecomicconverter/image.py
+++ b/kindlecomicconverter/image.py
@@ -206,7 +206,7 @@ class ComicPageParser:
 
 
 class ComicPage:
-    def __init__(self, mode, path, image, color, fill, options):
+    def __init__(self, options, mode, path, image, color, fill):
         self.opt = options
         _, self.size, self.palette, self.gamma = self.opt.profileData
         self.image = image
@@ -232,16 +232,16 @@ class ComicPage:
             if self.rotated:
                 flags.append('Rotated')
             if self.fill != 'white':
-                flags.append('BlackFill')
+                flags.append('BlackBackground')
             if self.opt.forcepng:
                 self.targetPath += '.png'
                 self.image.save(self.targetPath, 'PNG', optimize=1)
             else:
                 self.targetPath += '.jpg'
-                self.image.save(self.targetPath, 'JPEG', optimize=1, quality=80)
+                self.image.save(self.targetPath, 'JPEG', optimize=1, quality=85)
             return [md5Checksum(self.targetPath), flags, self.orgPath]
-        except IOError:
-            raise RuntimeError('Cannot save image.')
+        except IOError as err:
+            raise RuntimeError('Cannot save image. ' + str(err))
 
     def autocontrastImage(self):
         gamma = self.opt.gamma
@@ -361,7 +361,7 @@ class Cover:
 
     def save(self):
         try:
-            self.image.save(self.target, "JPEG", optimize=1, quality=80)
+            self.image.save(self.target, "JPEG", optimize=1, quality=85)
         except IOError:
             raise RuntimeError('Failed to process downloaded cover.')
 
@@ -369,6 +369,6 @@ class Cover:
         self.image = self.image.resize((300, 470), Image.ANTIALIAS)
         try:
             self.image.save(os.path.join(kindle.path.split('documents')[0], 'system', 'thumbnails',
-                                         'thumbnail_' + asin + '_EBOK_portrait.jpg'), 'JPEG')
+                                         'thumbnail_' + asin + '_EBOK_portrait.jpg'), 'JPEG', optimize=1, quality=85)
         except IOError:
             raise RuntimeError('Failed to upload cover.')
diff --git a/kindlecomicconverter/shared.py b/kindlecomicconverter/shared.py
index 3843f39..00ae3b9 100644
--- a/kindlecomicconverter/shared.py
+++ b/kindlecomicconverter/shared.py
@@ -27,10 +27,6 @@ from tempfile import mkdtemp
 from zipfile import ZipFile, ZIP_DEFLATED
 from re import split
 from traceback import format_tb
-try:
-    from scandir import walk
-except ImportError:
-    walk = os.walk
 
 
 class HTMLStripper(HTMLParser):
@@ -71,7 +67,7 @@ def walkLevel(some_dir, level=1):
     some_dir = some_dir.rstrip(os.path.sep)
     assert os.path.isdir(some_dir)
     num_sep = some_dir.count(os.path.sep)
-    for root, dirs, files in walk(some_dir):
+    for root, dirs, files in os.walk(some_dir):
         dirs, files = walkSort(dirs, files)
         yield root, dirs, files
         num_sep_this = root.count(os.path.sep)
@@ -96,30 +92,6 @@ def check7ZFile(filePath):
     return header == b"7z\xbc\xaf'\x1c"
 
 
-def saferReplace(old, new):
-    for x in range(30):
-        try:
-            os.replace(old, new)
-        except PermissionError:
-            sleep(1)
-        else:
-            break
-    else:
-        raise PermissionError("Failed to move the file.")
-
-
-def saferRemove(target):
-    for x in range(30):
-        try:
-            os.remove(target)
-        except PermissionError:
-            sleep(1)
-        else:
-            break
-    else:
-        raise PermissionError("Failed to remove the file.")
-
-
 def removeFromZIP(zipfname, *filenames):
     tempdir = mkdtemp('', 'KCC-')
     try:
@@ -129,15 +101,7 @@ def removeFromZIP(zipfname, *filenames):
                 for item in zipread.infolist():
                     if item.filename not in filenames:
                         zipwrite.writestr(item, zipread.read(item.filename))
-        for x in range(30):
-            try:
-                copy(tempname, zipfname)
-            except PermissionError:
-                sleep(1)
-            else:
-                break
-        else:
-            raise PermissionError
+        copy(tempname, zipfname)
     finally:
         rmtree(tempdir, True)
 
@@ -164,33 +128,26 @@ def dependencyCheck(level):
         try:
             import raven
         except ImportError:
-            missing.append('raven 5.13.0+')
+            missing.append('raven 6.0.0+')
     if level > 1:
         try:
             from psutil import __version__ as psutilVersion
-            if StrictVersion('4.1.0') > StrictVersion(psutilVersion):
-                missing.append('psutil 4.1.0+')
+            if StrictVersion('5.0.0') > StrictVersion(psutilVersion):
+                missing.append('psutil 5.0.0+')
         except ImportError:
-            missing.append('psutil 4.1.0+')
+            missing.append('psutil 5.0.0+')
         try:
             from slugify import __version__ as slugifyVersion
-            if StrictVersion('1.2.0') > StrictVersion(slugifyVersion):
-                missing.append('python-slugify 1.2.0+')
+            if StrictVersion('1.2.1') > StrictVersion(slugifyVersion):
+                missing.append('python-slugify 1.2.1+')
         except ImportError:
-            missing.append('python-slugify 1.2.0+')
+            missing.append('python-slugify 1.2.1+')
     try:
         from PIL import PILLOW_VERSION as pillowVersion
-        if StrictVersion('3.2.0') > StrictVersion(pillowVersion):
-            missing.append('Pillow 3.2.0+')
+        if StrictVersion('4.0.0') > StrictVersion(pillowVersion):
+            missing.append('Pillow 4.0.0+')
     except ImportError:
-        missing.append('Pillow 3.2.0+')
-    if version_info[1] < 5:
-        try:
-            from scandir import __version__ as scandirVersion
-            if StrictVersion('1.2') > StrictVersion(scandirVersion):
-                missing.append('scandir 1.2+')
-        except ImportError:
-            missing.append('scandir 1.2+')
+        missing.append('Pillow 4.0.0+')
     if len(missing) > 0:
         print('ERROR: ' + ', '.join(missing) + ' is not installed!')
         exit(1)
diff --git a/kindlecomicconverter/startup.py b/kindlecomicconverter/startup.py
new file mode 100644
index 0000000..4c47a17
--- /dev/null
+++ b/kindlecomicconverter/startup.py
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2012-2014 Ciro Mattia Gonano <[email protected]>
+# Copyright (c) 2013-2017 Pawel Jastrzebski <[email protected]>
+#
+# Permission to use, copy, modify, and/or distribute this software for
+# any purpose with or without fee is hereby granted, provided that the
+# above copyright notice and this permission notice appear in all
+# copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
+# OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+#
+
+import os
+import sys
+from . import __version__
+from .shared import dependencyCheck
+
+def start():
+    dependencyCheck(3)
+    from . import KCC_gui
+    os.environ['QT_AUTO_SCREEN_SCALE_FACTOR'] = "1"
+    KCCAplication = KCC_gui.QApplicationMessaging(sys.argv)
+    if KCCAplication.isRunning():
+        if len(sys.argv) > 1:
+            KCCAplication.sendMessage(sys.argv[1])
+        else:
+            KCCAplication.sendMessage('ARISE')
+    else:
+        KCCWindow = KCC_gui.QMainWindowKCC()
+        KCCUI = KCC_gui.KCCGUI(KCCAplication, KCCWindow)
+        if len(sys.argv) > 1:
+            KCCUI.handleMessage(sys.argv[1])
+        sys.exit(KCCAplication.exec_())
+
+def startC2E():
+    dependencyCheck(2)
+    from .comic2ebook import main
+    print('comic2ebook v' + __version__ + ' - Written by Ciro Mattia Gonano and Pawel Jastrzebski.')
+    sys.exit(main(sys.argv[1:]))
+
+def startC2P():
+    dependencyCheck(1)
+    from .comic2panel import main
+    print('comic2panel v' + __version__ + ' - Written by Ciro Mattia Gonano and Pawel Jastrzebski.')
+    sys.exit(main(sys.argv[1:]))
\ No newline at end of file
diff --git a/other/osx/Info.plist b/other/osx/Info.plist
index 7600993..dce11bb 100644
--- a/other/osx/Info.plist
+++ b/other/osx/Info.plist
@@ -30,7 +30,7 @@
 	<key>CFBundleExecutable</key>
 	<string>MacOS/Kindle Comic Converter</string>
 	<key>CFBundleGetInfoString</key>
-	<string>KindleComicConverter 5.3.0, written 2012-2017 by Ciro Mattia Gonano and Pawel Jastrzebski</string>
+	<string>KindleComicConverter 5.3.1, written 2012-2017 by Ciro Mattia Gonano and Pawel Jastrzebski</string>
 	<key>CFBundleIconFile</key>
 	<string>comic2ebook.icns</string>
 	<key>CFBundleIdentifier</key>
@@ -42,11 +42,11 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>5.3.0</string>
+	<string>5.3.1</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
-	<string>5.3.0</string>
+	<string>5.3.1</string>
 	<key>LSEnvironment</key>
 	<dict>
 		<key>PATH</key>
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..0478a95
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,5 @@
+PyQt5>=5.6.0
+Pillow>=4.0.0
+psutil>=5.0.0
+python-slugify>=1.2.1
+raven>=6.0.0
\ No newline at end of file
diff --git a/setup.py b/setup.py
index d355265..7e330fe 100755
--- a/setup.py
+++ b/setup.py
@@ -6,7 +6,7 @@ Usage (Windows):
     py -3 setup.py build_binary
 
 Usage (Linux/OS X):
-    python3 setup.py build_binary or python3 setup.py build_binary --pyz
+    python3 setup.py build_binary
 """
 
 import os
@@ -20,8 +20,6 @@ from kindlecomicconverter import __version__
 NAME = 'KindleComicConverter'
 MAIN = 'kcc.py'
 VERSION = __version__
-OPTIONS = {}
-
 
 class BuildBinaryCommand(distutils.cmd.Command):
     description = 'build binary release'
@@ -62,74 +60,12 @@ class BuildBinaryCommand(distutils.cmd.Command):
                 os.system('setup.bat')
             exit(0)
         else:
-            if self.pyz:
-                script = '''
-                cp kcc.py __main__.py
-                zip kcc.zip __main__.py kindlecomicconverter/*.py
-                echo "#!/usr/bin/env python3" > kcc-bin
-                cat kcc.zip >> kcc-bin
-                chmod +x kcc-bin
-
-                cp kcc-c2e.py __main__.py
-                zip kcc-c2e.zip __main__.py kindlecomicconverter/*.py
-                echo "#!/usr/bin/env python3" > kcc-c2e-bin
-                cat kcc-c2e.zip >> kcc-c2e-bin
-                chmod +x kcc-c2e-bin
-
-                cp kcc-c2p.py __main__.py
-                zip kcc-c2p.zip __main__.py kindlecomicconverter/*.py
-                echo "#!/usr/bin/env python3" > kcc-c2p-bin
-                cat kcc-c2p.zip >> kcc-c2p-bin
-                chmod +x kcc-c2p-bin
-
-                mkdir dist
-                tar --xform s:^.*/:: \
-                --xform s/LICENSE.txt/LICENSE/ \
-                --xform s/kcc-bin/kcc/ \
-                --xform s/kcc-c2p-bin/kcc-c2p/ \
-                --xform s/kcc-c2e-bin/kcc-c2e/ \
-                --xform s/comic2ebook/kcc/ \
-                -czf dist/KindleComicConverter_linux_''' + VERSION + '''.tar.gz \
-                kcc-bin kcc-c2e-bin kcc-c2p-bin LICENSE.txt README.md icons/comic2ebook.png
-                rm __main__.py kcc.zip kcc-c2e.zip kcc-c2p.zip kcc-bin kcc-c2e-bin kcc-c2p-bin
-                '''
-                os.system("bash -c '%s'" % script)
-                exit(0)
-            else:
-                os.system('docker run --rm -v ' + os.getcwd() + ':/app -e KCCVER=' + VERSION + ' acidweb/kcc')
-                exit(0)
-
-
-class BuildCommand(build):
-    def run(self):
-        os.makedirs('build/_scripts/', exist_ok=True)
-        shutil.copyfile('kcc.py', 'build/_scripts/kcc')
-        shutil.copyfile('kcc-c2e.py', 'build/_scripts/kcc-c2e')
-        shutil.copyfile('kcc-c2p.py', 'build/_scripts/kcc-c2p')
-        # noinspection PyShadowingNames
-        OPTIONS = dict(
-            scripts=['build/_scripts/kcc',
-                     'build/_scripts/kcc-c2e',
-                     'build/_scripts/kcc-c2p'],
-            packages=['kcc'],
-            install_requires=[
-                'PyQt5>=5.6.0'
-                'Pillow>=3.2.0',
-                'psutil>=4.1.0',
-                'python-slugify>=1.2.0',
-                'raven>=5.13.0',
-            ],
-            zip_safe=False,
-        )
-        if sys.version_info[1] < 5:
-            OPTIONS['install_requires'].append('scandir>=1.2.0')
-        build.run(self)
-
+            os.system('docker run --rm -v ' + os.getcwd() + ':/app -e KCCVER=' + VERSION + ' acidweb/kcc')
+            exit(0)
 
 setuptools.setup(
     cmdclass={
         'build_binary': BuildBinaryCommand,
-        'build': BuildCommand,
     },
     name=NAME,
     version=VERSION,
@@ -137,7 +73,25 @@ setuptools.setup(
     author_email='[email protected], [email protected]',
     description='Comic and Manga converter for e-book readers.',
     license='ISC License (ISCL)',
-    keywords='kindle comic mobipocket mobi cbz cbr manga',
+    keywords=['kindle', 'kobo', 'comic', 'manga', 'mobi', 'epub', 'cbz'],
     url='http://github.com/ciromattia/kcc',
-    **OPTIONS
+    entry_points={
+        'console_scripts': [
+            'kcc-c2e = kindlecomicconverter.startup:startC2E',
+            'kcc-c2p = kindlecomicconverter.startup:startC2P',
+        ],
+        'gui_scripts': [
+            'kcc = kindlecomicconverter.startup:start',
+        ],
+    },
+    packages=['kindlecomicconverter'],
+    install_requires=[
+        'PyQt5>=5.6.0',
+        'Pillow>=4.0.0',
+        'psutil>=5.0.0',
+        'python-slugify>=1.2.1',
+        'raven>=6.0.0',
+    ],
+    classifiers = [],
+    zip_safe=False,
 )