1
0
mirror of https://github.com/ciromattia/kcc synced 2026-04-18 06:58:58 +00:00

Compare commits

..

29 Commits
4.1 ... 4.3

Author SHA1 Message Date
Paweł Jastrzębski
b174534c1c Merge pull request #113 from ciromattia/4.x
4.3
2014-09-29 18:05:32 +02:00
Paweł Jastrzębski
19d486a4ee Updated README 2014-09-28 22:01:22 +02:00
Paweł Jastrzębski
652762b709 Updated README + version bump 2014-09-28 13:23:40 +02:00
Paweł Jastrzębski
e6df87f8fd CLI: Added tool detection 2014-09-28 13:16:13 +02:00
Paweł Jastrzębski
1a9cd0beb5 Moved MOBI creation to main code (close #111) 2014-09-28 13:01:42 +02:00
Paweł Jastrzębski
108e351126 Refactored locking mechanism (close #112) 2014-09-27 11:44:42 +02:00
Paweł Jastrzębski
dfe3e10470 Updated setup 2014-09-22 18:35:53 +02:00
Paweł Jastrzębski
787ad9fa66 Updated multiple device profiles 2014-09-18 19:05:24 +02:00
Paweł Jastrzębski
f10e8869a9 Added Kobo Aura H2O profile 2014-09-03 07:16:26 +02:00
Paweł Jastrzębski
715ada328f Tweaked error reporting (close #109) 2014-08-24 09:56:59 +02:00
Paweł Jastrzębski
56f23ab488 Merge pull request #108 from ciromattia/4.x
4.2.1
2014-08-03 11:22:28 +02:00
Paweł Jastrzębski
996af59e00 Updated README + version bump 2014-08-03 11:21:43 +02:00
Paweł Jastrzębski
37aa84c4aa Fixed MOBI processing anomalies 2014-08-02 07:54:15 +02:00
Paweł Jastrzębski
50574632e6 Replaced margin color detection algorithm 2014-08-01 07:23:55 +02:00
Paweł Jastrzębski
0afb9e8c0b Kindle: Fixed high quality mode (close #106) 2014-07-31 21:49:03 +02:00
Paweł Jastrzębski
7511c7eed6 Kindle DX: Changed default output format to CBZ 2014-07-29 19:59:21 +02:00
Paweł Jastrzębski
836a4146f9 MCD: Fixed small bug 2014-07-23 20:55:31 +02:00
Paweł Jastrzębski
15a240ccea Merge pull request #103 from ciromattia/4.x
Version 4.2
2014-07-18 10:29:14 +02:00
Paweł Jastrzębski
0722ddf8b0 Updated README + version bump 2014-07-18 08:45:57 +02:00
Paweł Jastrzębski
b3159b94e7 Prevented hypothetical problems with batch processing 2014-07-18 08:24:12 +02:00
Paweł Jastrzębski
ef5207c990 Dropped Windows XP support 2014-07-10 19:11:04 +02:00
Paweł Jastrzębski
db77d89817 Fixed Other profile 2014-07-05 09:38:10 +02:00
Paweł Jastrzębski
4571fadadb Resolved problems with page order on Kobo 2014-07-04 09:59:21 +02:00
Paweł Jastrzębski
94f56238ae Corruption detection now also delete non-image files (close #99) 2014-07-03 18:16:57 +02:00
Paweł Jastrzębski
5efb5d6dbb Updated Pillow (close #95) 2014-07-03 18:16:57 +02:00
Paweł Jastrzębski
623f615dd9 Added Manga Cover Database support 2014-07-03 18:16:56 +02:00
Paweł Jastrzębski
39fbbc42b3 Made KindleGen detection more foolproof 2014-07-03 18:16:56 +02:00
Paweł Jastrzębski
99405ab8a6 Disabled ultra quality mode for CBZ format 2014-07-03 18:16:55 +02:00
Paweł Jastrzębski
aadfca8306 Code cleanup 2014-07-03 18:16:54 +02:00
12 changed files with 888 additions and 834 deletions

View File

@@ -1,13 +1,13 @@
# KCC # KCC
**Kindle Comic Converter** is a Python app to convert comic files or folders to ePub, Panel View MOBI or E-Ink optimized CBZ. **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 initally developed for Kindle but since v2.2 it outputs valid ePub 2.0 so _**despite its name, KCC is It was initially developed for Kindle but since version 2.2 it outputs valid EPUB 2.0 so _**despite its name, KCC is
actually a comic to EPUB converter that every e-reader owner can happily use**_. actually a comic/manga to EPUB converter that every e-reader owner can happily use**_.
It can also optionally optimize images by applying a number of transformations. It can also optionally optimize images by applying a number of transformations.
### A word of warning ### A word of warning
**KCC** _is not_ [Amazon's Kindle Comic Creator](http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1001103761) nor is in any way endorsed by Amazon. **KCC** _is not_ [Amazon's Kindle Comic Creator](http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1001103761) nor is in any way endorsed by Amazon.
Amazon's tool is for comic publishers and involves a lot of manual effort, while **KCC** is for comic readers. Amazon's tool is for comic publishers and involves a lot of manual effort, while **KCC** is for comic/manga readers.
_KC2_ in no way is a replacement for **KCC** so you can be quite confident we'll going to carry on developing our little monster ;-) _KC2_ in no way is a replacement for **KCC** so you can be quite confident we'll going to carry on developing our little monster ;-)
### Issues / new features / donations ### Issues / new features / donations
@@ -26,7 +26,7 @@ If you find **KCC** valuable you can consider donating to the authors:
## BINARY RELEASES ## BINARY RELEASES
You can find the latest released binary at the following links: You can find the latest released binary at the following links:
- **Windows:** [http://kcc.iosphe.re/Windows/](http://kcc.iosphe.re/Windows/) - **Windows (Vista or newer):** [http://kcc.iosphe.re/Windows/](http://kcc.iosphe.re/Windows/)
- **Linux:** [http://kcc.iosphe.re/Linux/](http://kcc.iosphe.re/Linux/) - **Linux:** [http://kcc.iosphe.re/Linux/](http://kcc.iosphe.re/Linux/)
- **OS X (10.8+):** [http://kcc.iosphe.re/OSX/](http://kcc.iosphe.re/OSX/) - **OS X (10.8+):** [http://kcc.iosphe.re/OSX/](http://kcc.iosphe.re/OSX/)
@@ -36,7 +36,7 @@ You can find the latest released binary at the following links:
- CBZ, ZIP - CBZ, ZIP
- CBR, RAR *(With `unrar` executable)* - CBR, RAR *(With `unrar` executable)*
- CB7, 7Z *(With `7za` executable)* - CB7, 7Z *(With `7za` executable)*
- PDF *(Extracting only contained JPG images)* - PDF *(Only extracting JPG images)*
## OPTIONAL REQUIREMENTS ## OPTIONAL REQUIREMENTS
- [KindleGen](http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211) v2.9+ in a directory reachable by your _PATH_ or in _KCC_ directory *(For MOBI generation)* - [KindleGen](http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211) v2.9+ in a directory reachable by your _PATH_ or in _KCC_ directory *(For MOBI generation)*
@@ -46,7 +46,7 @@ You can find the latest released binary at the following links:
### For running from source: ### For running from source:
- Python 3.3+ - Python 3.3+
- [PyQt5](http://www.riverbankcomputing.co.uk/software/pyqt/download5) 5.2.0+ - [PyQt5](http://www.riverbankcomputing.co.uk/software/pyqt/download5) 5.2.0+
- [Pillow](http://pypi.python.org/pypi/Pillow/) 2.3.0+ - [Pillow](http://pypi.python.org/pypi/Pillow/) 2.5.0+
- [psutil](https://pypi.python.org/pypi/psutil) 2.0+ - [psutil](https://pypi.python.org/pypi/psutil) 2.0+
- [python-slugify](http://pypi.python.org/pypi/python-slugify) - [python-slugify](http://pypi.python.org/pypi/python-slugify)
@@ -67,6 +67,8 @@ After completed conversion you should find ready file alongside the original inp
Please check [our wiki](https://github.com/ciromattia/kcc/wiki/) for more details. Please check [our wiki](https://github.com/ciromattia/kcc/wiki/) for more details.
CLI version of **KCC** is intended for power users. It is not idiot-proof like GUI :-)
### Standalone `kcc-c2e.py` usage: ### Standalone `kcc-c2e.py` usage:
``` ```
@@ -75,7 +77,9 @@ Usage: kcc-c2e [options] comic_file|comic_folder
Options: Options:
MAIN: MAIN:
-p PROFILE, --profile=PROFILE -p PROFILE, --profile=PROFILE
Device profile (Choose one among K1, K2, K345, KDX, KHD, KF, KFHD, KFHD8, KFHDX, KFHDX8, KFA, KoMT, KoG, KoA, KoAHD) [Default=KHD] Device profile (Available options: K1, K2, K345, KDX,
KPW, KV, KFHD, KFHDX, KFHDX8, KFA, KoMT, KoG, KoA,
KoAHD, KoAH2O) [Default=KV]
-q QUALITY, --quality=QUALITY -q QUALITY, --quality=QUALITY
Quality of Panel View. 0 - Normal 1 - High 2 - Ultra [Default=0] Quality of Panel View. 0 - Normal 1 - High 2 - Ultra [Default=0]
-m, --manga-style Manga style (Right-to-left reading and splitting) -m, --manga-style Manga style (Right-to-left reading and splitting)
@@ -86,7 +90,9 @@ Options:
Output generated file to specified directory or file Output generated file to specified directory or file
-t TITLE, --title=TITLE -t TITLE, --title=TITLE
Comic title [Default=filename or directory name] Comic title [Default=filename or directory name]
--cbz-output Outputs a CBZ archive and does not generate EPUB -f FORMAT, --format=FORMAT
Output format (Available options: Auto, MOBI,
EPUB, CBZ) [Default=Auto]
--batchsplit Split output into multiple files --batchsplit Split output into multiple files
PROCESSING: PROCESSING:
@@ -134,7 +140,7 @@ Options:
This script born as a cross-platform alternative to `KindleComicParser` by **Dc5e** (published [here](http://www.mobileread.com/forums/showthread.php?t=192783)). This script born as a cross-platform alternative to `KindleComicParser` by **Dc5e** (published [here](http://www.mobileread.com/forums/showthread.php?t=192783)).
The app relies and includes the following scripts/binaries: The app relies and includes the following scripts:
- `DualMetaFix` script by **K. Hendricks**. Released with GPL-3 License. - `DualMetaFix` script by **K. Hendricks**. Released with GPL-3 License.
- `rarfile.py` script &copy; 2005-2011 **Marko Kreen** <markokr@gmail.com>. Released with ISC License. - `rarfile.py` script &copy; 2005-2011 **Marko Kreen** <markokr@gmail.com>. Released with ISC License.
@@ -142,17 +148,15 @@ The app relies and includes the following scripts/binaries:
- Icon is by **Nikolay Verin** ([http://ncrow.deviantart.com/](http://ncrow.deviantart.com/)) and released under [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/) License. - Icon is by **Nikolay Verin** ([http://ncrow.deviantart.com/](http://ncrow.deviantart.com/)) and released under [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/) License.
## SAMPLE FILES CREATED BY KCC ## SAMPLE FILES CREATED BY KCC
* [Kindle Voyage](http://kcc.iosphe.re/Samples/Ubunchu!-KV.mobi)
* [Kindle Paperwhite](http://kcc.iosphe.re/Samples/Ubunchu!-KPW.mobi) * [Kindle Paperwhite](http://kcc.iosphe.re/Samples/Ubunchu!-KPW.mobi)
* [Kindle](http://kcc.iosphe.re/Samples/Ubunchu!-K345.mobi) * [Kindle](http://kcc.iosphe.re/Samples/Ubunchu!-K345.mobi)
* [Kindle DX/DXG](http://kcc.iosphe.re/Samples/Ubunchu!-KDX.mobi) * [Kindle DX/DXG](http://kcc.iosphe.re/Samples/Ubunchu!-KDX.cbz)
* [Kindle Fire HD](http://kcc.iosphe.re/Samples/Ubunchu!-KFHD.mobi)
* [Kindle Fire HD 8.9"](http://kcc.iosphe.re/Samples/Ubunchu!-KFHD8.mobi)
* [Kindle Fire HDX](http://kcc.iosphe.re/Samples/Ubunchu!-KFHDX.mobi)
* [Kindle Fire HDX 8.9"](http://kcc.iosphe.re/Samples/Ubunchu!-KFHDX8.mobi)
* [Kobo Mini/Touch](http://kcc.iosphe.re/Samples/Ubunchu!-KoMT.cbz) * [Kobo Mini/Touch](http://kcc.iosphe.re/Samples/Ubunchu!-KoMT.cbz)
* [Kobo Glow](http://kcc.iosphe.re/Samples/Ubunchu!-KoG.cbz) * [Kobo Glow](http://kcc.iosphe.re/Samples/Ubunchu!-KoG.cbz)
* [Kobo Aura](http://kcc.iosphe.re/Samples/Ubunchu!-KoA.cbz) * [Kobo Aura](http://kcc.iosphe.re/Samples/Ubunchu!-KoA.cbz)
* [Kobo Aura HD](http://kcc.iosphe.re/Samples/Ubunchu!-KoAHD.cbz) * [Kobo Aura HD](http://kcc.iosphe.re/Samples/Ubunchu!-KoAHD.cbz)
* [Kobo Aura H2O](http://kcc.iosphe.re/Samples/Ubunchu!-KoAH2O.cbz)
## CHANGELOG ## CHANGELOG
####1.0 ####1.0
@@ -188,11 +192,11 @@ The app relies and includes the following scripts/binaries:
* Added basic error reporting * Added basic error reporting
####2.2: ####2.2:
* Added (valid!) ePub 2.0 output * Added (valid!) EPUB 2.0 output
* Rename .zip files to .cbz to avoid overwriting * Rename .zip files to .cbz to avoid overwriting
####2.3 ####2.3
* Fixed win32 ePub generation, folder handling, filenames with spaces and subfolders * Fixed win32 EPUB generation, folder handling, filenames with spaces and subfolders
####2.4 ####2.4
* Use temporary directory as workdir (fixes converting from external volumes and zipfiles renaming) * Use temporary directory as workdir (fixes converting from external volumes and zipfiles renaming)
@@ -200,22 +204,22 @@ The app relies and includes the following scripts/binaries:
####2.5 ####2.5
* Added --black-borders option to set added borders black when page's ratio is not the device's one (#11). * 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) * Fixes EPUB containing zipped itself (#10)
####2.6 ####2.6
* Added --rotate option to rotate landscape images instead of splitting them (#16, #24) * Added --rotate option to rotate landscape images instead of splitting them (#16, #24)
* Added --output option to customize ePub output dir/file (#22) * 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) * Add rendition:layout and rendition:orientation EPUB meta tags (supported by new kindlegen 2.8)
* Fixed natural sorting for files (#18) * Fixed natural sorting for files (#18)
####2.7 ####2.7
* Lots of GUI improvements (#27, #13) * Lots of GUI improvements (#27, #13)
* Added gamma support within --gamma option (defaults to profile-specified gamma) (#26, #27) * Added gamma support within --gamma option (defaults to profile-specified gamma) (#26, #27)
* Added --nodithering option to prevent dithering optimizations (#27) * Added --nodithering option to prevent dithering optimizations (#27)
* Epub margins support (#30) * EPUB margins support (#30)
* Fixed no file added if file has no spaces on Windows (#25) * Fixed no file added if file has no spaces on Windows (#25)
* Gracefully exit if unrar missing (#15) * Gracefully exit if unrar missing (#15)
* Do not call kindlegen if source epub is bigger than 320MB (#17) * Do not call kindlegen if source EPUB is bigger than 320MB (#17)
* Get filetype from magic number (#14) * Get filetype from magic number (#14)
* PDF conversion works again * PDF conversion works again
@@ -229,7 +233,7 @@ The app relies and includes the following scripts/binaries:
* Optimized archive extraction for zip/rar files (#40) * Optimized archive extraction for zip/rar files (#40)
####2.9 ####2.9
* Added support for generating a plain CBZ (skipping all the EPUB/Mobi generation) (#45) * 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 * Prevent output file overwriting the source one: if a duplicate name is detected, append _kcc to the name
* Rarfile library updated to 2.6 * Rarfile library updated to 2.6
* Added GIF, TIFF and BMP to supported formats (#42) * Added GIF, TIFF and BMP to supported formats (#42)
@@ -237,7 +241,7 @@ The app relies and includes the following scripts/binaries:
####2.10: ####2.10:
* Multiprocessing support * Multiprocessing support
* Kindle Fire support (color ePub/Mobi) * Kindle Fire support (color EPUB/MOBI)
* Panel View support for horizontal content * Panel View support for horizontal content
* Fixed panel order for horizontal pages when --rotate is enabled * Fixed panel order for horizontal pages when --rotate is enabled
* Disabled cropping and page number cutting for blank pages * Disabled cropping and page number cutting for blank pages
@@ -354,6 +358,25 @@ The app relies and includes the following scripts/binaries:
* Fixed _No optimization_ mode * Fixed _No optimization_ mode
* Multiple small tweaks nad minor bug fixes * Multiple small tweaks nad minor bug fixes
####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.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.3:
* Added profiles for Kindle Voyage and Kobo Aura H2O
* Added missing features to CLI version
* Other minor bug fixes
## KNOWN ISSUES ## KNOWN ISSUES
Please check [wiki page](https://github.com/ciromattia/kcc/wiki/Known-issues). Please check [wiki page](https://github.com/ciromattia/kcc/wiki/Known-issues).

View File

@@ -18,7 +18,7 @@
# 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.
__version__ = '4.1' __version__ = '4.3'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>' __copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
@@ -40,10 +40,10 @@ except ImportError:
try: try:
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
import PIL import PIL
if tuple(map(int, ('2.3.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))): if tuple(map(int, ('2.5.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))):
missing.append('Pillow 2.3.0+') missing.append('Pillow 2.5.0+')
except ImportError: except ImportError:
missing.append('Pillow 2.3.0+') missing.append('Pillow 2.5.0+')
try: try:
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
import slugify import slugify
@@ -63,10 +63,10 @@ if len(missing) > 0:
exit(1) exit(1)
from multiprocessing import freeze_support from multiprocessing import freeze_support
from kcc.comic2ebook import main, Copyright from kcc.comic2ebook import main
if __name__ == "__main__": if __name__ == "__main__":
freeze_support() freeze_support()
Copyright() print(('comic2ebook v%(__version__)s. Written by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals()))
main(sys.argv[1:]) main(sys.argv[1:])
sys.exit(0) sys.exit(0)

View File

@@ -18,7 +18,7 @@
# 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.
__version__ = '4.1' __version__ = '4.3'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>' __copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
@@ -33,10 +33,10 @@ missing = []
try: try:
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
import PIL import PIL
if tuple(map(int, ('2.3.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))): if tuple(map(int, ('2.5.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))):
missing.append('Pillow 2.3.0+') missing.append('Pillow 2.5.0+')
except ImportError: except ImportError:
missing.append('Pillow 2.3.0+') missing.append('Pillow 2.5.0+')
if len(missing) > 0: if len(missing) > 0:
try: try:
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
@@ -51,10 +51,10 @@ if len(missing) > 0:
exit(1) exit(1)
from multiprocessing import freeze_support from multiprocessing import freeze_support
from kcc.comic2panel import main, Copyright from kcc.comic2panel import main
if __name__ == "__main__": if __name__ == "__main__":
freeze_support() freeze_support()
Copyright() print(('comic2ebook v%(__version__)s. Written by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals()))
main(sys.argv[1:]) main(sys.argv[1:])
sys.exit(0) sys.exit(0)

View File

@@ -1,5 +1,5 @@
#define MyAppName "Kindle Comic Converter" #define MyAppName "Kindle Comic Converter"
#define MyAppVersion "4.1" #define MyAppVersion "4.3"
#define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski" #define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
#define MyAppURL "http://kcc.iosphe.re/" #define MyAppURL "http://kcc.iosphe.re/"
#define MyAppExeName "KCC.exe" #define MyAppExeName "KCC.exe"
@@ -30,6 +30,7 @@ UninstallDisplayIcon={app}\{#MyAppExeName}
ChangesAssociations=True ChangesAssociations=True
InfoAfterFile=other\InstallWarning.rtf InfoAfterFile=other\InstallWarning.rtf
SignTool=SignTool /d $q{#MyAppName}$q /du $q{#MyAppURL}$q $f SignTool=SignTool /d $q{#MyAppName}$q /du $q{#MyAppURL}$q $f
MinVersion=0,6.0
[Languages] [Languages]
Name: "english"; MessagesFile: "compiler:Default.isl" Name: "english"; MessagesFile: "compiler:Default.isl"
@@ -42,13 +43,11 @@ Name: "CB7association"; Description: "CB7"; GroupDescription: "File associations
[Files] [Files]
; x64 files ; x64 files
Source: "dist_64\imageformats\*"; DestDir: "{app}\imageformats\"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "dist_64\platforms\*"; DestDir: "{app}\platforms\"; Flags: ignoreversion; Check: Is64BitInstallMode Source: "dist_64\platforms\*"; DestDir: "{app}\platforms\"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "dist_64\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode Source: "dist_64\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "dist_64\*.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode Source: "dist_64\*.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "other\vcredist_x64.exe"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall; Check: Is64BitInstallMode Source: "other\vcredist_x64.exe"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall; Check: Is64BitInstallMode
; x86 files ; x86 files
Source: "dist\imageformats\*"; DestDir: "{app}\imageformats\"; Flags: ignoreversion; Check: not Is64BitInstallMode
Source: "dist\platforms\*"; DestDir: "{app}\platforms\"; Flags: ignoreversion; Check: not Is64BitInstallMode Source: "dist\platforms\*"; DestDir: "{app}\platforms\"; Flags: ignoreversion; Check: not Is64BitInstallMode
Source: "dist\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode Source: "dist\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
Source: "dist\*.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode Source: "dist\*.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode

57
kcc.py
View File

@@ -18,7 +18,7 @@
# 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.
__version__ = '4.1' __version__ = '4.3'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>' __copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
@@ -47,10 +47,10 @@ except ImportError:
try: try:
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
import PIL import PIL
if tuple(map(int, ('2.3.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))): if tuple(map(int, ('2.5.0'.split(".")))) > tuple(map(int, (PIL.PILLOW_VERSION.split(".")))):
missing.append('Pillow 2.3.0+') missing.append('Pillow 2.5.0+')
except ImportError: except ImportError:
missing.append('Pillow 2.3.0+') missing.append('Pillow 2.5.0+')
try: try:
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
import slugify import slugify
@@ -84,14 +84,14 @@ elif sys.platform.startswith('win'):
os.chdir(os.path.dirname(os.path.abspath(sys.executable))) os.chdir(os.path.dirname(os.path.abspath(sys.executable)))
# Implementing dummy stdout and stderr for frozen Windows release # Implementing dummy stdout and stderr for frozen Windows release
class fakestd(object): class FakeSTD(object):
def write(self, string): def write(self, string):
pass pass
def flush(self): def flush(self):
pass pass
sys.stdout = fakestd() sys.stdout = FakeSTD()
sys.stderr = fakestd() sys.stderr = FakeSTD()
else: else:
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/;' + os.environ['PATH'] os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/;' + os.environ['PATH']
os.chdir(os.path.dirname(os.path.abspath(__file__))) os.chdir(os.path.dirname(os.path.abspath(__file__)))
@@ -103,36 +103,33 @@ class QApplicationMessaging(QtWidgets.QApplication):
def __init__(self, argv): def __init__(self, argv):
QtWidgets.QApplication.__init__(self, argv) QtWidgets.QApplication.__init__(self, argv)
self._memory = QtCore.QSharedMemory(self)
self._memory.setKey('KCC')
if self._memory.attach():
self._running = True
else:
self._running = False
self._memory.create(1)
self._key = 'KCC' self._key = 'KCC'
self._timeout = 1000 self._timeout = 1000
self._server = QtNetwork.QLocalServer(self) self._locked = False
if not self.isRunning(): socket = QtNetwork.QLocalSocket(self)
socket.connectToServer(self._key, QtCore.QIODevice.WriteOnly)
if not socket.waitForConnected(self._timeout):
self._server = QtNetwork.QLocalServer(self)
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
self._server.newConnection.connect(self.handleMessage) self._server.newConnection.connect(self.handleMessage)
self._server.listen(self._key) self._server.listen(self._key)
else:
self._locked = True
socket.disconnectFromServer()
def shutdown(self): def __del__(self):
if self._memory.isAttached(): if not self._locked:
self._memory.detach()
self._server.close() self._server.close()
def event(self, e): def event(self, e):
if e.type() == QtCore.QEvent.FileOpen: if e.type() == QtCore.QEvent.FileOpen:
# noinspection PyArgumentList
self.messageFromOtherInstance.emit(bytes(e.file(), 'UTF-8')) self.messageFromOtherInstance.emit(bytes(e.file(), 'UTF-8'))
return True return True
else: else:
return QtWidgets.QApplication.event(self, e) return QtWidgets.QApplication.event(self, e)
def isRunning(self): def isRunning(self):
return self._running return self._locked
def handleMessage(self): def handleMessage(self):
socket = self._server.nextPendingConnection() socket = self._server.nextPendingConnection()
@@ -140,18 +137,12 @@ class QApplicationMessaging(QtWidgets.QApplication):
self.messageFromOtherInstance.emit(socket.readAll().data()) self.messageFromOtherInstance.emit(socket.readAll().data())
def sendMessage(self, message): def sendMessage(self, message):
if self.isRunning(): socket = QtNetwork.QLocalSocket(self)
socket = QtNetwork.QLocalSocket(self) socket.connectToServer(self._key, QtCore.QIODevice.WriteOnly)
socket.connectToServer(self._key, QtCore.QIODevice.WriteOnly) socket.waitForConnected(self._timeout)
if not socket.waitForConnected(self._timeout): socket.write(bytes(message, 'UTF-8'))
return False socket.waitForBytesWritten(self._timeout)
# noinspection PyArgumentList socket.disconnectFromServer()
socket.write(bytes(message, 'UTF-8'))
if not socket.waitForBytesWritten(self._timeout):
return False
socket.disconnectFromServer()
return True
return False
# Adding signals to QMainWindow # Adding signals to QMainWindow

View File

@@ -17,7 +17,7 @@
# 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.
__version__ = '4.1' __version__ = '4.3'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>' __copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
@@ -36,11 +36,10 @@ from subprocess import STDOUT, PIPE
from PyQt5 import QtGui, QtCore, QtWidgets from PyQt5 import QtGui, QtCore, QtWidgets
from xml.dom.minidom import parse from xml.dom.minidom import parse
from html.parser import HTMLParser from html.parser import HTMLParser
from psutil import virtual_memory, Popen, Process from psutil import Popen, Process
from uuid import uuid4 from copy import copy
from .shared import md5Checksum from .shared import md5Checksum
from . import comic2ebook from . import comic2ebook
from . import dualmetafix
from . import KCC_rc_web from . import KCC_rc_web
if sys.platform.startswith('darwin'): if sys.platform.startswith('darwin'):
from . import KCC_ui_osx as KCC_ui from . import KCC_ui_osx as KCC_ui
@@ -196,7 +195,6 @@ class VersionThread(QtCore.QThread):
def run(self): def run(self):
try: try:
sleep(1)
XML = urlopen('http://kcc.iosphe.re/Version.php') XML = urlopen('http://kcc.iosphe.re/Version.php')
XML = parse(XML) XML = parse(XML)
except Exception: except Exception:
@@ -265,84 +263,14 @@ class ProgressThread(QtCore.QThread):
self.running = False self.running = False
class WorkerSignals(QtCore.QObject):
result = QtCore.pyqtSignal(list)
class KindleGenThread(QtCore.QRunnable):
def __init__(self, batch):
super(KindleGenThread, self).__init__()
self.signals = WorkerSignals()
self.work = batch
def run(self):
kindlegenErrorCode = 0
kindlegenError = ''
try:
if os.path.getsize(self.work) < 629145600:
output = Popen('kindlegen -dont_append_source -locale en "' + self.work + '"', stdout=PIPE,
stderr=STDOUT, shell=True)
for line in output.stdout:
line = line.decode('utf-8')
# ERROR: Generic error
if "Error(" in line:
kindlegenErrorCode = 1
kindlegenError = line
# ERROR: EPUB too big
if ":E23026:" in line:
kindlegenErrorCode = 23026
if kindlegenErrorCode > 0:
break
else:
# ERROR: EPUB too big
kindlegenErrorCode = 23026
self.signals.result.emit([kindlegenErrorCode, kindlegenError, self.work])
except Exception as err:
# ERROR: KCC unknown generic error
kindlegenErrorCode = 1
kindlegenError = format(err)
self.signals.result.emit([kindlegenErrorCode, kindlegenError, self.work])
class DualMetaFixThread(QtCore.QRunnable):
def __init__(self, batch):
super(DualMetaFixThread, self).__init__()
self.signals = WorkerSignals()
self.work = batch
def run(self):
item = self.work
os.remove(item)
mobiPath = item.replace('.epub', '.mobi')
move(mobiPath, mobiPath + '_toclean')
try:
# noinspection PyArgumentList
dualmetafix.DualMobiMetaFix(mobiPath + '_toclean', mobiPath, bytes(str(uuid4()), 'UTF-8'))
self.signals.result.emit([True])
except Exception as err:
self.signals.result.emit([False, format(err)])
class WorkerThread(QtCore.QThread): class WorkerThread(QtCore.QThread):
#noinspection PyArgumentList # noinspection PyArgumentList
def __init__(self): def __init__(self):
QtCore.QThread.__init__(self) QtCore.QThread.__init__(self)
self.pool = QtCore.QThreadPool()
self.conversionAlive = False self.conversionAlive = False
self.errors = False self.errors = False
self.kindlegenErrorCode = [0] self.kindlegenErrorCode = [0]
self.workerOutput = [] self.workerOutput = []
# Let's make sure that we don't fill the memory
availableMemory = virtual_memory().total/1000000000
if availableMemory <= 2:
self.threadNumber = 1
elif 2 < availableMemory <= 4:
self.threadNumber = 2
else:
self.threadNumber = 4
# Let's make sure that we don't use too many threads
if self.threadNumber > QtCore.QThread.idealThreadCount():
self.threadNumber = QtCore.QThread.idealThreadCount()
self.progressBarTick = MW.progressBarTick self.progressBarTick = MW.progressBarTick
self.addMessage = MW.addMessage self.addMessage = MW.addMessage
@@ -361,9 +289,11 @@ class WorkerThread(QtCore.QThread):
MW.addTrayMessage.emit('Conversion interrupted.', 'Critical') MW.addTrayMessage.emit('Conversion interrupted.', 'Critical')
MW.modeConvert.emit(1) MW.modeConvert.emit(1)
def addResult(self, output): def sanitizeTrace(self, traceback):
MW.progressBarTick.emit('tick') return ''.join(format_tb(traceback))\
self.workerOutput.append(output) .replace('C:\\Users\\AcidWeb\\Documents\\Projekty\\KCC\\', '')\
.replace('C:\\Python34\\', '')\
.replace('C:\\Python34_64\\', '')
def run(self): def run(self):
MW.modeConvert.emit(0) MW.modeConvert.emit(0)
@@ -385,10 +315,9 @@ class WorkerThread(QtCore.QThread):
options.quality = 1 options.quality = 1
elif GUI.QualityBox.checkState() == 2: elif GUI.QualityBox.checkState() == 2:
options.quality = 2 options.quality = 2
if str(GUI.FormatBox.currentText()) == 'CBZ': options.format = str(GUI.FormatBox.currentText())
options.cbzoutput = True
if GUI.currentMode == 1: if GUI.currentMode == 1:
if profile in ['KFHD', 'KFHD8', 'KFHDX', 'KFHDX8']: if 'KFH' in profile:
options.upscale = True options.upscale = True
# Advanced mode settings # Advanced mode settings
@@ -410,10 +339,7 @@ class WorkerThread(QtCore.QThread):
if GUI.WebtoonBox.isChecked(): if GUI.WebtoonBox.isChecked():
options.webtoon = True options.webtoon = True
if float(GUI.GammaValue) > 0.09: if float(GUI.GammaValue) > 0.09:
# noinspection PyTypeChecker
options.gamma = float(GUI.GammaValue) options.gamma = float(GUI.GammaValue)
if str(GUI.FormatBox.currentText()) == 'MOBI':
options.batchsplit = True
# Other/custom settings. # Other/custom settings.
if GUI.currentMode > 2: if GUI.currentMode > 2:
@@ -422,9 +348,6 @@ class WorkerThread(QtCore.QThread):
if GUI.ColorBox.isChecked(): if GUI.ColorBox.isChecked():
options.forcecolor = True options.forcecolor = True
comic2ebook.options = options
comic2ebook.checkOptions()
for i in range(GUI.JobList.count()): for i in range(GUI.JobList.count()):
# Make sure that we don't consider any system message as job to do # Make sure that we don't consider any system message as job to do
if GUI.JobList.item(i).icon().isNull(): if GUI.JobList.item(i).icon().isNull():
@@ -446,7 +369,8 @@ class WorkerThread(QtCore.QThread):
jobargv = list(argv) jobargv = list(argv)
jobargv.append(job) jobargv.append(job)
try: try:
comic2ebook.options.title = 'defaulttitle' comic2ebook.options = copy(options)
comic2ebook.checkOptions()
outputPath = comic2ebook.makeBook(job, self) outputPath = comic2ebook.makeBook(job, self)
MW.hideProgressBar.emit() MW.hideProgressBar.emit()
except UserWarning as warn: except UserWarning as warn:
@@ -464,7 +388,7 @@ class WorkerThread(QtCore.QThread):
self.errors = True self.errors = True
_, _, traceback = sys.exc_info() _, _, traceback = sys.exc_info()
MW.showDialog.emit("Error during conversion %s:\n\n%s\n\nTraceback:\n%s" MW.showDialog.emit("Error during conversion %s:\n\n%s\n\nTraceback:\n%s"
% (jobargv[-1], str(err), "".join(format_tb(traceback))), 'error') % (jobargv[-1], str(err), self.sanitizeTrace(traceback)), 'error')
MW.addMessage.emit('Failed to create EPUB!', 'error', False) MW.addMessage.emit('Failed to create EPUB!', 'error', False)
MW.addTrayMessage.emit('Failed to create EPUB!', 'Critical') MW.addTrayMessage.emit('Failed to create EPUB!', 'Critical')
if not self.conversionAlive: if not self.conversionAlive:
@@ -485,15 +409,10 @@ class WorkerThread(QtCore.QThread):
MW.progressBarTick.emit('tick') MW.progressBarTick.emit('tick')
MW.addMessage.emit('Creating MOBI files', 'info', False) MW.addMessage.emit('Creating MOBI files', 'info', False)
GUI.progress.content = 'Creating MOBI files' GUI.progress.content = 'Creating MOBI files'
self.workerOutput = [] work = []
# Number of KindleGen threads depends on the size of RAM
self.pool.setMaxThreadCount(self.threadNumber)
for item in outputPath: for item in outputPath:
worker = KindleGenThread(item) work.append([item])
worker.signals.result.connect(self.addResult) self.workerOutput = comic2ebook.makeMOBI(work, self)
self.pool.start(worker)
self.pool.waitForDone()
sleep(0.5)
self.kindlegenErrorCode = [0] self.kindlegenErrorCode = [0]
for errors in self.workerOutput: for errors in self.workerOutput:
if errors[0] != 0: if errors[0] != 0:
@@ -503,7 +422,6 @@ class WorkerThread(QtCore.QThread):
for item in outputPath: for item in outputPath:
if os.path.exists(item): if os.path.exists(item):
os.remove(item) os.remove(item)
sleep(1)
if os.path.exists(item.replace('.epub', '.mobi')): if os.path.exists(item.replace('.epub', '.mobi')):
os.remove(item.replace('.epub', '.mobi')) os.remove(item.replace('.epub', '.mobi'))
self.clean() self.clean()
@@ -514,14 +432,9 @@ class WorkerThread(QtCore.QThread):
MW.addMessage.emit('Processing MOBI files', 'info', False) MW.addMessage.emit('Processing MOBI files', 'info', False)
GUI.progress.content = 'Processing MOBI files' GUI.progress.content = 'Processing MOBI files'
self.workerOutput = [] self.workerOutput = []
# DualMetaFix is very fast and there is not reason to use multithreading.
self.pool.setMaxThreadCount(1)
for item in outputPath: for item in outputPath:
worker = DualMetaFixThread(item) self.workerOutput.append(comic2ebook.makeMOBIFix(item))
worker.signals.result.connect(self.addResult) MW.progressBarTick.emit('tick')
self.pool.start(worker)
self.pool.waitForDone()
sleep(0.5)
for success in self.workerOutput: for success in self.workerOutput:
if not success[0]: if not success[0]:
self.errors = True self.errors = True
@@ -555,7 +468,6 @@ class WorkerThread(QtCore.QThread):
for item in outputPath: for item in outputPath:
if os.path.exists(item): if os.path.exists(item):
os.remove(item) os.remove(item)
sleep(1)
if os.path.exists(item.replace('.epub', '.mobi')): if os.path.exists(item.replace('.epub', '.mobi')):
os.remove(item.replace('.epub', '.mobi')) os.remove(item.replace('.epub', '.mobi'))
MW.addMessage.emit('KindleGen failed to create MOBI!', 'error', False) MW.addMessage.emit('KindleGen failed to create MOBI!', 'error', False)
@@ -834,6 +746,9 @@ class KCCGUI(KCC_ui.Ui_KCC):
if value == 2 and 'Kobo' in str(GUI.DeviceBox.currentText()): if value == 2 and 'Kobo' in str(GUI.DeviceBox.currentText()):
self.addMessage('Kobo devices can\'t use ultra quality mode!', 'warning') self.addMessage('Kobo devices can\'t use ultra quality mode!', 'warning')
GUI.QualityBox.setCheckState(0) GUI.QualityBox.setCheckState(0)
elif value == 2 and 'CBZ' in str(GUI.FormatBox.currentText()):
self.addMessage('CBZ format don\'t support ultra quality mode!', 'warning')
GUI.QualityBox.setCheckState(0)
def changeGamma(self, value): def changeGamma(self, value):
value = float(value) value = float(value)
@@ -861,7 +776,7 @@ class KCCGUI(KCC_ui.Ui_KCC):
GUI.AdvModeButton.setEnabled(True) GUI.AdvModeButton.setEnabled(True)
if self.currentMode == 3: if self.currentMode == 3:
self.modeBasic() self.modeBasic()
self.changeFormat() self.changeFormat(event=False)
GUI.GammaSlider.setValue(0) GUI.GammaSlider.setValue(0)
self.changeGamma(0) self.changeGamma(0)
if profile['DefaultUpscale']: if profile['DefaultUpscale']:
@@ -870,19 +785,12 @@ class KCCGUI(KCC_ui.Ui_KCC):
self.addMessage('<a href="https://github.com/ciromattia/kcc/wiki/NonKindle-devices">' self.addMessage('<a href="https://github.com/ciromattia/kcc/wiki/NonKindle-devices">'
'List of supported Non-Kindle devices.</a>', 'info') 'List of supported Non-Kindle devices.</a>', 'info')
def changeFormat(self, outputFormat=None): def changeFormat(self, outputFormat=None, event=True):
profile = GUI.profiles[str(GUI.DeviceBox.currentText())] profile = GUI.profiles[str(GUI.DeviceBox.currentText())]
if outputFormat is not None: if outputFormat is not None:
GUI.FormatBox.setCurrentIndex(outputFormat) GUI.FormatBox.setCurrentIndex(outputFormat)
else: else:
if GUI.FormatBox.count() == 3: GUI.FormatBox.setCurrentIndex(profile['DefaultFormat'])
GUI.FormatBox.setCurrentIndex(profile['DefaultFormat'])
else:
if profile['DefaultFormat'] != 0:
tmpFormat = profile['DefaultFormat'] - 1
else:
tmpFormat = 0
GUI.FormatBox.setCurrentIndex(tmpFormat)
if GUI.WebtoonBox.isChecked(): if GUI.WebtoonBox.isChecked():
GUI.MangaBox.setEnabled(False) GUI.MangaBox.setEnabled(False)
GUI.QualityBox.setEnabled(False) GUI.QualityBox.setEnabled(False)
@@ -895,6 +803,10 @@ class KCCGUI(KCC_ui.Ui_KCC):
if GUI.ProcessingBox.isChecked(): if GUI.ProcessingBox.isChecked():
GUI.QualityBox.setEnabled(False) GUI.QualityBox.setEnabled(False)
GUI.QualityBox.setChecked(False) GUI.QualityBox.setChecked(False)
if event and GUI.QualityBox.isEnabled() and 'CBZ' in str(GUI.FormatBox.currentText()) and\
GUI.QualityBox.checkState() == 2:
self.addMessage('CBZ format don\'t support ultra quality mode!', 'warning')
GUI.QualityBox.setCheckState(0)
def stripTags(self, html): def stripTags(self, html):
s = HTMLStripper() s = HTMLStripper()
@@ -973,6 +885,15 @@ class KCCGUI(KCC_ui.Ui_KCC):
self.addMessage('Target resolution is not set!', 'error') self.addMessage('Target resolution is not set!', 'error')
self.needClean = True self.needClean = True
return return
if str(GUI.FormatBox.currentText()) == 'MOBI' and not GUI.KindleGen:
self.addMessage('Cannot find <a href="http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211">'
'<b>KindleGen</b></a>! MOBI conversion is not possible!', 'error')
if sys.platform.startswith('win'):
self.addMessage('Download it and place EXE in KCC directory.', 'error')
else:
self.addMessage('Download it, and place executable in /usr/local/bin directory.', 'error')
self.needClean = True
return
self.worker.start() self.worker.start()
def hideProgressBar(self): def hideProgressBar(self):
@@ -1011,7 +932,6 @@ class KCCGUI(KCC_ui.Ui_KCC):
'GammaSlider': float(self.GammaValue)*100}) 'GammaSlider': float(self.GammaValue)*100})
self.settings.sync() self.settings.sync()
self.tray.hide() self.tray.hide()
APP.shutdown()
def handleMessage(self, message): def handleMessage(self, message):
MW.raise_() MW.raise_()
@@ -1114,22 +1034,20 @@ class KCCGUI(KCC_ui.Ui_KCC):
self.p.ionice(1) self.p.ionice(1)
self.profiles = { self.profiles = {
"Kindle Voyage": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'KV'},
"Kindle Paperwhite": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0, "Kindle Paperwhite": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'KHD'}, 'DefaultUpscale': False, 'Label': 'KPW'},
"Kindle": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0, "Kindle": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'K345'}, 'DefaultUpscale': False, 'Label': 'K345'},
"Kindle DX/DXG": {'Quality': False, 'ForceExpert': False, 'DefaultFormat': 0, "Kindle DX/DXG": {'Quality': False, 'ForceExpert': False, 'DefaultFormat': 2,
'DefaultUpscale': False, 'Label': 'KDX'}, 'DefaultUpscale': False, 'Label': 'KDX'},
"Kindle Fire": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0, "K. Fire HD": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'KF'}, 'DefaultUpscale': True, 'Label': 'KFHD'},
"K. Fire HD 7\"": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0, "K. Fire HDX": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'Label': 'KFHD'}, 'DefaultUpscale': True, 'Label': 'KFHDX'},
"K. Fire HD 8.9\"": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0, "K. Fire HDX 8.9": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'Label': 'KFHD8'}, 'DefaultUpscale': True, 'Label': 'KFHDX8'},
"K. Fire HDX 7\"": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'Label': 'KFHDX'},
"K. Fire HDX 8.9\"": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'Label': 'KFHDX8'},
"Kobo Mini/Touch": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 2, "Kobo Mini/Touch": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 2,
'DefaultUpscale': False, 'Label': 'KoMT'}, 'DefaultUpscale': False, 'Label': 'KoMT'},
"Kobo Glow": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 2, "Kobo Glow": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 2,
@@ -1138,6 +1056,8 @@ class KCCGUI(KCC_ui.Ui_KCC):
'DefaultUpscale': False, 'Label': 'KoA'}, 'DefaultUpscale': False, 'Label': 'KoA'},
"Kobo Aura HD": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 2, "Kobo Aura HD": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 2,
'DefaultUpscale': False, 'Label': 'KoAHD'}, 'DefaultUpscale': False, 'Label': 'KoAHD'},
"Kobo Aura H2O": {'Quality': True, 'ForceExpert': False, 'DefaultFormat': 2,
'DefaultUpscale': False, 'Label': 'KoAH2O'},
"Other": {'Quality': False, 'ForceExpert': True, 'DefaultFormat': 1, "Other": {'Quality': False, 'ForceExpert': True, 'DefaultFormat': 1,
'DefaultUpscale': False, 'Label': 'OTHER'}, 'DefaultUpscale': False, 'Label': 'OTHER'},
"Kindle for Android": {'Quality': False, 'ForceExpert': True, 'DefaultFormat': 0, "Kindle for Android": {'Quality': False, 'ForceExpert': True, 'DefaultFormat': 0,
@@ -1148,26 +1068,26 @@ class KCCGUI(KCC_ui.Ui_KCC):
'DefaultUpscale': False, 'Label': 'K2'} 'DefaultUpscale': False, 'Label': 'K2'}
} }
profilesGUI = [ profilesGUI = [
"Kindle Voyage",
"Kindle Paperwhite", "Kindle Paperwhite",
"Kindle", "Kindle",
"Kindle DX/DXG",
"Separator", "Separator",
"Kindle Fire", "K. Fire HD",
"K. Fire HD 7\"", "K. Fire HDX",
"K. Fire HD 8.9\"", "K. Fire HDX 8.9",
"K. Fire HDX 7\"",
"K. Fire HDX 8.9\"",
"Separator", "Separator",
"Kobo Mini/Touch", "Kobo Mini/Touch",
"Kobo Glow", "Kobo Glow",
"Kobo Aura", "Kobo Aura",
"Kobo Aura HD", "Kobo Aura HD",
"Kobo Aura H2O",
"Separator", "Separator",
"Other", "Other",
"Separator", "Separator",
"Kindle for Android", "Kindle for Android",
"Kindle 1", "Kindle 1",
"Kindle 2", "Kindle 2",
"Kindle DX/DXG",
] ]
statusBarLabel = QtWidgets.QLabel('<b><a href="http://kcc.iosphe.re/">HOMEPAGE</a> - <a href="https://github.' statusBarLabel = QtWidgets.QLabel('<b><a href="http://kcc.iosphe.re/">HOMEPAGE</a> - <a href="https://github.'
@@ -1196,7 +1116,6 @@ class KCCGUI(KCC_ui.Ui_KCC):
kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True) kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True)
if kindleGenExitCode.wait() == 0: if kindleGenExitCode.wait() == 0:
self.KindleGen = True self.KindleGen = True
formats = ['MOBI', 'EPUB', 'CBZ']
versionCheck = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True) versionCheck = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True)
for line in versionCheck.stdout: for line in versionCheck.stdout:
line = line.decode("utf-8") line = line.decode("utf-8")
@@ -1210,13 +1129,6 @@ class KCCGUI(KCC_ui.Ui_KCC):
break break
else: else:
self.KindleGen = False self.KindleGen = False
formats = ['EPUB', 'CBZ']
if sys.platform.startswith('win'):
self.addMessage('Cannot find <a href="http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211">'
'kindlegen</a> in KCC directory! MOBI creation will be disabled.', 'warning')
else:
self.addMessage('Cannot find <a href="http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211">'
'kindlegen</a> in PATH! MOBI creation will be disabled.', 'warning')
rarExitCode = Popen('unrar', stdout=PIPE, stderr=STDOUT, shell=True) rarExitCode = Popen('unrar', stdout=PIPE, stderr=STDOUT, shell=True)
rarExitCode = rarExitCode.wait() rarExitCode = rarExitCode.wait()
if rarExitCode == 0 or rarExitCode == 7: if rarExitCode == 0 or rarExitCode == 7:
@@ -1271,7 +1183,7 @@ class KCCGUI(KCC_ui.Ui_KCC):
GUI.DeviceBox.addItem(self.icons.deviceKobo, profile) GUI.DeviceBox.addItem(self.icons.deviceKobo, profile)
else: else:
GUI.DeviceBox.addItem(self.icons.deviceKindle, profile) GUI.DeviceBox.addItem(self.icons.deviceKindle, profile)
for f in formats: for f in ['MOBI', 'EPUB', 'CBZ']:
GUI.FormatBox.addItem(eval('self.icons.' + f + 'Format'), f) GUI.FormatBox.addItem(eval('self.icons.' + f + 'Format'), f)
if self.lastDevice > GUI.DeviceBox.count(): if self.lastDevice > GUI.DeviceBox.count():
self.lastDevice = 0 self.lastDevice = 0
@@ -1282,7 +1194,7 @@ class KCCGUI(KCC_ui.Ui_KCC):
GUI.DeviceBox.setCurrentIndex(self.lastDevice) GUI.DeviceBox.setCurrentIndex(self.lastDevice)
self.changeDevice() self.changeDevice()
if self.currentFormat != self.profiles[str(GUI.DeviceBox.currentText())]['DefaultFormat']: if self.currentFormat != self.profiles[str(GUI.DeviceBox.currentText())]['DefaultFormat']:
self.changeFormat(self.currentFormat) self.changeFormat(self.currentFormat, False)
for option in self.options: for option in self.options:
if str(option) == "customWidth": if str(option) == "customWidth":
GUI.customWidth.setText(str(self.options[option])) GUI.customWidth.setText(str(self.options[option]))

View File

@@ -1,4 +1,4 @@
__version__ = '4.1' __version__ = '4.3'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>' __copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,7 @@
# PERFORMANCE OF THIS SOFTWARE. # PERFORMANCE OF THIS SOFTWARE.
# #
__version__ = '4.1' __version__ = '4.3'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>' __copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
@@ -36,7 +36,7 @@ except ImportError:
QtCore = None QtCore = None
def mergeDirectory_tick(output): def mergeDirectoryTick(output):
if output: if output:
mergeWorkerOutput.append(output) mergeWorkerOutput.append(output)
mergeWorkerPool.terminate() mergeWorkerPool.terminate()
@@ -108,7 +108,7 @@ def sanitizePanelSize(panel, opt):
return newPanels return newPanels
def splitImage_tick(output): def splitImageTick(output):
if output: if output:
splitWorkerOutput.append(output) splitWorkerOutput.append(output)
splitWorkerPool.terminate() splitWorkerPool.terminate()
@@ -118,7 +118,6 @@ def splitImage_tick(output):
splitWorkerPool.terminate() splitWorkerPool.terminate()
#noinspection PyUnboundLocalVariable
def splitImage(work): def splitImage(work):
try: try:
path = work[0] path = work[0]
@@ -165,6 +164,7 @@ def splitImage(work):
for panel in panelsCleaned: for panel in panelsCleaned:
panels.append(panel) panels.append(panel)
if opt.debug: if opt.debug:
# noinspection PyUnboundLocalVariable
debugImage.save(os.path.join(path, fileExpanded[0] + '-debug.png'), 'PNG') debugImage.save(os.path.join(path, fileExpanded[0] + '-debug.png'), 'PNG')
# Create virtual pages # Create virtual pages
@@ -207,10 +207,6 @@ def splitImage(work):
return str(sys.exc_info()[1]) return str(sys.exc_info()[1])
def Copyright():
print(('comic2panel v%(__version__)s. Written by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals()))
def main(argv=None, qtGUI=None): def main(argv=None, qtGUI=None):
global options, GUI, splitWorkerPool, splitWorkerOutput, mergeWorkerPool, mergeWorkerOutput global options, GUI, splitWorkerPool, splitWorkerOutput, mergeWorkerPool, mergeWorkerOutput
parser = OptionParser(usage="Usage: kcc-c2p [options] comic_folder", add_help_option=False) parser = OptionParser(usage="Usage: kcc-c2p [options] comic_folder", add_help_option=False)
@@ -261,7 +257,7 @@ def main(argv=None, qtGUI=None):
GUI.progressBarTick.emit('Combining images') GUI.progressBarTick.emit('Combining images')
GUI.progressBarTick.emit(str(directoryNumer)) GUI.progressBarTick.emit(str(directoryNumer))
for i in mergeWork: for i in mergeWork:
mergeWorkerPool.apply_async(func=mergeDirectory, args=(i, ), callback=mergeDirectory_tick) mergeWorkerPool.apply_async(func=mergeDirectory, args=(i, ), callback=mergeDirectoryTick)
mergeWorkerPool.close() mergeWorkerPool.close()
mergeWorkerPool.join() mergeWorkerPool.join()
if GUI and not GUI.conversionAlive: if GUI and not GUI.conversionAlive:
@@ -284,7 +280,7 @@ def main(argv=None, qtGUI=None):
GUI.progressBarTick.emit('tick') GUI.progressBarTick.emit('tick')
if len(work) > 0: if len(work) > 0:
for i in work: for i in work:
splitWorkerPool.apply_async(func=splitImage, args=(i, ), callback=splitImage_tick) splitWorkerPool.apply_async(func=splitImage, args=(i, ), callback=splitImageTick)
splitWorkerPool.close() splitWorkerPool.close()
splitWorkerPool.join() splitWorkerPool.join()
if GUI and not GUI.conversionAlive: if GUI and not GUI.conversionAlive:

View File

@@ -16,11 +16,15 @@
# 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/>.
__version__ = '4.3'
__license__ = 'ISC' __license__ = 'ISC'
__copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>' __copyright__ = '2012-2014, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import os import os
from io import BytesIO
from urllib.request import Request, urlopen
from urllib.parse import quote
from functools import reduce from functools import reduce
from PIL import Image, ImageOps, ImageStat, ImageChops from PIL import Image, ImageOps, ImageStat, ImageChops
from .shared import md5Checksum from .shared import md5Checksum
@@ -81,18 +85,18 @@ class ProfileData:
'K1': ("Kindle 1", (600, 670), Palette4, 1.8, (900, 1005)), 'K1': ("Kindle 1", (600, 670), Palette4, 1.8, (900, 1005)),
'K2': ("Kindle 2", (600, 670), Palette15, 1.8, (900, 1005)), 'K2': ("Kindle 2", (600, 670), Palette15, 1.8, (900, 1005)),
'K345': ("Kindle", (600, 800), Palette16, 1.8, (900, 1200)), 'K345': ("Kindle", (600, 800), Palette16, 1.8, (900, 1200)),
'KHD': ("Kindle Paperwhite", (758, 1024), Palette16, 1.8, (1137, 1536)),
'KDX': ("Kindle DX/DXG", (824, 1000), Palette16, 1.8, (1236, 1500)), 'KDX': ("Kindle DX/DXG", (824, 1000), Palette16, 1.8, (1236, 1500)),
'KF': ("Kindle Fire", (600, 1024), PalleteNull, 1.0, (900, 1536)), 'KPW': ("Kindle Paperwhite", (758, 1024), Palette16, 1.8, (1137, 1536)),
'KFHD': ("K. Fire HD 7\"", (800, 1280), PalleteNull, 1.0, (1200, 1920)), 'KV': ("Kindle Voyage", (1080, 1440), Palette16, 1.8, (1620, 2160)),
'KFHD8': ("K. Fire HD 8.9\"", (1200, 1920), PalleteNull, 1.0, (1800, 2880)), 'KFHD': ("K. Fire HD", (800, 1280), PalleteNull, 1.0, (1200, 1920)),
'KFHDX': ("K. Fire HDX 7\"", (1200, 1920), PalleteNull, 1.0, (1800, 2880)), 'KFHDX': ("K. Fire HDX", (1200, 1920), PalleteNull, 1.0, (1800, 2880)),
'KFHDX8': ("K. Fire HDX 8.9\"", (1600, 2560), PalleteNull, 1.0, (2400, 3840)), 'KFHDX8': ("K. Fire HDX 8.9", (1600, 2560), PalleteNull, 1.0, (2400, 3840)),
'KFA': ("Kindle for Android", (0, 0), PalleteNull, 1.0, (0, 0)),
'KoMT': ("Kobo Mini/Touch", (600, 800), Palette16, 1.8, (900, 1200)), 'KoMT': ("Kobo Mini/Touch", (600, 800), Palette16, 1.8, (900, 1200)),
'KoG': ("Kobo Glow", (768, 1024), Palette16, 1.8, (1152, 1536)), 'KoG': ("Kobo Glow", (768, 1024), Palette16, 1.8, (1152, 1536)),
'KoA': ("Kobo Aura", (758, 1024), Palette16, 1.8, (1137, 1536)), 'KoA': ("Kobo Aura", (758, 1024), Palette16, 1.8, (1137, 1536)),
'KoAHD': ("Kobo Aura HD", (1080, 1440), Palette16, 1.8, (1620, 2160)), 'KoAHD': ("Kobo Aura HD", (1080, 1440), Palette16, 1.8, (1620, 2160)),
'KFA': ("Kindle for Android", (0, 0), PalleteNull, 1.0, (0, 0)), 'KoAH2O': ("Kobo Aura H2O", (1080, 1430), Palette16, 1.8, (1620, 2145)),
'OTHER': ("Other", (0, 0), Palette16, 1.8, (0, 0)), 'OTHER': ("Other", (0, 0), Palette16, 1.8, (0, 0)),
} }
@@ -400,50 +404,44 @@ class ComicPage:
def getImageHistogram(self, image): def getImageHistogram(self, image):
histogram = image.histogram() histogram = image.histogram()
RBGW = [] if histogram[0] == 0:
pixelCount = 0
for i in range(256):
pixelCount += histogram[i] + histogram[256 + i] + histogram[512 + i]
RBGW.append(histogram[i] + histogram[256 + i] + histogram[512 + i])
white = 0
black = 0
for i in range(251, 256):
white += RBGW[i]
for i in range(5):
black += RBGW[i]
if black > pixelCount*0.8 and white == 0:
return 1
elif white > pixelCount*0.8 and black == 0:
return -1 return -1
elif histogram[255] == 0:
return 1
else: else:
return False return 0
def getImageFill(self, webtoon): def getImageFill(self):
fill = 0 bw = self.image.convert('L').point(lambda x: 0 if x < 128 else 255, '1')
if not webtoon and not self.rotated: imageBoxA = bw.getbbox()
# Search for horizontal solid lines imageBoxB = ImageChops.invert(bw).getbbox()
startY = 0 if imageBoxA is None or imageBoxB is None:
while startY < self.image.size[1]: surfaceB, surfaceW = 0, 0
if startY + 5 > self.image.size[1]:
startY = self.image.size[1] - 5
checkSolid = self.getImageHistogram(self.image.crop((0, startY, self.image.size[0], startY+5)))
if checkSolid:
fill += checkSolid
startY += 5
else: else:
# Search for vertical solid lines surfaceB = (imageBoxA[2] - imageBoxA[0]) * (imageBoxA[3] - imageBoxA[1])
startX = 0 surfaceW = (imageBoxB[2] - imageBoxB[0]) * (imageBoxB[3] - imageBoxB[1])
while startX < self.image.size[0]: if surfaceW < surfaceB:
if startX + 5 > self.image.size[0]: self.fill = 'white'
startX = self.image.size[0] - 5 elif surfaceW > surfaceB:
checkSolid = self.getImageHistogram(self.image.crop((startX, 0, startX+5, self.image.size[1])))
if checkSolid:
fill += checkSolid
startX += 5
if fill > 0:
self.fill = 'black' self.fill = 'black'
else: else:
self.fill = 'white' fill = 0
startY = 0
while startY < bw.size[1]:
if startY + 5 > bw.size[1]:
startY = bw.size[1] - 5
fill += self.getImageHistogram(bw.crop((0, startY, bw.size[0], startY+5)))
startY += 5
startX = 0
while startX < bw.size[0]:
if startX + 5 > bw.size[0]:
startX = bw.size[0] - 5
fill += self.getImageHistogram(bw.crop((startX, 0, startX+5, bw.size[1])))
startX += 5
if fill > 0:
self.fill = 'black'
else:
self.fill = 'white'
def isImageColor(self): def isImageColor(self):
v = ImageStat.Stat(self.image).var v = ImageStat.Stat(self.image).var
@@ -472,14 +470,37 @@ class ComicPage:
class Cover: class Cover:
def __init__(self, source, target): def __init__(self, source, target, opt, tomeNumber):
self.options = opt
self.source = source self.source = source
self.target = target self.target = target
self.image = Image.open(source) if tomeNumber == 0:
self.tomeNumber = 1
else:
self.tomeNumber = tomeNumber
if self.tomeNumber in self.options.remoteCovers:
try:
source = urlopen(Request(quote(self.options.remoteCovers[self.tomeNumber]).replace('%3A', ':', 1),
headers={'User-Agent': 'KindleComicConverter/' + __version__})).read()
self.image = Image.open(BytesIO(source))
self.processExternal()
except Exception:
self.image = Image.open(source)
self.processInternal()
else:
self.image = Image.open(source)
self.processInternal()
def processInternal(self):
self.image = self.image.convert('RGB') self.image = self.image.convert('RGB')
self.process() self.image = self.trim()
self.save() self.save()
def processExternal(self):
self.image = self.image.convert('RGB')
self.image.thumbnail(self.options.profileData[1], Image.ANTIALIAS)
self.save(True)
def trim(self): def trim(self):
bg = Image.new(self.image.mode, self.image.size, self.image.getpixel((0, 0))) bg = Image.new(self.image.mode, self.image.size, self.image.getpixel((0, 0)))
diff = ImageChops.difference(self.image, bg) diff = ImageChops.difference(self.image, bg)
@@ -490,12 +511,13 @@ class Cover:
else: else:
return self.image return self.image
def process(self): def save(self, external=False):
self.image = self.trim() if external:
source = self.options.remoteCovers[self.tomeNumber].split('/')[-1]
def save(self): else:
source = self.source
try: try:
if os.path.splitext(self.source)[1].lower() == '.png': if os.path.splitext(source)[1].lower() == '.png':
self.image.save(self.target, "PNG", optimize=1) self.image.save(self.target, "PNG", optimize=1)
else: else:
self.image.save(self.target, "JPEG", optimize=1) self.image.save(self.target, "JPEG", optimize=1)

View File

@@ -1,12 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
cx_Freeze/py2app build script for KCC. py2exe/py2app build script for KCC.
Usage (Mac OS X):
python setup.py py2app
Usage (Windows): Usage (Windows):
python setup.py py2exe python setup.py py2exe
Usage (Mac OS X):
python setup.py py2app
""" """
from sys import platform, version_info from sys import platform, version_info
if version_info[0] != 3: if version_info[0] != 3:
@@ -14,7 +14,7 @@ if version_info[0] != 3:
exit(1) exit(1)
NAME = "KindleComicConverter" NAME = "KindleComicConverter"
VERSION = "4.1" VERSION = "4.3"
MAIN = "kcc.py" MAIN = "kcc.py"
if platform == "darwin": if platform == "darwin":
@@ -63,43 +63,22 @@ elif platform == "win32":
suffix = '_64' suffix = '_64'
else: else:
suffix = '' suffix = ''
additional_files = [('imageformats', ['C:\Python34' + suffix + additional_files = [('platforms', ['C:\Python34' + suffix +
'\Lib\site-packages\PyQt5\plugins\imageformats\qgif.dll',
'C:\Python34' + suffix +
'\Lib\site-packages\PyQt5\plugins\imageformats\qico.dll',
'C:\Python34' + suffix +
'\Lib\site-packages\PyQt5\plugins\imageformats\qjpeg.dll',
'C:\Python34' + suffix +
'\Lib\site-packages\PyQt5\plugins\imageformats\qmng.dll',
'C:\Python34' + suffix +
'\Lib\site-packages\PyQt5\plugins\imageformats\qsvg.dll',
'C:\Python34' + suffix +
'\Lib\site-packages\PyQt5\plugins\imageformats\qtga.dll',
'C:\Python34' + suffix +
'\Lib\site-packages\PyQt5\plugins\imageformats\qtiff.dll',
'C:\Python34' + suffix +
'\Lib\site-packages\PyQt5\plugins\imageformats\qwbmp.dll']),
('platforms', ['C:\Python34' + suffix +
'\Lib\site-packages\PyQt5\plugins\platforms\qminimal.dll',
'C:\Python34' + suffix +
'\Lib\site-packages\PyQt5\plugins\platforms\qoffscreen.dll',
'C:\Python34' + suffix +
'\Lib\site-packages\PyQt5\plugins\platforms\qwindows.dll']), '\Lib\site-packages\PyQt5\plugins\platforms\qwindows.dll']),
('', ['LICENSE.txt', ('', ['LICENSE.txt',
'other\\7za.exe', 'other\\7za.exe',
'other\\UnRAR.exe', 'other\\UnRAR.exe',
'other\\Additional-LICENSE.txt', 'other\\Additional-LICENSE.txt',
'other\\7za.exe',
'C:\Python34' + suffix + '\Lib\site-packages\PyQt5\libEGL.dll'])] 'C:\Python34' + suffix + '\Lib\site-packages\PyQt5\libEGL.dll'])]
extra_options = dict( extra_options = dict(
options={'py2exe': {"bundle_files": 2, options={'py2exe': {"bundle_files": 1,
"dll_excludes": ["tcl85.dll", "tk85.dll"], "dll_excludes": ["tcl85.dll", "tk85.dll"],
"dist_dir": "dist" + suffix, "dist_dir": "dist" + suffix,
"compressed": True, "compressed": True,
"includes": ["sip"], "includes": ["sip"],
"excludes": ["tkinter"], "excludes": ["tkinter"],
"optimize": 2}}, "optimize": 2}},
windows=[{"script": "kcc.py", windows=[{"script": MAIN,
"dest_base": "KCC", "dest_base": "KCC",
"version": VERSION, "version": VERSION,
"copyright": "Ciro Mattia Gonano, Pawel Jastrzebski © 2014", "copyright": "Ciro Mattia Gonano, Pawel Jastrzebski © 2014",
@@ -114,7 +93,7 @@ else:
print('Please use setup.sh to build Linux package.') print('Please use setup.sh to build Linux package.')
exit() exit()
#noinspection PyUnboundLocalVariable # noinspection PyUnboundLocalVariable
setup( setup(
name=NAME, name=NAME,
version=VERSION, version=VERSION,

View File

@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
# Linux Python package build script # Linux Python package build script
VERSION="4.1" VERSION="4.3"
cp kcc.py __main__.py cp kcc.py __main__.py
zip kcc.zip __main__.py kcc/*.py zip kcc.zip __main__.py kcc/*.py