mirror of
https://github.com/ciromattia/kcc
synced 2026-04-18 06:58:58 +00:00
Compare commits
83 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf0b6b3484 | ||
|
|
96a8c1d354 | ||
|
|
20712b6c42 | ||
|
|
84d836bf0e | ||
|
|
d944d6385e | ||
|
|
a38013eabc | ||
|
|
def9e42a61 | ||
|
|
34aaeab8b1 | ||
|
|
eaff6cc633 | ||
|
|
54f48d2156 | ||
|
|
42d845cf07 | ||
|
|
e5e53d3aa7 | ||
|
|
f952634971 | ||
|
|
19ff6a51cc | ||
|
|
8fbe558f65 | ||
|
|
6bdb0ab942 | ||
|
|
7656a85708 | ||
|
|
d016bade8e | ||
|
|
3cc99c6221 | ||
|
|
93f5d105cf | ||
|
|
c1c44bdf88 | ||
|
|
72132ea908 | ||
|
|
29f901f92a | ||
|
|
22b7258aa3 | ||
|
|
c0f788bd67 | ||
|
|
8f10e93c08 | ||
|
|
4a473e3716 | ||
|
|
80b65b12b7 | ||
|
|
e835502837 | ||
|
|
5bcdc78725 | ||
|
|
acb4dfad8f | ||
|
|
7f5de29174 | ||
|
|
11007402cd | ||
|
|
0cf92fc48f | ||
|
|
953942ca00 | ||
|
|
c46ca8b507 | ||
|
|
48d3bee225 | ||
|
|
3b0e5cc309 | ||
|
|
e5be31f9d5 | ||
|
|
17ea85c31f | ||
|
|
572e1422bf | ||
|
|
af263073b5 | ||
|
|
7facf2d620 | ||
|
|
eef3ff434b | ||
|
|
c680cfd5c5 | ||
|
|
3e8469611d | ||
|
|
39ab475156 | ||
|
|
636de67a17 | ||
|
|
d80c18f652 | ||
|
|
557bd2bbbf | ||
|
|
ddd223c2ec | ||
|
|
50f5b600b1 | ||
|
|
d94df8390a | ||
|
|
8b33331929 | ||
|
|
86a9dde1eb | ||
|
|
33dec77063 | ||
|
|
fe06e2fa19 | ||
|
|
7b5e3eaafd | ||
|
|
0a30f1ffb9 | ||
|
|
8687604d26 | ||
|
|
0a9fd6c439 | ||
|
|
c95a9395de | ||
|
|
77066d7a9f | ||
|
|
c8e5b7de9a | ||
|
|
3e11a88a7c | ||
|
|
a7e4968836 | ||
|
|
6d9e2d3c03 | ||
|
|
0789e7a353 | ||
|
|
ff97a85552 | ||
|
|
33cfd92cef | ||
|
|
58513ef59f | ||
|
|
6056e3e767 | ||
|
|
1b1ed7c4ab | ||
|
|
5b44e4bddd | ||
|
|
54592969a4 | ||
|
|
38007ab3d5 | ||
|
|
bdd10c7617 | ||
|
|
c0f4bc021a | ||
|
|
34d6af93a6 | ||
|
|
0df481dabb | ||
|
|
55c5b91411 | ||
|
|
be745f4602 | ||
|
|
8bf5ad0f12 |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -2,11 +2,11 @@
|
|||||||
*.cbz
|
*.cbz
|
||||||
*.cbr
|
*.cbr
|
||||||
.idea
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
build
|
build
|
||||||
dist
|
dist
|
||||||
Output
|
Output
|
||||||
|
test
|
||||||
|
solaio
|
||||||
kindlegen*
|
kindlegen*
|
||||||
UnRAR*
|
|
||||||
7za*
|
|
||||||
.DS_Store
|
|
||||||
Thumbs.db
|
|
||||||
|
|||||||
32
KCC-Linux.ui
32
KCC-Linux.ui
@@ -7,19 +7,19 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>420</width>
|
<width>420</width>
|
||||||
<height>380</height>
|
<height>397</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>420</width>
|
<width>420</width>
|
||||||
<height>380</height>
|
<height>397</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>420</width>
|
<width>420</width>
|
||||||
<height>380</height>
|
<height>397</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
@@ -27,9 +27,6 @@
|
|||||||
<pointsize>9</pointsize>
|
<pointsize>9</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="focusPolicy">
|
|
||||||
<enum>Qt::NoFocus</enum>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Kindle Comic Converter</string>
|
<string>Kindle Comic Converter</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -391,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>
|
||||||
<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></string>
|
<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></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -419,7 +416,7 @@ p, li { white-space: pre-wrap; }
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Disable page spliting.<br/>They will be rotated instead.</p></body></html></string>
|
<string><html><head/><body><p>Disable splitting of two-page spreads.<br/>They will be rotated instead.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Horizontal mode</string>
|
<string>Horizontal mode</string>
|
||||||
@@ -546,9 +543,6 @@ p, li { white-space: pre-wrap; }
|
|||||||
<family>DejaVu Sans</family>
|
<family>DejaVu Sans</family>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>When converting color images setting this option to 1.0 <span style=" font-weight:600;">might</span> improve readability.</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Gamma: Auto</string>
|
<string>Gamma: Auto</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -570,9 +564,6 @@ p, li { white-space: pre-wrap; }
|
|||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::ClickFocus</enum>
|
<enum>Qt::ClickFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>When converting color images setting this option to 1.0 <span style=" font-weight:600;">might</span> improve readability.</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>500</number>
|
<number>500</number>
|
||||||
</property>
|
</property>
|
||||||
@@ -644,7 +635,7 @@ p, li { white-space: pre-wrap; }
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Do not convert images to grayscale.</string>
|
<string><html><head/><body><p>Don't convert images to grayscale.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Color mode</string>
|
<string>Color mode</string>
|
||||||
@@ -785,6 +776,17 @@ p, li { white-space: pre-wrap; }
|
|||||||
<zorder>OptionsExpert</zorder>
|
<zorder>OptionsExpert</zorder>
|
||||||
<zorder>ProgressBar</zorder>
|
<zorder>ProgressBar</zorder>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QStatusBar" name="statusBar">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="sizeGripEnabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
<action name="ActionBasic">
|
<action name="ActionBasic">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
|||||||
32
KCC-OSX.ui
32
KCC-OSX.ui
@@ -7,19 +7,19 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>420</width>
|
<width>420</width>
|
||||||
<height>380</height>
|
<height>397</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>420</width>
|
<width>420</width>
|
||||||
<height>380</height>
|
<height>397</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>420</width>
|
<width>420</width>
|
||||||
<height>380</height>
|
<height>397</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
@@ -27,9 +27,6 @@
|
|||||||
<pointsize>9</pointsize>
|
<pointsize>9</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="focusPolicy">
|
|
||||||
<enum>Qt::NoFocus</enum>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Kindle Comic Converter</string>
|
<string>Kindle Comic Converter</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -391,7 +388,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><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></string>
|
<string><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></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>High/Ultra quality</string>
|
<string>High/Ultra quality</string>
|
||||||
@@ -419,7 +416,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p><span style=" font-size:12pt;">Disable page spliting.<br/>They will be rotated instead.</span></p></body></html></string>
|
<string><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></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Horizontal mode</string>
|
<string>Horizontal mode</string>
|
||||||
@@ -546,9 +543,6 @@
|
|||||||
<bold>false</bold>
|
<bold>false</bold>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p><span style=" font-size:12pt;">When converting color images setting this option to 1.0 </span><span style=" font-size:12pt; font-weight:600;">might</span><span style=" font-size:12pt;"> improve readability.</span></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Gamma: Auto</string>
|
<string>Gamma: Auto</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -570,9 +564,6 @@
|
|||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::ClickFocus</enum>
|
<enum>Qt::ClickFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p><span style=" font-size:12pt;">When converting color images setting this option to 1.0 </span><span style=" font-size:12pt; font-weight:600;">might</span><span style=" font-size:12pt;"> improve readability.</span></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>500</number>
|
<number>500</number>
|
||||||
</property>
|
</property>
|
||||||
@@ -648,7 +639,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p><span style=" font-size:12pt;">Do not convert images to grayscale.</span></p></body></html></string>
|
<string><html><head/><body><p><span style=" font-size:12pt;">Don't convert images to grayscale.</span></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Color mode</string>
|
<string>Color mode</string>
|
||||||
@@ -797,6 +788,17 @@
|
|||||||
<zorder>OptionsAdvancedGamma</zorder>
|
<zorder>OptionsAdvancedGamma</zorder>
|
||||||
<zorder>OptionsExpert</zorder>
|
<zorder>OptionsExpert</zorder>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QStatusBar" name="statusBar">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Aharoni</family>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="sizeGripEnabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
<action name="ActionBasic">
|
<action name="ActionBasic">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
|||||||
1
KCC.qrc
1
KCC.qrc
@@ -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>
|
||||||
|
|||||||
32
KCC.ui
32
KCC.ui
@@ -7,19 +7,19 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>420</width>
|
<width>420</width>
|
||||||
<height>380</height>
|
<height>397</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>420</width>
|
<width>420</width>
|
||||||
<height>380</height>
|
<height>397</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>420</width>
|
<width>420</width>
|
||||||
<height>380</height>
|
<height>397</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
@@ -27,9 +27,6 @@
|
|||||||
<pointsize>9</pointsize>
|
<pointsize>9</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="focusPolicy">
|
|
||||||
<enum>Qt::NoFocus</enum>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Kindle Comic Converter</string>
|
<string>Kindle Comic Converter</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -343,7 +340,7 @@
|
|||||||
p, li { white-space: pre-wrap; }
|
p, li { white-space: pre-wrap; }
|
||||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;">
|
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; 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-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>
|
<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>
|
||||||
<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>
|
<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>
|
||||||
<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></string>
|
<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></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -366,7 +363,7 @@ p, li { white-space: pre-wrap; }
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Disable page spliting.<br/>They will be rotated instead.</p></body></html></string>
|
<string><html><head/><body><p>Disable splitting of two-page spreads.<br/>They will be rotated instead.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Horizontal mode</string>
|
<string>Horizontal mode</string>
|
||||||
@@ -472,9 +469,6 @@ p, li { white-space: pre-wrap; }
|
|||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
|
||||||
<string>When converting color images setting this option to 1.0 MIGHT improve readability.</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Gamma: Auto</string>
|
<string>Gamma: Auto</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -491,9 +485,6 @@ p, li { white-space: pre-wrap; }
|
|||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::ClickFocus</enum>
|
<enum>Qt::ClickFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>When converting color images setting this option to 1.0 <span style=" font-weight:600;">might</span> improve readability.</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>500</number>
|
<number>500</number>
|
||||||
</property>
|
</property>
|
||||||
@@ -558,7 +549,7 @@ p, li { white-space: pre-wrap; }
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Do not convert images to grayscale.</string>
|
<string><html><head/><body><p>Don't convert images to grayscale.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Color mode</string>
|
<string>Color mode</string>
|
||||||
@@ -674,6 +665,17 @@ p, li { white-space: pre-wrap; }
|
|||||||
<zorder>OptionsExpert</zorder>
|
<zorder>OptionsExpert</zorder>
|
||||||
<zorder>ProgressBar</zorder>
|
<zorder>ProgressBar</zorder>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QStatusBar" name="statusBar">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>MS Shell Dlg 2</family>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="sizeGripEnabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
<action name="ActionBasic">
|
<action name="ActionBasic">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
|||||||
114
README.md
114
README.md
@@ -1,6 +1,6 @@
|
|||||||
# KCC
|
# KCC
|
||||||
|
|
||||||
**KindleComicConverter** 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.
|
||||||
@@ -8,60 +8,51 @@ It can also optionally optimize images by applying a number of transformations.
|
|||||||
### A word of warning
|
### A word of warning
|
||||||
**KCC** _is not_ [Amazon's Kindle Comic Creator](http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1001103761) nor is in any way endorsed by Amazon.
|
**KCC** _is not_ [Amazon's Kindle Comic Creator](http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1001103761) nor is in any way endorsed by Amazon.
|
||||||
Amazon's tool is for comic publishers and involves a lot of manual effort, while **KCC** is for comic readers.
|
Amazon's tool is for comic publishers and involves a lot of manual effort, while **KCC** is for comic readers.
|
||||||
If you want to read some comments over *Amazon's KC2* you can take a look at [this](http://www.mobileread.com/forums/showthread.php?t=207461&page=7#96) and [that](http://www.mobileread.com/forums/showthread.php?t=211047) threads on Mobileread.
|
_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
|
||||||
|
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 want more chances an issue is fixes or your wanted feature added, consider [placing a bounty](https://www.bountysource.com/trackers/65571-ciromattia-kcc)!
|
||||||
|
|
||||||
### Donations
|
|
||||||
If you find **KCC** valuable you can consider donating to the authors:
|
If you find **KCC** valuable you can consider donating to the authors:
|
||||||
|
* Ciro Mattia Gonano: [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=D8WNYNPBGDAS2) [](http://flattr.com/thing/2260449/ciromattiakcc-on-GitHub)
|
||||||
* Ciro Mattia Gonano [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=D8WNYNPBGDAS2)
|
* Paweł Jastrzębski: [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YTTJ4LK2JDHPS) [](bitcoin:1W15wwqsfd7wbaZ6wvSJf1LW1bz6q5L8b?label=KCC) [1W15wwqsfd7wbaZ6wvSJf1LW1bz6q5L8b](bitcoin:1W15wwqsfd7wbaZ6wvSJf1LW1bz6q5L8b?label=KCC)
|
||||||
* Paweł Jastrzębski [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YTTJ4LK2JDHPS)
|
|
||||||
|
|
||||||
## BINARY RELEASES
|
## BINARY RELEASES
|
||||||
You can find the latest released binary at the following links:
|
You can find the latest released binary at the following links:
|
||||||
- **Win64:** [http://kcc.vulturis.eu/Win64/](http://kcc.vulturis.eu/Win64/)
|
- **Windows:** [http://kcc.vulturis.eu/Windows/](http://kcc.vulturis.eu/Windows/)
|
||||||
- **Win32:** [http://kcc.vulturis.eu/Win32/](http://kcc.vulturis.eu/Win32/)
|
- **Linux:** [http://kcc.vulturis.eu/Linux/](http://kcc.vulturis.eu/Linux/)
|
||||||
- **OS X:** [http://kcc.vulturis.eu/OSX/](http://kcc.vulturis.eu/OSX/)
|
- **OS X 10.8+:** [http://kcc.vulturis.eu/OSX/](http://kcc.vulturis.eu/OSX/)
|
||||||
- **Linux:** Just download sourcecode and launch: `python kcc.py`
|
|
||||||
|
|
||||||
## 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 - 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.
|
||||||
- **To build OS X release a modified QT is required:** [Patch](https://github.com/ciromattia/kcc/blob/master/other/QT-4.8.5-QListWidget.patch)
|
- [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)
|
||||||
|
|
||||||
## 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.
|
|
||||||
* If you're converting color images and the end result is not satisfactory, experiment with gamma correction option (check 1.0 setting first).
|
|
||||||
* 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.
|
|
||||||
* Output MOBI file should be uploaded via USB. Other methods might corrupt it.
|
|
||||||
|
|
||||||
### 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:
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -70,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)
|
||||||
@@ -118,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
|
||||||
@@ -140,37 +132,40 @@ 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.00
|
####1.0
|
||||||
* Initial version
|
* Initial version
|
||||||
|
|
||||||
####1.10
|
####1.1
|
||||||
* Added support for CBZ/CBR files in comic2ebook.py
|
* Added support for CBZ/CBR files in comic2ebook.py
|
||||||
|
|
||||||
####1.11
|
####1.1.1
|
||||||
* Added support for CBZ/CBR files in KindleComicConverter
|
* Added support for CBZ/CBR files in Kindle Comic Converter
|
||||||
|
|
||||||
####1.20
|
####1.2
|
||||||
* Comic optimizations! Split pages not target-oriented (landscape with portrait target or portrait with landscape target), add palette and other image optimizations from Mangle. WARNING: PIL is required for all image mangling!
|
* Comic optimizations! Split pages not target-oriented (landscape with portrait target or portrait with landscape target), add palette and other image optimizations from Mangle. WARNING: PIL is required for all image mangling!
|
||||||
|
|
||||||
####1.30
|
####1.3
|
||||||
* Fixed an issue in OPF generation for device resolution
|
* Fixed an issue in OPF generation for device resolution
|
||||||
* Reworked options system (call with -h option to get the inline help)
|
* Reworked options system (call with -h option to get the inline help)
|
||||||
|
|
||||||
####1.40
|
####1.4
|
||||||
* Added some options for controlling image optimization
|
* Added some options for controlling image optimization
|
||||||
* Further optimization (ImageOps, page numbering cut, autocontrast)
|
* Further optimization (ImageOps, page numbering cut, autocontrast)
|
||||||
|
|
||||||
####1.41
|
####1.4.1
|
||||||
* Fixed a serious bug on resizing when img ratio was bigger than device one
|
* Fixed a serious bug on resizing when img ratio was bigger than device one
|
||||||
|
|
||||||
####1.50
|
####1.5
|
||||||
* Added subfolder support for multiple chapters.
|
* Added subfolder support for multiple chapters.
|
||||||
|
|
||||||
####2.0
|
####2.0
|
||||||
@@ -179,7 +174,7 @@ The app relies and includes the following scripts/binaries:
|
|||||||
####2.1
|
####2.1
|
||||||
* Added basic error reporting
|
* Added basic error reporting
|
||||||
|
|
||||||
#### 2.2:
|
####2.2:
|
||||||
* Added (valid!) ePub 2.0 output
|
* Added (valid!) ePub 2.0 output
|
||||||
* Rename .zip files to .cbz to avoid overwriting
|
* Rename .zip files to .cbz to avoid overwriting
|
||||||
|
|
||||||
@@ -284,6 +279,39 @@ The app relies and includes the following scripts/binaries:
|
|||||||
* Improved multiprocessing speed
|
* Improved multiprocessing speed
|
||||||
* GUI tweaks and minor bug fixes
|
* GUI tweaks and minor bug fixes
|
||||||
|
|
||||||
|
####3.6:
|
||||||
|
* Increased quality of Panel View zoom
|
||||||
|
* Creation of multipart MOBI output is now faster on machines with 4GB+ RAM
|
||||||
|
* Automatic gamma correction now distinguishes color and grayscale images
|
||||||
|
* Added ComicRack metadata parser
|
||||||
|
* Implemented new method to detect border color in non-webtoon comics
|
||||||
|
* Upscaling is now enabled by default for Kindle Fire HD/HDX
|
||||||
|
* Windows nad Linux releases now have tray icon
|
||||||
|
* Fixed Kindle Fire HDX 7" output
|
||||||
|
* Increased target resolution for Kindle DX/DXG CBZ output
|
||||||
|
|
||||||
|
####3.6.1:
|
||||||
|
* Fixed PNG output
|
||||||
|
|
||||||
|
####3.6.2:
|
||||||
|
* Fixed previous PNG output fix
|
||||||
|
* 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
BIN
icons/Kobo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
10
kcc.iss
10
kcc.iss
@@ -1,5 +1,5 @@
|
|||||||
#define MyAppName "Kindle Comic Converter"
|
#define MyAppName "Kindle Comic Converter"
|
||||||
#define MyAppVersion "3.5"
|
#define MyAppVersion "3.7.2"
|
||||||
#define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
|
#define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
|
||||||
#define MyAppURL "http://kcc.vulturis.eu/"
|
#define MyAppURL "http://kcc.vulturis.eu/"
|
||||||
#define MyAppExeName "KCC.exe"
|
#define MyAppExeName "KCC.exe"
|
||||||
@@ -12,6 +12,7 @@ AppPublisher={#MyAppPublisher}
|
|||||||
AppPublisherURL={#MyAppURL}
|
AppPublisherURL={#MyAppURL}
|
||||||
AppSupportURL={#MyAppURL}
|
AppSupportURL={#MyAppURL}
|
||||||
AppUpdatesURL={#MyAppURL}
|
AppUpdatesURL={#MyAppURL}
|
||||||
|
AppCopyright=Copyright (C) 2012-2013 Ciro Mattia Gonano and Paweł Jastrzębski
|
||||||
DefaultDirName={pf}\{#MyAppName}
|
DefaultDirName={pf}\{#MyAppName}
|
||||||
DefaultGroupName={#MyAppName}
|
DefaultGroupName={#MyAppName}
|
||||||
AllowNoIcons=yes
|
AllowNoIcons=yes
|
||||||
@@ -28,6 +29,7 @@ UninstallDisplayName={#MyAppName}
|
|||||||
UninstallDisplayIcon={app}\{#MyAppExeName}
|
UninstallDisplayIcon={app}\{#MyAppExeName}
|
||||||
ChangesAssociations=True
|
ChangesAssociations=True
|
||||||
InfoAfterFile=other\InstallWarning.rtf
|
InfoAfterFile=other\InstallWarning.rtf
|
||||||
|
SignTool=SignTool /d $q{#MyAppName}$q /du $q{#MyAppURL}$q $f
|
||||||
|
|
||||||
[Languages]
|
[Languages]
|
||||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||||
@@ -63,6 +65,8 @@ Source: "build\exe.win-amd64-2.7\select.pyd"; DestDir: "{app}"; Flags: ignorever
|
|||||||
Source: "build\exe.win-amd64-2.7\sip.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: Is64BitInstallMode
|
Source: "build\exe.win-amd64-2.7\sip.pyd"; 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\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: "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
|
||||||
@@ -87,6 +91,8 @@ Source: "build\exe.win32-2.7\select.pyd"; DestDir: "{app}"; Flags: ignoreversion
|
|||||||
Source: "build\exe.win32-2.7\sip.pyd"; DestDir: "{app}"; Flags: ignoreversion; Check: not Is64BitInstallMode
|
Source: "build\exe.win32-2.7\sip.pyd"; 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\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: "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
|
||||||
@@ -100,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
|
||||||
|
|||||||
47
kcc.py
47
kcc.py
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python2
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
# PERFORMANCE OF THIS SOFTWARE.
|
# PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
__version__ = '3.5'
|
__version__ = '3.7.2'
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
@@ -26,26 +26,32 @@ __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!"
|
||||||
|
if sys.platform.startswith('linux'):
|
||||||
|
import Tkinter
|
||||||
|
import tkMessageBox
|
||||||
|
importRoot = Tkinter.Tk()
|
||||||
|
importRoot.withdraw()
|
||||||
|
tkMessageBox.showerror("KCC - Error", "PyQT4 is not installed!")
|
||||||
exit(1)
|
exit(1)
|
||||||
from kcc import KCC_gui
|
from kcc import KCC_gui
|
||||||
from multiprocessing import freeze_support
|
from multiprocessing import freeze_support
|
||||||
|
|
||||||
|
# OS specific PATH variable workarounds
|
||||||
if sys.platform.startswith('darwin'):
|
if sys.platform.startswith('darwin'):
|
||||||
# Workaround Finder-launched app PATH evaluation
|
if 'RESOURCEPATH' in os.environ:
|
||||||
os.environ['PATH'] = '/usr/local/bin:' + os.environ['PATH']
|
os.environ['PATH'] = os.environ['RESOURCEPATH'] + ':' + os.environ['PATH']
|
||||||
from kcc import KCC_ui_osx as KCC_ui
|
else:
|
||||||
elif sys.platform.startswith('linux'):
|
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/:' + os.environ['PATH']
|
||||||
from kcc import KCC_ui_linux as KCC_ui
|
elif sys.platform.startswith('win'):
|
||||||
else:
|
|
||||||
# Workaround for Windows file association mechanism
|
|
||||||
if getattr(sys, 'frozen', False):
|
if getattr(sys, 'frozen', False):
|
||||||
os.chdir(os.path.dirname(os.path.abspath(sys.executable)))
|
os.chdir(os.path.dirname(os.path.abspath(sys.executable)))
|
||||||
else:
|
else:
|
||||||
|
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/;' + os.environ['PATH']
|
||||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||||
from kcc import KCC_ui
|
|
||||||
|
|
||||||
|
|
||||||
# Implementing detection of already running KCC instance and forwarding argv to it
|
# Implementing detection of already running KCC instance and forwarding argv to it
|
||||||
@@ -89,10 +95,10 @@ class QApplicationMessaging(QtGui.QApplication):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
freeze_support()
|
freeze_support()
|
||||||
APP = QApplicationMessaging(sys.argv)
|
KCCAplication = QApplicationMessaging(sys.argv)
|
||||||
if APP.isRunning():
|
if KCCAplication.isRunning():
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
APP.sendMessage(sys.argv[1].decode(sys.getfilesystemencoding()))
|
KCCAplication.sendMessage(sys.argv[1].decode(sys.getfilesystemencoding()))
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
else:
|
else:
|
||||||
messageBox = QtGui.QMessageBox()
|
messageBox = QtGui.QMessageBox()
|
||||||
@@ -101,13 +107,8 @@ if APP.isRunning():
|
|||||||
messageBox.setWindowIcon(icon)
|
messageBox.setWindowIcon(icon)
|
||||||
QtGui.QMessageBox.critical(messageBox, 'KCC - Error', 'KCC is already running!', QtGui.QMessageBox.Ok)
|
QtGui.QMessageBox.critical(messageBox, 'KCC - Error', 'KCC is already running!', QtGui.QMessageBox.Ok)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
KCC = QtGui.QMainWindow()
|
KCCWindow = QtGui.QMainWindow()
|
||||||
UI = KCC_ui.Ui_KCC()
|
KCCUI = KCC_gui.KCCGUI(KCCAplication, KCCWindow)
|
||||||
UI.setupUi(KCC)
|
|
||||||
GUI = KCC_gui.Ui_KCC(UI, KCC, APP)
|
|
||||||
KCC.setWindowTitle("Kindle Comic Converter " + __version__)
|
|
||||||
KCC.show()
|
|
||||||
KCC.raise_()
|
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
GUI.handleMessage(sys.argv[1].decode(sys.getfilesystemencoding()))
|
KCCUI.handleMessage(sys.argv[1].decode(sys.getfilesystemencoding()))
|
||||||
sys.exit(APP.exec_())
|
sys.exit(KCCAplication.exec_())
|
||||||
|
|||||||
835
kcc/KCC_gui.py
835
kcc/KCC_gui.py
File diff suppressed because it is too large
Load Diff
173
kcc/KCC_rc.py
173
kcc/KCC_rc.py
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Resource object code
|
# Resource object code
|
||||||
#
|
#
|
||||||
# Created: N 6. paź 13:26:15 2013
|
# Created: Pt 27. gru 09:24:15 2013
|
||||||
# by: The Resource Compiler for PyQt (Qt v4.8.5)
|
# by: The Resource Compiler for PyQt (Qt v4.8.5)
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
@@ -8358,6 +8358,158 @@ qt_resource_data = "\
|
|||||||
\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 = "\
|
qt_resource_name = "\
|
||||||
@@ -8442,33 +8594,38 @@ qt_resource_name = "\
|
|||||||
\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 = "\
|
qt_resource_struct = "\
|
||||||
\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\
|
||||||
"
|
"
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'KCC.ui'
|
# Form implementation generated from reading ui file 'KCC.ui'
|
||||||
#
|
#
|
||||||
# Created: Sat Oct 12 11:28:00 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!
|
||||||
@@ -26,13 +26,12 @@ except AttributeError:
|
|||||||
class Ui_KCC(object):
|
class Ui_KCC(object):
|
||||||
def setupUi(self, KCC):
|
def setupUi(self, KCC):
|
||||||
KCC.setObjectName(_fromUtf8("KCC"))
|
KCC.setObjectName(_fromUtf8("KCC"))
|
||||||
KCC.resize(420, 380)
|
KCC.resize(420, 397)
|
||||||
KCC.setMinimumSize(QtCore.QSize(420, 380))
|
KCC.setMinimumSize(QtCore.QSize(420, 397))
|
||||||
KCC.setMaximumSize(QtCore.QSize(420, 380))
|
KCC.setMaximumSize(QtCore.QSize(420, 397))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(9)
|
font.setPointSize(9)
|
||||||
KCC.setFont(font)
|
KCC.setFont(font)
|
||||||
KCC.setFocusPolicy(QtCore.Qt.NoFocus)
|
|
||||||
icon = QtGui.QIcon()
|
icon = QtGui.QIcon()
|
||||||
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/Icon/icons/comic2ebook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/Icon/icons/comic2ebook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
KCC.setWindowIcon(icon)
|
KCC.setWindowIcon(icon)
|
||||||
@@ -247,6 +246,14 @@ class Ui_KCC(object):
|
|||||||
self.customHeight.setObjectName(_fromUtf8("customHeight"))
|
self.customHeight.setObjectName(_fromUtf8("customHeight"))
|
||||||
self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1)
|
self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1)
|
||||||
KCC.setCentralWidget(self.Form)
|
KCC.setCentralWidget(self.Form)
|
||||||
|
self.statusBar = QtGui.QStatusBar(KCC)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("MS Shell Dlg 2"))
|
||||||
|
font.setPointSize(8)
|
||||||
|
self.statusBar.setFont(font)
|
||||||
|
self.statusBar.setSizeGripEnabled(False)
|
||||||
|
self.statusBar.setObjectName(_fromUtf8("statusBar"))
|
||||||
|
KCC.setStatusBar(self.statusBar)
|
||||||
self.ActionBasic = QtGui.QAction(KCC)
|
self.ActionBasic = QtGui.QAction(KCC)
|
||||||
self.ActionBasic.setCheckable(True)
|
self.ActionBasic.setCheckable(True)
|
||||||
self.ActionBasic.setChecked(False)
|
self.ActionBasic.setChecked(False)
|
||||||
@@ -291,17 +298,15 @@ 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 page spliting.<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))
|
||||||
self.RotateBox.setText(_translate("KCC", "Horizontal mode", None))
|
self.RotateBox.setText(_translate("KCC", "Horizontal mode", None))
|
||||||
self.BasicModeButton.setText(_translate("KCC", "Basic", None))
|
self.BasicModeButton.setText(_translate("KCC", "Basic", None))
|
||||||
self.AdvModeButton.setText(_translate("KCC", "Advanced", None))
|
self.AdvModeButton.setText(_translate("KCC", "Advanced", None))
|
||||||
self.GammaLabel.setToolTip(_translate("KCC", "When converting color images setting this option to 1.0 MIGHT improve readability.", None))
|
|
||||||
self.GammaLabel.setText(_translate("KCC", "Gamma: Auto", None))
|
self.GammaLabel.setText(_translate("KCC", "Gamma: Auto", None))
|
||||||
self.GammaSlider.setToolTip(_translate("KCC", "<html><head/><body><p>When converting color images setting this option to 1.0 <span style=\" font-weight:600;\">might</span> improve readability.</p></body></html>", None))
|
self.ColorBox.setToolTip(_translate("KCC", "<html><head/><body><p>Don\'t convert images to grayscale.</p></body></html>", None))
|
||||||
self.ColorBox.setToolTip(_translate("KCC", "Do not convert images to grayscale.", None))
|
|
||||||
self.ColorBox.setText(_translate("KCC", "Color mode", None))
|
self.ColorBox.setText(_translate("KCC", "Color mode", None))
|
||||||
self.wLabel.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
self.wLabel.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||||
self.wLabel.setText(_translate("KCC", "Custom width: ", None))
|
self.wLabel.setText(_translate("KCC", "Custom width: ", None))
|
||||||
|
|||||||
@@ -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: Sat Oct 12 11:28:11 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!
|
||||||
@@ -26,13 +26,12 @@ except AttributeError:
|
|||||||
class Ui_KCC(object):
|
class Ui_KCC(object):
|
||||||
def setupUi(self, KCC):
|
def setupUi(self, KCC):
|
||||||
KCC.setObjectName(_fromUtf8("KCC"))
|
KCC.setObjectName(_fromUtf8("KCC"))
|
||||||
KCC.resize(420, 380)
|
KCC.resize(420, 397)
|
||||||
KCC.setMinimumSize(QtCore.QSize(420, 380))
|
KCC.setMinimumSize(QtCore.QSize(420, 397))
|
||||||
KCC.setMaximumSize(QtCore.QSize(420, 380))
|
KCC.setMaximumSize(QtCore.QSize(420, 397))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(9)
|
font.setPointSize(9)
|
||||||
KCC.setFont(font)
|
KCC.setFont(font)
|
||||||
KCC.setFocusPolicy(QtCore.Qt.NoFocus)
|
|
||||||
icon = QtGui.QIcon()
|
icon = QtGui.QIcon()
|
||||||
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/Icon/icons/comic2ebook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/Icon/icons/comic2ebook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
KCC.setWindowIcon(icon)
|
KCC.setWindowIcon(icon)
|
||||||
@@ -317,6 +316,14 @@ class Ui_KCC(object):
|
|||||||
self.customHeight.setObjectName(_fromUtf8("customHeight"))
|
self.customHeight.setObjectName(_fromUtf8("customHeight"))
|
||||||
self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1)
|
self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1)
|
||||||
KCC.setCentralWidget(self.Form)
|
KCC.setCentralWidget(self.Form)
|
||||||
|
self.statusBar = QtGui.QStatusBar(KCC)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
font.setPointSize(8)
|
||||||
|
self.statusBar.setFont(font)
|
||||||
|
self.statusBar.setSizeGripEnabled(False)
|
||||||
|
self.statusBar.setObjectName(_fromUtf8("statusBar"))
|
||||||
|
KCC.setStatusBar(self.statusBar)
|
||||||
self.ActionBasic = QtGui.QAction(KCC)
|
self.ActionBasic = QtGui.QAction(KCC)
|
||||||
self.ActionBasic.setCheckable(True)
|
self.ActionBasic.setCheckable(True)
|
||||||
self.ActionBasic.setChecked(False)
|
self.ActionBasic.setChecked(False)
|
||||||
@@ -360,17 +367,15 @@ 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 page spliting.<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))
|
||||||
self.RotateBox.setText(_translate("KCC", "Horizontal mode", None))
|
self.RotateBox.setText(_translate("KCC", "Horizontal mode", None))
|
||||||
self.BasicModeButton.setText(_translate("KCC", "Basic", None))
|
self.BasicModeButton.setText(_translate("KCC", "Basic", None))
|
||||||
self.AdvModeButton.setText(_translate("KCC", "Advanced", None))
|
self.AdvModeButton.setText(_translate("KCC", "Advanced", None))
|
||||||
self.GammaLabel.setToolTip(_translate("KCC", "<html><head/><body><p>When converting color images setting this option to 1.0 <span style=\" font-weight:600;\">might</span> improve readability.</p></body></html>", None))
|
|
||||||
self.GammaLabel.setText(_translate("KCC", "Gamma: Auto", None))
|
self.GammaLabel.setText(_translate("KCC", "Gamma: Auto", None))
|
||||||
self.GammaSlider.setToolTip(_translate("KCC", "<html><head/><body><p>When converting color images setting this option to 1.0 <span style=\" font-weight:600;\">might</span> improve readability.</p></body></html>", None))
|
self.ColorBox.setToolTip(_translate("KCC", "<html><head/><body><p>Don\'t convert images to grayscale.</p></body></html>", None))
|
||||||
self.ColorBox.setToolTip(_translate("KCC", "Do not convert images to grayscale.", None))
|
|
||||||
self.ColorBox.setText(_translate("KCC", "Color mode", None))
|
self.ColorBox.setText(_translate("KCC", "Color mode", None))
|
||||||
self.wLabel.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
self.wLabel.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||||
self.wLabel.setText(_translate("KCC", "Custom width: ", None))
|
self.wLabel.setText(_translate("KCC", "Custom width: ", None))
|
||||||
|
|||||||
@@ -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: Sat Oct 12 11:28:19 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!
|
||||||
@@ -26,13 +26,12 @@ except AttributeError:
|
|||||||
class Ui_KCC(object):
|
class Ui_KCC(object):
|
||||||
def setupUi(self, KCC):
|
def setupUi(self, KCC):
|
||||||
KCC.setObjectName(_fromUtf8("KCC"))
|
KCC.setObjectName(_fromUtf8("KCC"))
|
||||||
KCC.resize(420, 380)
|
KCC.resize(420, 397)
|
||||||
KCC.setMinimumSize(QtCore.QSize(420, 380))
|
KCC.setMinimumSize(QtCore.QSize(420, 397))
|
||||||
KCC.setMaximumSize(QtCore.QSize(420, 380))
|
KCC.setMaximumSize(QtCore.QSize(420, 397))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(9)
|
font.setPointSize(9)
|
||||||
KCC.setFont(font)
|
KCC.setFont(font)
|
||||||
KCC.setFocusPolicy(QtCore.Qt.NoFocus)
|
|
||||||
icon = QtGui.QIcon()
|
icon = QtGui.QIcon()
|
||||||
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/Icon/icons/comic2ebook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/Icon/icons/comic2ebook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
KCC.setWindowIcon(icon)
|
KCC.setWindowIcon(icon)
|
||||||
@@ -340,6 +339,14 @@ class Ui_KCC(object):
|
|||||||
self.customHeight.setObjectName(_fromUtf8("customHeight"))
|
self.customHeight.setObjectName(_fromUtf8("customHeight"))
|
||||||
self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1)
|
self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1)
|
||||||
KCC.setCentralWidget(self.Form)
|
KCC.setCentralWidget(self.Form)
|
||||||
|
self.statusBar = QtGui.QStatusBar(KCC)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Aharoni"))
|
||||||
|
font.setPointSize(8)
|
||||||
|
self.statusBar.setFont(font)
|
||||||
|
self.statusBar.setSizeGripEnabled(False)
|
||||||
|
self.statusBar.setObjectName(_fromUtf8("statusBar"))
|
||||||
|
KCC.setStatusBar(self.statusBar)
|
||||||
self.ActionBasic = QtGui.QAction(KCC)
|
self.ActionBasic = QtGui.QAction(KCC)
|
||||||
self.ActionBasic.setCheckable(True)
|
self.ActionBasic.setCheckable(True)
|
||||||
self.ActionBasic.setChecked(False)
|
self.ActionBasic.setChecked(False)
|
||||||
@@ -379,16 +386,14 @@ 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 page spliting.<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))
|
||||||
self.BasicModeButton.setText(_translate("KCC", "Basic", None))
|
self.BasicModeButton.setText(_translate("KCC", "Basic", None))
|
||||||
self.AdvModeButton.setText(_translate("KCC", "Advanced", None))
|
self.AdvModeButton.setText(_translate("KCC", "Advanced", None))
|
||||||
self.GammaLabel.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">When converting color images setting this option to 1.0 </span><span style=\" font-size:12pt; font-weight:600;\">might</span><span style=\" font-size:12pt;\"> improve readability.</span></p></body></html>", None))
|
|
||||||
self.GammaLabel.setText(_translate("KCC", "Gamma: Auto", None))
|
self.GammaLabel.setText(_translate("KCC", "Gamma: Auto", None))
|
||||||
self.GammaSlider.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">When converting color images setting this option to 1.0 </span><span style=\" font-size:12pt; font-weight:600;\">might</span><span style=\" font-size:12pt;\"> improve readability.</span></p></body></html>", None))
|
self.ColorBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Don\'t convert images to grayscale.</span></p></body></html>", None))
|
||||||
self.ColorBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Do not convert images to grayscale.</span></p></body></html>", None))
|
|
||||||
self.ColorBox.setText(_translate("KCC", "Color mode", None))
|
self.ColorBox.setText(_translate("KCC", "Color mode", None))
|
||||||
self.wLabel.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Resolution of target device.</span></p></body></html>", None))
|
self.wLabel.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Resolution of target device.</span></p></body></html>", None))
|
||||||
self.wLabel.setText(_translate("KCC", "Custom width: ", None))
|
self.wLabel.setText(_translate("KCC", "Custom width: ", None))
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
__version__ = '3.5'
|
__version__ = '3.7.2'
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
@@ -23,7 +23,21 @@ import os
|
|||||||
import zipfile
|
import zipfile
|
||||||
import rarfile
|
import rarfile
|
||||||
import locale
|
import locale
|
||||||
from subprocess import Popen, STDOUT, PIPE
|
from sys import platform
|
||||||
|
from subprocess import STDOUT, PIPE
|
||||||
|
try:
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
|
from psutil import Popen
|
||||||
|
except ImportError:
|
||||||
|
print "ERROR: Psutil is not installed!"
|
||||||
|
if platform.startswith('linux'):
|
||||||
|
import Tkinter
|
||||||
|
import tkMessageBox
|
||||||
|
importRoot = Tkinter.Tk()
|
||||||
|
importRoot.withdraw()
|
||||||
|
tkMessageBox.showerror("KCC - Error", "Psutil is not installed!")
|
||||||
|
exit(1)
|
||||||
|
from shutil import move
|
||||||
|
|
||||||
|
|
||||||
class CBxArchive:
|
class CBxArchive:
|
||||||
@@ -91,9 +105,10 @@ class CBxArchive:
|
|||||||
elif self.compressor == '7z':
|
elif self.compressor == '7z':
|
||||||
self.extractCB7(targetdir)
|
self.extractCB7(targetdir)
|
||||||
adir = os.listdir(targetdir)
|
adir = os.listdir(targetdir)
|
||||||
|
if 'ComicInfo.xml' in adir:
|
||||||
|
adir.remove('ComicInfo.xml')
|
||||||
if len(adir) == 1 and os.path.isdir(os.path.join(targetdir, adir[0])):
|
if len(adir) == 1 and os.path.isdir(os.path.join(targetdir, adir[0])):
|
||||||
import shutil
|
|
||||||
for f in os.listdir(os.path.join(targetdir, adir[0])):
|
for f in os.listdir(os.path.join(targetdir, adir[0])):
|
||||||
shutil.move(os.path.join(targetdir, adir[0], f), targetdir)
|
move(os.path.join(targetdir, adir[0], f), targetdir)
|
||||||
os.rmdir(os.path.join(targetdir, adir[0]))
|
os.rmdir(os.path.join(targetdir, adir[0]))
|
||||||
return targetdir
|
return targetdir
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python2
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
@@ -18,20 +18,45 @@
|
|||||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
# PERFORMANCE OF THIS SOFTWARE.
|
# PERFORMANCE OF THIS SOFTWARE.
|
||||||
#
|
#
|
||||||
__version__ = '3.5'
|
__version__ = '3.7.2'
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
|
||||||
import re
|
import re
|
||||||
import stat
|
import stat
|
||||||
import string
|
import string
|
||||||
from shutil import move, copyfile, copytree, rmtree, make_archive
|
import unicodedata
|
||||||
|
import zipfile
|
||||||
|
from tempfile import mkdtemp
|
||||||
|
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 uuid import uuid4
|
||||||
|
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:
|
||||||
@@ -49,6 +74,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:
|
||||||
@@ -86,7 +115,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:
|
||||||
@@ -102,9 +131,9 @@ def buildHTML(path, imgfile):
|
|||||||
elif noHorizontalPV and not noVerticalPV:
|
elif noHorizontalPV and not noVerticalPV:
|
||||||
if rotatedPage:
|
if rotatedPage:
|
||||||
if options.righttoleft:
|
if options.righttoleft:
|
||||||
order = [2, 1]
|
|
||||||
else:
|
|
||||||
order = [1, 2]
|
order = [1, 2]
|
||||||
|
else:
|
||||||
|
order = [2, 1]
|
||||||
else:
|
else:
|
||||||
order = [1, 2]
|
order = [1, 2]
|
||||||
boxes = ["BoxT", "BoxB"]
|
boxes = ["BoxT", "BoxB"]
|
||||||
@@ -126,35 +155,48 @@ def buildHTML(path, imgfile):
|
|||||||
"}'></a></div>\n"])
|
"}'></a></div>\n"])
|
||||||
if options.quality == 2:
|
if options.quality == 2:
|
||||||
imgfilepv = string.split(imgfile, ".")
|
imgfilepv = string.split(imgfile, ".")
|
||||||
imgfilepv[0] = imgfilepv[0].split("_kccx")[0].replace("_kccnh", "").replace("_kccnv", "")
|
imgfilepv[0] = imgfilepv[0].split("_kccxl")[0].replace("_kccnh", "").replace("_kccnv", "")
|
||||||
imgfilepv[0] += "_kcchq"
|
imgfilepv[0] += "_kcchq"
|
||||||
imgfilepv = string.join(imgfilepv, ".")
|
imgfilepv = string.join(imgfilepv, ".")
|
||||||
else:
|
else:
|
||||||
imgfilepv = imgfile
|
imgfilepv = imgfile
|
||||||
if "_kccx" in filename[0]:
|
if "_kccxl" in filename[0]:
|
||||||
xy = string.split(filename[0], "_kccx")[1]
|
borders = filename[0].split('_kccxl')[1]
|
||||||
x = string.split(xy, "_kccy")[0].lstrip("0")
|
borders = re.findall('[0-9]{1,6}', borders)
|
||||||
y = string.split(xy, "_kccy")[1].lstrip("0")
|
xl = borders[0].lstrip("0")
|
||||||
if x != "":
|
yu = borders[1].lstrip("0")
|
||||||
x = "-" + str(float(x)/100) + "%"
|
xr = borders[2].lstrip("0")
|
||||||
|
yd = borders[3].lstrip("0")
|
||||||
|
if xl != "":
|
||||||
|
xl = "-" + str(float(xl)/100) + "%"
|
||||||
else:
|
else:
|
||||||
x = "0%"
|
xl = "0%"
|
||||||
if y != "":
|
if xr != "":
|
||||||
y = "-" + str(float(y)/100) + "%"
|
xr = "-" + str(float(xr)/100) + "%"
|
||||||
else:
|
else:
|
||||||
y = "0%"
|
xr = "0%"
|
||||||
|
if yu != "":
|
||||||
|
yu = "-" + str(float(yu)/100) + "%"
|
||||||
|
else:
|
||||||
|
yu = "0%"
|
||||||
|
if yd != "":
|
||||||
|
yd = "-" + str(float(yd)/100) + "%"
|
||||||
|
else:
|
||||||
|
yd = "0%"
|
||||||
else:
|
else:
|
||||||
x = "0%"
|
xl = "0%"
|
||||||
y = "0%"
|
yu = "0%"
|
||||||
boxStyles = {"BoxTL": "left:" + x + ";top:" + y + ";",
|
xr = "0%"
|
||||||
"BoxTR": "right:" + x + ";top:" + y + ";",
|
yd = "0%"
|
||||||
"BoxBL": "left:" + x + ";bottom:" + y + ";",
|
boxStyles = {"BoxTL": "left:" + xl + ";top:" + yu + ";",
|
||||||
"BoxBR": "right:" + x + ";bottom:" + y + ";",
|
"BoxTR": "right:" + xr + ";top:" + yu + ";",
|
||||||
"BoxT": "left:-25%;top:" + y + ";",
|
"BoxBL": "left:" + xl + ";bottom:" + yd + ";",
|
||||||
"BoxB": "left:-25%;bottom:" + y + ";",
|
"BoxBR": "right:" + xr + ";bottom:" + yd + ";",
|
||||||
"BoxL": "left:" + x + ";top:-25%;",
|
"BoxT": "left:-25%;top:" + yu + ";",
|
||||||
"BoxR": "right:" + x + ";top:-25%;",
|
"BoxB": "left:-25%;bottom:" + yd + ";",
|
||||||
"BoxC": "right:-25%;top:-25%;"
|
"BoxL": "left:" + xl + ";top:-25%;",
|
||||||
|
"BoxR": "right:" + xr + ";top:-25%;",
|
||||||
|
"BoxC": "left:-25%;top:-25%;"
|
||||||
}
|
}
|
||||||
for box in boxes:
|
for box in boxes:
|
||||||
f.writelines(["<div id=\"" + box + "-Panel-Parent\" class=\"target-mag-parent\"><div id=\"",
|
f.writelines(["<div id=\"" + box + "-Panel-Parent\" class=\"target-mag-parent\"><div id=\"",
|
||||||
@@ -168,7 +210,6 @@ def buildHTML(path, imgfile):
|
|||||||
|
|
||||||
|
|
||||||
def buildNCX(dstdir, title, chapters):
|
def buildNCX(dstdir, title, chapters):
|
||||||
from uuid import uuid4
|
|
||||||
options.uuid = str(uuid4())
|
options.uuid = str(uuid4())
|
||||||
options.uuid = options.uuid.encode('utf-8')
|
options.uuid = options.uuid.encode('utf-8')
|
||||||
ncxfile = os.path.join(dstdir, 'OEBPS', 'toc.ncx')
|
ncxfile = os.path.join(dstdir, 'OEBPS', 'toc.ncx')
|
||||||
@@ -216,9 +257,10 @@ def buildOPF(dstdir, title, filelist, cover=None):
|
|||||||
"xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n",
|
"xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n",
|
||||||
"<dc:title>", title.encode('utf-8'), "</dc:title>\n",
|
"<dc:title>", title.encode('utf-8'), "</dc:title>\n",
|
||||||
"<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"])
|
||||||
"<dc:Creator>KCC</dc:Creator>\n",
|
for author in options.authors:
|
||||||
"<meta name=\"generator\" content=\"KindleComicConverter-" + __version__ + "\"/>\n",
|
f.writelines(["<dc:creator>", author.encode('utf-8'), "</dc:creator>\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",
|
||||||
"<meta name=\"cover\" content=\"cover\"/>\n",
|
"<meta name=\"cover\" content=\"cover\"/>\n",
|
||||||
@@ -264,9 +306,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",
|
||||||
@@ -292,17 +331,24 @@ def getImageFileName(imgfile):
|
|||||||
return filename
|
return filename
|
||||||
|
|
||||||
|
|
||||||
def applyImgOptimization(img, opt, overrideQuality=5):
|
def applyImgOptimization(img, opt, hqImage=None):
|
||||||
img.getImageFill(opt.webtoon)
|
if not img.fill:
|
||||||
|
img.getImageFill(opt.webtoon)
|
||||||
if not opt.webtoon:
|
if not opt.webtoon:
|
||||||
img.cropWhiteSpace(10.0)
|
img.cropWhiteSpace(10.0)
|
||||||
if opt.cutpagenumbers and not opt.webtoon:
|
if opt.cutpagenumbers and not opt.webtoon:
|
||||||
img.cutPageNumber()
|
img.cutPageNumber()
|
||||||
img.optimizeImage(opt.gamma)
|
img.optimizeImage(opt.gamma)
|
||||||
if overrideQuality != 5:
|
if hqImage:
|
||||||
img.resizeImage(opt.upscale, opt.stretch, opt.bordersColor, overrideQuality)
|
img.resizeImage(opt.upscale, opt.stretch, opt.bordersColor, 0)
|
||||||
|
img.calculateBorder(hqImage, True)
|
||||||
else:
|
else:
|
||||||
img.resizeImage(opt.upscale, opt.stretch, opt.bordersColor, opt.quality)
|
img.resizeImage(opt.upscale, opt.stretch, opt.bordersColor, opt.quality)
|
||||||
|
if opt.panelview:
|
||||||
|
if opt.quality == 0:
|
||||||
|
img.calculateBorder(img)
|
||||||
|
elif opt.quality == 1:
|
||||||
|
img.calculateBorder(img, True)
|
||||||
if opt.forcepng and not opt.forcecolor:
|
if opt.forcepng and not opt.forcecolor:
|
||||||
img.quantizeImage()
|
img.quantizeImage()
|
||||||
|
|
||||||
@@ -374,21 +420,21 @@ def fileImgProcess(work):
|
|||||||
applyImgOptimization(img1, opt)
|
applyImgOptimization(img1, opt)
|
||||||
img1.saveToDir(dirpath, opt.forcepng, opt.forcecolor, wipe)
|
img1.saveToDir(dirpath, opt.forcepng, opt.forcecolor, wipe)
|
||||||
if opt.quality == 2:
|
if opt.quality == 2:
|
||||||
img3 = image.ComicPage(split[0], opt.profileData)
|
img0b = image.ComicPage(split[0], opt.profileData, img0.fill)
|
||||||
applyImgOptimization(img3, opt, 0)
|
applyImgOptimization(img0b, opt, img0)
|
||||||
img3.saveToDir(dirpath, opt.forcepng, opt.forcecolor, True)
|
img0b.saveToDir(dirpath, opt.forcepng, opt.forcecolor, True)
|
||||||
img4 = image.ComicPage(split[1], opt.profileData)
|
img1b = image.ComicPage(split[1], opt.profileData, img1.fill)
|
||||||
applyImgOptimization(img4, opt, 0)
|
applyImgOptimization(img1b, opt, img1)
|
||||||
img4.saveToDir(dirpath, opt.forcepng, opt.forcecolor, True)
|
img1b.saveToDir(dirpath, opt.forcepng, opt.forcecolor, True)
|
||||||
else:
|
else:
|
||||||
applyImgOptimization(img, opt)
|
applyImgOptimization(img, opt)
|
||||||
img.saveToDir(dirpath, opt.forcepng, opt.forcecolor, wipe)
|
img.saveToDir(dirpath, opt.forcepng, opt.forcecolor, wipe)
|
||||||
if opt.quality == 2:
|
if opt.quality == 2:
|
||||||
img2 = image.ComicPage(os.path.join(dirpath, afile), opt.profileData)
|
img2 = image.ComicPage(os.path.join(dirpath, afile), opt.profileData, img.fill)
|
||||||
if img.rotated:
|
if img.rotated:
|
||||||
img2.image = img2.image.rotate(90)
|
img2.image = img2.image.rotate(90)
|
||||||
img2.rotated = True
|
img2.rotated = True
|
||||||
applyImgOptimization(img2, opt, 0)
|
applyImgOptimization(img2, opt, img)
|
||||||
img2.saveToDir(dirpath, opt.forcepng, opt.forcecolor, True)
|
img2.saveToDir(dirpath, opt.forcepng, opt.forcecolor, True)
|
||||||
except StandardError:
|
except StandardError:
|
||||||
return str(sys.exc_info()[1])
|
return str(sys.exc_info()[1])
|
||||||
@@ -535,7 +581,7 @@ def getWorkFolder(afile):
|
|||||||
if len(afile) > 240:
|
if len(afile) > 240:
|
||||||
raise UserWarning("Path is too long.")
|
raise UserWarning("Path is too long.")
|
||||||
if os.path.isdir(afile):
|
if os.path.isdir(afile):
|
||||||
workdir = tempfile.mkdtemp('', 'KCC-TMP-')
|
workdir = mkdtemp('', 'KCC-TMP-')
|
||||||
try:
|
try:
|
||||||
os.rmdir(workdir) # needed for copytree() fails if dst already exists
|
os.rmdir(workdir) # needed for copytree() fails if dst already exists
|
||||||
fullPath = os.path.join(workdir, 'OEBPS', 'Images')
|
fullPath = os.path.join(workdir, 'OEBPS', 'Images')
|
||||||
@@ -554,7 +600,7 @@ def getWorkFolder(afile):
|
|||||||
rmtree(path, True)
|
rmtree(path, True)
|
||||||
raise UserWarning("Failed to extract images.")
|
raise UserWarning("Failed to extract images.")
|
||||||
else:
|
else:
|
||||||
workdir = tempfile.mkdtemp('', 'KCC-TMP-')
|
workdir = mkdtemp('', 'KCC-TMP-')
|
||||||
cbx = cbxarchive.CBxArchive(afile)
|
cbx = cbxarchive.CBxArchive(afile)
|
||||||
if cbx.isCbxFile():
|
if cbx.isCbxFile():
|
||||||
try:
|
try:
|
||||||
@@ -573,9 +619,59 @@ def getWorkFolder(afile):
|
|||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def checkComicInfo(path, originalPath):
|
||||||
|
xmlPath = os.path.join(path, 'ComicInfo.xml')
|
||||||
|
options.authors = ['KCC']
|
||||||
|
titleSuffix = ''
|
||||||
|
if options.title == 'defaulttitle':
|
||||||
|
defaultTitle = True
|
||||||
|
if os.path.isdir(originalPath):
|
||||||
|
options.title = os.path.basename(originalPath)
|
||||||
|
else:
|
||||||
|
options.title = os.path.splitext(os.path.basename(originalPath))[0]
|
||||||
|
else:
|
||||||
|
defaultTitle = False
|
||||||
|
if os.path.exists(xmlPath):
|
||||||
|
try:
|
||||||
|
xml = parse(xmlPath)
|
||||||
|
except StandardError:
|
||||||
|
os.remove(xmlPath)
|
||||||
|
return
|
||||||
|
options.authors = []
|
||||||
|
if defaultTitle:
|
||||||
|
if len(xml.getElementsByTagName('Series')) != 0:
|
||||||
|
options.title = xml.getElementsByTagName('Series')[0].firstChild.nodeValue
|
||||||
|
if len(xml.getElementsByTagName('Volume')) != 0:
|
||||||
|
titleSuffix += ' V' + xml.getElementsByTagName('Volume')[0].firstChild.nodeValue
|
||||||
|
if len(xml.getElementsByTagName('Number')) != 0:
|
||||||
|
titleSuffix += ' #' + xml.getElementsByTagName('Number')[0].firstChild.nodeValue
|
||||||
|
options.title += titleSuffix
|
||||||
|
if len(xml.getElementsByTagName('Writer')) != 0:
|
||||||
|
authorsTemp = string.split(xml.getElementsByTagName('Writer')[0].firstChild.nodeValue, ', ')
|
||||||
|
for author in authorsTemp:
|
||||||
|
options.authors.append(author)
|
||||||
|
if len(xml.getElementsByTagName('Penciller')) != 0:
|
||||||
|
authorsTemp = string.split(xml.getElementsByTagName('Penciller')[0].firstChild.nodeValue, ', ')
|
||||||
|
for author in authorsTemp:
|
||||||
|
options.authors.append(author)
|
||||||
|
if len(xml.getElementsByTagName('Inker')) != 0:
|
||||||
|
authorsTemp = string.split(xml.getElementsByTagName('Inker')[0].firstChild.nodeValue, ', ')
|
||||||
|
for author in authorsTemp:
|
||||||
|
options.authors.append(author)
|
||||||
|
if len(xml.getElementsByTagName('Colorist')) != 0:
|
||||||
|
authorsTemp = string.split(xml.getElementsByTagName('Colorist')[0].firstChild.nodeValue, ', ')
|
||||||
|
for author in authorsTemp:
|
||||||
|
options.authors.append(author)
|
||||||
|
if len(options.authors) > 0:
|
||||||
|
options.authors = list(set(options.authors))
|
||||||
|
options.authors.sort()
|
||||||
|
else:
|
||||||
|
options.authors = ['KCC']
|
||||||
|
os.remove(xmlPath)
|
||||||
|
|
||||||
|
|
||||||
def slugify(value):
|
def slugify(value):
|
||||||
# Normalizes string, converts to lowercase, removes non-alpha characters and converts spaces to hyphens.
|
# Normalizes string, converts to lowercase, removes non-alpha characters and converts spaces to hyphens.
|
||||||
import unicodedata
|
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
#noinspection PyArgumentList
|
#noinspection PyArgumentList
|
||||||
value = unicodedata.normalize('NFKD', unicode(value, 'latin1')).encode('ascii', 'ignore')
|
value = unicodedata.normalize('NFKD', unicode(value, 'latin1')).encode('ascii', 'ignore')
|
||||||
@@ -614,9 +710,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)
|
||||||
|
|
||||||
@@ -631,7 +724,7 @@ def getDirectorySize(start_path='.'):
|
|||||||
|
|
||||||
|
|
||||||
def createNewTome():
|
def createNewTome():
|
||||||
tomePathRoot = tempfile.mkdtemp('', 'KCC-TMP-')
|
tomePathRoot = mkdtemp('', 'KCC-TMP-')
|
||||||
tomePath = os.path.join(tomePathRoot, 'OEBPS', 'Images')
|
tomePath = os.path.join(tomePathRoot, 'OEBPS', 'Images')
|
||||||
os.makedirs(tomePath)
|
os.makedirs(tomePath)
|
||||||
return tomePath, tomePathRoot
|
return tomePath, tomePathRoot
|
||||||
@@ -772,6 +865,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())
|
||||||
@@ -792,7 +919,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,
|
||||||
@@ -853,13 +980,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])
|
||||||
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:
|
||||||
@@ -879,19 +1006,13 @@ def main(argv=None, qtGUI=None):
|
|||||||
GUI.emit(QtCore.SIGNAL("progressBarTick"), 'status', 'Compressing CBZ files')
|
GUI.emit(QtCore.SIGNAL("progressBarTick"), 'status', 'Compressing CBZ files')
|
||||||
else:
|
else:
|
||||||
GUI.emit(QtCore.SIGNAL("progressBarTick"), 'status', 'Compressing EPUB files')
|
GUI.emit(QtCore.SIGNAL("progressBarTick"), 'status', 'Compressing EPUB files')
|
||||||
GUI.emit(QtCore.SIGNAL("progressBarTick"), len(tomes))
|
GUI.emit(QtCore.SIGNAL("progressBarTick"), len(tomes) + 1)
|
||||||
|
GUI.emit(QtCore.SIGNAL("progressBarTick"))
|
||||||
|
options.baseTitle = options.title
|
||||||
for tome in tomes:
|
for tome in tomes:
|
||||||
if GUI:
|
|
||||||
GUI.emit(QtCore.SIGNAL("progressBarTick"))
|
|
||||||
if os.path.isdir(args[0]):
|
|
||||||
barePath = os.path.basename(args[0])
|
|
||||||
else:
|
|
||||||
barePath = os.path.splitext(os.path.basename(args[0]))[0]
|
|
||||||
if len(tomes) > 1:
|
if len(tomes) > 1:
|
||||||
tomeNumber += 1
|
tomeNumber += 1
|
||||||
options.title = barePath + ' ' + str(tomeNumber)
|
options.title = options.baseTitle + ' [' + str(tomeNumber) + '/' + str(len(tomes)) + ']'
|
||||||
elif options.title == 'defaulttitle':
|
|
||||||
options.title = barePath
|
|
||||||
if options.cbzoutput:
|
if options.cbzoutput:
|
||||||
# if CBZ output wanted, compress all images and return filepath
|
# if CBZ output wanted, compress all images and return filepath
|
||||||
print "\nCreating CBZ file..."
|
print "\nCreating CBZ file..."
|
||||||
@@ -899,7 +1020,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)
|
||||||
@@ -908,9 +1029,11 @@ 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:
|
||||||
|
GUI.emit(QtCore.SIGNAL("progressBarTick"))
|
||||||
return filepath
|
return filepath
|
||||||
|
|
||||||
|
|
||||||
@@ -964,10 +1087,18 @@ 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!"
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
# CBZ files on Kindle DX/DXG support higher resolution
|
||||||
|
if options.profile == 'KDX' and options.cbzoutput:
|
||||||
|
options.customheight = 1200
|
||||||
# Override profile data
|
# Override profile data
|
||||||
if options.customwidth != 0 or options.customheight != 0:
|
if options.customwidth != 0 or options.customheight != 0:
|
||||||
X = image.ProfileData.Profiles[options.profile][1][0]
|
X = image.ProfileData.Profiles[options.profile][1][0]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python2
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
# PERFORMANCE OF THIS SOFTWARE.
|
# PERFORMANCE OF THIS SOFTWARE.
|
||||||
#
|
#
|
||||||
__version__ = '3.5'
|
__version__ = '3.7.2'
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
__copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@vulturis.eu>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
@@ -29,13 +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'):
|
||||||
|
import Tkinter
|
||||||
|
import tkMessageBox
|
||||||
|
importRoot = Tkinter.Tk()
|
||||||
|
importRoot.withdraw()
|
||||||
|
tkMessageBox.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'):
|
||||||
|
import Tkinter
|
||||||
|
import tkMessageBox
|
||||||
|
importRoot = Tkinter.Tk()
|
||||||
|
importRoot.withdraw()
|
||||||
|
tkMessageBox.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
|
||||||
@@ -57,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:
|
||||||
@@ -105,21 +170,6 @@ def splitImage(work):
|
|||||||
print ".",
|
print ".",
|
||||||
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
|
||||||
@@ -204,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")
|
||||||
@@ -212,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",
|
||||||
@@ -237,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:
|
||||||
@@ -245,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)
|
||||||
|
|||||||
303
kcc/image.py
303
kcc/image.py
@@ -21,14 +21,27 @@ __copyright__ = '2012-2013, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jas
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
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'):
|
||||||
|
import Tkinter
|
||||||
|
import tkMessageBox
|
||||||
|
importRoot = Tkinter.Tk()
|
||||||
|
importRoot.withdraw()
|
||||||
|
tkMessageBox.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'):
|
||||||
|
import Tkinter
|
||||||
|
import tkMessageBox
|
||||||
|
importRoot = Tkinter.Tk()
|
||||||
|
importRoot.withdraw()
|
||||||
|
tkMessageBox.showerror("KCC - Error", "Pillow 2.3.0 or newer is required!")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
@@ -94,76 +107,35 @@ 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):
|
def __init__(self, source, device, fill=None):
|
||||||
try:
|
try:
|
||||||
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.fill = None
|
self.noPV = None
|
||||||
|
self.purge = False
|
||||||
|
if fill:
|
||||||
|
self.fill = fill
|
||||||
|
else:
|
||||||
|
self.fill = None
|
||||||
|
|
||||||
def saveToDir(self, targetdir, forcepng, color, wipe):
|
def saveToDir(self, targetdir, forcepng, color, wipe):
|
||||||
try:
|
try:
|
||||||
@@ -176,24 +148,31 @@ 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 += "_kccx" + str(self.border[0]) + "_kccy" + str(self.border[1])
|
|
||||||
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))
|
||||||
|
|
||||||
def optimizeImage(self, gamma):
|
def optimizeImage(self, gamma):
|
||||||
if gamma < 0.1:
|
if gamma < 0.1:
|
||||||
gamma = self.gamma
|
gamma = self.gamma
|
||||||
|
if self.gamma != 1.0 and self.isImageColor(self.image):
|
||||||
|
gamma = 1.0
|
||||||
if gamma == 1.0:
|
if gamma == 1.0:
|
||||||
self.image = ImageOps.autocontrast(self.image)
|
self.image = ImageOps.autocontrast(self.image)
|
||||||
else:
|
else:
|
||||||
@@ -210,84 +189,88 @@ class ComicPage:
|
|||||||
# Quantize is deprecated but new function call it internally anyway...
|
# Quantize is deprecated but new function call it internally anyway...
|
||||||
self.image = self.image.quantize(palette=palImg)
|
self.image = self.image.quantize(palette=palImg)
|
||||||
|
|
||||||
|
def calculateBorderPercent(self, x, img, isWidth):
|
||||||
|
if isWidth:
|
||||||
|
return int(round(float(x)/float(img.image.size[0]), 4) * 10000 * 1.5)
|
||||||
|
else:
|
||||||
|
return int(round(float(x)/float(img.image.size[1]), 4) * 10000 * 1.5)
|
||||||
|
|
||||||
|
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':
|
||||||
|
# Only already saved files can have P mode. So we can break color quantization.
|
||||||
|
if sourceImage.image.mode == 'P':
|
||||||
|
sourceImage.image = sourceImage.image.convert('RGB')
|
||||||
|
border = ImageChops.invert(sourceImage.image).getbbox()
|
||||||
|
else:
|
||||||
|
border = sourceImage.image.getbbox()
|
||||||
|
if border is not None:
|
||||||
|
if isHQ:
|
||||||
|
multiplier = 1.0
|
||||||
|
else:
|
||||||
|
multiplier = 1.5
|
||||||
|
self.border = [self.calculateBorderPercent(border[0], sourceImage, True),
|
||||||
|
self.calculateBorderPercent(border[1], sourceImage, False),
|
||||||
|
self.calculateBorderPercent((sourceImage.image.size[0] - border[2]), sourceImage, True),
|
||||||
|
self.calculateBorderPercent((sourceImage.image.size[1] - border[3]), sourceImage, False)]
|
||||||
|
if int((border[2] - border[0]) * multiplier) < self.size[0]:
|
||||||
|
self.noHPV = True
|
||||||
|
if int((border[3] - border[1]) * multiplier) < self.size[1]:
|
||||||
|
self.noVPV = True
|
||||||
|
else:
|
||||||
|
self.border = [0, 0, 0, 0]
|
||||||
|
self.noHPV = True
|
||||||
|
self.noVPV = True
|
||||||
|
|
||||||
def resizeImage(self, upscale=False, stretch=False, bordersColor=None, qualityMode=0):
|
def resizeImage(self, upscale=False, stretch=False, bordersColor=None, qualityMode=0):
|
||||||
# High-quality downscaling filter
|
|
||||||
method = Image.ANTIALIAS
|
|
||||||
if bordersColor:
|
if bordersColor:
|
||||||
fill = bordersColor
|
fill = bordersColor
|
||||||
else:
|
else:
|
||||||
fill = self.fill
|
fill = self.fill
|
||||||
|
# Set target size
|
||||||
if qualityMode == 0:
|
if qualityMode == 0:
|
||||||
size = (self.size[0], self.size[1])
|
size = (self.size[0], self.size[1])
|
||||||
generateBorder = True
|
|
||||||
elif qualityMode == 1:
|
|
||||||
size = (self.panelviewsize[0], self.panelviewsize[1])
|
|
||||||
generateBorder = True
|
|
||||||
else:
|
else:
|
||||||
size = (self.panelviewsize[0], self.panelviewsize[1])
|
size = (self.panelviewsize[0], self.panelviewsize[1])
|
||||||
generateBorder = False
|
# If image is small and HQ mode is on we have to force upscaling. Otherwise non-zoomed image will be distorted
|
||||||
# If image is smaller than screen and upscale is off - Just expand it
|
if self.image.size[0] <= size[0] and self.image.size[1] <= size[1] and qualityMode == 1 and not stretch:
|
||||||
if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]:
|
upscale = True
|
||||||
if not upscale:
|
|
||||||
borderw = (self.size[0] - self.image.size[0]) / 2
|
|
||||||
borderh = (self.size[1] - self.image.size[1]) / 2
|
|
||||||
self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=fill)
|
|
||||||
if generateBorder:
|
|
||||||
if (self.image.size[0]-(2*borderw))*1.5 < self.size[0]:
|
|
||||||
self.noHPV = True
|
|
||||||
if (self.image.size[1]-(2*borderh))*1.5 < self.size[1]:
|
|
||||||
self.noVPV = True
|
|
||||||
self.border = [int(round(float(borderw)/float(self.image.size[0])*100, 2)*100*1.5),
|
|
||||||
int(round(float(borderh)/float(self.image.size[1])*100, 2)*100*1.5)]
|
|
||||||
return self.image
|
|
||||||
else:
|
|
||||||
# Cubic spline interpolation in a 4x4 environment
|
|
||||||
method = Image.BICUBIC
|
|
||||||
# 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]:
|
||||||
|
method = Image.BICUBIC
|
||||||
|
else:
|
||||||
|
method = Image.ANTIALIAS
|
||||||
self.image = self.image.resize(size, method)
|
self.image = self.image.resize(size, method)
|
||||||
if generateBorder:
|
return self.image
|
||||||
if fill == 'white':
|
# If image is smaller than target resolution and upscale is off - Just expand it by adding margins
|
||||||
border = ImageOps.invert(self.image).getbbox()
|
if self.image.size[0] <= size[0] and self.image.size[1] <= size[1] and not upscale:
|
||||||
else:
|
borderw = (size[0] - self.image.size[0]) / 2
|
||||||
border = self.image.getbbox()
|
borderh = (size[1] - self.image.size[1]) / 2
|
||||||
if border is not None:
|
# PV is disabled when source image is smaller than device screen and upscale is off - So we drop HQ image
|
||||||
if (border[2]-border[0])*1.5 < self.size[0]:
|
if qualityMode == 2 and self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]:
|
||||||
self.noHPV = True
|
self.purge = True
|
||||||
if (border[3]-border[1])*1.5 < self.size[1]:
|
self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=fill)
|
||||||
self.noVPV = True
|
# Border can't be float so sometimes image might be 1px too small/large
|
||||||
self.border = [int(round(float(border[0])/float(self.image.size[0])*100, 2)*100*1.5),
|
if self.image.size[0] != size[0] or self.image.size[1] != size[1]:
|
||||||
int(round(float(border[1])/float(self.image.size[1])*100, 2)*100*1.5)]
|
self.image = ImageOps.fit(self.image, size, method=Image.BICUBIC, centering=(0.5, 0.5))
|
||||||
else:
|
|
||||||
self.border = [0, 0]
|
|
||||||
self.noHPV = True
|
|
||||||
self.noVPV = True
|
|
||||||
return self.image
|
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=(diff / 2, 0), fill=fill)
|
self.image = ImageOps.expand(self.image, border=(diff / 2, 0), fill=fill)
|
||||||
elif (float(self.image.size[0]) / float(self.image.size[1])) > ratioDev:
|
elif (float(self.image.size[0]) / float(self.image.size[1])) > ratioDev:
|
||||||
diff = int(self.image.size[0] / ratioDev) - self.image.size[1]
|
diff = int(self.image.size[0] / ratioDev) - self.image.size[1]
|
||||||
self.image = ImageOps.expand(self.image, border=(0, diff / 2), fill=fill)
|
self.image = ImageOps.expand(self.image, border=(0, diff / 2), fill=fill)
|
||||||
|
if self.image.size[0] <= size[0] and self.image.size[1] <= size[1]:
|
||||||
|
method = Image.BICUBIC
|
||||||
|
else:
|
||||||
|
method = Image.ANTIALIAS
|
||||||
self.image = ImageOps.fit(self.image, size, method=method, centering=(0.5, 0.5))
|
self.image = ImageOps.fit(self.image, size, method=method, centering=(0.5, 0.5))
|
||||||
if generateBorder:
|
|
||||||
if fill == 'white':
|
|
||||||
border = ImageOps.invert(self.image).getbbox()
|
|
||||||
else:
|
|
||||||
border = self.image.getbbox()
|
|
||||||
if border is not None:
|
|
||||||
if (border[2]-border[0])*1.5 < self.size[0]:
|
|
||||||
self.noHPV = True
|
|
||||||
if (border[3]-border[1])*1.5 < self.size[1]:
|
|
||||||
self.noVPV = True
|
|
||||||
self.border = [int(round(float(border[0])/float(self.image.size[0])*100, 2)*100*1.5),
|
|
||||||
int(round(float(border[1])/float(self.image.size[1])*100, 2)*100*1.5)]
|
|
||||||
else:
|
|
||||||
self.border = [0, 0]
|
|
||||||
self.noHPV = True
|
|
||||||
self.noVPV = True
|
|
||||||
return self.image
|
return self.image
|
||||||
|
|
||||||
def splitPage(self, targetdir, righttoleft=False, rotate=False):
|
def splitPage(self, targetdir, righttoleft=False, rotate=False):
|
||||||
@@ -428,37 +411,61 @@ class ComicPage:
|
|||||||
RBGW.append(histogram[i] + histogram[256 + i] + histogram[512 + i])
|
RBGW.append(histogram[i] + histogram[256 + i] + histogram[512 + i])
|
||||||
white = 0
|
white = 0
|
||||||
black = 0
|
black = 0
|
||||||
for i in range(245, 256):
|
for i in range(251, 256):
|
||||||
white += RBGW[i]
|
white += RBGW[i]
|
||||||
for i in range(11):
|
for i in range(5):
|
||||||
black += RBGW[i]
|
black += RBGW[i]
|
||||||
if black > white and black > pixelCount*0.5:
|
if black > pixelCount*0.8 and white == 0:
|
||||||
return True
|
return 1
|
||||||
|
elif white > pixelCount*0.8 and black == 0:
|
||||||
|
return -1
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def getImageFill(self, isWebToon):
|
def getImageFill(self, webtoon):
|
||||||
fill = 0
|
fill = 0
|
||||||
if isWebToon or self.rotated:
|
if not webtoon and not self.rotated:
|
||||||
fill += self.getImageHistogram(self.image.crop((0, 0, self.image.size[0], 5)))
|
# Search for horizontal solid lines
|
||||||
fill += self.getImageHistogram(self.image.crop((0, self.image.size[1]-5, self.image.size[0],
|
startY = 0
|
||||||
self.image.size[1])))
|
while startY < self.image.size[1]:
|
||||||
|
checkSolid = self.getImageHistogram(self.image.crop((0, startY, self.image.size[0], startY+1)))
|
||||||
|
if checkSolid:
|
||||||
|
fill += checkSolid
|
||||||
|
startY += 1
|
||||||
else:
|
else:
|
||||||
fill += self.getImageHistogram(self.image.crop((0, 0, 5, self.image.size[1])))
|
# Search for vertical solid lines
|
||||||
fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, 0, self.image.size[0],
|
startX = 0
|
||||||
self.image.size[1])))
|
while startX < self.image.size[0]:
|
||||||
if fill == 2:
|
checkSolid = self.getImageHistogram(self.image.crop((startX, 0, startX+1, self.image.size[1])))
|
||||||
|
if checkSolid:
|
||||||
|
fill += checkSolid
|
||||||
|
startX += 1
|
||||||
|
if fill > 0:
|
||||||
self.fill = 'black'
|
self.fill = 'black'
|
||||||
elif fill == 0:
|
|
||||||
self.fill = 'white'
|
|
||||||
else:
|
else:
|
||||||
fill = 0
|
self.fill = 'white'
|
||||||
fill += self.getImageHistogram(self.image.crop((0, 0, 5, 5)))
|
|
||||||
fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, 0, self.image.size[0], 5)))
|
def isImageColor(self, image):
|
||||||
fill += self.getImageHistogram(self.image.crop((0, self.image.size[1]-5, 5, self.image.size[1])))
|
v = ImageStat.Stat(image).var
|
||||||
fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, self.image.size[1]-5,
|
isMonochromatic = reduce(lambda x, y: x and y < 0.005, v, True)
|
||||||
self.image.size[0], self.image.size[1])))
|
if isMonochromatic:
|
||||||
if fill > 1:
|
# Monochromatic
|
||||||
self.fill = 'black'
|
return False
|
||||||
|
else:
|
||||||
|
if len(v) == 3:
|
||||||
|
maxmin = abs(max(v) - min(v))
|
||||||
|
if maxmin > 1000:
|
||||||
|
# Color
|
||||||
|
return True
|
||||||
|
elif maxmin > 100:
|
||||||
|
# Probably color
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
# Grayscale
|
||||||
|
return False
|
||||||
|
elif len(v) == 1:
|
||||||
|
# Black and white
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
self.fill = 'white'
|
# Detection failed
|
||||||
|
return False
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# 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
|
||||||
@@ -15,10 +15,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
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
34
setup.py
34
setup.py
@@ -1,3 +1,4 @@
|
|||||||
|
#!/usr/bin/env python2
|
||||||
"""
|
"""
|
||||||
cx_Freeze build script for KCC.
|
cx_Freeze build script for KCC.
|
||||||
|
|
||||||
@@ -10,7 +11,7 @@ Usage (Windows):
|
|||||||
from sys import platform
|
from sys import platform
|
||||||
|
|
||||||
NAME = "KindleComicConverter"
|
NAME = "KindleComicConverter"
|
||||||
VERSION = "3.5"
|
VERSION = "3.7.2"
|
||||||
MAIN = "kcc.py"
|
MAIN = "kcc.py"
|
||||||
|
|
||||||
if platform == "darwin":
|
if platform == "darwin":
|
||||||
@@ -23,10 +24,11 @@ if platform == "darwin":
|
|||||||
argv_emulation=True,
|
argv_emulation=True,
|
||||||
iconfile='icons/comic2ebook.icns',
|
iconfile='icons/comic2ebook.icns',
|
||||||
includes=['PIL', 'sip', 'PyQt4', 'PyQt4.QtCore', 'PyQt4.QtGui', 'PyQt4.QtNetwork'],
|
includes=['PIL', 'sip', 'PyQt4', 'PyQt4.QtCore', 'PyQt4.QtGui', 'PyQt4.QtNetwork'],
|
||||||
|
qt_plugins=[],
|
||||||
excludes=['PyQt4.QtDeclarative', 'PyQt4.QtDesigner', 'PyQt4.QtHelp', 'PyQt4.QtMultimedia',
|
excludes=['PyQt4.QtDeclarative', 'PyQt4.QtDesigner', 'PyQt4.QtHelp', 'PyQt4.QtMultimedia',
|
||||||
'PyQt4.QtOpenGL', 'PyQt4.QtScript', 'PyQt4.QtScriptTools', 'PyQt4.QtSql', 'PyQt4.QtSvg',
|
'PyQt4.QtOpenGL', 'PyQt4.QtScript', 'PyQt4.QtScriptTools', 'PyQt4.QtSql', 'PyQt4.QtSvg',
|
||||||
'PyQt4.QtXmlPatterns', 'PyQt4.QtXml', 'PyQt4.QtWebKit', 'PyQt4.QtTest'],
|
'PyQt4.QtXmlPatterns', 'PyQt4.QtXml', 'PyQt4.QtWebKit', 'PyQt4.QtTest', 'Tkinter'],
|
||||||
resources=['LICENSE.txt', 'other/Additional-LICENSE.txt'],
|
resources=['LICENSE.txt', 'other/Additional-LICENSE.txt', 'other/unrar', 'other/7za'],
|
||||||
plist=dict(
|
plist=dict(
|
||||||
CFBundleName=NAME,
|
CFBundleName=NAME,
|
||||||
CFBundleShortVersionString=VERSION,
|
CFBundleShortVersionString=VERSION,
|
||||||
@@ -42,6 +44,10 @@ if platform == "darwin":
|
|||||||
CFBundleTypeRole='Viewer',
|
CFBundleTypeRole='Viewer',
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
LSMinimumSystemVersion='10.8.0',
|
||||||
|
LSEnvironment=dict(
|
||||||
|
PATH='/usr/local/bin:/usr/bin:/bin'
|
||||||
|
),
|
||||||
NSHumanReadableCopyright='ISC License (ISCL)'
|
NSHumanReadableCopyright='ISC License (ISCL)'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -55,7 +61,8 @@ elif platform == "win32":
|
|||||||
['other/UnRAR.exe', 'UnRAR.exe'],
|
['other/UnRAR.exe', 'UnRAR.exe'],
|
||||||
['other/7za.exe', '7za.exe'],
|
['other/7za.exe', '7za.exe'],
|
||||||
['other/Additional-LICENSE.txt', 'Additional-LICENSE.txt']
|
['other/Additional-LICENSE.txt', 'Additional-LICENSE.txt']
|
||||||
], "compressed": True}},
|
], "compressed": True,
|
||||||
|
"excludes": ['Tkinter']}},
|
||||||
executables=[Executable(MAIN,
|
executables=[Executable(MAIN,
|
||||||
base=base,
|
base=base,
|
||||||
targetName="KCC.exe",
|
targetName="KCC.exe",
|
||||||
@@ -65,18 +72,10 @@ elif platform == "win32":
|
|||||||
appendScriptToLibrary=False,
|
appendScriptToLibrary=False,
|
||||||
compress=True)])
|
compress=True)])
|
||||||
else:
|
else:
|
||||||
from cx_Freeze import setup, Executable
|
print 'Please use setup.sh to build Linux package.'
|
||||||
extra_options = dict(
|
exit()
|
||||||
options={"build_exe": {"include_files": ['LICENSE.txt',
|
|
||||||
['other/Additional-LICENSE.txt', 'Additional-LICENSE.txt']
|
|
||||||
], "compressed": True}},
|
|
||||||
executables=[Executable(MAIN,
|
|
||||||
icon="icons/comic2ebook.png",
|
|
||||||
copyDependentFiles=True,
|
|
||||||
appendScriptToExe=True,
|
|
||||||
appendScriptToLibrary=False,
|
|
||||||
compress=True)])
|
|
||||||
|
|
||||||
|
#noinspection PyUnboundLocalVariable
|
||||||
setup(
|
setup(
|
||||||
name=NAME,
|
name=NAME,
|
||||||
version=VERSION,
|
version=VERSION,
|
||||||
@@ -89,3 +88,8 @@ setup(
|
|||||||
packages=['kcc'], requires=['Pillow'],
|
packages=['kcc'], requires=['Pillow'],
|
||||||
**extra_options
|
**extra_options
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if platform == "darwin":
|
||||||
|
from os import chmod
|
||||||
|
chmod('dist/' + NAME + '.app/Contents/Resources/unrar', 0777)
|
||||||
|
chmod('dist/' + NAME + '.app/Contents/Resources/7za', 0777)
|
||||||
12
setup.sh
Normal file
12
setup.sh
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Linux Python package build script
|
||||||
|
|
||||||
|
VERSION="3.7.2"
|
||||||
|
|
||||||
|
cp kcc.py __main__.py
|
||||||
|
zip kcc.zip __main__.py kcc/*.py
|
||||||
|
echo "#!/usr/bin/env python2" > kcc-bin
|
||||||
|
cat kcc.zip >> kcc-bin
|
||||||
|
chmod +x kcc-bin
|
||||||
|
tar --xform s:^.*/:: --xform s/kcc-bin/kcc/ --xform s/comic2ebook/kcc/ -czf KindleComicConverter_linux_$VERSION.tar.gz kcc-bin LICENSE.txt icons/comic2ebook.png
|
||||||
|
rm __main__.py kcc.zip kcc-bin
|
||||||
Reference in New Issue
Block a user