1
0
mirror of https://github.com/ciromattia/kcc synced 2025-12-15 18:56:28 +00:00

Merge branch 'master' into python3

This commit is contained in:
Paweł Jastrzębski
2014-01-15 09:33:35 +01:00
20 changed files with 678 additions and 363 deletions

View File

@@ -388,7 +388,7 @@
p, li { white-space: pre-wrap; } p, li { white-space: pre-wrap; }
</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;"> </style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;">
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;">Unchecked - Normal quality mode<br /></span><span style=" font-family:'MS Shell Dlg 2'; font-style:italic;">Use it when Panel View support is not needed.</span><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;"><br /></span><span style=" font-family:'MS Shell Dlg 2';">- Maximum quality when zoom is not enabled.<br />- Poor quality when zoom is enabled.<br />- Lowest file size.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;">Unchecked - Normal quality mode<br /></span><span style=" font-family:'MS Shell Dlg 2'; font-style:italic;">Use it when Panel View support is not needed.</span><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;"><br /></span><span style=" font-family:'MS Shell Dlg 2';">- Maximum quality when zoom is not enabled.<br />- Poor quality when zoom is enabled.<br />- Lowest file size.</span></p>
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;">Indeterminate - High quality mode<br /></span><span style=" font-family:'MS Shell Dlg 2'; font-style:italic;">Not zoomed image </span><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; font-style:italic;">might </span><span style=" font-family:'MS Shell Dlg 2'; font-style:italic;">be a little blurry.</span><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;"><br /></span><span style=" font-family:'MS Shell Dlg 2';">- Medium/High quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;">Indeterminate - High quality mode<br /></span><span style=" font-family:'MS Shell Dlg 2'; font-style:italic;">Not zoomed image </span><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; font-style:italic;">might </span><span style=" font-family:'MS Shell Dlg 2'; font-style:italic;">be a little blurry.<br /></span><span style=" font-family:'MS Shell Dlg 2'; font-style:italic;">Smaller images might be forcefully upscaled in this mode.</span><span style=" font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;"><br /></span><span style=" font-family:'MS Shell Dlg 2';">- Medium/High quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.</span></p>
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Ultra quality mode&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-style:italic;&quot;&gt;Maximum possible quality.&lt;/span&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2';&quot;&gt;- Maximum quality when zoom is not enabled.&lt;br /&gt;- Maximum quality when zoom is enabled.&lt;br /&gt;- Very high file size.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> &lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Ultra quality mode&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-style:italic;&quot;&gt;Maximum possible quality.&lt;/span&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2';&quot;&gt;- Maximum quality when zoom is not enabled.&lt;br /&gt;- Maximum quality when zoom is enabled.&lt;br /&gt;- Very high file size.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">

View File

@@ -388,7 +388,7 @@
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot;font-size:12pt; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Normal quality mode&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot;font-size:12pt; font-style:italic;&quot;&gt;Use it when Panel View support is not needed.&lt;/span&gt;&lt;span style=&quot;font-size:12pt; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot;font-size:12pt;&quot;&gt;- Maximum quality when zoom is not enabled.&lt;br/&gt;- Poor quality when zoom is enabled.&lt;br/&gt;- Lowest file size.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size:12pt; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - High quality mode&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot;font-size:12pt; font-style:italic;&quot;&gt;Not zoomed image &lt;/span&gt;&lt;span style=&quot;font-size:12pt; font-weight:600; font-style:italic;&quot;&gt;might &lt;/span&gt;&lt;span style=&quot;font-size:12pt; font-style:italic;&quot;&gt;be a little blurry.&lt;/span&gt;&lt;span style=&quot;font-size:12pt; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot;font-size:12pt;&quot;&gt;- Medium/High quality when zoom is not enabled.&lt;br/&gt;- Maximum quality when zoom is enabled.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size:12pt; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Ultra quality mode&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot;font-size:12pt; font-style:italic;&quot;&gt;Maximum possible quality.&lt;/span&gt;&lt;span style=&quot;font-size:12pt; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot;font-size:12pt;&quot;&gt;- Maximum quality when zoom is not enabled.&lt;br/&gt;- Maximum quality when zoom is enabled.&lt;br/&gt;- Very high file size.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Normal quality mode&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot; font-size:12pt; font-style:italic;&quot;&gt;Use it when Panel View support is not needed.&lt;/span&gt;&lt;span style=&quot; font-size:12pt; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;- Maximum quality when zoom is not enabled.&lt;br/&gt;- Poor quality when zoom is enabled.&lt;br/&gt;- Lowest file size.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - High quality mode&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot; font-size:12pt; font-style:italic;&quot;&gt;Not zoomed image &lt;/span&gt;&lt;span style=&quot; font-size:12pt; font-weight:600; font-style:italic;&quot;&gt;might &lt;/span&gt;&lt;span style=&quot; font-size:12pt; font-style:italic;&quot;&gt;be a little blurry.&lt;br/&gt;Smaller images might be forcefully upscaled in this mode.&lt;/span&gt;&lt;span style=&quot; font-size:12pt; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;- Medium/High quality when zoom is not enabled.&lt;br/&gt;- Maximum quality when zoom is enabled.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Ultra quality mode&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot; font-size:12pt; font-style:italic;&quot;&gt;Maximum possible quality.&lt;/span&gt;&lt;span style=&quot; font-size:12pt; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;- Maximum quality when zoom is not enabled.&lt;br/&gt;- Maximum quality when zoom is enabled.&lt;br/&gt;- Very high file size.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>High/Ultra quality</string> <string>High/Ultra quality</string>

View File

@@ -3,6 +3,7 @@
<file>icons/comic2ebook.png</file> <file>icons/comic2ebook.png</file>
</qresource> </qresource>
<qresource prefix="Devices"> <qresource prefix="Devices">
<file>icons/Kobo.png</file>
<file>icons/Other.png</file> <file>icons/Other.png</file>
<file>icons/Kindle.png</file> <file>icons/Kindle.png</file>
</qresource> </qresource>

2
KCC.ui
View File

@@ -340,7 +340,7 @@
p, li { white-space: pre-wrap; } p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt; &lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Normal quality mode&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Use it when Panel View support is not needed.&lt;/span&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br /&gt;&lt;/span&gt;- Maximum quality when zoom is not enabled.&lt;br /&gt;- Poor quality when zoom is enabled.&lt;br /&gt;- Lowest file size.&lt;/p&gt; &lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Normal quality mode&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Use it when Panel View support is not needed.&lt;/span&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br /&gt;&lt;/span&gt;- Maximum quality when zoom is not enabled.&lt;br /&gt;- Poor quality when zoom is enabled.&lt;br /&gt;- Lowest file size.&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - High quality mode&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Not zoomed image &lt;/span&gt;&lt;span style=&quot; font-weight:600; font-style:italic;&quot;&gt;might &lt;/span&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;be &lt;/span&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;a little blurry.&lt;/span&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br /&gt;&lt;/span&gt;- Medium/High quality when zoom is not enabled.&lt;br /&gt;- Maximum quality when zoom is enabled.&lt;/p&gt; &lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - High quality mode&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Not zoomed image &lt;/span&gt;&lt;span style=&quot; font-weight:600; font-style:italic;&quot;&gt;might &lt;/span&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;be a little blurry.&lt;br /&gt;Smaller images might be forcefully upscaled in this mode.&lt;/span&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br /&gt;&lt;/span&gt;- Medium/High quality when zoom is not enabled.&lt;br /&gt;- Maximum quality when zoom is enabled.&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Ultra quality mode&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Maximum possible quality.&lt;/span&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br /&gt;&lt;/span&gt;- Maximum quality when zoom is not enabled.&lt;br /&gt;- Maximum quality when zoom is enabled.&lt;br /&gt;- Very high file size.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> &lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Ultra quality mode&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Maximum possible quality.&lt;/span&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;&lt;br /&gt;&lt;/span&gt;- Maximum quality when zoom is not enabled.&lt;br /&gt;- Maximum quality when zoom is enabled.&lt;br /&gt;- Very high file size.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">

View File

@@ -1,6 +1,6 @@
# KCC # KCC
**Kindle Comic Converter** is a Python app to convert comic files or folders to ePub or Panel View MOBI. **Kindle Comic Converter** is a Python app to convert comic 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 initally developed for Kindle but since v2.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 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.
@@ -11,7 +11,8 @@ Amazon's tool is for comic publishers and involves a lot of manual effort, while
_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
If you have some problems using KCC please [file an issue here](https://github.com/ciromattia/kcc/issues/new). If you have general questions about usage, feedback etc. please [post it here](http://www.mobileread.com/forums/showthread.php?t=207461).
If you have some **technical** problems using KCC please [file an issue here](https://github.com/ciromattia/kcc/issues/new).
If you can fix an open issue, fork & make a pull request. If you can fix an open issue, fork & make a pull request.
If you want more chances an issue is fixes or your wanted feature added, consider [placing a bounty](https://www.bountysource.com/trackers/65571-ciromattia-kcc)! If you want more chances an issue is fixes or your wanted feature added, consider [placing a bounty](https://www.bountysource.com/trackers/65571-ciromattia-kcc)!
@@ -23,54 +24,35 @@ If you find **KCC** valuable you can consider donating to the authors:
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.vulturis.eu/Windows/](http://kcc.vulturis.eu/Windows/) - **Windows:** [http://kcc.vulturis.eu/Windows/](http://kcc.vulturis.eu/Windows/)
- **Linux:** [http://kcc.vulturis.eu/Linux/](http://kcc.vulturis.eu/Linux/) - **Linux:** [http://kcc.vulturis.eu/Linux/](http://kcc.vulturis.eu/Linux/)
- **OS X (10.8 or later):** [http://kcc.vulturis.eu/OSX/](http://kcc.vulturis.eu/OSX/) - **OS X 10.8+:** [http://kcc.vulturis.eu/OSX/](http://kcc.vulturis.eu/OSX/)
- **OS X (10.7 or earlier):** Soon™
## INPUT FORMATS ## INPUT FORMATS
**KCC** can understand and convert, at the moment, the following file types: **KCC** can understand and convert, at the moment, the following input types:
- PNG, JPG, GIF, TIFF, BMP - Folders containing: PNG, JPG, GIF, TIFF or BMP files
- Folders
- 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 *(Extracting only contained 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)*
- [UnRAR](http://www.rarlab.com/download.htm) *(For CBR/RAR support)* - [UnRAR](http://www.rarlab.com/download.htm) *(For CBR/RAR support)*
- [7za](http://www.7-zip.org/download.html) *(For 7z/CB7 support)* - [7za](http://www.7-zip.org/download.html) *(For 7z/CB7 support)*
### For compiling/running from source: ### For compiling/running from source:
- Python 2.7 - Included in MacOS and Linux, follow the [official documentation](http://www.python.org/getit/windows/) to install on Windows. - Python 2.7 - Included in MacOS and Linux, follow the [official documentation](http://www.python.org/getit/windows/) to install on Windows.
- [PyQt4](http://www.riverbankcomputing.co.uk/software/pyqt/download) - Please refer to official documentation for installing into your system. - [PyQt4](http://www.riverbankcomputing.co.uk/software/pyqt/download) - Please refer to official documentation for installing into your system.
- [Pillow](http://pypi.python.org/pypi/Pillow/) 2.2.1+ - For comic optimizations. Please refer to official documentation for installing into your system. - [Pillow](http://pypi.python.org/pypi/Pillow/) 2.3.0+ - For comic optimizations. Please refer to official documentation for installing into your system.
- [Psutil](https://code.google.com/p/psutil/) - Please refer to official documentation for installing into your system. - [Psutil](https://code.google.com/p/psutil/) - Please refer to official documentation for installing into your system.
- **To build OS X release you need a modified QT:** [patch](https://github.com/ciromattia/kcc/blob/master/other/QT-4.8.5-QListWidget.patch) - **To build OS X release you need a modified QT:** [patch](https://github.com/ciromattia/kcc/blob/master/other/QT-4.8.5-QListWidget.patch)
## USAGE ## USAGE
### Important tips:
* Use high quality source files. **This little detail have a major impact on the final result.**
* Read tooltip of _High/Ultra quality_ option. There are many important informations there.
* When converting images smaller than device resolution remember to enable upscaling.
* Panel View (auto zooming every part of page) can be disabled directly on Kindle. There is no KCC option to do that.
* Check our [wiki](https://github.com/ciromattia/kcc/wiki/Other-devices) for a list of tested Non-Kindle E-Readers.
* The first image found will be set as the comic's cover.
* All files/directories will be added to EPUB in alphabetical order.
* Using high/ultra quality output option with Kindle Fire HD/HDX in most cases is just waste of space.
* ComicRack metadata will be parsed only if they are saved in *ComicInfo.xml* file.
### Calibre:
* Calibre can be used to upload files created by KCC.
* Uploading KCC output with Calibre will remove *Personal* tag from cover.
* **Don't convert files created by KCC with Calibre!** Any conversion process will corrupt the file!
* Don't use Calibre reader to preview files created by KCC. It can't parse them correctly.
### GUI
Should be pretty self-explanatory. All options have detailed informations in tooltips. Should be pretty self-explanatory. All options have detailed informations in tooltips.
After completed conversion you should find ready file alongside the original input file (same directory). After completed conversion you should find ready file alongside the original input file (same directory).
Please check [our wiki](https://github.com/ciromattia/kcc/wiki/) for more details.
### Standalone `comic2ebook.py` usage: ### Standalone `comic2ebook.py` usage:
``` ```
@@ -79,7 +61,7 @@ Usage: comic2ebook.py [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) [Default=KHD] Device profile (Choose one among K1, K2, K345, KDX, KHD, KF, KFHD, KFHD8, KFHDX, KFHDX8, KFA, KoMT, KoG, KoA, KoAHD) [Default=KHD]
-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)
@@ -127,6 +109,7 @@ Options:
-y HEIGHT, --height=HEIGHT -y HEIGHT, --height=HEIGHT
Height of the target device screen Height of the target device screen
-i, --in-place Overwrite source directory -i, --in-place Overwrite source directory
-m, --merge Combine every directory into a single image before splitting
OTHER: OTHER:
-d, --debug Create debug file for every splitted image -d, --debug Create debug file for every splitted image
@@ -149,11 +132,14 @@ The app relies and includes the following scripts/binaries:
* [Kindle Paperwhite](http://kcc.vulturis.eu/Samples/Ubunchu!-KPW.mobi) * [Kindle Paperwhite](http://kcc.vulturis.eu/Samples/Ubunchu!-KPW.mobi)
* [Kindle](http://kcc.vulturis.eu/Samples/Ubunchu!-K345.mobi) * [Kindle](http://kcc.vulturis.eu/Samples/Ubunchu!-K345.mobi)
* [Kindle DX/DXG](http://kcc.vulturis.eu/Samples/Ubunchu!-KDX.mobi) * [Kindle DX/DXG](http://kcc.vulturis.eu/Samples/Ubunchu!-KDX.mobi)
* [Kindle Fire](http://kcc.vulturis.eu/Samples/Ubunchu!-KF.mobi)
* [Kindle Fire HD](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHD.mobi) * [Kindle Fire HD](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHD.mobi)
* [Kindle Fire HD 8.9"](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHD8.mobi) * [Kindle Fire HD 8.9"](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHD8.mobi)
* [Kindle Fire HDX](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHDX.mobi) * [Kindle Fire HDX](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHDX.mobi)
* [Kindle Fire HDX 8.9"](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHDX8.mobi) * [Kindle Fire HDX 8.9"](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHDX8.mobi)
* [Kobo Mini/Touch](http://kcc.vulturis.eu/Samples/Ubunchu!-KoMT.cbz)
* [Kobo Glow](http://kcc.vulturis.eu/Samples/Ubunchu!-KoG.cbz)
* [Kobo Aura](http://kcc.vulturis.eu/Samples/Ubunchu!-KoA.cbz)
* [Kobo Aura HD](http://kcc.vulturis.eu/Samples/Ubunchu!-KoAHD.cbz)
## CHANGELOG ## CHANGELOG
####1.0 ####1.0
@@ -311,6 +297,21 @@ The app relies and includes the following scripts/binaries:
* Fixed previous PNG output fix * Fixed previous PNG output fix
* Fixed Panel View anomalies * Fixed Panel View anomalies
####3.7:
* Added profiles for KOBO devices
* Improved Panel View support
* Improved WebToon splitter
* Improved margin color autodetection
* Tweaked EPUB output
* Fixed stretching option
* GUI tweaks and minor bugfixes
####3.7.1:
* Hotfixed Kobo profiles
####3.7.2:
* Fixed problems with HQ mode
## COPYRIGHT ## COPYRIGHT
Copyright (c) 2012-2013 Ciro Mattia Gonano and Paweł Jastrzębski. Copyright (c) 2012-2013 Ciro Mattia Gonano and Paweł Jastrzębski.

BIN
icons/Kobo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -66,6 +66,7 @@ Source: "build\exe.win-amd64-2.7\sip.pyd"; DestDir: "{app}"; Flags: ignoreversio
Source: "build\exe.win-amd64-2.7\SSLEAY32.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode Source: "build\exe.win-amd64-2.7\SSLEAY32.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "build\exe.win-amd64-2.7\unicodedata.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode Source: "build\exe.win-amd64-2.7\unicodedata.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "build\exe.win-amd64-2.7\_psutil_mswindows.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode Source: "build\exe.win-amd64-2.7\_psutil_mswindows.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "other\vcredist_x64.exe"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall; Check: Is64BitInstallMode
; x86 files ; x86 files
Source: "build\exe.win32-2.7\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion solidbreak; Check: not Is64BitInstallMode Source: "build\exe.win32-2.7\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion solidbreak; Check: not Is64BitInstallMode
Source: "build\exe.win32-2.7\_ctypes.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode Source: "build\exe.win32-2.7\_ctypes.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
@@ -91,6 +92,7 @@ Source: "build\exe.win32-2.7\sip.pyd"; DestDir: "{app}"; Flags: ignoreversion; C
Source: "build\exe.win32-2.7\SSLEAY32.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode Source: "build\exe.win32-2.7\SSLEAY32.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
Source: "build\exe.win32-2.7\unicodedata.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode Source: "build\exe.win32-2.7\unicodedata.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
Source: "build\exe.win32-2.7\_psutil_mswindows.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode Source: "build\exe.win32-2.7\_psutil_mswindows.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
Source: "other\vcredist_x86.exe"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall; Check: not Is64BitInstallMode
; Common files ; Common files
Source: "LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion solidbreak Source: "LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion solidbreak
Source: "other\Additional-LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion Source: "other\Additional-LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion
@@ -104,6 +106,8 @@ Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks:
[Run] [Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
Filename: "{tmp}\vcredist_x64.exe"; Parameters: "/passive /Q:a /c:""msiexec /qb /i vcredist.msi"" "; StatusMsg: "Installing Microsoft Visual C++ 2008 Redistributable Package..."; Check: Is64BitInstallMode
Filename: "{tmp}\vcredist_x86.exe"; Parameters: "/passive /Q:a /c:""msiexec /qb /i vcredist.msi"" "; StatusMsg: "Installing Microsoft Visual C++ 2008 Redistributable Package..."; Check: not Is64BitInstallMode
[Messages] [Messages]
WelcomeLabel1=Welcome to the KCC Setup Wizard WelcomeLabel1=Welcome to the KCC Setup Wizard

2
kcc.py
View File

@@ -26,7 +26,7 @@ __docformat__ = 'restructuredtext en'
import sys import sys
import os import os
try: try:
#noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from PyQt4 import QtCore, QtGui, QtNetwork from PyQt4 import QtCore, QtGui, QtNetwork
except ImportError: except ImportError:
print("ERROR: PyQT4 is not installed!") print("ERROR: PyQT4 is not installed!")

View File

@@ -33,14 +33,13 @@ from time import sleep
from shutil import move from shutil import move
from http.server import BaseHTTPRequestHandler, HTTPServer from http.server import BaseHTTPRequestHandler, HTTPServer
from socketserver import ThreadingMixIn from socketserver import ThreadingMixIn
from .image import ProfileData
from subprocess import STDOUT, PIPE from subprocess import STDOUT, PIPE
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
from xml.dom.minidom import parse from xml.dom.minidom import parse
from html.parser import HTMLParser from html.parser import HTMLParser
from .KCC_rc_web import WebContent from .KCC_rc_web import WebContent
try: try:
#noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from psutil import TOTAL_PHYMEM, Popen from psutil import TOTAL_PHYMEM, Popen
except ImportError: except ImportError:
print("ERROR: Psutil is not installed!") print("ERROR: Psutil is not installed!")
@@ -63,6 +62,8 @@ class Icons:
def __init__(self): def __init__(self):
self.deviceKindle = QtGui.QIcon() self.deviceKindle = QtGui.QIcon()
self.deviceKindle.addPixmap(QtGui.QPixmap(":/Devices/icons/Kindle.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.deviceKindle.addPixmap(QtGui.QPixmap(":/Devices/icons/Kindle.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.deviceKobo = QtGui.QIcon()
self.deviceKobo.addPixmap(QtGui.QPixmap(":/Devices/icons/Kobo.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.deviceOther = QtGui.QIcon() self.deviceOther = QtGui.QIcon()
self.deviceOther.addPixmap(QtGui.QPixmap(":/Devices/icons/Other.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.deviceOther.addPixmap(QtGui.QPixmap(":/Devices/icons/Other.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
@@ -345,7 +346,7 @@ class WorkerThread(QtCore.QThread):
def run(self): def run(self):
self.emit(QtCore.SIGNAL("modeConvert"), False) self.emit(QtCore.SIGNAL("modeConvert"), False)
profile = ProfileData.ProfileLabels[str(GUI.DeviceBox.currentText())] profile = GUI.profiles[str(GUI.DeviceBox.currentText())]['Label']
argv = ["--profile=" + profile] argv = ["--profile=" + profile]
currentJobs = [] currentJobs = []
if GUI.MangaBox.isChecked(): if GUI.MangaBox.isChecked():
@@ -356,6 +357,8 @@ class WorkerThread(QtCore.QThread):
argv.append("--quality=1") argv.append("--quality=1")
elif GUI.QualityBox.checkState() == 2: elif GUI.QualityBox.checkState() == 2:
argv.append("--quality=2") argv.append("--quality=2")
if str(GUI.FormatBox.currentText()) == 'CBZ':
argv.append("--cbz-output")
if GUI.currentMode == 1: if GUI.currentMode == 1:
if profile in ['KFHD', 'KFHD8', 'KFHDX', 'KFHDX8']: if profile in ['KFHD', 'KFHD8', 'KFHDX', 'KFHDX8']:
argv.append("--upscale") argv.append("--upscale")
@@ -379,8 +382,6 @@ class WorkerThread(QtCore.QThread):
if float(GUI.GammaValue) > 0.09: if float(GUI.GammaValue) > 0.09:
# noinspection PyTypeChecker # noinspection PyTypeChecker
argv.append("--gamma=" + GUI.GammaValue) argv.append("--gamma=" + GUI.GammaValue)
if str(GUI.FormatBox.currentText()) == 'CBZ':
argv.append("--cbz-output")
if str(GUI.FormatBox.currentText()) == 'MOBI': if str(GUI.FormatBox.currentText()) == 'MOBI':
argv.append("--batchsplit") argv.append("--batchsplit")
if GUI.currentMode > 2: if GUI.currentMode > 2:
@@ -493,10 +494,8 @@ class WorkerThread(QtCore.QThread):
# break # break
#if not self.errors: #if not self.errors:
# for item in outputPath: # for item in outputPath:
# GUI.progress.content = '' # GUI.completedWork[os.path.basename(mobiPath).encode('utf-8')] = mobiPath.encode('utf-8')
# mobiPath = item.replace('.epub', '.mobi') # self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI files... <b>Done!</b>', 'info', True)
# os.remove(mobiPath + '_toclean')
# GUI.completedWork[os.path.basename(mobiPath).encode('utf-8')] = \
# mobiPath.encode('utf-8') # mobiPath.encode('utf-8')
# self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI files... <b>Done!</b>', 'info', # self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI files... <b>Done!</b>', 'info',
# True) # True)
@@ -523,7 +522,7 @@ class WorkerThread(QtCore.QThread):
self.emit(QtCore.SIGNAL("addTrayMessage"), 'KindleGen failed to create MOBI!', 'Critical') self.emit(QtCore.SIGNAL("addTrayMessage"), 'KindleGen failed to create MOBI!', 'Critical')
if self.kindlegenErrorCode[0] == 1 and self.kindlegenErrorCode[1] != '': if self.kindlegenErrorCode[0] == 1 and self.kindlegenErrorCode[1] != '':
self.emit(QtCore.SIGNAL("showDialog"), "KindleGen error:\n\n" + self.emit(QtCore.SIGNAL("showDialog"), "KindleGen error:\n\n" +
self.self.kindlegenErrorCode[1]) self.kindlegenErrorCode[1])
if self.kindlegenErrorCode[0] == 23026: if self.kindlegenErrorCode[0] == 23026:
self.emit(QtCore.SIGNAL("addMessage"), 'Created EPUB file was too big.', self.emit(QtCore.SIGNAL("addMessage"), 'Created EPUB file was too big.',
'error') 'error')
@@ -581,7 +580,7 @@ class KCCGUI(KCC_ui.Ui_KCC):
dnames = "" dnames = ""
for dname in dnames: for dname in dnames:
if str(dname) != "": if str(dname) != "":
if sys.platform == 'win32': if sys.platform.startswith('win'):
dname = dname.replace('/', '\\') dname = dname.replace('/', '\\')
self.lastPath = os.path.abspath(os.path.join(str(dname), os.pardir)) self.lastPath = os.path.abspath(os.path.join(str(dname), os.pardir))
GUI.JobList.addItem(dname) GUI.JobList.addItem(dname)
@@ -623,67 +622,103 @@ class KCCGUI(KCC_ui.Ui_KCC):
MW.setMinimumSize(QtCore.QSize(420, 287)) MW.setMinimumSize(QtCore.QSize(420, 287))
MW.setMaximumSize(QtCore.QSize(420, 287)) MW.setMaximumSize(QtCore.QSize(420, 287))
MW.resize(420, 287) MW.resize(420, 287)
GUI.BasicModeButton.setEnabled(True)
GUI.AdvModeButton.setEnabled(True)
GUI.BasicModeButton.setStyleSheet('font-weight:Bold;') GUI.BasicModeButton.setStyleSheet('font-weight:Bold;')
GUI.AdvModeButton.setStyleSheet('font-weight:Normal;') GUI.AdvModeButton.setStyleSheet('font-weight:Normal;')
GUI.FormatBox.setCurrentIndex(0)
GUI.FormatBox.setEnabled(False) GUI.FormatBox.setEnabled(False)
GUI.NoRotateBox.setChecked(False) GUI.OptionsBasic.setEnabled(True)
GUI.WebtoonBox.setChecked(False) GUI.OptionsBasic.setVisible(True)
GUI.ProcessingBox.setChecked(False) GUI.MangaBox.setChecked(False)
GUI.RotateBox.setChecked(False)
GUI.QualityBox.setChecked(False)
GUI.OptionsAdvanced.setEnabled(False) GUI.OptionsAdvanced.setEnabled(False)
GUI.OptionsAdvanced.setVisible(False)
GUI.ProcessingBox.setChecked(False)
GUI.UpscaleBox.setChecked(False)
GUI.NoRotateBox.setChecked(False)
GUI.BorderBox.setChecked(False)
GUI.WebtoonBox.setChecked(False)
GUI.NoDitheringBox.setChecked(False)
GUI.OptionsAdvancedGamma.setEnabled(False) GUI.OptionsAdvancedGamma.setEnabled(False)
GUI.OptionsAdvancedGamma.setVisible(False)
GUI.OptionsExpert.setEnabled(False) GUI.OptionsExpert.setEnabled(False)
GUI.ProcessingBox.hide() GUI.OptionsExpert.setVisible(False)
GUI.UpscaleBox.hide() GUI.ColorBox.setChecked(False)
GUI.NoRotateBox.hide()
GUI.MangaBox.setEnabled(True)
self.changeFormat()
def modeAdvanced(self): def modeAdvanced(self):
self.currentMode = 2 self.currentMode = 2
MW.setMinimumSize(QtCore.QSize(420, 365)) MW.setMinimumSize(QtCore.QSize(420, 365))
MW.setMaximumSize(QtCore.QSize(420, 365)) MW.setMaximumSize(QtCore.QSize(420, 365))
MW.resize(420, 365) MW.resize(420, 365)
GUI.BasicModeButton.setEnabled(True)
GUI.AdvModeButton.setEnabled(True)
GUI.BasicModeButton.setStyleSheet('font-weight:Normal;') GUI.BasicModeButton.setStyleSheet('font-weight:Normal;')
GUI.AdvModeButton.setStyleSheet('font-weight:Bold;') GUI.AdvModeButton.setStyleSheet('font-weight:Bold;')
GUI.FormatBox.setEnabled(True) GUI.FormatBox.setEnabled(True)
GUI.ProcessingBox.show() GUI.OptionsBasic.setEnabled(True)
GUI.UpscaleBox.show() GUI.OptionsBasic.setVisible(True)
GUI.NoRotateBox.show() GUI.MangaBox.setChecked(False)
GUI.OptionsAdvancedGamma.setEnabled(True) GUI.RotateBox.setChecked(False)
GUI.QualityBox.setChecked(False)
GUI.OptionsAdvanced.setEnabled(True) GUI.OptionsAdvanced.setEnabled(True)
GUI.OptionsExpert.setEnabled(False) GUI.OptionsAdvanced.setVisible(True)
GUI.MangaBox.setEnabled(True) GUI.ProcessingBox.setChecked(False)
GUI.UpscaleBox.setChecked(False)
GUI.NoRotateBox.setChecked(False)
GUI.BorderBox.setChecked(False)
GUI.WebtoonBox.setChecked(False)
GUI.NoDitheringBox.setChecked(False)
GUI.OptionsAdvancedGamma.setEnabled(True)
GUI.OptionsAdvancedGamma.setVisible(True)
GUI.OptionsExpert.setEnabled(True)
GUI.OptionsExpert.setVisible(True)
GUI.ColorBox.setChecked(False)
def modeExpert(self, KFA=False): def modeExpert(self):
self.modeAdvanced()
self.currentMode = 3 self.currentMode = 3
MW.setMinimumSize(QtCore.QSize(420, 397)) MW.setMinimumSize(QtCore.QSize(420, 397))
MW.setMaximumSize(QtCore.QSize(420, 397)) MW.setMaximumSize(QtCore.QSize(420, 397))
MW.resize(420, 397) MW.resize(420, 397)
GUI.BasicModeButton.setEnabled(False)
GUI.AdvModeButton.setEnabled(False)
GUI.BasicModeButton.setStyleSheet('font-weight:Normal;')
GUI.AdvModeButton.setStyleSheet('font-weight:Normal;')
GUI.FormatBox.setEnabled(True)
GUI.OptionsBasic.setEnabled(True)
GUI.OptionsBasic.setVisible(True)
GUI.MangaBox.setChecked(False)
GUI.RotateBox.setChecked(False)
GUI.QualityBox.setChecked(False)
GUI.OptionsAdvanced.setEnabled(True)
GUI.OptionsAdvanced.setVisible(True)
GUI.ProcessingBox.setChecked(False)
GUI.UpscaleBox.setChecked(False)
GUI.NoRotateBox.setChecked(False)
GUI.BorderBox.setChecked(False)
GUI.WebtoonBox.setChecked(False)
GUI.NoDitheringBox.setChecked(False)
GUI.OptionsAdvancedGamma.setEnabled(True)
GUI.OptionsAdvancedGamma.setVisible(True)
GUI.OptionsExpert.setEnabled(True) GUI.OptionsExpert.setEnabled(True)
if KFA: GUI.OptionsExpert.setVisible(True)
GUI.ColorBox.setChecked(True) GUI.ColorBox.setChecked(False)
GUI.FormatBox.setCurrentIndex(0)
GUI.FormatBox.setEnabled(False)
else:
GUI.FormatBox.setEnabled(True)
GUI.MangaBox.setChecked(False)
GUI.MangaBox.setEnabled(False)
def modeConvert(self, enable): def modeConvert(self, enable):
if self.currentMode != 3: if self.currentMode != 3:
GUI.BasicModeButton.setEnabled(enable) GUI.BasicModeButton.setEnabled(enable)
GUI.AdvModeButton.setEnabled(enable) GUI.AdvModeButton.setEnabled(enable)
if self.currentMode != 1:
GUI.FormatBox.setEnabled(enable)
GUI.DirectoryButton.setEnabled(enable) GUI.DirectoryButton.setEnabled(enable)
GUI.ClearButton.setEnabled(enable) GUI.ClearButton.setEnabled(enable)
GUI.FileButton.setEnabled(enable) GUI.FileButton.setEnabled(enable)
GUI.DeviceBox.setEnabled(enable) GUI.DeviceBox.setEnabled(enable)
GUI.FormatBox.setEnabled(enable)
GUI.OptionsBasic.setEnabled(enable) GUI.OptionsBasic.setEnabled(enable)
GUI.OptionsAdvanced.setEnabled(enable) GUI.OptionsAdvanced.setEnabled(enable)
GUI.OptionsAdvancedGamma.setEnabled(enable) GUI.OptionsAdvancedGamma.setEnabled(enable)
GUI.OptionsExpert.setEnabled(enable) GUI.OptionsExpert.setEnabled(enable)
GUI.ConvertButton.setEnabled(True)
if enable: if enable:
self.conversionAlive = False self.conversionAlive = False
self.worker.sync() self.worker.sync()
@@ -691,13 +726,6 @@ class KCCGUI(KCC_ui.Ui_KCC):
icon.addPixmap(QtGui.QPixmap(":/Other/icons/convert.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon.addPixmap(QtGui.QPixmap(":/Other/icons/convert.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
GUI.ConvertButton.setIcon(icon) GUI.ConvertButton.setIcon(icon)
GUI.ConvertButton.setText('Convert') GUI.ConvertButton.setText('Convert')
GUI.ConvertButton.setEnabled(True)
if self.currentMode == 1:
self.modeBasic()
elif self.currentMode == 2:
self.modeAdvanced()
elif self.currentMode == 3:
self.modeExpert()
else: else:
self.conversionAlive = True self.conversionAlive = True
self.worker.sync() self.worker.sync()
@@ -705,16 +733,6 @@ class KCCGUI(KCC_ui.Ui_KCC):
icon.addPixmap(QtGui.QPixmap(":/Other/icons/clear.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon.addPixmap(QtGui.QPixmap(":/Other/icons/clear.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
GUI.ConvertButton.setIcon(icon) GUI.ConvertButton.setIcon(icon)
GUI.ConvertButton.setText('Abort') GUI.ConvertButton.setText('Abort')
GUI.ConvertButton.setEnabled(True)
def changeGamma(self, value):
value = float(value)
value = '%.2f' % (value/100)
if float(value) <= 0.09:
GUI.GammaLabel.setText('Gamma: Auto')
else:
GUI.GammaLabel.setText('Gamma: ' + str(value))
self.GammaValue = value
def toggleWebtoonBox(self, value): def toggleWebtoonBox(self, value):
if value: if value:
@@ -729,9 +747,8 @@ class KCCGUI(KCC_ui.Ui_KCC):
if not GUI.ProcessingBox.isChecked(): if not GUI.ProcessingBox.isChecked():
GUI.NoRotateBox.setEnabled(True) GUI.NoRotateBox.setEnabled(True)
GUI.QualityBox.setEnabled(True) GUI.QualityBox.setEnabled(True)
GUI.MangaBox.setEnabled(True) if GUI.profiles[str(GUI.DeviceBox.currentText())]['MangaMode']:
self.changeDevice(GUI.DeviceBox.currentIndex(), False) GUI.MangaBox.setEnabled(True)
self.changeFormat()
def toggleNoSplitRotate(self, value): def toggleNoSplitRotate(self, value):
if value: if value:
@@ -740,8 +757,6 @@ class KCCGUI(KCC_ui.Ui_KCC):
else: else:
if not GUI.ProcessingBox.isChecked(): if not GUI.ProcessingBox.isChecked():
GUI.RotateBox.setEnabled(True) GUI.RotateBox.setEnabled(True)
self.changeDevice(GUI.DeviceBox.currentIndex(), False)
self.changeFormat()
def toggleProcessingBox(self, value): def toggleProcessingBox(self, value):
if value: if value:
@@ -765,7 +780,6 @@ class KCCGUI(KCC_ui.Ui_KCC):
GUI.GammaLabel.setEnabled(False) GUI.GammaLabel.setEnabled(False)
else: else:
GUI.RotateBox.setEnabled(True) GUI.RotateBox.setEnabled(True)
GUI.QualityBox.setEnabled(True)
GUI.UpscaleBox.setEnabled(True) GUI.UpscaleBox.setEnabled(True)
GUI.NoRotateBox.setEnabled(True) GUI.NoRotateBox.setEnabled(True)
GUI.BorderBox.setEnabled(True) GUI.BorderBox.setEnabled(True)
@@ -774,45 +788,73 @@ class KCCGUI(KCC_ui.Ui_KCC):
GUI.ColorBox.setEnabled(True) GUI.ColorBox.setEnabled(True)
GUI.GammaSlider.setEnabled(True) GUI.GammaSlider.setEnabled(True)
GUI.GammaLabel.setEnabled(True) GUI.GammaLabel.setEnabled(True)
self.changeDevice(GUI.DeviceBox.currentIndex(), False) if GUI.profiles[str(GUI.DeviceBox.currentText())]['Quality']:
self.changeFormat() GUI.QualityBox.setEnabled(True)
def changeDevice(self, value, showInfo=True): def changeGamma(self, value):
if value == 9: value = float(value)
GUI.BasicModeButton.setEnabled(False) value = '%.2f' % (value/100)
GUI.AdvModeButton.setEnabled(False) if float(value) <= 0.09:
if showInfo: GUI.GammaLabel.setText('Gamma: Auto')
self.addMessage('<a href="https://github.com/ciromattia/kcc/wiki/NonKindle-devices">' else:
'List of supported Non-Kindle devices</a>', 'info') GUI.GammaLabel.setText('Gamma: ' + str(value))
self.modeExpert() self.GammaValue = value
elif value == 8:
GUI.BasicModeButton.setEnabled(False) def changeDevice(self):
GUI.AdvModeButton.setEnabled(False) if self.currentMode == 1:
self.modeExpert(True) self.modeBasic()
elif self.currentMode == 2:
self.modeAdvanced()
elif self.currentMode == 3: elif self.currentMode == 3:
self.modeExpert()
profile = GUI.profiles[str(GUI.DeviceBox.currentText())]
if profile['ForceExpert']:
self.modeExpert()
GUI.BasicModeButton.setEnabled(False)
GUI.AdvModeButton.setEnabled(False)
else:
GUI.BasicModeButton.setEnabled(True) GUI.BasicModeButton.setEnabled(True)
GUI.AdvModeButton.setEnabled(True) GUI.AdvModeButton.setEnabled(True)
self.modeBasic() if self.currentMode == 3:
if value in [9, 11, 12, 13]: self.modeBasic()
GUI.QualityBox.setChecked(False) self.changeFormat()
GUI.QualityBox.setEnabled(False) GUI.GammaSlider.setValue(0)
self.QualityBoxDisabled = True self.changeGamma(0)
if value in [4, 5, 6, 7]: if profile['DefaultUpscale']:
if GUI.UpscaleBox.isEnabled(): GUI.UpscaleBox.setChecked(True)
GUI.UpscaleBox.setChecked(True) if str(GUI.DeviceBox.currentText()) == 'Other':
else: self.addMessage('<a href="https://github.com/ciromattia/kcc/wiki/NonKindle-devices">'
if not GUI.WebtoonBox.isChecked() and not GUI.ProcessingBox.isChecked() \ 'List of supported Non-Kindle devices.</a>', 'info')
and str(GUI.FormatBox.currentText()) != 'CBZ' and value not in [9, 11, 12, 13]:
GUI.QualityBox.setEnabled(True)
self.QualityBoxDisabled = False
def changeFormat(self): def changeFormat(self, outputFormat=None):
if str(GUI.FormatBox.currentText()) == 'CBZ': profile = GUI.profiles[str(GUI.DeviceBox.currentText())]
GUI.QualityBox.setChecked(False) if outputFormat is not None:
GUI.QualityBox.setEnabled(False) GUI.FormatBox.setCurrentIndex(outputFormat)
else: else:
if not GUI.WebtoonBox.isChecked() and not GUI.ProcessingBox.isChecked() and not self.QualityBoxDisabled: if GUI.FormatBox.count() == 3:
GUI.QualityBox.setEnabled(True) GUI.FormatBox.setCurrentIndex(profile['DefaultFormat'])
else:
if profile['DefaultFormat'] != 0:
tmpFormat = profile['DefaultFormat'] - 1
else:
tmpFormat = 0
GUI.FormatBox.setCurrentIndex(tmpFormat)
if (str(GUI.FormatBox.currentText()) == 'CBZ' and not 'Kobo' in str(GUI.DeviceBox.currentText())) or \
GUI.WebtoonBox.isChecked():
GUI.MangaBox.setEnabled(False)
GUI.QualityBox.setEnabled(False)
GUI.MangaBox.setChecked(False)
GUI.QualityBox.setChecked(False)
else:
GUI.MangaBox.setEnabled(profile['MangaMode'])
if not profile['MangaMode']:
GUI.MangaBox.setChecked(False)
GUI.QualityBox.setEnabled(profile['Quality'])
if not profile['Quality']:
GUI.QualityBox.setChecked(False)
if GUI.ProcessingBox.isChecked():
GUI.QualityBox.setEnabled(False)
GUI.QualityBox.setChecked(False)
def stripTags(self, html): def stripTags(self, html):
s = HTMLStripper() s = HTMLStripper()
@@ -873,6 +915,11 @@ 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 'Kobo' in str(GUI.DeviceBox.currentText()) and GUI.QualityBox.checkState() == 2:
GUI.JobList.clear()
self.addMessage('Kobo devices can\'t use ultra quality mode!', 'error')
self.needClean = True
return
self.worker.start() self.worker.start()
def hideProgressBar(self): def hideProgressBar(self):
@@ -964,7 +1011,6 @@ class KCCGUI(KCC_ui.Ui_KCC):
self.progress = ProgressThread() self.progress = ProgressThread()
self.conversionAlive = False self.conversionAlive = False
self.needClean = True self.needClean = True
self.QualityBoxDisabled = False
self.GammaValue = 1.0 self.GammaValue = 1.0
self.completedWork = {} self.completedWork = {}
if sys.platform.startswith('darwin'): if sys.platform.startswith('darwin'):
@@ -982,10 +1028,68 @@ class KCCGUI(KCC_ui.Ui_KCC):
self.statusBarStyle = 'QLabel{padding-top:3px;padding-bottom:3px;border-top:2px solid #C2C7CB}' self.statusBarStyle = 'QLabel{padding-top:3px;padding-bottom:3px;border-top:2px solid #C2C7CB}'
self.tray.show() self.tray.show()
self.profiles = {
"Kindle Paperwhite": {'MangaMode': True, 'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'KHD'},
"Kindle": {'MangaMode': True, 'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'K345'},
"Kindle DX/DXG": {'MangaMode': False, 'Quality': False, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'KDX'},
"Kindle Fire": {'MangaMode': True, 'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'KF'},
"K. Fire HD 7\"": {'MangaMode': True, 'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'Label': 'KFHD'},
"K. Fire HD 8.9\"": {'MangaMode': True, 'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'Label': 'KFHD8'},
"K. Fire HDX 7\"": {'MangaMode': True, 'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'Label': 'KFHDX'},
"K. Fire HDX 8.9\"": {'MangaMode': True, 'Quality': True, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': True, 'Label': 'KFHDX8'},
"Kobo Mini/Touch": {'MangaMode': False, 'Quality': True, 'ForceExpert': False, 'DefaultFormat': 2,
'DefaultUpscale': False, 'Label': 'KoMT'},
"Kobo Glow": {'MangaMode': False, 'Quality': True, 'ForceExpert': False, 'DefaultFormat': 2,
'DefaultUpscale': False, 'Label': 'KoG'},
"Kobo Aura": {'MangaMode': False, 'Quality': True, 'ForceExpert': False, 'DefaultFormat': 2,
'DefaultUpscale': False, 'Label': 'KoA'},
"Kobo Aura HD": {'MangaMode': False, 'Quality': True, 'ForceExpert': False, 'DefaultFormat': 2,
'DefaultUpscale': False, 'Label': 'KoAHD'},
"Other": {'MangaMode': False, 'Quality': False, 'ForceExpert': True, 'DefaultFormat': 1,
'DefaultUpscale': False, 'Label': 'OTHER'},
"Kindle for Android": {'MangaMode': True, 'Quality': False, 'ForceExpert': True, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'KFA'},
"Kindle 1": {'MangaMode': False, 'Quality': False, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'K1'},
"Kindle 2": {'MangaMode': False, 'Quality': False, 'ForceExpert': False, 'DefaultFormat': 0,
'DefaultUpscale': False, 'Label': 'K2'}
}
profilesGUI = [
"Kindle Paperwhite",
"Kindle",
"Kindle DX/DXG",
"Separator",
"Kindle Fire",
"K. Fire HD 7\"",
"K. Fire HD 8.9\"",
"K. Fire HDX 7\"",
"K. Fire HDX 8.9\"",
"Separator",
"Kobo Mini/Touch",
"Kobo Glow",
"Kobo Aura",
"Kobo Aura HD",
"Separator",
"Other",
"Separator",
"Kindle for Android",
"Kindle 1",
"Kindle 2",
]
statusBarLabel = QtGui.QLabel('<b><a href="http://kcc.vulturis.eu/">HOMEPAGE</a> - <a href="https://github.com/' statusBarLabel = QtGui.QLabel('<b><a href="http://kcc.vulturis.eu/">HOMEPAGE</a> - <a href="https://github.com/'
'ciromattia/kcc/blob/master/README.md#issues--new-features--donations">DONATE</a>' 'ciromattia/kcc/blob/master/README.md#issues--new-features--donations">DONATE</a>'
' - <a href="https://github.com/ciromattia/kcc/blob/master/README.md#kcc">README<' ' - <a href="https://github.com/ciromattia/kcc/wiki">WIKI</a>'
'/a> - <a href="https://github.com/ciromattia/kcc/wiki">WIKI</a></b>') ' - <a href="http://www.mobileread.com/forums/showthread.php?t=207461">FORUM</a>'
'</b>')
statusBarLabel.setAlignment(QtCore.Qt.AlignCenter) statusBarLabel.setAlignment(QtCore.Qt.AlignCenter)
statusBarLabel.setStyleSheet(self.statusBarStyle) statusBarLabel.setStyleSheet(self.statusBarStyle)
statusBarLabel.setOpenExternalLinks(True) statusBarLabel.setOpenExternalLinks(True)
@@ -998,7 +1102,8 @@ class KCCGUI(KCC_ui.Ui_KCC):
self.addMessage('<b>Remember:</b> All options have additional informations in tooltips.', 'info') self.addMessage('<b>Remember:</b> All options have additional informations in tooltips.', 'info')
if self.firstStart: if self.firstStart:
self.addMessage('Since you are using <b>KCC</b> for first time please see few ' self.addMessage('Since you are using <b>KCC</b> for first time please see few '
'<a href="https://github.com/ciromattia/kcc#important-tips">important tips</a>.', 'info') '<a href="https://github.com/ciromattia/kcc/wiki/Important-tips">important tips</a>.',
'info')
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
@@ -1017,8 +1122,12 @@ class KCCGUI(KCC_ui.Ui_KCC):
else: else:
self.KindleGen = False self.KindleGen = False
formats = ['EPUB', 'CBZ'] formats = ['EPUB', 'CBZ']
self.addMessage('Cannot find <a href="http://www.amazon.com/gp/feature.html?ie=UTF8&docId=' if sys.platform.startswith('win'):
'1000765211">kindlegen</a> in PATH! MOBI creation will be disabled.', 'warning') 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:
@@ -1060,44 +1169,40 @@ class KCCGUI(KCC_ui.Ui_KCC):
MW.connect(self.progress, QtCore.SIGNAL("addMessage"), self.addMessage) MW.connect(self.progress, QtCore.SIGNAL("addMessage"), self.addMessage)
MW.closeEvent = self.saveSettings MW.closeEvent = self.saveSettings
for profile in profilesGUI:
if profile == "Other":
GUI.DeviceBox.addItem(self.icons.deviceOther, profile)
elif profile == "Separator":
GUI.DeviceBox.insertSeparator(GUI.DeviceBox.count()+1)
elif 'Ko' in profile:
GUI.DeviceBox.addItem(self.icons.deviceKobo, profile)
else:
GUI.DeviceBox.addItem(self.icons.deviceKindle, profile)
for f in formats: for f in formats:
GUI.FormatBox.addItem(eval('self.icons.' + f + 'Format'), f) GUI.FormatBox.addItem(eval('self.icons.' + f + 'Format'), f)
if self.lastDevice > GUI.DeviceBox.count():
self.lastDevice = 0
if profilesGUI[self.lastDevice] == "Separator":
self.lastDevice = 0
if self.currentFormat > GUI.FormatBox.count(): if self.currentFormat > GUI.FormatBox.count():
GUI.FormatBox.setCurrentIndex(0)
self.currentFormat = 0 self.currentFormat = 0
else: GUI.DeviceBox.setCurrentIndex(self.lastDevice)
GUI.FormatBox.setCurrentIndex(self.currentFormat) self.changeDevice()
if self.currentFormat != self.profiles[str(GUI.DeviceBox.currentText())]['DefaultFormat']:
self.changeFormat(self.currentFormat)
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]))
elif str(option) == "customHeight": elif str(option) == "customHeight":
GUI.customHeight.setText(str(self.options[option])) GUI.customHeight.setText(str(self.options[option]))
elif str(option) == "GammaSlider": elif str(option) == "GammaSlider":
GUI.GammaSlider.setValue(int(self.options[option])) if GUI.GammaSlider.isEnabled():
self.changeGamma(int(self.options[option])) GUI.GammaSlider.setValue(int(self.options[option]))
self.changeGamma(int(self.options[option]))
else: else:
eval('GUI.' + str(option)).setCheckState(self.options[option]) if eval('GUI.' + str(option)).isEnabled():
for profile in ProfileData.ProfileLabelsGUI: eval('GUI.' + str(option)).setCheckState(self.options[option])
if profile == "Other":
GUI.DeviceBox.addItem(self.icons.deviceOther, profile)
elif profile == "Separator":
GUI.DeviceBox.insertSeparator(GUI.DeviceBox.count()+1)
else:
GUI.DeviceBox.addItem(self.icons.deviceKindle, profile)
if self.lastDevice > GUI.DeviceBox.count():
GUI.DeviceBox.setCurrentIndex(0)
self.lastDevice = 0
else:
GUI.DeviceBox.setCurrentIndex(self.lastDevice)
if self.currentMode == 1:
self.modeBasic()
elif self.currentMode == 2:
self.modeAdvanced()
elif self.currentMode == 3:
self.modeExpert()
self.changeDevice(self.lastDevice)
self.changeFormat()
self.versionCheck.start() self.versionCheck.start()
self.contentServer.start() self.contentServer.start()
self.hideProgressBar() self.hideProgressBar()

View File

@@ -8358,6 +8358,158 @@ qt_resource_data = b"\
\x5f\x00\xdc\x06\xf0\x91\x73\xee\x3b\x8e\x03\x82\x20\x08\x82\x20\ \x5f\x00\xdc\x06\xf0\x91\x73\xee\x3b\x8e\x03\x82\x20\x08\x82\x20\
\x08\x82\x20\x08\x82\x20\x08\x62\x23\xf8\x1f\x8e\x96\x1e\x7d\x49\ \x08\x82\x20\x08\x82\x20\x08\x62\x23\xf8\x1f\x8e\x96\x1e\x7d\x49\
\xfc\xce\x76\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ \xfc\xce\x76\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x09\x54\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x80\x00\x00\x00\x80\x08\x06\x00\x00\x00\xc3\x3e\x61\xcb\
\x00\x00\x09\x1b\x49\x44\x41\x54\x78\xda\xed\x9d\x7f\x8c\x14\x67\
\x19\xc7\x3f\xef\xec\xec\x71\xcb\x1d\x72\x77\xd8\xbb\x63\x0f\x7a\
\xb6\x0d\x28\x98\x6a\xea\x4a\x8c\xa5\x35\xa9\x56\x62\xa2\x89\x11\
\x88\xd4\xc6\x98\x02\x96\x06\x42\x4d\xda\x44\x8b\xda\x54\x8d\x36\
\xd5\xc4\x68\x62\xa9\x50\x51\x92\xca\x1f\x4d\x2d\xa8\x69\x54\x1a\
\xff\xb0\x92\xa0\xa9\xe0\x24\x10\x8b\x28\x1c\xe5\xc7\x71\x2c\x5c\
\xe1\xe0\x7e\x71\x77\xbb\x33\xf3\xfa\x47\xef\x70\x6f\xd9\x99\xdb\
\xe3\x6e\x77\xe7\xc7\xf3\x4d\x36\x7b\xb7\xb7\xb7\x33\xfb\x3c\x9f\
\xf7\x79\x9e\xf7\xc7\xcc\x0b\x22\x91\x48\x24\x12\x89\x44\x22\x91\
\x48\x24\x12\x89\x44\x22\x91\x28\xfa\x52\x41\x38\x89\x4c\x26\xd3\
\x01\xac\x02\x3a\x81\xf9\x31\xb2\xff\x75\xe0\x3c\xf0\x57\xcb\xb2\
\x8e\xc7\x0e\x80\x4c\x26\xb3\x0c\xf8\x21\xf0\x39\xc0\x88\x79\x63\
\x3c\x04\x7c\xc3\xb2\xac\x03\xd5\x3c\x68\xa2\x86\xce\x5f\x03\xfc\
\x09\xb8\x3b\x28\x91\xa8\xc6\xea\x00\xbe\x92\x4e\xa7\x73\xd9\x6c\
\xf6\x60\xa4\x01\xc8\x64\x32\x0f\x00\xbf\x07\xea\xc5\xef\x37\x45\
\xe4\x07\xd3\xe9\xf4\xe5\x6c\x36\x7b\x38\x92\x29\x20\x93\xc9\xa4\
\x80\x13\xc0\x22\xf1\xb7\xa7\xc6\x80\xe5\x96\x65\xbd\x5d\xe9\x03\
\xd5\x22\xef\x3e\x2a\xce\x9f\x52\x73\x80\x6f\x56\xe3\x40\xb5\x00\
\x60\xad\xf8\xb7\x2c\x7d\x21\x93\xc9\x24\xa2\x08\xc0\x3d\xe2\xdb\
\xb2\xb4\x60\xbc\x5b\x1c\x1d\x00\x32\x99\x4c\x03\xd0\x28\xbe\x2d\
\x5b\x6d\x51\x8b\x00\x49\xf1\x69\xb0\xec\x65\x88\x8d\xe3\x2d\x33\
\x48\x27\x93\x4a\xa5\xe8\xec\x2c\x2f\xed\x29\xf5\x6e\x0f\xd6\x30\
\x0c\x94\x52\x68\xad\x27\x3d\x82\xae\x91\x91\x11\xce\x9e\x3d\x2b\
\x00\x14\x6a\xc9\x92\x25\xec\xdc\xb9\x33\x16\x2d\xef\xe8\xd1\xa3\
\x6c\xde\xbc\x59\x00\x98\x89\x26\xa2\x40\xb1\xc2\x10\x01\x24\x05\
\xcc\x82\xe3\x0b\x01\x98\x48\x03\x85\x3f\x0b\x08\x11\x04\x40\x29\
\x35\x09\x80\x62\x08\x0a\x23\x80\x80\x10\x31\x00\x26\x1c\x5e\x0c\
\x81\xd7\x7b\x0b\x1d\x2f\x10\x44\x2c\x02\x78\x39\xbe\x54\x6a\x70\
\x5d\x57\x20\x08\x3b\x00\xa5\x5a\xbf\x57\x31\x58\x98\x02\x26\xba\
\x8a\x5a\x6b\x5c\xd7\x15\x08\x8a\x64\x44\xcd\xf9\xa5\x5e\x9b\xf8\
\x3f\xc3\x30\x6e\x8c\x1b\x88\x42\x12\x01\xa6\xeb\x7c\xbf\x82\x50\
\xba\x8b\x21\x03\xa0\xd8\xf9\xb7\xd2\x72\x6f\x14\x83\xae\x83\x32\
\x12\x32\x6e\x10\x16\x00\xa6\x72\xfe\x74\x60\x50\x4a\xa1\xc7\x9d\
\x3f\xf1\x59\xa5\x86\x8d\xe3\x08\x82\x19\x34\xa7\xfb\xf5\xfb\x8b\
\x5b\xed\xb4\x21\x28\x70\xf0\x74\x41\x88\xea\xa8\x63\xa0\x00\x30\
\x0c\xa3\xac\xae\xde\xad\x16\x71\xc5\x10\x14\x7e\x56\x21\x0c\x85\
\xf5\xc3\x74\x8e\x15\x46\x18\x02\x1d\x01\xbc\x46\xfa\x66\x7a\x0c\
\x2f\x08\x8a\x8b\x47\xaf\x88\x54\x1c\x49\xc2\x9c\x46\x02\x19\x01\
\x26\x0c\xfb\xef\x1e\x87\xbd\x87\xf2\x8c\xd9\x35\x34\xaa\xc6\x7b\
\xed\xb4\x9e\x78\xd2\x93\x5e\x9b\xf4\x3b\x30\xc7\x54\xac\x59\x61\
\xb2\x2c\x6d\x08\x00\x7e\x2d\xb3\x30\x05\x1c\xef\x71\xf8\xea\xaf\
\x46\x22\x53\x6c\xfd\xf9\x2d\x87\x17\xd7\xcf\x09\x1c\x04\x81\x43\
\x72\x22\xec\xbe\x7a\x28\x1f\xb9\x8a\x7b\xdf\x61\x3b\x70\xe7\x14\
\x18\x00\x8a\x73\x67\x4d\xc3\x7e\x85\x14\xc4\xef\x14\xa8\x08\x20\
\x63\xf5\x31\x2f\x02\x67\x6b\xd6\xce\x9d\xe2\xdf\x0d\x99\x0a\x08\
\x36\x00\x33\x91\xe3\xc2\x86\x95\x39\x96\xb6\xe9\x92\x8e\x3f\x91\
\x75\xd8\x75\x30\x89\x69\xca\x0a\xf5\xc0\x01\x30\x1b\xe1\xdf\xd5\
\x70\x7b\xb3\xcb\xf2\x76\xb7\x24\x00\xa3\xa3\x36\xb9\xbe\x33\x98\
\xb7\x2d\x05\x65\xc6\x1e\x00\x23\x88\x00\x54\xb6\x0e\x70\x41\xbb\
\xe4\xfa\xba\xfe\xdf\x91\x17\x00\x02\x28\x5d\x31\xca\xc6\x9f\x1d\
\x72\x57\xfe\x0b\x6e\x5e\x00\x88\x95\x0a\xeb\x0c\xed\x90\xbb\xda\
\x05\xda\x11\x00\x82\x17\x00\x2a\x14\x02\x8a\x7b\x00\xda\x25\xd7\
\x77\x32\xb6\xe9\x40\xae\x0d\xbc\x91\x0e\xfe\x53\xf1\x74\xa0\x02\
\x78\x2b\x24\x01\xa0\x30\x12\xc4\x30\x1d\x08\x00\x31\x4f\x07\x02\
\x40\x8d\xd2\x81\x00\x10\x8a\x74\xe0\xa2\xc7\xe3\x81\xd7\x23\xec\
\x92\xa1\x30\x0f\xe5\xf3\x0e\x1f\x6d\xee\xe6\xae\xce\x85\xe0\xb3\
\x34\xed\xd2\x35\x9b\x83\x6f\xd7\x13\xd6\x4b\x0d\x04\x80\x52\x01\
\x40\xc3\xa7\x3e\xd4\xc8\xf7\x1f\x6e\x63\x2c\xef\x3d\x87\xdf\xd3\
\x67\xb3\x71\x7b\x37\x24\xe7\x61\xbe\xe7\x76\x01\x20\x2a\xce\x5f\
\xfc\xde\x3a\xbe\xb5\xb6\x95\xa1\x51\xef\xc9\x29\x17\xd8\xfa\x8b\
\x9e\x77\x67\x1e\x73\x83\xe4\xfb\xcf\x92\x9c\xdf\x19\xba\xef\x2b\
\x35\x40\x91\x16\x36\x27\x79\x61\x53\x1a\xc7\x67\x62\xd2\x76\x34\
\x1b\x7e\xd6\x3d\x09\x10\x9d\x1f\x24\x7f\xcd\xff\xc6\x9e\x1a\x59\
\x10\x12\x68\x35\x37\x9a\x6c\xdf\x94\xc6\x4c\x78\x27\x74\x57\xc3\
\xb6\x3d\x59\x7a\xfb\xed\xa2\xbc\xaf\xd0\xf6\x08\xf6\xc0\x39\x89\
\x00\x61\x94\x52\xf0\x93\xf5\x0b\x49\xd5\x79\x9b\xc4\x50\xf0\xec\
\xde\x5e\x8e\x9f\x1f\xf3\x2c\xfa\xdc\xdc\x20\xf9\xfe\x33\x02\x40\
\x98\x94\x30\x14\x2f\x6e\x5e\x44\x7b\x93\xe9\xeb\xfc\xe7\xf6\xf5\
\x72\xf0\xf8\xd0\xd4\x75\x44\x7e\x88\xfc\xb5\xd3\x02\x40\x18\xe4\
\xb8\xf0\xd4\xea\xdb\xe8\x68\x49\x7a\x2e\x25\xab\x33\x15\xfb\xde\
\xec\xe7\xc0\xb1\x61\xcc\xb2\xd6\x93\x29\xb4\x7d\x1d\x7b\xa0\x5b\
\x00\x08\xba\x9e\x5e\xdb\xca\x7d\xcb\x1a\x7c\xdf\xf3\xbb\x7f\x0c\
\xb0\xf3\xf5\x2b\xd3\xee\xeb\xbb\xb9\x81\xc0\xa7\x83\xd8\x02\x90\
\xb3\x35\x1b\x1f\x6c\xe1\x13\x1f\x6c\xc0\x6b\x01\x52\xc2\x50\x1c\
\x3a\x79\x9d\x9f\xef\xbf\xec\x5b\x18\x86\x39\x1d\xc4\x12\x80\xbc\
\xa3\xf9\x6c\x66\x1e\x5f\xbc\xb7\xc9\x33\xec\x1b\x0a\xba\xb2\x63\
\x3c\xf3\xf2\xc5\x99\x96\x97\x81\x4e\x07\xf1\x03\x40\xc3\xfd\xcb\
\x1b\x79\x6a\x75\x2b\xb6\xcf\xfa\xf1\x2b\x83\x0e\x8f\xed\x38\x4f\
\x62\x96\xd6\x90\xbb\xb9\x01\xec\xc1\xf3\x02\x40\x8d\x7d\x4f\x6b\
\x93\xc9\xb7\xd7\xb6\x32\x96\xf7\x76\xbe\xd6\xb0\x75\x57\x0f\x49\
\x33\xfa\x17\x10\xc4\x6a\x28\x58\x6b\xe8\x58\x90\xc4\x6f\xd1\x71\
\xde\xd6\xac\xdf\x7e\x9e\xab\x43\x0e\x71\xb8\x97\x54\xec\x52\x80\
\x9f\xf3\xeb\xeb\x14\x4f\xbf\x7c\x89\xab\x43\x36\x71\xb9\x91\x58\
\xec\x00\xf0\x73\xec\x58\x5e\xb3\xe5\x33\x2d\xbe\xb5\x81\x00\x10\
\x72\xe7\x5f\xee\xb7\x71\x3c\x1c\xac\x35\xdc\xd1\x5a\xc7\x8e\xc7\
\x16\x49\x04\x88\x24\x00\x40\xf7\xe5\x3c\x3f\x7d\xed\x1d\xea\x3d\
\xc6\xfc\x5d\x0d\x77\xb6\xd5\xf1\xdd\x75\xed\x8c\xe4\x5c\x01\xa0\
\x76\xce\x52\x15\xa3\xe0\x0f\xff\x1c\xe4\xf9\x3f\xbe\xe3\x3b\xb8\
\x73\xef\x07\xe6\xf2\xbd\x87\xda\x7d\xa7\x85\x05\x80\x90\x6a\x4e\
\x52\xf1\x9b\xbf\xf5\xf3\xda\xa1\x01\xcf\x4b\xc5\x73\xb6\xe6\x81\
\xbb\x1b\x79\xe4\x93\xcd\x44\xb9\x24\x88\xed\x50\x70\x9d\xa9\x78\
\x61\xff\x65\xde\xf8\xd7\x90\xe7\x60\x8f\xed\x68\xbe\x74\x7f\x13\
\x0f\xdd\xd7\xe4\x59\x37\x08\x00\x95\x4c\xd8\x55\xd0\x0f\xf6\xf6\
\xf2\xc6\x5b\x43\x9e\x45\x9f\xd6\xb0\xe9\xd3\x2d\xac\xfd\x78\x13\
\x51\xbc\x79\x49\xa0\x00\x98\x6a\x13\x88\x4a\x45\x82\x1f\xfd\xb6\
\x97\x33\xbd\x39\xcf\x74\x30\x66\x6b\x1e\x5d\xd5\xc2\x47\xee\x4a\
\xe1\xba\x02\x40\xc5\x54\xcb\xfb\x03\x3d\xbe\xeb\x02\xa7\x7b\x73\
\x3e\xe7\x06\xcf\x3e\xdc\xce\xc7\x96\xce\x15\x00\x2a\x1d\x01\x6a\
\x21\xc7\xd5\x3c\xb9\x3b\xcb\x85\x3e\xef\x2b\x82\x34\xf0\xcc\xba\
\x56\x96\x2f\xae\x8f\x4c\x3a\x90\x08\x50\xa0\xd1\xbc\xcb\x13\xbb\
\x2f\x70\x7d\xcc\xf5\x2c\x41\x0c\xa5\x78\xee\xcb\xed\xb4\x35\x99\
\x91\x80\x20\x90\x45\x60\x2d\x41\x18\x1c\x71\x59\xff\x7c\x37\xc3\
\x63\xde\xc9\xde\x4c\x28\x76\x6d\x59\x44\x5b\x93\x29\x00\x54\x8e\
\x82\x5a\xa5\x21\x18\x1a\x75\xd9\xb6\x27\xeb\xdb\xc2\xcd\x84\xe2\
\xc7\x8f\xa4\x69\x98\x63\x84\xfa\x1a\x41\x59\x15\xec\xa1\xae\x8b\
\x39\xb6\xee\xea\xf1\xed\xff\x2f\x98\x97\x60\xf7\xe3\x8b\x99\x5b\
\x67\x08\x00\xb3\x1f\x00\x6e\xb5\x5d\x29\x52\x49\x97\xc6\x7a\xe3\
\xe6\x47\x2a\xe1\xbb\xee\xbf\x78\x18\xe2\xf4\xa5\x1c\xdb\xf6\x5c\
\x64\x5e\xca\x28\xfd\x79\xf5\x06\x0b\x9b\x4d\x5e\xfa\xda\x62\x92\
\x65\xac\x19\x0c\xe2\xfc\x52\xe4\x16\x84\x24\x13\x9a\x27\x5e\x49\
\x32\xd2\x77\x0a\xed\xe4\x6e\x32\xbb\x99\xa0\x7c\x08\x14\x1c\x3b\
\x37\xca\x3d\x4f\x9e\x9c\xf2\x7d\x8d\xf5\xe1\x8c\x02\x91\x5c\x11\
\x94\xaa\x4f\x92\x4a\xbf\x9f\x7c\xdf\x09\xb4\x3b\xb3\x3b\x74\x2b\
\x05\xf3\x52\xd1\xcd\x94\x11\xae\x01\x14\xc9\xe6\x25\xa8\x84\xdc\
\x12\x36\xbe\x45\xa0\x32\x48\xce\xbf\x13\x65\xc8\x55\xf0\xa1\x00\
\xa0\x70\x24\xb0\x3e\x39\x4b\x25\x93\x61\x92\x6c\x59\x1a\x08\x08\
\x82\xb8\xca\x38\xb0\x00\xac\x59\x31\x9b\x0e\x1b\x4f\x07\x46\x6d\
\xd3\xc1\xea\x95\x6d\x52\x04\x96\x03\x80\x52\x8a\xe5\x1d\x26\xbf\
\xdc\x68\xb0\xf7\x70\x9e\xb1\xd9\xda\x69\xc5\x5d\x8a\x3d\x7c\xb1\
\x3a\x5f\xa6\x60\x14\x29\x69\x2a\x56\xaf\x6c\xe3\xc3\x77\x34\x04\
\x6e\x43\x8c\x40\x6f\x1b\xb7\xac\x23\xc1\x77\x16\x27\x3d\xff\x7e\
\x6b\x9a\x3f\x73\xc7\x4e\x75\x1e\x5a\xa3\xb5\x03\x2a\x31\x69\x63\
\x4a\x37\x80\x73\xc9\x32\x12\x78\x2b\xfd\x42\x5f\xdf\x6b\xb4\x76\
\x27\x45\x80\xe2\x9d\x49\x05\x00\x1f\xe3\xf9\xbd\x16\xf4\xfd\x84\
\x26\x1c\x9d\xb7\x1d\x30\xcc\x40\x3b\x3e\xd0\x00\xf8\x19\xae\x5a\
\x06\x2d\xde\xbc\xc2\xef\xb9\xf0\x7c\x95\x52\x98\xa6\xe9\xf9\x77\
\x29\x02\xa7\x11\x01\x8a\xb7\x68\xf5\x7a\xbd\x78\x9b\xd7\x89\xdf\
\x67\x6a\xf4\x72\x21\x98\x4e\x44\x13\x00\xca\x34\x58\xb9\x3b\x78\
\x7b\x39\xa3\x56\xc6\x2f\x6c\xed\x41\x6f\xfd\x81\x03\x60\x3a\x2d\
\x48\x05\xe8\xda\x2d\x5d\xa2\xe0\xab\xce\xfe\x47\x11\x07\xa0\x94\
\x71\x55\xc0\x2e\xda\x2b\x15\xb5\xc2\xe2\xfc\x50\x00\xe0\x05\x41\
\xd0\x8c\x1b\xd6\x2d\xe4\x43\x33\x4b\xe2\x65\xe0\xa0\x44\x84\xb0\
\x6e\x79\x1b\xfa\x69\x32\xd9\x6b\x38\x42\x00\x0c\x0f\x0f\x73\xe4\
\xc8\x91\x58\x18\xbe\xab\xab\x4b\x00\x28\xd6\xa9\x53\xa7\xd8\xb2\
\x65\x8b\x34\xcb\x2a\x4a\xe6\x02\x04\x00\x91\x00\x20\x12\x00\x44\
\x02\x80\x48\x00\x10\x09\x00\x22\x01\xa0\x82\x92\x61\xbb\x80\xd9\
\xab\xda\x00\x0c\x02\xb6\xf8\xb5\x6c\x5d\x8b\x14\x00\x96\x65\xb9\
\xc0\x39\xf1\x6b\x59\x72\xaa\x61\xab\x5a\xd4\x00\xfb\xc5\xb7\x65\
\xe9\xef\x96\x65\xf5\x47\x11\x80\x1d\xe3\x74\x8b\xfc\xb5\x3d\x92\
\xbd\x00\xcb\xb2\x8e\x55\xeb\xcb\x85\x58\x7f\x01\x5e\x8d\x72\x37\
\xf0\xeb\xc0\xeb\xe2\xe7\x92\x3a\x0e\xac\xb3\x2c\xab\x2a\x3d\xa6\
\x44\x2d\xbe\x61\x36\x9b\x75\xd3\xe9\xf4\x2b\x40\x03\xb0\xa2\x56\
\xe7\x11\xc0\x2e\xdf\x5e\xe0\xf3\x96\x65\x5d\xad\xd6\x41\x6b\xbe\
\x9e\x2a\x93\xc9\x2c\x01\x36\x00\xab\x80\xf7\x01\x4d\x31\x72\xfa\
\x30\xd0\x0d\x1c\x00\x7e\x6d\x59\xd6\x9b\xd2\x0e\x44\x22\x91\x48\
\x24\x12\x89\x44\x22\x91\x48\x24\x12\x89\x44\x15\xd1\xff\x00\x56\
\x1c\x01\xcd\xc9\x01\xf3\xd5\x00\x00\x00\x00\x49\x45\x4e\x44\xae\
\x42\x60\x82\
" "
qt_resource_name = b"\ qt_resource_name = b"\
@@ -8442,33 +8594,38 @@ qt_resource_name = b"\
\x0e\xc5\xfa\x07\ \x0e\xc5\xfa\x07\
\x00\x4f\ \x00\x4f\
\x00\x74\x00\x68\x00\x65\x00\x72\x00\x2e\x00\x70\x00\x6e\x00\x67\ \x00\x74\x00\x68\x00\x65\x00\x72\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x08\
\x05\x92\x5d\x07\
\x00\x4b\
\x00\x6f\x00\x62\x00\x6f\x00\x2e\x00\x70\x00\x6e\x00\x67\
" "
qt_resource_struct = b"\ qt_resource_struct = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x01\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x01\
\x00\x00\x00\x28\x00\x02\x00\x00\x00\x01\x00\x00\x00\x17\ \x00\x00\x00\x28\x00\x02\x00\x00\x00\x01\x00\x00\x00\x18\
\x00\x00\x00\x36\x00\x02\x00\x00\x00\x01\x00\x00\x00\x11\ \x00\x00\x00\x36\x00\x02\x00\x00\x00\x01\x00\x00\x00\x12\
\x00\x00\x00\x46\x00\x02\x00\x00\x00\x01\x00\x00\x00\x0d\ \x00\x00\x00\x46\x00\x02\x00\x00\x00\x01\x00\x00\x00\x0e\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x0a\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x0a\
\x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x06\ \x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x06\
\x00\x00\x00\x58\x00\x02\x00\x00\x00\x03\x00\x00\x00\x07\ \x00\x00\x00\x58\x00\x02\x00\x00\x00\x03\x00\x00\x00\x07\
\x00\x00\x01\x94\x00\x00\x00\x00\x00\x01\x00\x01\xad\xa7\ \x00\x00\x01\x94\x00\x00\x00\x00\x00\x01\x00\x01\xad\xa7\
\x00\x00\x01\x7e\x00\x00\x00\x00\x00\x01\x00\x01\x91\x58\ \x00\x00\x01\x7e\x00\x00\x00\x00\x00\x01\x00\x01\x91\x58\
\x00\x00\x01\xaa\x00\x00\x00\x00\x00\x01\x00\x01\xcc\xe3\ \x00\x00\x01\xaa\x00\x00\x00\x00\x00\x01\x00\x01\xcc\xe3\
\x00\x00\x00\x58\x00\x02\x00\x00\x00\x02\x00\x00\x00\x0b\ \x00\x00\x00\x58\x00\x02\x00\x00\x00\x03\x00\x00\x00\x0b\
\x00\x00\x01\xf0\x00\x00\x00\x00\x00\x01\x00\x02\x07\xc9\
\x00\x00\x01\xbe\x00\x00\x00\x00\x00\x01\x00\x01\xf6\xde\ \x00\x00\x01\xbe\x00\x00\x00\x00\x00\x01\x00\x01\xf6\xde\
\x00\x00\x01\xd8\x00\x00\x00\x00\x00\x01\x00\x02\x01\xe5\ \x00\x00\x01\xd8\x00\x00\x00\x00\x00\x01\x00\x02\x01\xe5\
\x00\x00\x00\x58\x00\x02\x00\x00\x00\x03\x00\x00\x00\x0e\ \x00\x00\x00\x58\x00\x02\x00\x00\x00\x03\x00\x00\x00\x0f\
\x00\x00\x00\x7e\x00\x00\x00\x00\x00\x01\x00\x00\x09\x5d\ \x00\x00\x00\x7e\x00\x00\x00\x00\x00\x01\x00\x00\x09\x5d\
\x00\x00\x00\x68\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ \x00\x00\x00\x68\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x00\x9a\x00\x00\x00\x00\x00\x01\x00\x00\x1e\x9a\ \x00\x00\x00\x9a\x00\x00\x00\x00\x00\x01\x00\x00\x1e\x9a\
\x00\x00\x00\x58\x00\x02\x00\x00\x00\x05\x00\x00\x00\x12\ \x00\x00\x00\x58\x00\x02\x00\x00\x00\x05\x00\x00\x00\x13\
\x00\x00\x01\x38\x00\x00\x00\x00\x00\x01\x00\x00\x6a\x71\ \x00\x00\x01\x38\x00\x00\x00\x00\x00\x01\x00\x00\x6a\x71\
\x00\x00\x01\x0c\x00\x00\x00\x00\x00\x01\x00\x00\x46\x38\ \x00\x00\x01\x0c\x00\x00\x00\x00\x00\x01\x00\x00\x46\x38\
\x00\x00\x00\xce\x00\x00\x00\x00\x00\x01\x00\x00\x37\xa3\ \x00\x00\x00\xce\x00\x00\x00\x00\x00\x01\x00\x00\x37\xa3\
\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x2b\x3a\ \x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x2b\x3a\
\x00\x00\x00\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x3c\x02\ \x00\x00\x00\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x3c\x02\
\x00\x00\x00\x58\x00\x02\x00\x00\x00\x01\x00\x00\x00\x18\ \x00\x00\x00\x58\x00\x02\x00\x00\x00\x01\x00\x00\x00\x19\
\x00\x00\x01\x5a\x00\x00\x00\x00\x00\x01\x00\x00\x73\xc8\ \x00\x00\x01\x5a\x00\x00\x00\x00\x00\x01\x00\x00\x73\xc8\
" "

View File

@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'KCC.ui' # Form implementation generated from reading ui file 'KCC.ui'
# #
# Created: Fri Dec 13 19:22:05 2013 # Created: Tue Jan 14 15:50:02 2014
# by: PyQt4 UI code generator 4.10.3 # by: PyQt4 UI code generator 4.10.3
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
@@ -298,7 +298,7 @@ class Ui_KCC(object):
"p, li { white-space: pre-wrap; }\n" "p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt; font-weight:400; font-style:normal;\">\n" "</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode<br /></span><span style=\" font-style:italic;\">Use it when Panel View support is not needed.</span><span style=\" font-weight:600; text-decoration: underline;\"><br /></span>- Maximum quality when zoom is not enabled.<br />- Poor quality when zoom is enabled.<br />- Lowest file size.</p>\n" "<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode<br /></span><span style=\" font-style:italic;\">Use it when Panel View support is not needed.</span><span style=\" font-weight:600; text-decoration: underline;\"><br /></span>- Maximum quality when zoom is not enabled.<br />- Poor quality when zoom is enabled.<br />- Lowest file size.</p>\n"
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode<br /></span><span style=\" font-style:italic;\">Not zoomed image </span><span style=\" font-weight:600; font-style:italic;\">might </span><span style=\" font-style:italic;\">be </span><span style=\" font-style:italic;\">a little blurry.</span><span style=\" font-weight:600; text-decoration: underline;\"><br /></span>- Medium/High quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.</p>\n" "<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode<br /></span><span style=\" font-style:italic;\">Not zoomed image </span><span style=\" font-weight:600; font-style:italic;\">might </span><span style=\" font-style:italic;\">be a little blurry.<br />Smaller images might be forcefully upscaled in this mode.</span><span style=\" font-weight:600; text-decoration: underline;\"><br /></span>- Medium/High quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.</p>\n"
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode<br /></span><span style=\" font-style:italic;\">Maximum possible quality.</span><span style=\" font-weight:600; text-decoration: underline;\"><br /></span>- Maximum quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.<br />- Very high file size.</p></body></html>", None)) "<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode<br /></span><span style=\" font-style:italic;\">Maximum possible quality.</span><span style=\" font-weight:600; text-decoration: underline;\"><br /></span>- Maximum quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.<br />- Very high file size.</p></body></html>", None))
self.QualityBox.setText(_translate("KCC", "High/Ultra quality", None)) self.QualityBox.setText(_translate("KCC", "High/Ultra quality", None))
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable splitting of two-page spreads.<br/>They will be rotated instead.</p></body></html>", None)) self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable splitting of two-page spreads.<br/>They will be rotated instead.</p></body></html>", None))

View File

@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'KCC-Linux.ui' # Form implementation generated from reading ui file 'KCC-Linux.ui'
# #
# Created: Fri Dec 13 19:22:17 2013 # Created: Tue Jan 14 15:50:14 2014
# by: PyQt4 UI code generator 4.10.3 # by: PyQt4 UI code generator 4.10.3
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
@@ -367,7 +367,7 @@ class Ui_KCC(object):
"p, li { white-space: pre-wrap; }\n" "p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Sans\'; font-size:9pt; font-weight:400; font-style:normal;\">\n" "</style></head><body style=\" font-family:\'Sans\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode<br /></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-style:italic;\">Use it when Panel View support is not needed.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\"><br /></span><span style=\" font-family:\'MS Shell Dlg 2\';\">- Maximum quality when zoom is not enabled.<br />- Poor quality when zoom is enabled.<br />- Lowest file size.</span></p>\n" "<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode<br /></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-style:italic;\">Use it when Panel View support is not needed.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\"><br /></span><span style=\" font-family:\'MS Shell Dlg 2\';\">- Maximum quality when zoom is not enabled.<br />- Poor quality when zoom is enabled.<br />- Lowest file size.</span></p>\n"
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode<br /></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-style:italic;\">Not zoomed image </span><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; font-style:italic;\">might </span><span style=\" font-family:\'MS Shell Dlg 2\'; font-style:italic;\">be a little blurry.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\"><br /></span><span style=\" font-family:\'MS Shell Dlg 2\';\">- Medium/High quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.</span></p>\n" "<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode<br /></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-style:italic;\">Not zoomed image </span><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; font-style:italic;\">might </span><span style=\" font-family:\'MS Shell Dlg 2\'; font-style:italic;\">be a little blurry.<br /></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-style:italic;\">Smaller images might be forcefully upscaled in this mode.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\"><br /></span><span style=\" font-family:\'MS Shell Dlg 2\';\">- Medium/High quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.</span></p>\n"
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode<br /></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-style:italic;\">Maximum possible quality.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\"><br /></span><span style=\" font-family:\'MS Shell Dlg 2\';\">- Maximum quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.<br />- Very high file size.</span></p></body></html>", None)) "<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode<br /></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-style:italic;\">Maximum possible quality.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-weight:600; text-decoration: underline;\"><br /></span><span style=\" font-family:\'MS Shell Dlg 2\';\">- Maximum quality when zoom is not enabled.<br />- Maximum quality when zoom is enabled.<br />- Very high file size.</span></p></body></html>", None))
self.QualityBox.setText(_translate("KCC", "High/Ultra quality", None)) self.QualityBox.setText(_translate("KCC", "High/Ultra quality", None))
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable splitting of two-page spreads.<br/>They will be rotated instead.</p></body></html>", None)) self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable splitting of two-page spreads.<br/>They will be rotated instead.</p></body></html>", None))

View File

@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'KCC-OSX.ui' # Form implementation generated from reading ui file 'KCC-OSX.ui'
# #
# Created: Fri Dec 13 19:22:27 2013 # Created: Tue Jan 14 15:50:25 2014
# by: PyQt4 UI code generator 4.10.3 # by: PyQt4 UI code generator 4.10.3
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
@@ -386,7 +386,7 @@ class Ui_KCC(object):
self.ClearButton.setText(_translate("KCC", "Clear list", None)) self.ClearButton.setText(_translate("KCC", "Clear list", None))
self.MangaBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Enable right-to-left reading.</span></p></body></html>", None)) self.MangaBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Enable right-to-left reading.</span></p></body></html>", None))
self.MangaBox.setText(_translate("KCC", "Manga mode", None)) self.MangaBox.setText(_translate("KCC", "Manga mode", None))
self.QualityBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode<br/></span><span style=\"font-size:12pt; font-style:italic;\">Use it when Panel View support is not needed.</span><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\"font-size:12pt;\">- Maximum quality when zoom is not enabled.<br/>- Poor quality when zoom is enabled.<br/>- Lowest file size.</span></p><p><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode<br/></span><span style=\"font-size:12pt; font-style:italic;\">Not zoomed image </span><span style=\"font-size:12pt; font-weight:600; font-style:italic;\">might </span><span style=\"font-size:12pt; font-style:italic;\">be a little blurry.</span><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\"font-size:12pt;\">- Medium/High quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.</span></p><p><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode<br/></span><span style=\"font-size:12pt; font-style:italic;\">Maximum possible quality.</span><span style=\"font-size:12pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\"font-size:12pt;\">- Maximum quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.<br/>- Very high file size.</span></p></body></html>", None)) self.QualityBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode<br/></span><span style=\" font-size:12pt; font-style:italic;\">Use it when Panel View support is not needed.</span><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\" font-size:12pt;\">- Maximum quality when zoom is not enabled.<br/>- Poor quality when zoom is enabled.<br/>- Lowest file size.</span></p><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode<br/></span><span style=\" font-size:12pt; font-style:italic;\">Not zoomed image </span><span style=\" font-size:12pt; font-weight:600; font-style:italic;\">might </span><span style=\" font-size:12pt; font-style:italic;\">be a little blurry.<br/>Smaller images might be forcefully upscaled in this mode.</span><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\" font-size:12pt;\">- Medium/High quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.</span></p><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode<br/></span><span style=\" font-size:12pt; font-style:italic;\">Maximum possible quality.</span><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\" font-size:12pt;\">- Maximum quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.<br/>- Very high file size.</span></p></body></html>", None))
self.QualityBox.setText(_translate("KCC", "High/Ultra quality", None)) self.QualityBox.setText(_translate("KCC", "High/Ultra quality", None))
self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Disable splitting of two-page spreads.<br/>They will be rotated instead.</span></p></body></html>", None)) self.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Disable splitting of two-page spreads.<br/>They will be rotated instead.</span></p></body></html>", None))
self.RotateBox.setText(_translate("KCC", "Horizontal mode", None)) self.RotateBox.setText(_translate("KCC", "Horizontal mode", None))

View File

@@ -26,7 +26,7 @@ import locale
from sys import platform from sys import platform
from subprocess import STDOUT, PIPE from subprocess import STDOUT, PIPE
try: try:
#noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from psutil import Popen from psutil import Popen
except ImportError: except ImportError:
print("ERROR: Psutil is not installed!") print("ERROR: Psutil is not installed!")

View File

@@ -29,13 +29,35 @@ import re
import stat import stat
import string import string
import unicodedata import unicodedata
import zipfile
from tempfile import mkdtemp from tempfile import mkdtemp
from shutil import move, copyfile, copytree, rmtree, make_archive from shutil import move, copyfile, copytree, rmtree
from optparse import OptionParser, OptionGroup from optparse import OptionParser, OptionGroup
from multiprocessing import Pool, freeze_support from multiprocessing import Pool, freeze_support
from xml.dom.minidom import parse from xml.dom.minidom import parse
from uuid import uuid4 from uuid import uuid4
from slugify import slugify from slugify import slugify
try:
# noinspection PyUnresolvedReferences
from PIL import Image
if tuple(map(int, ('2.3.0'.split(".")))) > tuple(map(int, (Image.PILLOW_VERSION.split(".")))):
print "ERROR: Pillow 2.3.0 or newer is required!"
if sys.platform.startswith('linux'):
import Tkinter
import tkMessageBox
importRoot = Tkinter.Tk()
importRoot.withdraw()
tkMessageBox.showerror("KCC - Error", "Pillow 2.3.0 or newer is required!")
exit(1)
except ImportError:
print "ERROR: Pillow is not installed!"
if sys.platform.startswith('linux'):
import Tkinter
import tkMessageBox
importRoot = Tkinter.Tk()
importRoot.withdraw()
tkMessageBox.showerror("KCC - Error", "Pillow 2.3.0 or newer is required!")
exit(1)
try: try:
from PyQt4 import QtCore from PyQt4 import QtCore
except ImportError: except ImportError:
@@ -53,6 +75,10 @@ def buildHTML(path, imgfile):
rotatedPage = True rotatedPage = True
else: else:
rotatedPage = False rotatedPage = False
if "_kccnpv" in str(filename):
noPV = True
else:
noPV = False
if "_kccnh" in str(filename): if "_kccnh" in str(filename):
noHorizontalPV = True noHorizontalPV = True
else: else:
@@ -90,7 +116,7 @@ def buildHTML(path, imgfile):
"<div><img src=\"", "../" * backref, "Images/", postfix, imgfile, "\" alt=\"", "<div><img src=\"", "../" * backref, "Images/", postfix, imgfile, "\" alt=\"",
imgfile, "\" class=\"singlePage\"/></div>\n" imgfile, "\" class=\"singlePage\"/></div>\n"
]) ])
if options.panelview: if options.panelview and not noPV:
if not noHorizontalPV and not noVerticalPV: if not noHorizontalPV and not noVerticalPV:
if rotatedPage: if rotatedPage:
if options.righttoleft: if options.righttoleft:
@@ -234,7 +260,7 @@ def buildOPF(dstdir, title, filelist, cover=None):
"<dc:language>en-US</dc:language>\n", "<dc:language>en-US</dc:language>\n",
"<dc:identifier id=\"BookID\" opf:scheme=\"UUID\">", options.uuid, "</dc:identifier>\n"]) "<dc:identifier id=\"BookID\" opf:scheme=\"UUID\">", options.uuid, "</dc:identifier>\n"])
for author in options.authors: for author in options.authors:
f.writelines(["<dc:Creator>", author, "</dc:Creator>\n"]) f.writelines(["<dc:creator>", author.encode('utf-8'), "</dc:creator>\n"])
f.writelines(["<meta name=\"generator\" content=\"KindleComicConverter-" + __version__ + "\"/>\n", f.writelines(["<meta name=\"generator\" content=\"KindleComicConverter-" + __version__ + "\"/>\n",
"<meta name=\"RegionMagnification\" content=\"true\"/>\n", "<meta name=\"RegionMagnification\" content=\"true\"/>\n",
"<meta name=\"region-mag\" content=\"true\"/>\n", "<meta name=\"region-mag\" content=\"true\"/>\n",
@@ -281,9 +307,6 @@ def buildOPF(dstdir, title, filelist, cover=None):
f.write("</spine>\n<guide>\n</guide>\n</package>\n") f.write("</spine>\n<guide>\n</guide>\n</package>\n")
f.close() f.close()
os.mkdir(os.path.join(dstdir, 'META-INF')) os.mkdir(os.path.join(dstdir, 'META-INF'))
f = open(os.path.join(dstdir, 'mimetype'), 'w')
f.write('application/epub+zip')
f.close()
f = open(os.path.join(dstdir, 'META-INF', 'container.xml'), 'w') f = open(os.path.join(dstdir, 'META-INF', 'container.xml'), 'w')
f.writelines(["<?xml version=\"1.0\"?>\n", f.writelines(["<?xml version=\"1.0\"?>\n",
"<container version=\"1.0\" xmlns=\"urn:oasis:names:tc:opendocument:xmlns:container\">\n", "<container version=\"1.0\" xmlns=\"urn:oasis:names:tc:opendocument:xmlns:container\">\n",
@@ -686,9 +709,6 @@ def sanitizeTreeBeforeConversion(filetree):
for root, dirs, files in os.walk(filetree, False): for root, dirs, files in os.walk(filetree, False):
for name in files: for name in files:
os.chmod(os.path.join(root, name), stat.S_IWRITE | stat.S_IREAD) os.chmod(os.path.join(root, name), stat.S_IWRITE | stat.S_IREAD)
# Detect corrupted files - Phase 1
if os.path.getsize(os.path.join(root, name)) == 0:
os.remove(os.path.join(root, name))
for name in dirs: for name in dirs:
os.chmod(os.path.join(root, name), stat.S_IWRITE | stat.S_IREAD | stat.S_IEXEC) os.chmod(os.path.join(root, name), stat.S_IWRITE | stat.S_IREAD | stat.S_IEXEC)
@@ -844,6 +864,40 @@ def preSplitDirectory(path):
return [path] return [path]
def detectCorruption(tmpPath, orgPath):
for root, dirs, files in os.walk(tmpPath, False):
for name in files:
if getImageFileName(name) is not None:
path = os.path.join(root, name)
pathOrg = os.path.join(orgPath, name)
if os.path.getsize(path) == 0:
rmtree(os.path.join(tmpPath, '..', '..'), True)
raise RuntimeError('Image file %s is corrupted.' % pathOrg)
try:
img = Image.open(path)
img.verify()
img = Image.open(path)
img.load()
except:
rmtree(os.path.join(tmpPath, '..', '..'), True)
raise RuntimeError('Image file %s is corrupted.' % pathOrg)
def makeZIP(zipFilename, baseDir, isEPUB=False):
zipFilename = os.path.abspath(zipFilename) + '.zip'
zipOutput = zipfile.ZipFile(zipFilename, 'w', zipfile.ZIP_DEFLATED)
if isEPUB:
zipOutput.writestr('mimetype', 'application/epub+zip', zipfile.ZIP_STORED)
for dirpath, dirnames, 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))
if os.path.isfile(path):
zipOutput.write(path, aPath)
zipOutput.close()
return zipFilename
def Copyright(): def Copyright():
print(('comic2ebook v%(__version__)s. ' print(('comic2ebook v%(__version__)s. '
'Written 2013 by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals())) 'Written 2013 by Ciro Mattia Gonano and Pawel Jastrzebski.' % globals()))
@@ -864,7 +918,7 @@ def main(argv=None, qtGUI=None):
otherOptions = OptionGroup(parser, "OTHER") otherOptions = OptionGroup(parser, "OTHER")
mainOptions.add_option("-p", "--profile", action="store", dest="profile", default="KHD", mainOptions.add_option("-p", "--profile", action="store", dest="profile", default="KHD",
help="Device profile (Choose one among K1, K2, K345, KDX, KHD, KF, KFHD, KFHD8, KFHDX," help="Device profile (Choose one among K1, K2, K345, KDX, KHD, KF, KFHD, KFHD8, KFHDX,"
" KFHDX8, KFA) [Default=KHD]") " KFHDX8, KFA, KoMT, KoG, KoA, KoAHD) [Default=KHD]")
mainOptions.add_option("-q", "--quality", type="int", dest="quality", default="0", mainOptions.add_option("-q", "--quality", type="int", dest="quality", default="0",
help="Quality of Panel View. 0 - Normal 1 - High 2 - Ultra [Default=0]") help="Quality of Panel View. 0 - Normal 1 - High 2 - Ultra [Default=0]")
mainOptions.add_option("-m", "--manga-style", action="store_true", dest="righttoleft", default=False, mainOptions.add_option("-m", "--manga-style", action="store_true", dest="righttoleft", default=False,
@@ -925,14 +979,13 @@ def main(argv=None, qtGUI=None):
parser.print_help() parser.print_help()
return return
path = getWorkFolder(args[0]) path = getWorkFolder(args[0])
detectCorruption(path + "/OEBPS/Images/", args[0])
checkComicInfo(path + "/OEBPS/Images/", args[0]) checkComicInfo(path + "/OEBPS/Images/", args[0])
if options.webtoon: if options.webtoon:
if GUI:
GUI.emit(QtCore.SIGNAL("progressBarTick"), 'status', 'Splitting images')
if options.customheight > 0: if options.customheight > 0:
comic2panel.main(['-y ' + str(options.customheight), '-i', path], qtGUI) comic2panel.main(['-y ' + str(options.customheight), '-i', '-m', path], qtGUI)
else: else:
comic2panel.main(['-y ' + str(image.ProfileData.Profiles[options.profile][1][1]), '-i', path], qtGUI) comic2panel.main(['-y ' + str(image.ProfileData.Profiles[options.profile][1][1]), '-i', '-m', path], qtGUI)
if options.imgproc: if options.imgproc:
print("\nProcessing images...") print("\nProcessing images...")
if GUI: if GUI:
@@ -966,7 +1019,7 @@ def main(argv=None, qtGUI=None):
filepath.append(getOutputFilename(args[0], options.output, '.cbz', ' ' + str(tomeNumber))) filepath.append(getOutputFilename(args[0], options.output, '.cbz', ' ' + str(tomeNumber)))
else: else:
filepath.append(getOutputFilename(args[0], options.output, '.cbz', '')) filepath.append(getOutputFilename(args[0], options.output, '.cbz', ''))
make_archive(tome + '_comic', 'zip', tome + '/OEBPS/Images') makeZIP(tome + '_comic', tome + '/OEBPS/Images')
else: else:
print("\nCreating EPUB structure...") print("\nCreating EPUB structure...")
genEpubStruct(tome) genEpubStruct(tome)
@@ -975,7 +1028,7 @@ def main(argv=None, qtGUI=None):
filepath.append(getOutputFilename(args[0], options.output, '.epub', ' ' + str(tomeNumber))) filepath.append(getOutputFilename(args[0], options.output, '.epub', ' ' + str(tomeNumber)))
else: else:
filepath.append(getOutputFilename(args[0], options.output, '.epub', '')) filepath.append(getOutputFilename(args[0], options.output, '.epub', ''))
make_archive(tome + '_comic', 'zip', tome) makeZIP(tome + '_comic', tome, True)
move(tome + '_comic.zip', filepath[-1]) move(tome + '_comic.zip', filepath[-1])
rmtree(tome, True) rmtree(tome, True)
if GUI: if GUI:
@@ -1033,6 +1086,11 @@ def checkOptions():
if options.profile == 'OTHER': if options.profile == 'OTHER':
options.panelview = False options.panelview = False
options.quality = 0 options.quality = 0
if 'Ko' in options.profile:
options.panelview = False
# Kobo models can't use ultra quality mode
if options.quality == 2:
options.quality = 1
# Kindle for Android profile require target resolution. # Kindle for Android profile require target resolution.
if options.profile == 'KFA' and (options.customwidth == 0 or options.customheight == 0): if options.profile == 'KFA' and (options.customwidth == 0 or options.customheight == 0):
print("ERROR: Kindle for Android profile require --customwidth and --customheight options!") print("ERROR: Kindle for Android profile require --customwidth and --customheight options!")

View File

@@ -29,29 +29,25 @@ from shutil import rmtree, copytree, move
from optparse import OptionParser, OptionGroup from optparse import OptionParser, OptionGroup
from multiprocessing import Pool, freeze_support from multiprocessing import Pool, freeze_support
try: try:
#noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from PIL import Image, ImageStat from PIL import Image, ImageStat
if tuple(map(int, ('2.2.1'.split(".")))) > tuple(map(int, (Image.PILLOW_VERSION.split(".")))): if tuple(map(int, ('2.3.0'.split(".")))) > tuple(map(int, (Image.PILLOW_VERSION.split(".")))):
print("ERROR: Pillow 2.2.1 or newer is required!") print("ERROR: Pillow 2.3.0 or newer is required!")
if sys.platform.startswith('linux'): if sys.platform.startswith('linux'):
#noinspection PyUnresolvedReferences
import tkinter import tkinter
#noinspection PyUnresolvedReferences
import tkinter.messagebox import tkinter.messagebox
importRoot = tkinter.Tk() importRoot = tkinter.Tk()
importRoot.withdraw() importRoot.withdraw()
tkinter.messagebox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!") tkinter.messagebox.showerror("KCC - Error", "Pillow 2.3.0 or newer is required!")
exit(1) exit(1)
except ImportError: except ImportError:
print("ERROR: Pillow is not installed!") print("ERROR: Pillow is not installed!")
if sys.platform.startswith('linux'): if sys.platform.startswith('linux'):
#noinspection PyUnresolvedReferences
import tkinter import tkinter
#noinspection PyUnresolvedReferences
import tkinter.messagebox import tkinter.messagebox
importRoot = tkinter.Tk() importRoot = tkinter.Tk()
importRoot.withdraw() importRoot.withdraw()
tkinter.messagebox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!") tkinter.messagebox.showerror("KCC - Error", "Pillow 2.3.0 or newer is required!")
exit(1) exit(1)
try: try:
from PyQt4 import QtCore from PyQt4 import QtCore
@@ -73,6 +69,59 @@ def getImageFileName(imgfile):
return filename return filename
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 os.walk(some_dir):
yield root, dirs, files
num_sep_this = root.count(os.path.sep)
if num_sep + level <= num_sep_this:
del dirs[:]
def mergeDirectory_tick(output):
if output:
mergeWorkerOutput.append(output)
mergeWorkerPool.terminate()
if GUI:
GUI.emit(QtCore.SIGNAL("progressBarTick"))
if not GUI.conversionAlive:
mergeWorkerPool.terminate()
def mergeDirectory(work):
try:
directory = work[0]
images = []
imagesClear = []
sizes = []
for root, dirs, files in walkLevel(directory, 0):
for name in files:
if getImageFileName(name) is not None:
images.append([Image.open(os.path.join(root, name)), os.path.join(root, name)])
if len(images) > 0:
for i in images:
sizes.append(i[0].size[0])
mw = max(set(sizes), key=sizes.count)
for i in images:
if i[0].size[0] == mw:
i[0] = i[0].convert('RGB')
imagesClear.append(i)
h = sum(i[0].size[1] for i in imagesClear)
result = Image.new('RGB', (mw, h))
y = 0
for i in imagesClear:
result.paste(i[0], (0, y))
y += i[0].size[1]
for i in imagesClear:
os.remove(i[1])
savePath = os.path.split(imagesClear[0][1])
result.save(os.path.join(savePath[0], os.path.splitext(savePath[1])[0] + '.png'), 'PNG')
except StandardError:
return str(sys.exc_info()[1])
def sanitizePanelSize(panel, opt): def sanitizePanelSize(panel, opt):
newPanels = [] newPanels = []
if panel[2] > 8 * opt.height: if panel[2] > 8 * opt.height:
@@ -121,21 +170,6 @@ def splitImage(work):
print(".", end=' ') print(".", end=' ')
fileExpanded = os.path.splitext(name) fileExpanded = os.path.splitext(name)
filePath = os.path.join(path, name) filePath = os.path.join(path, name)
# Detect corrupted files
try:
Image.open(filePath)
except IOError:
raise RuntimeError('Cannot read image file %s' % filePath)
try:
image = Image.open(filePath)
image.verify()
except:
raise RuntimeError('Image file %s is corrupted' % filePath)
try:
image = Image.open(filePath)
image.load()
except:
raise RuntimeError('Image file %s is corrupted' % filePath)
image = Image.open(filePath) image = Image.open(filePath)
image = image.convert('RGB') image = image.convert('RGB')
widthImg, heightImg = image.size widthImg, heightImg = image.size
@@ -220,7 +254,7 @@ def Copyright():
def main(argv=None, qtGUI=None): def main(argv=None, qtGUI=None):
global options, GUI, splitWorkerPool, splitWorkerOutput global options, GUI, splitWorkerPool, splitWorkerOutput, mergeWorkerPool, mergeWorkerOutput
parser = OptionParser(usage="Usage: %prog [options] comic_folder", add_help_option=False) parser = OptionParser(usage="Usage: %prog [options] comic_folder", add_help_option=False)
mainOptions = OptionGroup(parser, "MANDATORY") mainOptions = OptionGroup(parser, "MANDATORY")
otherOptions = OptionGroup(parser, "OTHER") otherOptions = OptionGroup(parser, "OTHER")
@@ -228,6 +262,8 @@ def main(argv=None, qtGUI=None):
help="Height of the target device screen") help="Height of the target device screen")
mainOptions.add_option("-i", "--in-place", action="store_true", dest="inPlace", default=False, mainOptions.add_option("-i", "--in-place", action="store_true", dest="inPlace", default=False,
help="Overwrite source directory") help="Overwrite source directory")
mainOptions.add_option("-m", "--merge", action="store_true", dest="merge", default=False,
help="Combine every directory into a single image before splitting")
otherOptions.add_option("-d", "--debug", action="store_true", dest="debug", default=False, otherOptions.add_option("-d", "--debug", action="store_true", dest="debug", default=False,
help="Create debug file for every splitted image") help="Create debug file for every splitted image")
otherOptions.add_option("-h", "--help", action="help", otherOptions.add_option("-h", "--help", action="help",
@@ -253,6 +289,29 @@ def main(argv=None, qtGUI=None):
pagenumber = 0 pagenumber = 0
splitWorkerOutput = [] splitWorkerOutput = []
splitWorkerPool = Pool() splitWorkerPool = Pool()
if options.merge:
directoryNumer = 1
mergeWork = []
mergeWorkerOutput = []
mergeWorkerPool = Pool()
mergeWork.append([options.targetDir])
for root, dirs, files in os.walk(options.targetDir, False):
for directory in dirs:
directoryNumer += 1
mergeWork.append([os.path.join(root, directory)])
if GUI:
GUI.emit(QtCore.SIGNAL("progressBarTick"), 'status', 'Combining images')
GUI.emit(QtCore.SIGNAL("progressBarTick"), directoryNumer)
for i in mergeWork:
mergeWorkerPool.apply_async(func=mergeDirectory, args=(i, ), callback=mergeDirectory_tick)
mergeWorkerPool.close()
mergeWorkerPool.join()
if GUI and not GUI.conversionAlive:
rmtree(options.targetDir, True)
raise UserWarning("Conversion interrupted.")
if len(mergeWorkerOutput) > 0:
rmtree(options.targetDir, True)
raise RuntimeError("One of workers crashed. Cause: " + mergeWorkerOutput[0])
for root, dirs, files in os.walk(options.targetDir, False): for root, dirs, files in os.walk(options.targetDir, False):
for name in files: for name in files:
if getImageFileName(name) is not None: if getImageFileName(name) is not None:
@@ -261,7 +320,9 @@ def main(argv=None, qtGUI=None):
else: else:
os.remove(os.path.join(root, name)) os.remove(os.path.join(root, name))
if GUI: if GUI:
GUI.emit(QtCore.SIGNAL("progressBarTick"), 'status', 'Splitting images')
GUI.emit(QtCore.SIGNAL("progressBarTick"), pagenumber) GUI.emit(QtCore.SIGNAL("progressBarTick"), pagenumber)
GUI.emit(QtCore.SIGNAL("progressBarTick"))
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=splitImage_tick)

View File

@@ -25,27 +25,23 @@ from sys import platform
try: try:
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from PIL import Image, ImageOps, ImageStat, ImageChops from PIL import Image, ImageOps, ImageStat, ImageChops
if tuple(map(int, ('2.2.1'.split(".")))) > tuple(map(int, (Image.PILLOW_VERSION.split(".")))): if tuple(map(int, ('2.3.0'.split(".")))) > tuple(map(int, (Image.PILLOW_VERSION.split(".")))):
print("ERROR: Pillow 2.2.1 or newer is required!") print("ERROR: Pillow 2.3.0 or newer is required!")
if platform.startswith('linux'): if platform.startswith('linux'):
#noinspection PyUnresolvedReferences
import tkinter import tkinter
#noinspection PyUnresolvedReferences
import tkinter.messagebox import tkinter.messagebox
importRoot = tkinter.Tk() importRoot = tkinter.Tk()
importRoot.withdraw() importRoot.withdraw()
tkinter.messagebox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!") tkinter.messagebox.showerror("KCC - Error", "Pillow 2.3.0 or newer is required!")
exit(1) exit(1)
except ImportError: except ImportError:
print("ERROR: Pillow is not installed!") print("ERROR: Pillow is not installed!")
if platform.startswith('linux'): if platform.startswith('linux'):
#noinspection PyUnresolvedReferences
import tkinter import tkinter
#noinspection PyUnresolvedReferences
import tkinter.messagebox import tkinter.messagebox
importRoot = tkinter.Tk() importRoot = tkinter.Tk()
importRoot.withdraw() importRoot.withdraw()
tkinter.messagebox.showerror("KCC - Error", "Pillow 2.2.1 or newer is required!") tkinter.messagebox.showerror("KCC - Error", "Pillow 2.3.0 or newer is required!")
exit(1) exit(1)
@@ -111,43 +107,14 @@ class ProfileData:
'KFHD8': ("K. Fire HD 8.9\"", (1200, 1920), PalleteNull, 1.0, (1800, 2880)), 'KFHD8': ("K. Fire HD 8.9\"", (1200, 1920), PalleteNull, 1.0, (1800, 2880)),
'KFHDX': ("K. Fire HDX 7\"", (1200, 1920), PalleteNull, 1.0, (1800, 2880)), 'KFHDX': ("K. Fire HDX 7\"", (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)),
'KoMT': ("Kobo Mini/Touch", (600, 800), Palette16, 1.8, (900, 1200)),
'KoG': ("Kobo Glow", (768, 1024), Palette16, 1.8, (1152, 1536)),
'KoA': ("Kobo Aura", (758, 1024), Palette16, 1.8, (1137, 1536)),
'KoAHD': ("Kobo Aura HD", (1080, 1440), Palette16, 1.8, (1620, 2160)),
'KFA': ("Kindle for Android", (0, 0), PalleteNull, 1.0, (0, 0)), 'KFA': ("Kindle for Android", (0, 0), PalleteNull, 1.0, (0, 0)),
'OTHER': ("Other", (0, 0), Palette16, 1.8, (0, 0)), 'OTHER': ("Other", (0, 0), Palette16, 1.8, (0, 0)),
} }
ProfileLabels = {
"Kindle 1": 'K1',
"Kindle 2": 'K2',
"Kindle": 'K345',
"Kindle Paperwhite": 'KHD',
"Kindle DX/DXG": 'KDX',
"Kindle Fire": 'KF',
"K. Fire HD 7\"": 'KFHD',
"K. Fire HD 8.9\"": 'KFHD8',
"K. Fire HDX 7\"": 'KFHDX',
"K. Fire HDX 8.9\"": 'KFHDX8',
"Kindle for Android": 'KFA',
"Other": 'OTHER'
}
ProfileLabelsGUI = [
"Kindle Paperwhite",
"Kindle",
"Separator",
"K. Fire HD 7\"",
"K. Fire HD 8.9\"",
"K. Fire HDX 7\"",
"K. Fire HDX 8.9\"",
"Separator",
"Kindle for Android",
"Other",
"Separator",
"Kindle 1",
"Kindle 2",
"Kindle DX/DXG",
"Kindle Fire"
]
class ComicPage: class ComicPage:
def __init__(self, source, device, fill=None): def __init__(self, source, device, fill=None):
@@ -155,31 +122,16 @@ class ComicPage:
self.profile_label, self.size, self.palette, self.gamma, self.panelviewsize = device self.profile_label, self.size, self.palette, self.gamma, self.panelviewsize = device
except KeyError: except KeyError:
raise RuntimeError('Unexpected output device %s' % device) raise RuntimeError('Unexpected output device %s' % device)
# Detect corrupted files - Phase 2 self.origFileName = source
try: self.filename = os.path.basename(self.origFileName)
self.origFileName = source
self.filename = os.path.basename(self.origFileName)
self.image = Image.open(source)
except IOError:
raise RuntimeError('Cannot read image file %s' % source)
# Detect corrupted files - Phase 3
try:
self.image = Image.open(source)
self.image.verify()
except:
raise RuntimeError('Image file %s is corrupted' % source)
# Detect corrupted files - Phase 4
try:
self.image = Image.open(source)
self.image.load()
except:
raise RuntimeError('Image file %s is corrupted' % source)
self.image = Image.open(source) self.image = Image.open(source)
self.image = self.image.convert('RGB') self.image = self.image.convert('RGB')
self.rotated = None self.rotated = None
self.border = None self.border = None
self.noHPV = None self.noHPV = None
self.noVPV = None self.noVPV = None
self.noPV = None
self.purge = False
if fill: if fill:
self.fill = fill self.fill = fill
else: else:
@@ -196,19 +148,23 @@ class ComicPage:
os.remove(os.path.join(targetdir, self.filename)) os.remove(os.path.join(targetdir, self.filename))
else: else:
suffix += "_kcchq" suffix += "_kcchq"
if self.noHPV: if self.noPV:
suffix += "_kccnh" suffix += "_kccnpv"
if self.noVPV:
suffix += "_kccnv"
if self.border:
suffix += "_kccxl" + str(self.border[0]) + "_kccyu" + str(self.border[1]) + "_kccxr" +\
str(self.border[2]) + "_kccyd" + str(self.border[3])
if forcepng:
self.image.save(os.path.join(targetdir, os.path.splitext(self.filename)[0] + suffix + ".png"), "PNG",
optimize=1)
else: else:
self.image.save(os.path.join(targetdir, os.path.splitext(self.filename)[0] + suffix + ".jpg"), "JPEG", if self.noHPV:
optimize=1) suffix += "_kccnh"
if self.noVPV:
suffix += "_kccnv"
if self.border:
suffix += "_kccxl" + str(self.border[0]) + "_kccyu" + str(self.border[1]) + "_kccxr" +\
str(self.border[2]) + "_kccyd" + str(self.border[3])
if not self.purge:
if forcepng:
self.image.save(os.path.join(targetdir, os.path.splitext(self.filename)[0] + suffix + ".png"),
"PNG", optimize=1)
else:
self.image.save(os.path.join(targetdir, os.path.splitext(self.filename)[0] + suffix + ".jpg"),
"JPEG", optimize=1)
except IOError as e: except IOError as e:
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e)) raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
@@ -240,8 +196,12 @@ class ComicPage:
return int(round(float(x)/float(img.image.size[1]), 4) * 10000 * 1.5) return int(round(float(x)/float(img.image.size[1]), 4) * 10000 * 1.5)
def calculateBorder(self, sourceImage, isHQ=False): def calculateBorder(self, sourceImage, isHQ=False):
if isHQ and sourceImage.purge:
self.border = [0, 0, 0, 0]
self.noPV = True
return
if self.fill == 'white': if self.fill == 'white':
# This code trigger only when sourceImage is already saved. So we can break color quantization. # Only already saved files can have P mode. So we can break color quantization.
if sourceImage.image.mode == 'P': if sourceImage.image.mode == 'P':
sourceImage.image = sourceImage.image.convert('RGB') sourceImage.image = sourceImage.image.convert('RGB')
border = ImageChops.invert(sourceImage.image).getbbox() border = ImageChops.invert(sourceImage.image).getbbox()
@@ -275,12 +235,9 @@ class ComicPage:
size = (self.size[0], self.size[1]) size = (self.size[0], self.size[1])
else: else:
size = (self.panelviewsize[0], self.panelviewsize[1]) size = (self.panelviewsize[0], self.panelviewsize[1])
# If image is smaller than device resolution and upscale is off - Just expand it by adding margins # If image is small and HQ mode is on we have to force upscaling. Otherwise non-zoomed image will be distorted
if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1] and not upscale: if self.image.size[0] <= size[0] and self.image.size[1] <= size[1] and qualityMode == 1 and not stretch:
borderw = (self.size[0] - self.image.size[0]) / 2 upscale = True
borderh = (self.size[1] - self.image.size[1]) / 2
self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=fill)
return self.image
# If stretching is on - Resize without other considerations # If stretching is on - Resize without other considerations
if stretch: if stretch:
if self.image.size[0] <= size[0] and self.image.size[1] <= size[1]: if self.image.size[0] <= size[0] and self.image.size[1] <= size[1]:
@@ -289,8 +246,20 @@ class ComicPage:
method = Image.ANTIALIAS method = Image.ANTIALIAS
self.image = self.image.resize(size, method) self.image = self.image.resize(size, method)
return self.image return self.image
# If image is smaller than target resolution and upscale is off - Just expand it by adding margins
if self.image.size[0] <= size[0] and self.image.size[1] <= size[1] and not upscale:
borderw = (size[0] - self.image.size[0]) / 2
borderh = (size[1] - self.image.size[1]) / 2
# PV is disabled when source image is smaller than device screen and upscale is off - So we drop HQ image
if qualityMode == 2 and self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]:
self.purge = True
self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=fill)
# Border can't be float so sometimes image might be 1px too small/large
if self.image.size[0] != size[0] or self.image.size[1] != size[1]:
self.image = ImageOps.fit(self.image, size, method=Image.BICUBIC, centering=(0.5, 0.5))
return self.image
# Otherwise - Upscale/Downscale # Otherwise - Upscale/Downscale
ratioDev = float(self.size[0]) / float(self.size[1]) ratioDev = float(size[0]) / float(size[1])
if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev: if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev:
diff = int(self.image.size[1] * ratioDev) - self.image.size[0] diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
self.image = ImageOps.expand(self.image, border=(int(diff / 2), 0), fill=fill) self.image = ImageOps.expand(self.image, border=(int(diff / 2), 0), fill=fill)
@@ -433,7 +402,7 @@ class ComicPage:
self.image = self.image.crop((0, 0, widthImg - diff, heightImg)) self.image = self.image.crop((0, 0, widthImg - diff, heightImg))
return self.image return self.image
def getImageHistogram(self, image, new=True): def getImageHistogram(self, image):
histogram = image.histogram() histogram = image.histogram()
RBGW = [] RBGW = []
pixelCount = 0 pixelCount = 0
@@ -446,74 +415,35 @@ class ComicPage:
white += RBGW[i] white += RBGW[i]
for i in range(5): for i in range(5):
black += RBGW[i] black += RBGW[i]
if new: if black > pixelCount*0.8 and white == 0:
if black > 0 and white == 0: return 1
return 1 elif white > pixelCount*0.8 and black == 0:
elif white > 0 and black == 0: return -1
return -1
else:
return False
else: else:
if black > white and black > pixelCount*0.5: return False
return True
else:
return False
def getImageFill(self, isWebToon): def getImageFill(self, webtoon):
if isWebToon: fill = 0
fill = 0 if not webtoon and not self.rotated:
fill += self.getImageHistogram(self.image.crop((0, 0, self.image.size[0], 5)), False) # Search for horizontal solid lines
fill += self.getImageHistogram(self.image.crop((0, self.image.size[1]-5, self.image.size[0],
self.image.size[1])), False)
if fill == 2:
self.fill = 'black'
elif fill == 0:
self.fill = 'white'
else:
fill = 0
fill += self.getImageHistogram(self.image.crop((0, 0, 5, 5)), False)
fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, 0, self.image.size[0], 5)), False)
fill += self.getImageHistogram(self.image.crop((0, self.image.size[1]-5, 5, self.image.size[1])), False)
fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, self.image.size[1]-5,
self.image.size[0], self.image.size[1])), False)
if fill > 1:
self.fill = 'black'
else:
self.fill = 'white'
else:
fill = 0
# Search fom horizontal solid lines
startY = 0 startY = 0
stopY = 3 while startY < self.image.size[1]:
searching = True checkSolid = self.getImageHistogram(self.image.crop((0, startY, self.image.size[0], startY+1)))
while stopY <= self.image.size[1]:
checkSolid = self.getImageHistogram(self.image.crop((0, startY, self.image.size[0], stopY)))
if checkSolid: if checkSolid:
fill += checkSolid fill += checkSolid
startY = stopY + 1 startY += 1
stopY = startY + 3 else:
if stopY > self.image.size[1] and searching: # Search for vertical solid lines
startY = self.image.size[1] - 3
stopY = self.image.size[1]
searching = False
# Search fom vertical solid lines
startX = 0 startX = 0
stopX = 3 while startX < self.image.size[0]:
searching = True checkSolid = self.getImageHistogram(self.image.crop((startX, 0, startX+1, self.image.size[1])))
while stopX <= self.image.size[0]:
checkSolid = self.getImageHistogram(self.image.crop((startX, 0, stopX, self.image.size[1])))
if checkSolid: if checkSolid:
fill += checkSolid fill += checkSolid
startX = stopX + 1 startX += 1
stopX = startX + 3 if fill > 0:
if stopX > self.image.size[0] and searching: self.fill = 'black'
startX = self.image.size[0] - 3 else:
stopX = self.image.size[0] self.fill = 'white'
searching = False
if fill > 0:
self.fill = 'black'
else:
self.fill = 'white'
def isImageColor(self, image): def isImageColor(self, image):
v = ImageStat.Stat(image).var v = ImageStat.Stat(image).var

View File

@@ -3,7 +3,7 @@
# #
# Based on initial version of KindleUnpack. Copyright (C) 2009 Charles M. Hannum <root@ihack.net> # Based on initial version of KindleUnpack. Copyright (C) 2009 Charles M. Hannum <root@ihack.net>
# Improvements Copyright (C) 2009-2012 P. Durrant, K. Hendricks, S. Siebert, fandrieu, DiapDealer, nickredding # Improvements Copyright (C) 2009-2012 P. Durrant, K. Hendricks, S. Siebert, fandrieu, DiapDealer, nickredding
# Copyright (C) 2013 Pawel Jastrzebski <pawelj@vulturis.eu> # Changes for KCC Copyright (C) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -18,10 +18,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
__license__ = 'ISC'
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
__docformat__ = 'restructuredtext en'
import struct import struct
# from uuid import uuid4 # from uuid import uuid4

View File

@@ -24,13 +24,16 @@ __copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jas
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import os import os
from random import choice
from string import ascii_uppercase, digits
class PdfJpgExtract: class PdfJpgExtract:
def __init__(self, origFileName): def __init__(self, origFileName):
self.origFileName = origFileName self.origFileName = origFileName
self.filename = os.path.splitext(origFileName) self.filename = os.path.splitext(origFileName)
self.path = self.filename[0] + "-KCC-TMP" # noinspection PyUnusedLocal
self.path = self.filename[0] + "-KCC-TMP-" + ''.join(choice(ascii_uppercase + digits) for x in range(3))
def getPath(self): def getPath(self):
return self.path return self.path
@@ -63,7 +66,6 @@ class PdfJpgExtract:
istart += startfix istart += startfix
iend += endfix iend += endfix
print("JPG %d from %d to %d" % (njpg, istart, iend))
jpg = pdf[istart:iend] jpg = pdf[istart:iend]
jpgfile = file(self.path + "/jpg%d.jpg" % njpg, "wb") jpgfile = file(self.path + "/jpg%d.jpg" % njpg, "wb")
jpgfile.write(jpg) jpgfile.write(jpg)

View File

@@ -44,7 +44,7 @@ if platform == "darwin":
CFBundleTypeRole='Viewer', CFBundleTypeRole='Viewer',
) )
], ],
LSMinimumSystemVersion='10.6.0', LSMinimumSystemVersion='10.8.0',
LSEnvironment=dict( LSEnvironment=dict(
PATH='/usr/local/bin:/usr/bin:/bin' PATH='/usr/local/bin:/usr/bin:/bin'
), ),