mirror of
https://github.com/ciromattia/kcc
synced 2025-12-13 17:56:30 +00:00
Merge branch 'v3.3'
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -7,4 +7,5 @@ dist
|
|||||||
kindlegen*
|
kindlegen*
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
UnRAR.exe
|
/UnRAR.exe
|
||||||
|
/7za.exe
|
||||||
|
|||||||
812
KCC-Linux.ui
Normal file
812
KCC-Linux.ui
Normal file
@@ -0,0 +1,812 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>KCC</class>
|
||||||
|
<widget class="QMainWindow" name="KCC">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>420</width>
|
||||||
|
<height>380</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>420</width>
|
||||||
|
<height>380</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>420</width>
|
||||||
|
<height>380</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Kindle Comic Converter</string>
|
||||||
|
</property>
|
||||||
|
<property name="windowIcon">
|
||||||
|
<iconset resource="KCC.qrc">
|
||||||
|
<normaloff>:/Icon/icons/comic2ebook.png</normaloff>:/Icon/icons/comic2ebook.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="locale">
|
||||||
|
<locale language="C" country="AnyCountry"/>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="Form">
|
||||||
|
<widget class="QFrame" name="OptionsAdvanced">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>1</x>
|
||||||
|
<y>254</y>
|
||||||
|
<width>421</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>9</number>
|
||||||
|
</property>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QCheckBox" name="ProcessingBox">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Disable image optimizations.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>No optimisation</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QCheckBox" name="UpscaleBox">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=" font-weight:600; text-decoration: underline;">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=" font-weight:600; text-decoration: underline;">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Stretch/Upscale</string>
|
||||||
|
</property>
|
||||||
|
<property name="tristate">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QCheckBox" name="WebtoonBox">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Enable auto-splitting of webtoons like <span style=" font-style:italic;">Tower of God</span> or <span style=" font-style:italic;">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Webtoon mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="2">
|
||||||
|
<widget class="QCheckBox" name="NoDitheringBox">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Create PNG files instead JPEG.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PNG output</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QCheckBox" name="BorderBox">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - Autodetection<br/></span>Color of margins fill will be detected automatically.</p><p><span style=" font-weight:600; text-decoration: underline;">Indeterminate - White<br/></span>Margins will be filled with white color.</p><p><span style=" font-weight:600; text-decoration: underline;">Checked - Black<br/></span>Margins will be filled with black color.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>W/B margins</string>
|
||||||
|
</property>
|
||||||
|
<property name="tristate">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QCheckBox" name="NoRotateBox">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Disable splitting and rotation.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>No split/rotate</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QComboBox" name="DeviceBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>200</y>
|
||||||
|
<width>141</width>
|
||||||
|
<height>31</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Target device.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QComboBox" name="FormatBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>260</x>
|
||||||
|
<y>200</y>
|
||||||
|
<width>151</width>
|
||||||
|
<height>31</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Output format.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="ConvertButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>160</x>
|
||||||
|
<y>200</y>
|
||||||
|
<width>91</width>
|
||||||
|
<height>32</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Convert</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="KCC.qrc">
|
||||||
|
<normaloff>:/Other/icons/convert.png</normaloff>:/Other/icons/convert.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="DirectoryButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>160</y>
|
||||||
|
<width>141</width>
|
||||||
|
<height>32</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Add directory</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="KCC.qrc">
|
||||||
|
<normaloff>:/Other/icons/folder_new.png</normaloff>:/Other/icons/folder_new.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="FileButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>260</x>
|
||||||
|
<y>160</y>
|
||||||
|
<width>151</width>
|
||||||
|
<height>32</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Add file</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="KCC.qrc">
|
||||||
|
<normaloff>:/Other/icons/document_new.png</normaloff>:/Other/icons/document_new.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="ClearButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>160</x>
|
||||||
|
<y>160</y>
|
||||||
|
<width>91</width>
|
||||||
|
<height>32</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Clear list</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="KCC.qrc">
|
||||||
|
<normaloff>:/Other/icons/clear.png</normaloff>:/Other/icons/clear.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QFrame" name="OptionsBasic">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>1</x>
|
||||||
|
<y>230</y>
|
||||||
|
<width>421</width>
|
||||||
|
<height>41</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<widget class="QCheckBox" name="MangaBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>9</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>130</width>
|
||||||
|
<height>18</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Enable right-to-left reading.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Manga mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QCheckBox" name="QualityBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>282</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>135</width>
|
||||||
|
<height>18</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
</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;">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;">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 name="text">
|
||||||
|
<string>High/Ultra quality</string>
|
||||||
|
</property>
|
||||||
|
<property name="tristate">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QCheckBox" name="RotateBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>145</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>130</width>
|
||||||
|
<height>18</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Disable page spliting.<br/>They will be rotated instead.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Horizontal mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<zorder>RotateBox</zorder>
|
||||||
|
<zorder>MangaBox</zorder>
|
||||||
|
<zorder>QualityBox</zorder>
|
||||||
|
</widget>
|
||||||
|
<widget class="QListWidget" name="JobList">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>50</y>
|
||||||
|
<width>401</width>
|
||||||
|
<height>101</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
<italic>false</italic>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="showDropIndicator" stdset="0">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="selectionMode">
|
||||||
|
<enum>QAbstractItemView::NoSelection</enum>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>18</width>
|
||||||
|
<height>18</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="BasicModeButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>195</width>
|
||||||
|
<height>32</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Basic</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="AdvModeButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>217</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>195</width>
|
||||||
|
<height>32</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Advanced</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QFrame" name="OptionsAdvancedGamma">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>305</y>
|
||||||
|
<width>401</width>
|
||||||
|
<height>41</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<widget class="QLabel" name="GammaLabel">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>15</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>100</width>
|
||||||
|
<height>40</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
</font>
|
||||||
|
</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">
|
||||||
|
<string>Gamma: Auto</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QSlider" name="GammaSlider">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>110</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>275</width>
|
||||||
|
<height>22</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::ClickFocus</enum>
|
||||||
|
</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">
|
||||||
|
<number>500</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QProgressBar" name="ProgressBar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>401</width>
|
||||||
|
<height>31</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="format">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QFrame" name="OptionsExpert">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>1</x>
|
||||||
|
<y>337</y>
|
||||||
|
<width>421</width>
|
||||||
|
<height>41</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<widget class="QCheckBox" name="ColorBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>9</x>
|
||||||
|
<y>11</y>
|
||||||
|
<width>130</width>
|
||||||
|
<height>18</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Do not convert images to grayscale.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Color mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QFrame" name="OptionsExpertInternal">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>105</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>295</width>
|
||||||
|
<height>40</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="wLabel">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Resolution of target device.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Custom width: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="customWidth">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::ClickFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="acceptDrops">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Resolution of target device.</string>
|
||||||
|
</property>
|
||||||
|
<property name="inputMask">
|
||||||
|
<string>0000; </string>
|
||||||
|
</property>
|
||||||
|
<property name="maxLength">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QLabel" name="hLabel">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Resolution of target device.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Custom height: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QLineEdit" name="customHeight">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>DejaVu Sans</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::ClickFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="acceptDrops">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Resolution of target device.</string>
|
||||||
|
</property>
|
||||||
|
<property name="inputMask">
|
||||||
|
<string>0000; </string>
|
||||||
|
</property>
|
||||||
|
<property name="maxLength">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<zorder>OptionsAdvanced</zorder>
|
||||||
|
<zorder>DeviceBox</zorder>
|
||||||
|
<zorder>FormatBox</zorder>
|
||||||
|
<zorder>ConvertButton</zorder>
|
||||||
|
<zorder>DirectoryButton</zorder>
|
||||||
|
<zorder>FileButton</zorder>
|
||||||
|
<zorder>ClearButton</zorder>
|
||||||
|
<zorder>OptionsBasic</zorder>
|
||||||
|
<zorder>JobList</zorder>
|
||||||
|
<zorder>BasicModeButton</zorder>
|
||||||
|
<zorder>AdvModeButton</zorder>
|
||||||
|
<zorder>OptionsAdvancedGamma</zorder>
|
||||||
|
<zorder>OptionsExpert</zorder>
|
||||||
|
<zorder>ProgressBar</zorder>
|
||||||
|
</widget>
|
||||||
|
<action name="ActionBasic">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Basic</string>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font/>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="ActionAdvanced">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Advanced</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<tabstops>
|
||||||
|
<tabstop>DirectoryButton</tabstop>
|
||||||
|
<tabstop>FileButton</tabstop>
|
||||||
|
<tabstop>ConvertButton</tabstop>
|
||||||
|
<tabstop>ClearButton</tabstop>
|
||||||
|
</tabstops>
|
||||||
|
<resources>
|
||||||
|
<include location="KCC.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
96
KCC-OSX.ui
96
KCC-OSX.ui
@@ -47,7 +47,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>9</x>
|
<x>4</x>
|
||||||
<y>253</y>
|
<y>253</y>
|
||||||
<width>421</width>
|
<width>421</width>
|
||||||
<height>61</height>
|
<height>61</height>
|
||||||
@@ -55,6 +55,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>9</pointsize>
|
<pointsize>9</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
@@ -63,7 +64,8 @@
|
|||||||
<widget class="QCheckBox" name="ProcessingBox">
|
<widget class="QCheckBox" name="ProcessingBox">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>11</pointsize>
|
<family>Lucida Grande</family>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
@@ -81,14 +83,15 @@
|
|||||||
<widget class="QCheckBox" name="UpscaleBox">
|
<widget class="QCheckBox" name="UpscaleBox">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>11</pointsize>
|
<family>Lucida Grande</family>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=" font-weight:600; text-decoration: underline;">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=" font-weight:600; text-decoration: underline;">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html></string>
|
<string><html><head/><body><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Unchecked - Nothing<br/></span><span style=" font-size:12pt;">Images smaller than device resolution will not be resized.</span></p><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Indeterminate - Stretching<br/></span><span style=" font-size:12pt;">Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</span></p><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Checked - Upscaling<br/></span><span style=" font-size:12pt;">Images smaller than device resolution will be resized. Aspect ratio will be preserved.</span></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Stretch/Upscale</string>
|
<string>Stretch/Upscale</string>
|
||||||
@@ -102,14 +105,15 @@
|
|||||||
<widget class="QCheckBox" name="WebtoonBox">
|
<widget class="QCheckBox" name="WebtoonBox">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>11</pointsize>
|
<family>Lucida Grande</family>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p><span style=" font-weight:600;">EXPERIMENTAL!<br/></span>Enable auto-splitting of webtoons like <span style=" font-style:italic;">Tower of God</span> or <span style=" font-style:italic;">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html></string>
|
<string><html><head/><body><p><span style=" font-size:12pt;">Enable auto-splitting of webtoons like </span><span style=" font-size:12pt; font-style:italic;">Tower of God</span><span style=" font-size:12pt;"> or </span><span style=" font-size:12pt; font-style:italic;">Noblesse</span><span style=" font-size:12pt;">.<br/>Pages with a low width, high height and vertical panel flow.</span></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Webtoon mode</string>
|
<string>Webtoon mode</string>
|
||||||
@@ -120,14 +124,15 @@
|
|||||||
<widget class="QCheckBox" name="NoDitheringBox">
|
<widget class="QCheckBox" name="NoDitheringBox">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>11</pointsize>
|
<family>Lucida Grande</family>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<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;">Create PNG files instead JPEG.<br/></span><span style=" font-size:12pt; font-weight:600;">Only for non-Kindle devices!</span></p></body></html></string>
|
<string><html><head/><body><p><span style=" font-size:12pt;">Create PNG files instead JPEG.</span></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>PNG output</string>
|
<string>PNG output</string>
|
||||||
@@ -138,17 +143,21 @@
|
|||||||
<widget class="QCheckBox" name="BorderBox">
|
<widget class="QCheckBox" name="BorderBox">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>11</pointsize>
|
<family>Lucida Grande</family>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<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;">Fill space around images with black color.</span></p></body></html></string>
|
<string><html><head/><body><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Unchecked - Autodetection<br/></span><span style=" font-size:12pt;">Color of margins fill will be detected automatically.</span></p><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Indeterminate - White<br/></span><span style=" font-size:12pt;">Margins will be filled with white color.</span></p><p><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Checked - Black<br/></span><span style=" font-size:12pt;">Margins will be filled with black color.</span></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Black borders</string>
|
<string>W/B margins</string>
|
||||||
|
</property>
|
||||||
|
<property name="tristate">
|
||||||
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -156,7 +165,8 @@
|
|||||||
<widget class="QCheckBox" name="NoRotateBox">
|
<widget class="QCheckBox" name="NoRotateBox">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>11</pointsize>
|
<family>Lucida Grande</family>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
@@ -183,6 +193,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>11</pointsize>
|
<pointsize>11</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
@@ -190,7 +201,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Target device.</string>
|
<string><html><head/><body><p><span style=" font-size:12pt;">Target device.</span></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QComboBox" name="FormatBox">
|
<widget class="QComboBox" name="FormatBox">
|
||||||
@@ -204,6 +215,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>11</pointsize>
|
<pointsize>11</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
@@ -211,7 +223,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Output format.</string>
|
<string><html><head/><body><p><span style=" font-size:12pt;">Output format.</span></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QPushButton" name="ConvertButton">
|
<widget class="QPushButton" name="ConvertButton">
|
||||||
@@ -225,6 +237,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>11</pointsize>
|
<pointsize>11</pointsize>
|
||||||
<weight>75</weight>
|
<weight>75</weight>
|
||||||
<bold>true</bold>
|
<bold>true</bold>
|
||||||
@@ -252,6 +265,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>11</pointsize>
|
<pointsize>11</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
@@ -277,6 +291,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>11</pointsize>
|
<pointsize>11</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
@@ -302,6 +317,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>11</pointsize>
|
<pointsize>11</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
@@ -319,7 +335,7 @@
|
|||||||
<widget class="QFrame" name="OptionsBasic">
|
<widget class="QFrame" name="OptionsBasic">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>10</x>
|
<x>5</x>
|
||||||
<y>233</y>
|
<y>233</y>
|
||||||
<width>421</width>
|
<width>421</width>
|
||||||
<height>41</height>
|
<height>41</height>
|
||||||
@@ -327,7 +343,8 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>9</pointsize>
|
<family>Lucida Grande</family>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QCheckBox" name="MangaBox">
|
<widget class="QCheckBox" name="MangaBox">
|
||||||
@@ -341,7 +358,8 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>11</pointsize>
|
<family>Lucida Grande</family>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
@@ -359,20 +377,21 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>282</x>
|
<x>282</x>
|
||||||
<y>10</y>
|
<y>10</y>
|
||||||
<width>130</width>
|
<width>135</width>
|
||||||
<height>18</height>
|
<height>18</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>11</pointsize>
|
<family>Lucida Grande</family>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;">Unchecked - Normal quality mode<br/></span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-style:italic;">Use it when Panel View support is not needed.</span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;"><br/></span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">- Maximum quality when zoom is not enabled.<br/>- Poor quality when zoom is enabled.<br/>- Lowest file size.</span></p><p><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;">Indeterminate - High quality mode<br/></span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-style:italic;">Not zoomed image </span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; font-style:italic;">might </span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-style:italic;">be a little blurry.</span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;"><br/></span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">- Medium/High quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.</span></p><p><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;">Checked - Ultra quality mode<br/></span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-style:italic;">Maximum possible quality.</span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600; text-decoration: underline;"><br/></span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">- 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.</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>
|
||||||
@@ -392,7 +411,8 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>11</pointsize>
|
<family>Lucida Grande</family>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
@@ -420,6 +440,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>11</pointsize>
|
<pointsize>11</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
@@ -444,6 +465,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>12</pointsize>
|
<pointsize>12</pointsize>
|
||||||
<weight>50</weight>
|
<weight>50</weight>
|
||||||
<bold>false</bold>
|
<bold>false</bold>
|
||||||
@@ -467,6 +489,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>12</pointsize>
|
<pointsize>12</pointsize>
|
||||||
<weight>50</weight>
|
<weight>50</weight>
|
||||||
<bold>false</bold>
|
<bold>false</bold>
|
||||||
@@ -485,7 +508,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>10</x>
|
<x>5</x>
|
||||||
<y>303</y>
|
<y>303</y>
|
||||||
<width>401</width>
|
<width>401</width>
|
||||||
<height>41</height>
|
<height>41</height>
|
||||||
@@ -493,6 +516,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>9</pointsize>
|
<pointsize>9</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
@@ -507,13 +531,14 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>12</pointsize>
|
<pointsize>12</pointsize>
|
||||||
<weight>50</weight>
|
<weight>50</weight>
|
||||||
<bold>false</bold>
|
<bold>false</bold>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p><span style=" font-size:12pt;">When converting color images setting this option to 1.0 MIGHT improve readability.</span></p></body></html></string>
|
<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>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Gamma: Auto</string>
|
<string>Gamma: Auto</string>
|
||||||
@@ -524,10 +549,15 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>110</x>
|
<x>110</x>
|
||||||
<y>10</y>
|
<y>10</y>
|
||||||
<width>280</width>
|
<width>290</width>
|
||||||
<height>22</height>
|
<height>22</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::ClickFocus</enum>
|
<enum>Qt::ClickFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
@@ -556,6 +586,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>10</pointsize>
|
<pointsize>10</pointsize>
|
||||||
<weight>75</weight>
|
<weight>75</weight>
|
||||||
<bold>true</bold>
|
<bold>true</bold>
|
||||||
@@ -577,7 +608,7 @@
|
|||||||
<widget class="QFrame" name="OptionsExpert">
|
<widget class="QFrame" name="OptionsExpert">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>10</x>
|
<x>5</x>
|
||||||
<y>335</y>
|
<y>335</y>
|
||||||
<width>421</width>
|
<width>421</width>
|
||||||
<height>41</height>
|
<height>41</height>
|
||||||
@@ -585,6 +616,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>9</pointsize>
|
<pointsize>9</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
@@ -599,7 +631,8 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>11</pointsize>
|
<family>Lucida Grande</family>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
@@ -615,17 +648,23 @@
|
|||||||
<widget class="QFrame" name="OptionsExpertInternal">
|
<widget class="QFrame" name="OptionsExpertInternal">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>90</x>
|
<x>95</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>315</width>
|
<width>315</width>
|
||||||
<height>40</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="wLabel">
|
<widget class="QLabel" name="wLabel">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>12</pointsize>
|
<pointsize>12</pointsize>
|
||||||
<weight>50</weight>
|
<weight>50</weight>
|
||||||
<bold>false</bold>
|
<bold>false</bold>
|
||||||
@@ -655,6 +694,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>12</pointsize>
|
<pointsize>12</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
@@ -679,6 +719,7 @@
|
|||||||
<widget class="QLabel" name="hLabel">
|
<widget class="QLabel" name="hLabel">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>12</pointsize>
|
<pointsize>12</pointsize>
|
||||||
<weight>50</weight>
|
<weight>50</weight>
|
||||||
<bold>false</bold>
|
<bold>false</bold>
|
||||||
@@ -708,6 +749,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
|
<family>Lucida Grande</family>
|
||||||
<pointsize>12</pointsize>
|
<pointsize>12</pointsize>
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
|
|||||||
11
KCC.ui
11
KCC.ui
@@ -97,7 +97,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-weight:600;">EXPERIMENTAL!<br/></span>Enable auto-splitting of webtoons like <span style=" font-style:italic;">Tower of God</span> or <span style=" font-style:italic;">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html></string>
|
<string><html><head/><body><p>Enable auto-splitting of webtoons like <span style=" font-style:italic;">Tower of God</span> or <span style=" font-style:italic;">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Webtoon mode</string>
|
<string>Webtoon mode</string>
|
||||||
@@ -110,7 +110,7 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Create PNG files instead JPEG.<br/><span style=" font-weight:600;">Only for non-Kindle devices!</span></p></body></html></string>
|
<string><html><head/><body><p>Create PNG files instead JPEG.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>PNG output</string>
|
<string>PNG output</string>
|
||||||
@@ -123,10 +123,13 @@
|
|||||||
<enum>Qt::NoFocus</enum>
|
<enum>Qt::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Fill space around images with black color.</string>
|
<string><html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - Autodetection<br/></span>Color of margins fill will be detected automatically.</p><p><span style=" font-weight:600; text-decoration: underline;">Indeterminate - White<br/></span>Margins will be filled with white color.</p><p><span style=" font-weight:600; text-decoration: underline;">Checked - Black<br/></span>Margins will be filled with black color.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Black borders</string>
|
<string>W/B margins</string>
|
||||||
|
</property>
|
||||||
|
<property name="tristate">
|
||||||
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
44
README.md
44
README.md
@@ -30,11 +30,13 @@ You can find the latest released binary at the following links:
|
|||||||
- Folders
|
- Folders
|
||||||
- CBZ, ZIP
|
- CBZ, ZIP
|
||||||
- CBR, RAR *(With `unrar` executable)*
|
- CBR, RAR *(With `unrar` 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)*
|
||||||
|
|
||||||
### 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.
|
||||||
@@ -52,7 +54,7 @@ You can find the latest released binary at the following links:
|
|||||||
* Check our [wiki](https://github.com/ciromattia/kcc/wiki/Other-devices) for a list of tested Non-Kindle E-Readers.
|
* 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.
|
* The first image found will be set as the comic's cover.
|
||||||
* All files/directories will be added to EPUB in alphabetical order.
|
* All files/directories will be added to EPUB in alphabetical order.
|
||||||
* Output MOBI file should be uploaded via USB. Other methods (e.g. via Calibre) might corrupt it.
|
* Output MOBI file should be uploaded via USB. Other methods might corrupt it.
|
||||||
|
|
||||||
### GUI
|
### GUI
|
||||||
|
|
||||||
@@ -67,12 +69,10 @@ 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, K3, K4NT, K4T, KDX, KDXG, KHD, KF, KFHD, KFHD8, KFA) [Default=KHD]
|
Device profile (Choose one among K1, K2, K345, KDX, KDXG, KHD, KF, KFHD, KFHD8, KFHDX, KFHDX8, KFA) [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)
|
||||||
|
|
||||||
EXPERIMENTAL:
|
|
||||||
-w, --webtoon Webtoon processing mode
|
-w, --webtoon Webtoon processing mode
|
||||||
|
|
||||||
OUTPUT SETTINGS:
|
OUTPUT SETTINGS:
|
||||||
@@ -84,7 +84,8 @@ Options:
|
|||||||
--batchsplit Split output into multiple files
|
--batchsplit Split output into multiple files
|
||||||
|
|
||||||
PROCESSING:
|
PROCESSING:
|
||||||
--blackborders Use black borders instead of white ones
|
--blackborders Disable autodetection and force black borders
|
||||||
|
--whiteborders Disable autodetection and force white borders
|
||||||
--forcecolor Don't convert images to grayscale
|
--forcecolor Don't convert images to grayscale
|
||||||
--forcepng Create PNG files instead JPEG (For non-Kindle devices)
|
--forcepng Create PNG files instead JPEG (For non-Kindle devices)
|
||||||
--gamma=GAMMA Apply gamma correction to linearize the image [Default=Auto]
|
--gamma=GAMMA Apply gamma correction to linearize the image [Default=Auto]
|
||||||
@@ -129,22 +130,20 @@ This script born as a cross-platform alternative to `KindleComicParser` by **Dc5
|
|||||||
|
|
||||||
The app relies and includes the following scripts/binaries:
|
The app relies and includes the following scripts/binaries:
|
||||||
|
|
||||||
- `KindleStrip` script © 2010-2012 by **Paul Durrant** and released in public domain
|
- `KindleUnpack` script by Charles **M. Hannum, P. Durrant, K. Hendricks, S. Siebert, fandrieu, DiapDealer, nickredding**. Released with GPLv3 License.
|
||||||
([forum thread](http://www.mobileread.com/forums/showthread.php?t=96903))
|
- `rarfile.py` script © 2005-2011 **Marko Kreen** <markokr@gmail.com>. Released with ISC License.
|
||||||
- `rarfile.py` script © 2005-2011 **Marko Kreen** <markokr@gmail.com>, released with ISC License
|
- `image.py` class from **Alex Yatskov**'s [Mangle](http://foosoft.net/mangle/) with subsequent [proDOOMman](https://github.com/proDOOMman/Mangle)'s and [Birua](https://github.com/Birua/Mangle)'s patches.
|
||||||
- `image.py` class from **Alex Yatskov**'s [Mangle](http://foosoft.net/mangle/) with subsequent [proDOOMman](https://github.com/proDOOMman/Mangle)'s and [Birua](https://github.com/Birua/Mangle)'s patches
|
- Icon is by **Nikolay Verin** ([http://ncrow.deviantart.com/](http://ncrow.deviantart.com/)) and released under [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/) License.
|
||||||
- Icon is by **Nikolay Verin** ([http://ncrow.deviantart.com/](http://ncrow.deviantart.com/)) and released under [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/) License
|
|
||||||
|
|
||||||
## SAMPLE FILES CREATED BY KCC
|
## SAMPLE FILES CREATED BY KCC
|
||||||
* [Kindle Keyboard](http://kcc.vulturis.eu/Samples/Ubunchu!-K3.mobi)
|
|
||||||
* [Kindle DX](http://kcc.vulturis.eu/Samples/Ubunchu!-KDX.mobi)
|
|
||||||
* [Kindle DXG](http://kcc.vulturis.eu/Samples/Ubunchu!-KDXG.mobi)
|
|
||||||
* [Kindle Non-Touch](http://kcc.vulturis.eu/Samples/Ubunchu!-K4NT.mobi)
|
|
||||||
* [Kindle Touch](http://kcc.vulturis.eu/Samples/Ubunchu!-K4T.mobi)
|
|
||||||
* [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 DX/DXG](http://kcc.vulturis.eu/Samples/Ubunchu!-KDX.mobi)
|
||||||
* [Kindle Fire](http://kcc.vulturis.eu/Samples/Ubunchu!-KF.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 8.9"](http://kcc.vulturis.eu/Samples/Ubunchu!-KFHDX8.mobi)
|
||||||
|
|
||||||
## CHANGELOG
|
## CHANGELOG
|
||||||
####1.00
|
####1.00
|
||||||
@@ -255,8 +254,19 @@ The app relies and includes the following scripts/binaries:
|
|||||||
####3.2.1:
|
####3.2.1:
|
||||||
* Hotfixed crash occurring on OS with Russian locale
|
* Hotfixed crash occurring on OS with Russian locale
|
||||||
|
|
||||||
## KNOWN ISSUES
|
####3.3:
|
||||||
* Removing SRCS headers sometimes fail in 32bit enviroments. Due to memory limitations.
|
* Margins are now automatically omitted in Panel View mode
|
||||||
|
* Margin color fill is now autodetected
|
||||||
|
* Created MOBI files are not longer marked as _Personal_ on newer Kindle models
|
||||||
|
* Layout of panels in Panel View mode is now automatically adjusted to content
|
||||||
|
* Fixed Kindle 2/DX/DXG profiles - no more blank pages
|
||||||
|
* All Kindle Fire profiles now support hiqh quality Panel View
|
||||||
|
* Added support of 7z/CB7 files
|
||||||
|
* Added Kindle Fire HDX profile
|
||||||
|
* Support for Virtual Panel View was removed
|
||||||
|
* Profiles for Kindle Keyboard, Touch and Non-Touch are now merged
|
||||||
|
* Windows release is now bundled with UnRAR and 7za
|
||||||
|
* Small GUI tweaks
|
||||||
|
|
||||||
## COPYRIGHT
|
## COPYRIGHT
|
||||||
|
|
||||||
|
|||||||
10
kcc.py
10
kcc.py
@@ -1,7 +1,8 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
|
# Copyright (c) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -17,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.2.1'
|
__version__ = '3.3'
|
||||||
__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'
|
||||||
@@ -32,9 +33,10 @@ except ImportError:
|
|||||||
exit(1)
|
exit(1)
|
||||||
from kcc import KCC_gui
|
from kcc import KCC_gui
|
||||||
from multiprocessing import freeze_support
|
from multiprocessing import freeze_support
|
||||||
|
if sys.platform.startswith('darwin'):
|
||||||
if sys.platform == 'darwin':
|
|
||||||
from kcc import KCC_ui_osx as KCC_ui
|
from kcc import KCC_ui_osx as KCC_ui
|
||||||
|
elif sys.platform.startswith('linux'):
|
||||||
|
from kcc import KCC_ui_linux as KCC_ui
|
||||||
else:
|
else:
|
||||||
from kcc import KCC_ui
|
from kcc import KCC_ui
|
||||||
|
|
||||||
|
|||||||
121
kcc/KCC_gui.py
121
kcc/KCC_gui.py
@@ -1,7 +1,8 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
|
# Copyright (c) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -17,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.2.1'
|
__version__ = '3.3'
|
||||||
__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,7 +30,7 @@ import traceback
|
|||||||
import urllib2
|
import urllib2
|
||||||
import time
|
import time
|
||||||
import comic2ebook
|
import comic2ebook
|
||||||
import kindlestrip
|
import kindlesplit
|
||||||
from image import ProfileData
|
from image import ProfileData
|
||||||
from subprocess import call, Popen, STDOUT, PIPE
|
from subprocess import call, Popen, STDOUT, PIPE
|
||||||
from PyQt4 import QtGui, QtCore
|
from PyQt4 import QtGui, QtCore
|
||||||
@@ -98,6 +99,10 @@ class WorkerThread(QtCore.QThread):
|
|||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
QtCore.QThread.__init__(self)
|
QtCore.QThread.__init__(self)
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
self.conversionAlive = False
|
||||||
|
self.errors = False
|
||||||
|
self.kindlegenErrorCode = 0
|
||||||
|
self.kindlegenError = None
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.wait()
|
self.wait()
|
||||||
@@ -111,7 +116,6 @@ class WorkerThread(QtCore.QThread):
|
|||||||
self.emit(QtCore.SIGNAL("addMessage"), '<b>Conversion interrupted.</b>', 'error')
|
self.emit(QtCore.SIGNAL("addMessage"), '<b>Conversion interrupted.</b>', 'error')
|
||||||
self.emit(QtCore.SIGNAL("modeConvert"), True)
|
self.emit(QtCore.SIGNAL("modeConvert"), True)
|
||||||
|
|
||||||
# noinspection PyUnboundLocalVariable
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.emit(QtCore.SIGNAL("modeConvert"), False)
|
self.emit(QtCore.SIGNAL("modeConvert"), False)
|
||||||
profile = ProfileData.ProfileLabels[str(GUI.DeviceBox.currentText())]
|
profile = ProfileData.ProfileLabels[str(GUI.DeviceBox.currentText())]
|
||||||
@@ -130,12 +134,14 @@ class WorkerThread(QtCore.QThread):
|
|||||||
argv.append("--noprocessing")
|
argv.append("--noprocessing")
|
||||||
if GUI.NoRotateBox.isChecked():
|
if GUI.NoRotateBox.isChecked():
|
||||||
argv.append("--nosplitrotate")
|
argv.append("--nosplitrotate")
|
||||||
if GUI.BorderBox.isChecked():
|
|
||||||
argv.append("--blackborders")
|
|
||||||
if GUI.UpscaleBox.checkState() == 1:
|
if GUI.UpscaleBox.checkState() == 1:
|
||||||
argv.append("--stretch")
|
argv.append("--stretch")
|
||||||
elif GUI.UpscaleBox.checkState() == 2:
|
elif GUI.UpscaleBox.checkState() == 2:
|
||||||
argv.append("--upscale")
|
argv.append("--upscale")
|
||||||
|
if GUI.BorderBox.checkState() == 1:
|
||||||
|
argv.append("--whiteborders")
|
||||||
|
elif GUI.BorderBox.checkState() == 2:
|
||||||
|
argv.append("--blackborders")
|
||||||
if GUI.NoDitheringBox.isChecked():
|
if GUI.NoDitheringBox.isChecked():
|
||||||
argv.append("--forcepng")
|
argv.append("--forcepng")
|
||||||
if GUI.WebtoonBox.isChecked():
|
if GUI.WebtoonBox.isChecked():
|
||||||
@@ -209,7 +215,8 @@ class WorkerThread(QtCore.QThread):
|
|||||||
try:
|
try:
|
||||||
self.kindlegenErrorCode = 0
|
self.kindlegenErrorCode = 0
|
||||||
if os.path.getsize(item) < 367001600:
|
if os.path.getsize(item) < 367001600:
|
||||||
output = Popen('kindlegen -locale en "' + item + '"', stdout=PIPE, stderr=STDOUT, shell=True)
|
output = Popen('kindlegen -locale en "' + item + '"', stdout=PIPE, stderr=STDOUT,
|
||||||
|
shell=True)
|
||||||
for line in output.stdout:
|
for line in output.stdout:
|
||||||
# ERROR: Generic error
|
# ERROR: Generic error
|
||||||
if "Error(" in line:
|
if "Error(" in line:
|
||||||
@@ -242,23 +249,27 @@ class WorkerThread(QtCore.QThread):
|
|||||||
True)
|
True)
|
||||||
else:
|
else:
|
||||||
self.emit(QtCore.SIGNAL("addMessage"), 'Creating MOBI file... Done!', 'info', True)
|
self.emit(QtCore.SIGNAL("addMessage"), 'Creating MOBI file... Done!', 'info', True)
|
||||||
self.emit(QtCore.SIGNAL("addMessage"), 'Removing SRCS header...', 'info')
|
self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI file...', 'info')
|
||||||
os.remove(item)
|
os.remove(item)
|
||||||
mobiPath = item.replace('.epub', '.mobi')
|
mobiPath = item.replace('.epub', '.mobi')
|
||||||
shutil.move(mobiPath, mobiPath + '_tostrip')
|
shutil.move(mobiPath, mobiPath + '_toclean')
|
||||||
try:
|
try:
|
||||||
kindlestrip.main((mobiPath + '_tostrip', mobiPath))
|
if profile in ['K345', 'KHD', 'KF', 'KFHD', 'KFHD8', 'KFHDX', 'KFHDX8', 'KFA']:
|
||||||
|
newKindle = True
|
||||||
|
else:
|
||||||
|
newKindle = False
|
||||||
|
mobisplit = kindlesplit.mobi_split(mobiPath + '_toclean', newKindle)
|
||||||
|
open(mobiPath, 'wb').write(mobisplit.getResult())
|
||||||
except Exception:
|
except Exception:
|
||||||
self.errors = True
|
self.errors = True
|
||||||
if not self.errors:
|
if not self.errors:
|
||||||
os.remove(mobiPath + '_tostrip')
|
os.remove(mobiPath + '_toclean')
|
||||||
self.emit(QtCore.SIGNAL("addMessage"), 'Removing SRCS header... Done!', 'info', True)
|
self.emit(QtCore.SIGNAL("addMessage"), 'Cleaning MOBI file... Done!', 'info', True)
|
||||||
else:
|
else:
|
||||||
shutil.move(mobiPath + '_tostrip', mobiPath)
|
os.remove(mobiPath + '_toclean')
|
||||||
|
os.remove(mobiPath)
|
||||||
self.emit(QtCore.SIGNAL("addMessage"),
|
self.emit(QtCore.SIGNAL("addMessage"),
|
||||||
'KindleStrip failed to remove SRCS header!', 'warning')
|
'KindleUnpack failed to clean MOBI file!', 'error')
|
||||||
self.emit(QtCore.SIGNAL("addMessage"),
|
|
||||||
'MOBI file will work correctly but it will be highly oversized.', 'warning')
|
|
||||||
else:
|
else:
|
||||||
epubSize = (os.path.getsize(item))/1024/1024
|
epubSize = (os.path.getsize(item))/1024/1024
|
||||||
os.remove(item)
|
os.remove(item)
|
||||||
@@ -318,11 +329,19 @@ class Ui_KCC(object):
|
|||||||
self.needClean = False
|
self.needClean = False
|
||||||
GUI.JobList.clear()
|
GUI.JobList.clear()
|
||||||
if self.UnRAR:
|
if self.UnRAR:
|
||||||
fnames = QtGui.QFileDialog.getOpenFileNames(MainWindow, 'Select file', self.lastPath,
|
if self.sevenza:
|
||||||
'*.cbz *.cbr *.zip *.rar *.pdf')
|
fnames = QtGui.QFileDialog.getOpenFileNames(MainWindow, 'Select file', self.lastPath,
|
||||||
|
'*.cbz *.cbr *.cb7 *.zip *.rar *.7z *.pdf')
|
||||||
|
else:
|
||||||
|
fnames = QtGui.QFileDialog.getOpenFileNames(MainWindow, 'Select file', self.lastPath,
|
||||||
|
'*.cbz *.cbr *.zip *.rar *.pdf')
|
||||||
else:
|
else:
|
||||||
fnames = QtGui.QFileDialog.getOpenFileNames(MainWindow, 'Select file', self.lastPath,
|
if self.sevenza:
|
||||||
'*.cbz *.zip *.pdf')
|
fnames = QtGui.QFileDialog.getOpenFileNames(MainWindow, 'Select file', self.lastPath,
|
||||||
|
'*.cbz *.cb7 *.zip *.7z *.pdf')
|
||||||
|
else:
|
||||||
|
fnames = QtGui.QFileDialog.getOpenFileNames(MainWindow, 'Select file', self.lastPath,
|
||||||
|
'*.cbz *.zip *.pdf')
|
||||||
# Lame UTF-8 security measure
|
# Lame UTF-8 security measure
|
||||||
for fname in fnames:
|
for fname in fnames:
|
||||||
try:
|
try:
|
||||||
@@ -438,13 +457,13 @@ class Ui_KCC(object):
|
|||||||
GUI.NoRotateBox.setChecked(True)
|
GUI.NoRotateBox.setChecked(True)
|
||||||
GUI.QualityBox.setEnabled(False)
|
GUI.QualityBox.setEnabled(False)
|
||||||
GUI.QualityBox.setChecked(False)
|
GUI.QualityBox.setChecked(False)
|
||||||
GUI.BorderBox.setEnabled(False)
|
GUI.MangaBox.setEnabled(False)
|
||||||
GUI.BorderBox.setChecked(False)
|
GUI.MangaBox.setChecked(False)
|
||||||
self.addMessage('If images are color setting <i>Gamma</i> to 1.0 is recommended.', 'info')
|
self.addMessage('If images are color setting <i>Gamma</i> to 1.0 is recommended.', 'info')
|
||||||
else:
|
else:
|
||||||
GUI.NoRotateBox.setEnabled(True)
|
GUI.NoRotateBox.setEnabled(True)
|
||||||
GUI.QualityBox.setEnabled(True)
|
GUI.QualityBox.setEnabled(True)
|
||||||
GUI.BorderBox.setEnabled(True)
|
GUI.MangaBox.setEnabled(True)
|
||||||
|
|
||||||
def toggleNoSplitRotate(self, value):
|
def toggleNoSplitRotate(self, value):
|
||||||
if value:
|
if value:
|
||||||
@@ -454,13 +473,13 @@ class Ui_KCC(object):
|
|||||||
GUI.RotateBox.setEnabled(True)
|
GUI.RotateBox.setEnabled(True)
|
||||||
|
|
||||||
def changeDevice(self, value):
|
def changeDevice(self, value):
|
||||||
if value == 12:
|
if value == 9:
|
||||||
GUI.BasicModeButton.setEnabled(False)
|
GUI.BasicModeButton.setEnabled(False)
|
||||||
GUI.AdvModeButton.setEnabled(False)
|
GUI.AdvModeButton.setEnabled(False)
|
||||||
self.addMessage('<a href="https://github.com/ciromattia/kcc/wiki/NonKindle-devices">'
|
self.addMessage('<a href="https://github.com/ciromattia/kcc/wiki/NonKindle-devices">'
|
||||||
'List of supported Non-Kindle devices</a>', 'info')
|
'List of supported Non-Kindle devices</a>', 'info')
|
||||||
self.modeExpert()
|
self.modeExpert()
|
||||||
elif value == 11:
|
elif value == 8:
|
||||||
GUI.BasicModeButton.setEnabled(False)
|
GUI.BasicModeButton.setEnabled(False)
|
||||||
GUI.AdvModeButton.setEnabled(False)
|
GUI.AdvModeButton.setEnabled(False)
|
||||||
self.modeExpert(True)
|
self.modeExpert(True)
|
||||||
@@ -468,11 +487,17 @@ class Ui_KCC(object):
|
|||||||
GUI.BasicModeButton.setEnabled(True)
|
GUI.BasicModeButton.setEnabled(True)
|
||||||
GUI.AdvModeButton.setEnabled(True)
|
GUI.AdvModeButton.setEnabled(True)
|
||||||
self.modeBasic()
|
self.modeBasic()
|
||||||
if value in [0, 1, 5, 6, 7, 8, 9, 12]:
|
if value in [9, 11, 12, 13, 14]:
|
||||||
GUI.QualityBox.setCheckState(0)
|
GUI.QualityBox.setCheckState(0)
|
||||||
GUI.QualityBox.setEnabled(False)
|
GUI.QualityBox.setEnabled(False)
|
||||||
else:
|
else:
|
||||||
GUI.QualityBox.setEnabled(True)
|
if not GUI.WebtoonBox.isChecked():
|
||||||
|
GUI.QualityBox.setEnabled(True)
|
||||||
|
if value in [3, 4, 5, 6, 8, 15]:
|
||||||
|
GUI.NoDitheringBox.setCheckState(0)
|
||||||
|
GUI.NoDitheringBox.setEnabled(False)
|
||||||
|
else:
|
||||||
|
GUI.NoDitheringBox.setEnabled(True)
|
||||||
|
|
||||||
def stripTags(self, html):
|
def stripTags(self, html):
|
||||||
s = HTMLStripper()
|
s = HTMLStripper()
|
||||||
@@ -544,10 +569,12 @@ class Ui_KCC(object):
|
|||||||
event.ignore()
|
event.ignore()
|
||||||
if not GUI.ConvertButton.isEnabled():
|
if not GUI.ConvertButton.isEnabled():
|
||||||
event.ignore()
|
event.ignore()
|
||||||
|
self.settings.setValue('settingsVersion', __version__)
|
||||||
self.settings.setValue('lastPath', self.lastPath)
|
self.settings.setValue('lastPath', self.lastPath)
|
||||||
self.settings.setValue('lastDevice', GUI.DeviceBox.currentIndex())
|
self.settings.setValue('lastDevice', GUI.DeviceBox.currentIndex())
|
||||||
self.settings.setValue('currentFormat', GUI.FormatBox.currentIndex())
|
self.settings.setValue('currentFormat', GUI.FormatBox.currentIndex())
|
||||||
self.settings.setValue('currentMode', self.currentMode)
|
self.settings.setValue('currentMode', self.currentMode)
|
||||||
|
self.settings.setValue('firstStart', False)
|
||||||
self.settings.setValue('options', QtCore.QVariant({'MangaBox': GUI.MangaBox.checkState(),
|
self.settings.setValue('options', QtCore.QVariant({'MangaBox': GUI.MangaBox.checkState(),
|
||||||
'RotateBox': GUI.RotateBox.checkState(),
|
'RotateBox': GUI.RotateBox.checkState(),
|
||||||
'QualityBox': GUI.QualityBox.checkState(),
|
'QualityBox': GUI.QualityBox.checkState(),
|
||||||
@@ -567,22 +594,33 @@ class Ui_KCC(object):
|
|||||||
global GUI, MainWindow
|
global GUI, MainWindow
|
||||||
GUI = UI
|
GUI = UI
|
||||||
MainWindow = KCC
|
MainWindow = KCC
|
||||||
profiles = sorted(ProfileData.ProfileLabels.iterkeys())
|
# User settings will be reverted to default ones if were created in one of the following versions
|
||||||
|
# Empty string cover all versions before this system was implemented
|
||||||
|
purgeSettingsVersions = ['']
|
||||||
self.icons = Icons()
|
self.icons = Icons()
|
||||||
self.settings = QtCore.QSettings('KindleComicConverter', 'KindleComicConverter')
|
self.settings = QtCore.QSettings('KindleComicConverter', 'KindleComicConverter')
|
||||||
|
self.settingsVersion = self.settings.value('settingsVersion', '', type=str)
|
||||||
|
if self.settingsVersion in purgeSettingsVersions:
|
||||||
|
QtCore.QSettings.clear(self.settings)
|
||||||
|
self.settingsVersion = self.settings.value('settingsVersion', '', type=str)
|
||||||
self.lastPath = self.settings.value('lastPath', '', type=str)
|
self.lastPath = self.settings.value('lastPath', '', type=str)
|
||||||
self.lastDevice = self.settings.value('lastDevice', 10, type=int)
|
self.lastDevice = self.settings.value('lastDevice', 0, type=int)
|
||||||
self.currentMode = self.settings.value('currentMode', 1, type=int)
|
self.currentMode = self.settings.value('currentMode', 1, type=int)
|
||||||
self.currentFormat = self.settings.value('currentFormat', 0, type=int)
|
self.currentFormat = self.settings.value('currentFormat', 0, type=int)
|
||||||
|
self.firstStart = self.settings.value('firstStart', True, type=bool)
|
||||||
self.options = self.settings.value('options', QtCore.QVariant({'GammaSlider': 0}))
|
self.options = self.settings.value('options', QtCore.QVariant({'GammaSlider': 0}))
|
||||||
self.options = self.options.toPyObject()
|
self.options = self.options.toPyObject()
|
||||||
self.worker = WorkerThread(self)
|
self.worker = WorkerThread(self)
|
||||||
self.versionCheck = VersionThread(self)
|
self.versionCheck = VersionThread(self)
|
||||||
self.conversionAlive = False
|
self.conversionAlive = False
|
||||||
self.needClean = True
|
self.needClean = True
|
||||||
|
self.GammaValue = 1.0
|
||||||
|
|
||||||
self.addMessage('<b>Welcome!</b>', 'info')
|
self.addMessage('<b>Welcome!</b>', 'info')
|
||||||
self.addMessage('<b>Remember:</b> All options have additional informations in tooltips.', 'info')
|
self.addMessage('<b>Remember:</b> All options have additional informations in tooltips.', 'info')
|
||||||
|
if self.firstStart:
|
||||||
|
self.addMessage('Since you are using <b>KCC</b> for first time please see few '
|
||||||
|
'<a href="https://github.com/ciromattia/kcc#important-tips">important tips</a>.', 'info')
|
||||||
if call('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True) == 0:
|
if call('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, shell=True) == 0:
|
||||||
self.KindleGen = True
|
self.KindleGen = True
|
||||||
formats = ['MOBI', 'EPUB', 'CBZ']
|
formats = ['MOBI', 'EPUB', 'CBZ']
|
||||||
@@ -608,6 +646,13 @@ class Ui_KCC(object):
|
|||||||
self.UnRAR = False
|
self.UnRAR = False
|
||||||
self.addMessage('Cannot find <a href="http://www.rarlab.com/rar_add.htm">UnRAR</a>!'
|
self.addMessage('Cannot find <a href="http://www.rarlab.com/rar_add.htm">UnRAR</a>!'
|
||||||
' Processing of CBR/RAR files will be disabled.', 'warning')
|
' Processing of CBR/RAR files will be disabled.', 'warning')
|
||||||
|
sevenzaExitCode = call('7za', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
|
if sevenzaExitCode == 0 or sevenzaExitCode == 7:
|
||||||
|
self.sevenza = True
|
||||||
|
else:
|
||||||
|
self.sevenza = False
|
||||||
|
self.addMessage('Cannot find <a href="http://www.7-zip.org/download.html">7za</a>!'
|
||||||
|
' Processing of CB7/7Z files will be disabled.', 'warning')
|
||||||
|
|
||||||
GUI.BasicModeButton.clicked.connect(self.modeBasic)
|
GUI.BasicModeButton.clicked.connect(self.modeBasic)
|
||||||
GUI.AdvModeButton.clicked.connect(self.modeAdvanced)
|
GUI.AdvModeButton.clicked.connect(self.modeAdvanced)
|
||||||
@@ -627,12 +672,18 @@ class Ui_KCC(object):
|
|||||||
KCC.connect(self.versionCheck, QtCore.SIGNAL("addMessage"), self.addMessage)
|
KCC.connect(self.versionCheck, QtCore.SIGNAL("addMessage"), self.addMessage)
|
||||||
KCC.closeEvent = self.saveSettings
|
KCC.closeEvent = self.saveSettings
|
||||||
|
|
||||||
for profile in profiles:
|
for profile in ProfileData.ProfileLabelsGUI:
|
||||||
if profile != "Other":
|
if profile == "Other":
|
||||||
GUI.DeviceBox.addItem(self.icons.deviceKindle, profile)
|
|
||||||
else:
|
|
||||||
GUI.DeviceBox.addItem(self.icons.deviceOther, profile)
|
GUI.DeviceBox.addItem(self.icons.deviceOther, profile)
|
||||||
GUI.DeviceBox.setCurrentIndex(self.lastDevice)
|
elif profile == "Separator":
|
||||||
|
GUI.DeviceBox.insertSeparator(GUI.DeviceBox.count()+1)
|
||||||
|
else:
|
||||||
|
GUI.DeviceBox.addItem(self.icons.deviceKindle, profile)
|
||||||
|
if self.lastDevice > GUI.DeviceBox.count():
|
||||||
|
GUI.DeviceBox.setCurrentIndex(0)
|
||||||
|
self.lastDevice = 0
|
||||||
|
else:
|
||||||
|
GUI.DeviceBox.setCurrentIndex(self.lastDevice)
|
||||||
|
|
||||||
for f in formats:
|
for f in formats:
|
||||||
GUI.FormatBox.addItem(eval('self.icons.' + f + 'Format'), f)
|
GUI.FormatBox.addItem(eval('self.icons.' + f + 'Format'), f)
|
||||||
@@ -650,8 +701,6 @@ class Ui_KCC(object):
|
|||||||
elif str(option) == "GammaSlider":
|
elif str(option) == "GammaSlider":
|
||||||
GUI.GammaSlider.setValue(int(self.options[option]))
|
GUI.GammaSlider.setValue(int(self.options[option]))
|
||||||
self.changeGamma(int(self.options[option]))
|
self.changeGamma(int(self.options[option]))
|
||||||
elif str(option) == "StretchBox" or str(option) == "WebstripBox":
|
|
||||||
pass
|
|
||||||
else:
|
else:
|
||||||
eval('GUI.' + str(option)).setCheckState(self.options[option])
|
eval('GUI.' + str(option)).setCheckState(self.options[option])
|
||||||
if self.currentMode == 1:
|
if self.currentMode == 1:
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'KCC.ui'
|
# Form implementation generated from reading ui file 'KCC.ui'
|
||||||
#
|
#
|
||||||
# Created: Wed Aug 14 08:39:46 2013
|
# Created: Wed Sep 18 12:12:45 2013
|
||||||
# by: PyQt4 UI code generator 4.10.2
|
# 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!
|
||||||
|
|
||||||
@@ -68,6 +68,7 @@ class Ui_KCC(object):
|
|||||||
self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1)
|
self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1)
|
||||||
self.BorderBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
self.BorderBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.BorderBox.setTristate(True)
|
||||||
self.BorderBox.setObjectName(_fromUtf8("BorderBox"))
|
self.BorderBox.setObjectName(_fromUtf8("BorderBox"))
|
||||||
self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1)
|
self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1)
|
||||||
self.NoRotateBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
self.NoRotateBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
@@ -266,12 +267,12 @@ class Ui_KCC(object):
|
|||||||
self.ProcessingBox.setText(_translate("KCC", "No optimisation", None))
|
self.ProcessingBox.setText(_translate("KCC", "No optimisation", None))
|
||||||
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html>", None))
|
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html>", None))
|
||||||
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale", None))
|
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale", None))
|
||||||
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600;\">EXPERIMENTAL!<br/></span>Enable auto-splitting of webtoons like <span style=\" font-style:italic;\">Tower of God</span> or <span style=\" font-style:italic;\">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html>", None))
|
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p>Enable auto-splitting of webtoons like <span style=\" font-style:italic;\">Tower of God</span> or <span style=\" font-style:italic;\">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html>", None))
|
||||||
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode", None))
|
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode", None))
|
||||||
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p>Create PNG files instead JPEG.<br/><span style=\" font-weight:600;\">Only for non-Kindle devices!</span></p></body></html>", None))
|
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p>Create PNG files instead JPEG.</p></body></html>", None))
|
||||||
self.NoDitheringBox.setText(_translate("KCC", "PNG output", None))
|
self.NoDitheringBox.setText(_translate("KCC", "PNG output", None))
|
||||||
self.BorderBox.setToolTip(_translate("KCC", "Fill space around images with black color.", None))
|
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span>Color of margins fill will be detected automatically.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - White<br/></span>Margins will be filled with white color.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Black<br/></span>Margins will be filled with black color.</p></body></html>", None))
|
||||||
self.BorderBox.setText(_translate("KCC", "Black borders", None))
|
self.BorderBox.setText(_translate("KCC", "W/B margins", None))
|
||||||
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable splitting and rotation.</p></body></html>", None))
|
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable splitting and rotation.</p></body></html>", None))
|
||||||
self.NoRotateBox.setText(_translate("KCC", "No split/rotate", None))
|
self.NoRotateBox.setText(_translate("KCC", "No split/rotate", None))
|
||||||
self.DeviceBox.setToolTip(_translate("KCC", "Target device.", None))
|
self.DeviceBox.setToolTip(_translate("KCC", "Target device.", None))
|
||||||
|
|||||||
383
kcc/KCC_ui_linux.py
Normal file
383
kcc/KCC_ui_linux.py
Normal file
@@ -0,0 +1,383 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file 'KCC-Linux.ui'
|
||||||
|
#
|
||||||
|
# Created: Fri Sep 20 10:25:30 2013
|
||||||
|
# by: PyQt4 UI code generator 4.10
|
||||||
|
#
|
||||||
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
|
try:
|
||||||
|
_fromUtf8 = QtCore.QString.fromUtf8
|
||||||
|
except AttributeError:
|
||||||
|
def _fromUtf8(s):
|
||||||
|
return s
|
||||||
|
|
||||||
|
try:
|
||||||
|
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||||
|
def _translate(context, text, disambig):
|
||||||
|
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||||
|
except AttributeError:
|
||||||
|
def _translate(context, text, disambig):
|
||||||
|
return QtGui.QApplication.translate(context, text, disambig)
|
||||||
|
|
||||||
|
class Ui_KCC(object):
|
||||||
|
def setupUi(self, KCC):
|
||||||
|
KCC.setObjectName(_fromUtf8("KCC"))
|
||||||
|
KCC.resize(420, 380)
|
||||||
|
KCC.setMinimumSize(QtCore.QSize(420, 380))
|
||||||
|
KCC.setMaximumSize(QtCore.QSize(420, 380))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(9)
|
||||||
|
KCC.setFont(font)
|
||||||
|
KCC.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
icon = QtGui.QIcon()
|
||||||
|
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/Icon/icons/comic2ebook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
KCC.setWindowIcon(icon)
|
||||||
|
KCC.setLocale(QtCore.QLocale(QtCore.QLocale.C, QtCore.QLocale.AnyCountry))
|
||||||
|
self.Form = QtGui.QWidget(KCC)
|
||||||
|
self.Form.setObjectName(_fromUtf8("Form"))
|
||||||
|
self.OptionsAdvanced = QtGui.QFrame(self.Form)
|
||||||
|
self.OptionsAdvanced.setEnabled(True)
|
||||||
|
self.OptionsAdvanced.setGeometry(QtCore.QRect(1, 254, 421, 61))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.OptionsAdvanced.setFont(font)
|
||||||
|
self.OptionsAdvanced.setObjectName(_fromUtf8("OptionsAdvanced"))
|
||||||
|
self.gridLayout = QtGui.QGridLayout(self.OptionsAdvanced)
|
||||||
|
self.gridLayout.setContentsMargins(9, -1, -1, -1)
|
||||||
|
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||||
|
self.ProcessingBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
self.ProcessingBox.setFont(font)
|
||||||
|
self.ProcessingBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.ProcessingBox.setObjectName(_fromUtf8("ProcessingBox"))
|
||||||
|
self.gridLayout.addWidget(self.ProcessingBox, 1, 0, 1, 1)
|
||||||
|
self.UpscaleBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
self.UpscaleBox.setFont(font)
|
||||||
|
self.UpscaleBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.UpscaleBox.setTristate(True)
|
||||||
|
self.UpscaleBox.setObjectName(_fromUtf8("UpscaleBox"))
|
||||||
|
self.gridLayout.addWidget(self.UpscaleBox, 1, 1, 1, 1)
|
||||||
|
self.WebtoonBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
self.WebtoonBox.setFont(font)
|
||||||
|
self.WebtoonBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.WebtoonBox.setObjectName(_fromUtf8("WebtoonBox"))
|
||||||
|
self.gridLayout.addWidget(self.WebtoonBox, 3, 1, 1, 1)
|
||||||
|
self.NoDitheringBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
self.NoDitheringBox.setFont(font)
|
||||||
|
self.NoDitheringBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.NoDitheringBox.setObjectName(_fromUtf8("NoDitheringBox"))
|
||||||
|
self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1)
|
||||||
|
self.BorderBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
self.BorderBox.setFont(font)
|
||||||
|
self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.BorderBox.setTristate(True)
|
||||||
|
self.BorderBox.setObjectName(_fromUtf8("BorderBox"))
|
||||||
|
self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1)
|
||||||
|
self.NoRotateBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
self.NoRotateBox.setFont(font)
|
||||||
|
self.NoRotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.NoRotateBox.setObjectName(_fromUtf8("NoRotateBox"))
|
||||||
|
self.gridLayout.addWidget(self.NoRotateBox, 1, 2, 1, 1)
|
||||||
|
self.DeviceBox = QtGui.QComboBox(self.Form)
|
||||||
|
self.DeviceBox.setGeometry(QtCore.QRect(10, 200, 141, 31))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
font.setPointSize(8)
|
||||||
|
self.DeviceBox.setFont(font)
|
||||||
|
self.DeviceBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.DeviceBox.setObjectName(_fromUtf8("DeviceBox"))
|
||||||
|
self.FormatBox = QtGui.QComboBox(self.Form)
|
||||||
|
self.FormatBox.setGeometry(QtCore.QRect(260, 200, 151, 31))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
font.setPointSize(8)
|
||||||
|
self.FormatBox.setFont(font)
|
||||||
|
self.FormatBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.FormatBox.setObjectName(_fromUtf8("FormatBox"))
|
||||||
|
self.ConvertButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.ConvertButton.setGeometry(QtCore.QRect(160, 200, 91, 32))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
font.setPointSize(9)
|
||||||
|
font.setBold(True)
|
||||||
|
font.setWeight(75)
|
||||||
|
self.ConvertButton.setFont(font)
|
||||||
|
self.ConvertButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
icon1 = QtGui.QIcon()
|
||||||
|
icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/convert.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.ConvertButton.setIcon(icon1)
|
||||||
|
self.ConvertButton.setObjectName(_fromUtf8("ConvertButton"))
|
||||||
|
self.DirectoryButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.DirectoryButton.setGeometry(QtCore.QRect(10, 160, 141, 32))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
font.setPointSize(8)
|
||||||
|
self.DirectoryButton.setFont(font)
|
||||||
|
self.DirectoryButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
icon2 = QtGui.QIcon()
|
||||||
|
icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/folder_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.DirectoryButton.setIcon(icon2)
|
||||||
|
self.DirectoryButton.setObjectName(_fromUtf8("DirectoryButton"))
|
||||||
|
self.FileButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.FileButton.setGeometry(QtCore.QRect(260, 160, 151, 32))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
font.setPointSize(8)
|
||||||
|
self.FileButton.setFont(font)
|
||||||
|
self.FileButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
icon3 = QtGui.QIcon()
|
||||||
|
icon3.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/document_new.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.FileButton.setIcon(icon3)
|
||||||
|
self.FileButton.setObjectName(_fromUtf8("FileButton"))
|
||||||
|
self.ClearButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.ClearButton.setGeometry(QtCore.QRect(160, 160, 91, 32))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
font.setPointSize(8)
|
||||||
|
self.ClearButton.setFont(font)
|
||||||
|
self.ClearButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
icon4 = QtGui.QIcon()
|
||||||
|
icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/Other/icons/clear.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.ClearButton.setIcon(icon4)
|
||||||
|
self.ClearButton.setObjectName(_fromUtf8("ClearButton"))
|
||||||
|
self.OptionsBasic = QtGui.QFrame(self.Form)
|
||||||
|
self.OptionsBasic.setGeometry(QtCore.QRect(1, 230, 421, 41))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.OptionsBasic.setFont(font)
|
||||||
|
self.OptionsBasic.setObjectName(_fromUtf8("OptionsBasic"))
|
||||||
|
self.MangaBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||||
|
self.MangaBox.setGeometry(QtCore.QRect(9, 10, 130, 18))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
self.MangaBox.setFont(font)
|
||||||
|
self.MangaBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.MangaBox.setObjectName(_fromUtf8("MangaBox"))
|
||||||
|
self.QualityBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||||
|
self.QualityBox.setGeometry(QtCore.QRect(282, 10, 135, 18))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
self.QualityBox.setFont(font)
|
||||||
|
self.QualityBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.QualityBox.setTristate(True)
|
||||||
|
self.QualityBox.setObjectName(_fromUtf8("QualityBox"))
|
||||||
|
self.RotateBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||||
|
self.RotateBox.setGeometry(QtCore.QRect(145, 10, 130, 18))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
self.RotateBox.setFont(font)
|
||||||
|
self.RotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.RotateBox.setObjectName(_fromUtf8("RotateBox"))
|
||||||
|
self.JobList = QtGui.QListWidget(self.Form)
|
||||||
|
self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
font.setPointSize(8)
|
||||||
|
font.setItalic(False)
|
||||||
|
self.JobList.setFont(font)
|
||||||
|
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.JobList.setProperty("showDropIndicator", False)
|
||||||
|
self.JobList.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
|
||||||
|
self.JobList.setIconSize(QtCore.QSize(18, 18))
|
||||||
|
self.JobList.setObjectName(_fromUtf8("JobList"))
|
||||||
|
self.BasicModeButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.BasicModeButton.setGeometry(QtCore.QRect(10, 10, 195, 32))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.BasicModeButton.setFont(font)
|
||||||
|
self.BasicModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.BasicModeButton.setObjectName(_fromUtf8("BasicModeButton"))
|
||||||
|
self.AdvModeButton = QtGui.QPushButton(self.Form)
|
||||||
|
self.AdvModeButton.setGeometry(QtCore.QRect(217, 10, 195, 32))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.AdvModeButton.setFont(font)
|
||||||
|
self.AdvModeButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.AdvModeButton.setObjectName(_fromUtf8("AdvModeButton"))
|
||||||
|
self.OptionsAdvancedGamma = QtGui.QFrame(self.Form)
|
||||||
|
self.OptionsAdvancedGamma.setEnabled(True)
|
||||||
|
self.OptionsAdvancedGamma.setGeometry(QtCore.QRect(10, 305, 401, 41))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.OptionsAdvancedGamma.setFont(font)
|
||||||
|
self.OptionsAdvancedGamma.setObjectName(_fromUtf8("OptionsAdvancedGamma"))
|
||||||
|
self.GammaLabel = QtGui.QLabel(self.OptionsAdvancedGamma)
|
||||||
|
self.GammaLabel.setGeometry(QtCore.QRect(15, 0, 100, 40))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
self.GammaLabel.setFont(font)
|
||||||
|
self.GammaLabel.setObjectName(_fromUtf8("GammaLabel"))
|
||||||
|
self.GammaSlider = QtGui.QSlider(self.OptionsAdvancedGamma)
|
||||||
|
self.GammaSlider.setGeometry(QtCore.QRect(110, 10, 275, 22))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
self.GammaSlider.setFont(font)
|
||||||
|
self.GammaSlider.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||||
|
self.GammaSlider.setMaximum(500)
|
||||||
|
self.GammaSlider.setSingleStep(5)
|
||||||
|
self.GammaSlider.setOrientation(QtCore.Qt.Horizontal)
|
||||||
|
self.GammaSlider.setObjectName(_fromUtf8("GammaSlider"))
|
||||||
|
self.ProgressBar = QtGui.QProgressBar(self.Form)
|
||||||
|
self.ProgressBar.setGeometry(QtCore.QRect(10, 10, 401, 31))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
font.setPointSize(10)
|
||||||
|
font.setBold(True)
|
||||||
|
font.setWeight(75)
|
||||||
|
self.ProgressBar.setFont(font)
|
||||||
|
self.ProgressBar.setProperty("value", 0)
|
||||||
|
self.ProgressBar.setAlignment(QtCore.Qt.AlignJustify|QtCore.Qt.AlignVCenter)
|
||||||
|
self.ProgressBar.setFormat(_fromUtf8(""))
|
||||||
|
self.ProgressBar.setObjectName(_fromUtf8("ProgressBar"))
|
||||||
|
self.OptionsExpert = QtGui.QFrame(self.Form)
|
||||||
|
self.OptionsExpert.setGeometry(QtCore.QRect(1, 337, 421, 41))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
font.setPointSize(9)
|
||||||
|
self.OptionsExpert.setFont(font)
|
||||||
|
self.OptionsExpert.setObjectName(_fromUtf8("OptionsExpert"))
|
||||||
|
self.ColorBox = QtGui.QCheckBox(self.OptionsExpert)
|
||||||
|
self.ColorBox.setGeometry(QtCore.QRect(9, 11, 130, 18))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
self.ColorBox.setFont(font)
|
||||||
|
self.ColorBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.ColorBox.setObjectName(_fromUtf8("ColorBox"))
|
||||||
|
self.OptionsExpertInternal = QtGui.QFrame(self.OptionsExpert)
|
||||||
|
self.OptionsExpertInternal.setGeometry(QtCore.QRect(105, 0, 295, 40))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
self.OptionsExpertInternal.setFont(font)
|
||||||
|
self.OptionsExpertInternal.setObjectName(_fromUtf8("OptionsExpertInternal"))
|
||||||
|
self.gridLayout_2 = QtGui.QGridLayout(self.OptionsExpertInternal)
|
||||||
|
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
||||||
|
self.wLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
self.wLabel.setFont(font)
|
||||||
|
self.wLabel.setObjectName(_fromUtf8("wLabel"))
|
||||||
|
self.gridLayout_2.addWidget(self.wLabel, 0, 0, 1, 1)
|
||||||
|
self.customWidth = QtGui.QLineEdit(self.OptionsExpertInternal)
|
||||||
|
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.customWidth.sizePolicy().hasHeightForWidth())
|
||||||
|
self.customWidth.setSizePolicy(sizePolicy)
|
||||||
|
self.customWidth.setMaximumSize(QtCore.QSize(40, 16777215))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
self.customWidth.setFont(font)
|
||||||
|
self.customWidth.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||||
|
self.customWidth.setAcceptDrops(False)
|
||||||
|
self.customWidth.setMaxLength(4)
|
||||||
|
self.customWidth.setObjectName(_fromUtf8("customWidth"))
|
||||||
|
self.gridLayout_2.addWidget(self.customWidth, 0, 1, 1, 1)
|
||||||
|
self.hLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
self.hLabel.setFont(font)
|
||||||
|
self.hLabel.setObjectName(_fromUtf8("hLabel"))
|
||||||
|
self.gridLayout_2.addWidget(self.hLabel, 0, 2, 1, 1)
|
||||||
|
self.customHeight = QtGui.QLineEdit(self.OptionsExpertInternal)
|
||||||
|
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.customHeight.sizePolicy().hasHeightForWidth())
|
||||||
|
self.customHeight.setSizePolicy(sizePolicy)
|
||||||
|
self.customHeight.setMaximumSize(QtCore.QSize(40, 16777215))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("DejaVu Sans"))
|
||||||
|
self.customHeight.setFont(font)
|
||||||
|
self.customHeight.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||||
|
self.customHeight.setAcceptDrops(False)
|
||||||
|
self.customHeight.setMaxLength(4)
|
||||||
|
self.customHeight.setObjectName(_fromUtf8("customHeight"))
|
||||||
|
self.gridLayout_2.addWidget(self.customHeight, 0, 3, 1, 1)
|
||||||
|
KCC.setCentralWidget(self.Form)
|
||||||
|
self.ActionBasic = QtGui.QAction(KCC)
|
||||||
|
self.ActionBasic.setCheckable(True)
|
||||||
|
self.ActionBasic.setChecked(False)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
self.ActionBasic.setFont(font)
|
||||||
|
self.ActionBasic.setObjectName(_fromUtf8("ActionBasic"))
|
||||||
|
self.ActionAdvanced = QtGui.QAction(KCC)
|
||||||
|
self.ActionAdvanced.setCheckable(True)
|
||||||
|
self.ActionAdvanced.setObjectName(_fromUtf8("ActionAdvanced"))
|
||||||
|
|
||||||
|
self.retranslateUi(KCC)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(KCC)
|
||||||
|
KCC.setTabOrder(self.DirectoryButton, self.FileButton)
|
||||||
|
KCC.setTabOrder(self.FileButton, self.ConvertButton)
|
||||||
|
KCC.setTabOrder(self.ConvertButton, self.ClearButton)
|
||||||
|
|
||||||
|
def retranslateUi(self, KCC):
|
||||||
|
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter", None))
|
||||||
|
self.ProcessingBox.setToolTip(_translate("KCC", "Disable image optimizations.", None))
|
||||||
|
self.ProcessingBox.setText(_translate("KCC", "No optimisation", None))
|
||||||
|
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html>", None))
|
||||||
|
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale", None))
|
||||||
|
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p>Enable auto-splitting of webtoons like <span style=\" font-style:italic;\">Tower of God</span> or <span style=\" font-style:italic;\">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html>", None))
|
||||||
|
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode", None))
|
||||||
|
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p>Create PNG files instead JPEG.</p></body></html>", None))
|
||||||
|
self.NoDitheringBox.setText(_translate("KCC", "PNG output", None))
|
||||||
|
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span>Color of margins fill will be detected automatically.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - White<br/></span>Margins will be filled with white color.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Black<br/></span>Margins will be filled with black color.</p></body></html>", None))
|
||||||
|
self.BorderBox.setText(_translate("KCC", "W/B margins", None))
|
||||||
|
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable splitting and rotation.</p></body></html>", None))
|
||||||
|
self.NoRotateBox.setText(_translate("KCC", "No split/rotate", None))
|
||||||
|
self.DeviceBox.setToolTip(_translate("KCC", "Target device.", None))
|
||||||
|
self.FormatBox.setToolTip(_translate("KCC", "Output format.", None))
|
||||||
|
self.ConvertButton.setText(_translate("KCC", "Convert", None))
|
||||||
|
self.DirectoryButton.setText(_translate("KCC", "Add directory", None))
|
||||||
|
self.FileButton.setText(_translate("KCC", "Add file", None))
|
||||||
|
self.ClearButton.setText(_translate("KCC", "Clear list", None))
|
||||||
|
self.MangaBox.setToolTip(_translate("KCC", "Enable right-to-left reading.", None))
|
||||||
|
self.MangaBox.setText(_translate("KCC", "Manga mode", None))
|
||||||
|
self.QualityBox.setToolTip(_translate("KCC", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
||||||
|
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\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"
|
||||||
|
"<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;\">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.RotateBox.setToolTip(_translate("KCC", "<html><head/><body><p>Disable page spliting.<br/>They will be rotated instead.</p></body></html>", None))
|
||||||
|
self.RotateBox.setText(_translate("KCC", "Horizontal mode", None))
|
||||||
|
self.BasicModeButton.setText(_translate("KCC", "Basic", 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.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", "Do not convert images to grayscale.", None))
|
||||||
|
self.ColorBox.setText(_translate("KCC", "Color mode", None))
|
||||||
|
self.wLabel.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||||
|
self.wLabel.setText(_translate("KCC", "Custom width: ", None))
|
||||||
|
self.customWidth.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||||
|
self.customWidth.setInputMask(_translate("KCC", "0000; ", None))
|
||||||
|
self.hLabel.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||||
|
self.hLabel.setText(_translate("KCC", "Custom height: ", None))
|
||||||
|
self.customHeight.setToolTip(_translate("KCC", "Resolution of target device.", None))
|
||||||
|
self.customHeight.setInputMask(_translate("KCC", "0000; ", None))
|
||||||
|
self.ActionBasic.setText(_translate("KCC", "Basic", None))
|
||||||
|
self.ActionAdvanced.setText(_translate("KCC", "Advanced", None))
|
||||||
|
|
||||||
|
import KCC_rc
|
||||||
@@ -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: Wed Aug 14 08:39:45 2013
|
# Created: Fri Sep 20 10:57:31 2013
|
||||||
# by: PyQt4 UI code generator 4.10.2
|
# by: PyQt4 UI code generator 4.10.2
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
@@ -41,8 +41,9 @@ class Ui_KCC(object):
|
|||||||
self.Form.setObjectName(_fromUtf8("Form"))
|
self.Form.setObjectName(_fromUtf8("Form"))
|
||||||
self.OptionsAdvanced = QtGui.QFrame(self.Form)
|
self.OptionsAdvanced = QtGui.QFrame(self.Form)
|
||||||
self.OptionsAdvanced.setEnabled(True)
|
self.OptionsAdvanced.setEnabled(True)
|
||||||
self.OptionsAdvanced.setGeometry(QtCore.QRect(9, 253, 421, 61))
|
self.OptionsAdvanced.setGeometry(QtCore.QRect(4, 253, 421, 61))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(9)
|
font.setPointSize(9)
|
||||||
self.OptionsAdvanced.setFont(font)
|
self.OptionsAdvanced.setFont(font)
|
||||||
self.OptionsAdvanced.setObjectName(_fromUtf8("OptionsAdvanced"))
|
self.OptionsAdvanced.setObjectName(_fromUtf8("OptionsAdvanced"))
|
||||||
@@ -50,14 +51,16 @@ class Ui_KCC(object):
|
|||||||
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
|
||||||
self.ProcessingBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
self.ProcessingBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(11)
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
|
font.setPointSize(12)
|
||||||
self.ProcessingBox.setFont(font)
|
self.ProcessingBox.setFont(font)
|
||||||
self.ProcessingBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.ProcessingBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
self.ProcessingBox.setObjectName(_fromUtf8("ProcessingBox"))
|
self.ProcessingBox.setObjectName(_fromUtf8("ProcessingBox"))
|
||||||
self.gridLayout.addWidget(self.ProcessingBox, 1, 0, 1, 1)
|
self.gridLayout.addWidget(self.ProcessingBox, 1, 0, 1, 1)
|
||||||
self.UpscaleBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
self.UpscaleBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(11)
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
|
font.setPointSize(12)
|
||||||
self.UpscaleBox.setFont(font)
|
self.UpscaleBox.setFont(font)
|
||||||
self.UpscaleBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.UpscaleBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
self.UpscaleBox.setTristate(True)
|
self.UpscaleBox.setTristate(True)
|
||||||
@@ -65,28 +68,33 @@ class Ui_KCC(object):
|
|||||||
self.gridLayout.addWidget(self.UpscaleBox, 1, 1, 1, 1)
|
self.gridLayout.addWidget(self.UpscaleBox, 1, 1, 1, 1)
|
||||||
self.WebtoonBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
self.WebtoonBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(11)
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
|
font.setPointSize(12)
|
||||||
self.WebtoonBox.setFont(font)
|
self.WebtoonBox.setFont(font)
|
||||||
self.WebtoonBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.WebtoonBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
self.WebtoonBox.setObjectName(_fromUtf8("WebtoonBox"))
|
self.WebtoonBox.setObjectName(_fromUtf8("WebtoonBox"))
|
||||||
self.gridLayout.addWidget(self.WebtoonBox, 3, 1, 1, 1)
|
self.gridLayout.addWidget(self.WebtoonBox, 3, 1, 1, 1)
|
||||||
self.NoDitheringBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
self.NoDitheringBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(11)
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
|
font.setPointSize(12)
|
||||||
self.NoDitheringBox.setFont(font)
|
self.NoDitheringBox.setFont(font)
|
||||||
self.NoDitheringBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.NoDitheringBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
self.NoDitheringBox.setObjectName(_fromUtf8("NoDitheringBox"))
|
self.NoDitheringBox.setObjectName(_fromUtf8("NoDitheringBox"))
|
||||||
self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1)
|
self.gridLayout.addWidget(self.NoDitheringBox, 3, 2, 1, 1)
|
||||||
self.BorderBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
self.BorderBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(11)
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
|
font.setPointSize(12)
|
||||||
self.BorderBox.setFont(font)
|
self.BorderBox.setFont(font)
|
||||||
self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.BorderBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
self.BorderBox.setTristate(True)
|
||||||
self.BorderBox.setObjectName(_fromUtf8("BorderBox"))
|
self.BorderBox.setObjectName(_fromUtf8("BorderBox"))
|
||||||
self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1)
|
self.gridLayout.addWidget(self.BorderBox, 3, 0, 1, 1)
|
||||||
self.NoRotateBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
self.NoRotateBox = QtGui.QCheckBox(self.OptionsAdvanced)
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(11)
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
|
font.setPointSize(12)
|
||||||
self.NoRotateBox.setFont(font)
|
self.NoRotateBox.setFont(font)
|
||||||
self.NoRotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.NoRotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
self.NoRotateBox.setObjectName(_fromUtf8("NoRotateBox"))
|
self.NoRotateBox.setObjectName(_fromUtf8("NoRotateBox"))
|
||||||
@@ -94,6 +102,7 @@ class Ui_KCC(object):
|
|||||||
self.DeviceBox = QtGui.QComboBox(self.Form)
|
self.DeviceBox = QtGui.QComboBox(self.Form)
|
||||||
self.DeviceBox.setGeometry(QtCore.QRect(8, 200, 151, 34))
|
self.DeviceBox.setGeometry(QtCore.QRect(8, 200, 151, 34))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(11)
|
font.setPointSize(11)
|
||||||
self.DeviceBox.setFont(font)
|
self.DeviceBox.setFont(font)
|
||||||
self.DeviceBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.DeviceBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
@@ -101,6 +110,7 @@ class Ui_KCC(object):
|
|||||||
self.FormatBox = QtGui.QComboBox(self.Form)
|
self.FormatBox = QtGui.QComboBox(self.Form)
|
||||||
self.FormatBox.setGeometry(QtCore.QRect(262, 200, 152, 34))
|
self.FormatBox.setGeometry(QtCore.QRect(262, 200, 152, 34))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(11)
|
font.setPointSize(11)
|
||||||
self.FormatBox.setFont(font)
|
self.FormatBox.setFont(font)
|
||||||
self.FormatBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.FormatBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
@@ -108,6 +118,7 @@ class Ui_KCC(object):
|
|||||||
self.ConvertButton = QtGui.QPushButton(self.Form)
|
self.ConvertButton = QtGui.QPushButton(self.Form)
|
||||||
self.ConvertButton.setGeometry(QtCore.QRect(160, 200, 101, 41))
|
self.ConvertButton.setGeometry(QtCore.QRect(160, 200, 101, 41))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(11)
|
font.setPointSize(11)
|
||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
font.setWeight(75)
|
font.setWeight(75)
|
||||||
@@ -120,6 +131,7 @@ class Ui_KCC(object):
|
|||||||
self.DirectoryButton = QtGui.QPushButton(self.Form)
|
self.DirectoryButton = QtGui.QPushButton(self.Form)
|
||||||
self.DirectoryButton.setGeometry(QtCore.QRect(5, 160, 156, 41))
|
self.DirectoryButton.setGeometry(QtCore.QRect(5, 160, 156, 41))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(11)
|
font.setPointSize(11)
|
||||||
self.DirectoryButton.setFont(font)
|
self.DirectoryButton.setFont(font)
|
||||||
self.DirectoryButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.DirectoryButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
@@ -130,6 +142,7 @@ class Ui_KCC(object):
|
|||||||
self.FileButton = QtGui.QPushButton(self.Form)
|
self.FileButton = QtGui.QPushButton(self.Form)
|
||||||
self.FileButton.setGeometry(QtCore.QRect(260, 160, 157, 41))
|
self.FileButton.setGeometry(QtCore.QRect(260, 160, 157, 41))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(11)
|
font.setPointSize(11)
|
||||||
self.FileButton.setFont(font)
|
self.FileButton.setFont(font)
|
||||||
self.FileButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.FileButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
@@ -140,6 +153,7 @@ class Ui_KCC(object):
|
|||||||
self.ClearButton = QtGui.QPushButton(self.Form)
|
self.ClearButton = QtGui.QPushButton(self.Form)
|
||||||
self.ClearButton.setGeometry(QtCore.QRect(160, 160, 101, 41))
|
self.ClearButton.setGeometry(QtCore.QRect(160, 160, 101, 41))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(11)
|
font.setPointSize(11)
|
||||||
self.ClearButton.setFont(font)
|
self.ClearButton.setFont(font)
|
||||||
self.ClearButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.ClearButton.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
@@ -148,22 +162,25 @@ class Ui_KCC(object):
|
|||||||
self.ClearButton.setIcon(icon4)
|
self.ClearButton.setIcon(icon4)
|
||||||
self.ClearButton.setObjectName(_fromUtf8("ClearButton"))
|
self.ClearButton.setObjectName(_fromUtf8("ClearButton"))
|
||||||
self.OptionsBasic = QtGui.QFrame(self.Form)
|
self.OptionsBasic = QtGui.QFrame(self.Form)
|
||||||
self.OptionsBasic.setGeometry(QtCore.QRect(10, 233, 421, 41))
|
self.OptionsBasic.setGeometry(QtCore.QRect(5, 233, 421, 41))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(9)
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
|
font.setPointSize(12)
|
||||||
self.OptionsBasic.setFont(font)
|
self.OptionsBasic.setFont(font)
|
||||||
self.OptionsBasic.setObjectName(_fromUtf8("OptionsBasic"))
|
self.OptionsBasic.setObjectName(_fromUtf8("OptionsBasic"))
|
||||||
self.MangaBox = QtGui.QCheckBox(self.OptionsBasic)
|
self.MangaBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||||
self.MangaBox.setGeometry(QtCore.QRect(9, 10, 130, 18))
|
self.MangaBox.setGeometry(QtCore.QRect(9, 10, 130, 18))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(11)
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
|
font.setPointSize(12)
|
||||||
self.MangaBox.setFont(font)
|
self.MangaBox.setFont(font)
|
||||||
self.MangaBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.MangaBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
self.MangaBox.setObjectName(_fromUtf8("MangaBox"))
|
self.MangaBox.setObjectName(_fromUtf8("MangaBox"))
|
||||||
self.QualityBox = QtGui.QCheckBox(self.OptionsBasic)
|
self.QualityBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||||
self.QualityBox.setGeometry(QtCore.QRect(282, 10, 130, 18))
|
self.QualityBox.setGeometry(QtCore.QRect(282, 10, 135, 18))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(11)
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
|
font.setPointSize(12)
|
||||||
self.QualityBox.setFont(font)
|
self.QualityBox.setFont(font)
|
||||||
self.QualityBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.QualityBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
self.QualityBox.setTristate(True)
|
self.QualityBox.setTristate(True)
|
||||||
@@ -171,13 +188,15 @@ class Ui_KCC(object):
|
|||||||
self.RotateBox = QtGui.QCheckBox(self.OptionsBasic)
|
self.RotateBox = QtGui.QCheckBox(self.OptionsBasic)
|
||||||
self.RotateBox.setGeometry(QtCore.QRect(145, 10, 130, 18))
|
self.RotateBox.setGeometry(QtCore.QRect(145, 10, 130, 18))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(11)
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
|
font.setPointSize(12)
|
||||||
self.RotateBox.setFont(font)
|
self.RotateBox.setFont(font)
|
||||||
self.RotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.RotateBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
self.RotateBox.setObjectName(_fromUtf8("RotateBox"))
|
self.RotateBox.setObjectName(_fromUtf8("RotateBox"))
|
||||||
self.JobList = QtGui.QListWidget(self.Form)
|
self.JobList = QtGui.QListWidget(self.Form)
|
||||||
self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101))
|
self.JobList.setGeometry(QtCore.QRect(10, 50, 401, 101))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(11)
|
font.setPointSize(11)
|
||||||
self.JobList.setFont(font)
|
self.JobList.setFont(font)
|
||||||
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.JobList.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
@@ -187,6 +206,7 @@ class Ui_KCC(object):
|
|||||||
self.BasicModeButton = QtGui.QPushButton(self.Form)
|
self.BasicModeButton = QtGui.QPushButton(self.Form)
|
||||||
self.BasicModeButton.setGeometry(QtCore.QRect(5, 10, 210, 41))
|
self.BasicModeButton.setGeometry(QtCore.QRect(5, 10, 210, 41))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(12)
|
font.setPointSize(12)
|
||||||
font.setBold(False)
|
font.setBold(False)
|
||||||
font.setWeight(50)
|
font.setWeight(50)
|
||||||
@@ -196,6 +216,7 @@ class Ui_KCC(object):
|
|||||||
self.AdvModeButton = QtGui.QPushButton(self.Form)
|
self.AdvModeButton = QtGui.QPushButton(self.Form)
|
||||||
self.AdvModeButton.setGeometry(QtCore.QRect(207, 10, 210, 41))
|
self.AdvModeButton.setGeometry(QtCore.QRect(207, 10, 210, 41))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(12)
|
font.setPointSize(12)
|
||||||
font.setBold(False)
|
font.setBold(False)
|
||||||
font.setWeight(50)
|
font.setWeight(50)
|
||||||
@@ -204,21 +225,26 @@ class Ui_KCC(object):
|
|||||||
self.AdvModeButton.setObjectName(_fromUtf8("AdvModeButton"))
|
self.AdvModeButton.setObjectName(_fromUtf8("AdvModeButton"))
|
||||||
self.OptionsAdvancedGamma = QtGui.QFrame(self.Form)
|
self.OptionsAdvancedGamma = QtGui.QFrame(self.Form)
|
||||||
self.OptionsAdvancedGamma.setEnabled(True)
|
self.OptionsAdvancedGamma.setEnabled(True)
|
||||||
self.OptionsAdvancedGamma.setGeometry(QtCore.QRect(10, 303, 401, 41))
|
self.OptionsAdvancedGamma.setGeometry(QtCore.QRect(5, 303, 401, 41))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(9)
|
font.setPointSize(9)
|
||||||
self.OptionsAdvancedGamma.setFont(font)
|
self.OptionsAdvancedGamma.setFont(font)
|
||||||
self.OptionsAdvancedGamma.setObjectName(_fromUtf8("OptionsAdvancedGamma"))
|
self.OptionsAdvancedGamma.setObjectName(_fromUtf8("OptionsAdvancedGamma"))
|
||||||
self.GammaLabel = QtGui.QLabel(self.OptionsAdvancedGamma)
|
self.GammaLabel = QtGui.QLabel(self.OptionsAdvancedGamma)
|
||||||
self.GammaLabel.setGeometry(QtCore.QRect(20, 0, 100, 40))
|
self.GammaLabel.setGeometry(QtCore.QRect(20, 0, 100, 40))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(12)
|
font.setPointSize(12)
|
||||||
font.setBold(False)
|
font.setBold(False)
|
||||||
font.setWeight(50)
|
font.setWeight(50)
|
||||||
self.GammaLabel.setFont(font)
|
self.GammaLabel.setFont(font)
|
||||||
self.GammaLabel.setObjectName(_fromUtf8("GammaLabel"))
|
self.GammaLabel.setObjectName(_fromUtf8("GammaLabel"))
|
||||||
self.GammaSlider = QtGui.QSlider(self.OptionsAdvancedGamma)
|
self.GammaSlider = QtGui.QSlider(self.OptionsAdvancedGamma)
|
||||||
self.GammaSlider.setGeometry(QtCore.QRect(110, 10, 280, 22))
|
self.GammaSlider.setGeometry(QtCore.QRect(110, 10, 290, 22))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
|
self.GammaSlider.setFont(font)
|
||||||
self.GammaSlider.setFocusPolicy(QtCore.Qt.ClickFocus)
|
self.GammaSlider.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||||
self.GammaSlider.setMaximum(500)
|
self.GammaSlider.setMaximum(500)
|
||||||
self.GammaSlider.setSingleStep(5)
|
self.GammaSlider.setSingleStep(5)
|
||||||
@@ -227,6 +253,7 @@ class Ui_KCC(object):
|
|||||||
self.ProgressBar = QtGui.QProgressBar(self.Form)
|
self.ProgressBar = QtGui.QProgressBar(self.Form)
|
||||||
self.ProgressBar.setGeometry(QtCore.QRect(10, 10, 401, 35))
|
self.ProgressBar.setGeometry(QtCore.QRect(10, 10, 401, 35))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(10)
|
font.setPointSize(10)
|
||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
font.setWeight(75)
|
font.setWeight(75)
|
||||||
@@ -237,25 +264,31 @@ class Ui_KCC(object):
|
|||||||
self.ProgressBar.setFormat(_fromUtf8(""))
|
self.ProgressBar.setFormat(_fromUtf8(""))
|
||||||
self.ProgressBar.setObjectName(_fromUtf8("ProgressBar"))
|
self.ProgressBar.setObjectName(_fromUtf8("ProgressBar"))
|
||||||
self.OptionsExpert = QtGui.QFrame(self.Form)
|
self.OptionsExpert = QtGui.QFrame(self.Form)
|
||||||
self.OptionsExpert.setGeometry(QtCore.QRect(10, 335, 421, 41))
|
self.OptionsExpert.setGeometry(QtCore.QRect(5, 335, 421, 41))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(9)
|
font.setPointSize(9)
|
||||||
self.OptionsExpert.setFont(font)
|
self.OptionsExpert.setFont(font)
|
||||||
self.OptionsExpert.setObjectName(_fromUtf8("OptionsExpert"))
|
self.OptionsExpert.setObjectName(_fromUtf8("OptionsExpert"))
|
||||||
self.ColorBox = QtGui.QCheckBox(self.OptionsExpert)
|
self.ColorBox = QtGui.QCheckBox(self.OptionsExpert)
|
||||||
self.ColorBox.setGeometry(QtCore.QRect(9, 11, 130, 18))
|
self.ColorBox.setGeometry(QtCore.QRect(9, 11, 130, 18))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(11)
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
|
font.setPointSize(12)
|
||||||
self.ColorBox.setFont(font)
|
self.ColorBox.setFont(font)
|
||||||
self.ColorBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
self.ColorBox.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
self.ColorBox.setObjectName(_fromUtf8("ColorBox"))
|
self.ColorBox.setObjectName(_fromUtf8("ColorBox"))
|
||||||
self.OptionsExpertInternal = QtGui.QFrame(self.OptionsExpert)
|
self.OptionsExpertInternal = QtGui.QFrame(self.OptionsExpert)
|
||||||
self.OptionsExpertInternal.setGeometry(QtCore.QRect(90, 0, 315, 40))
|
self.OptionsExpertInternal.setGeometry(QtCore.QRect(95, 0, 315, 40))
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
|
self.OptionsExpertInternal.setFont(font)
|
||||||
self.OptionsExpertInternal.setObjectName(_fromUtf8("OptionsExpertInternal"))
|
self.OptionsExpertInternal.setObjectName(_fromUtf8("OptionsExpertInternal"))
|
||||||
self.gridLayout_2 = QtGui.QGridLayout(self.OptionsExpertInternal)
|
self.gridLayout_2 = QtGui.QGridLayout(self.OptionsExpertInternal)
|
||||||
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
|
||||||
self.wLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
self.wLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(12)
|
font.setPointSize(12)
|
||||||
font.setBold(False)
|
font.setBold(False)
|
||||||
font.setWeight(50)
|
font.setWeight(50)
|
||||||
@@ -270,6 +303,7 @@ class Ui_KCC(object):
|
|||||||
self.customWidth.setSizePolicy(sizePolicy)
|
self.customWidth.setSizePolicy(sizePolicy)
|
||||||
self.customWidth.setMaximumSize(QtCore.QSize(45, 16777215))
|
self.customWidth.setMaximumSize(QtCore.QSize(45, 16777215))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(12)
|
font.setPointSize(12)
|
||||||
self.customWidth.setFont(font)
|
self.customWidth.setFont(font)
|
||||||
self.customWidth.setFocusPolicy(QtCore.Qt.ClickFocus)
|
self.customWidth.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||||
@@ -279,6 +313,7 @@ class Ui_KCC(object):
|
|||||||
self.gridLayout_2.addWidget(self.customWidth, 0, 1, 1, 1)
|
self.gridLayout_2.addWidget(self.customWidth, 0, 1, 1, 1)
|
||||||
self.hLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
self.hLabel = QtGui.QLabel(self.OptionsExpertInternal)
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(12)
|
font.setPointSize(12)
|
||||||
font.setBold(False)
|
font.setBold(False)
|
||||||
font.setWeight(50)
|
font.setWeight(50)
|
||||||
@@ -293,6 +328,7 @@ class Ui_KCC(object):
|
|||||||
self.customHeight.setSizePolicy(sizePolicy)
|
self.customHeight.setSizePolicy(sizePolicy)
|
||||||
self.customHeight.setMaximumSize(QtCore.QSize(45, 16777215))
|
self.customHeight.setMaximumSize(QtCore.QSize(45, 16777215))
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Lucida Grande"))
|
||||||
font.setPointSize(12)
|
font.setPointSize(12)
|
||||||
self.customHeight.setFont(font)
|
self.customHeight.setFont(font)
|
||||||
self.customHeight.setFocusPolicy(QtCore.Qt.ClickFocus)
|
self.customHeight.setFocusPolicy(QtCore.Qt.ClickFocus)
|
||||||
@@ -322,31 +358,31 @@ class Ui_KCC(object):
|
|||||||
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter", None))
|
KCC.setWindowTitle(_translate("KCC", "Kindle Comic Converter", None))
|
||||||
self.ProcessingBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Disable image optimizations.</span></p></body></html>", None))
|
self.ProcessingBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Disable image optimizations.</span></p></body></html>", None))
|
||||||
self.ProcessingBox.setText(_translate("KCC", "No optimisation", None))
|
self.ProcessingBox.setText(_translate("KCC", "No optimisation", None))
|
||||||
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span>Images smaller than device resolution will not be resized.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span>Images smaller than device resolution will be resized. Aspect ratio will be preserved.</p></body></html>", None))
|
self.UpscaleBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Unchecked - Nothing<br/></span><span style=\" font-size:12pt;\">Images smaller than device resolution will not be resized.</span></p><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Indeterminate - Stretching<br/></span><span style=\" font-size:12pt;\">Images smaller than device resolution will be resized. Aspect ratio will be not preserved.</span></p><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Checked - Upscaling<br/></span><span style=\" font-size:12pt;\">Images smaller than device resolution will be resized. Aspect ratio will be preserved.</span></p></body></html>", None))
|
||||||
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale", None))
|
self.UpscaleBox.setText(_translate("KCC", "Stretch/Upscale", None))
|
||||||
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-weight:600;\">EXPERIMENTAL!<br/></span>Enable auto-splitting of webtoons like <span style=\" font-style:italic;\">Tower of God</span> or <span style=\" font-style:italic;\">Noblesse</span>.<br/>Pages with a low width, high height and vertical panel flow.</p></body></html>", None))
|
self.WebtoonBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Enable auto-splitting of webtoons like </span><span style=\" font-size:12pt; font-style:italic;\">Tower of God</span><span style=\" font-size:12pt;\"> or </span><span style=\" font-size:12pt; font-style:italic;\">Noblesse</span><span style=\" font-size:12pt;\">.<br/>Pages with a low width, high height and vertical panel flow.</span></p></body></html>", None))
|
||||||
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode", None))
|
self.WebtoonBox.setText(_translate("KCC", "Webtoon mode", None))
|
||||||
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Create PNG files instead JPEG.<br/></span><span style=\" font-size:12pt; font-weight:600;\">Only for non-Kindle devices!</span></p></body></html>", None))
|
self.NoDitheringBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Create PNG files instead JPEG.</span></p></body></html>", None))
|
||||||
self.NoDitheringBox.setText(_translate("KCC", "PNG output", None))
|
self.NoDitheringBox.setText(_translate("KCC", "PNG output", None))
|
||||||
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Fill space around images with black color.</span></p></body></html>", None))
|
self.BorderBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span><span style=\" font-size:12pt;\">Color of margins fill will be detected automatically.</span></p><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Indeterminate - White<br/></span><span style=\" font-size:12pt;\">Margins will be filled with white color.</span></p><p><span style=\" font-size:12pt; font-weight:600; text-decoration: underline;\">Checked - Black<br/></span><span style=\" font-size:12pt;\">Margins will be filled with black color.</span></p></body></html>", None))
|
||||||
self.BorderBox.setText(_translate("KCC", "Black borders", None))
|
self.BorderBox.setText(_translate("KCC", "W/B margins", None))
|
||||||
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Disable splitting and rotation.</span></p></body></html>", None))
|
self.NoRotateBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Disable splitting and rotation.</span></p></body></html>", None))
|
||||||
self.NoRotateBox.setText(_translate("KCC", "No split/rotate", None))
|
self.NoRotateBox.setText(_translate("KCC", "No split/rotate", None))
|
||||||
self.DeviceBox.setToolTip(_translate("KCC", "Target device.", None))
|
self.DeviceBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Target device.</span></p></body></html>", None))
|
||||||
self.FormatBox.setToolTip(_translate("KCC", "Output format.", None))
|
self.FormatBox.setToolTip(_translate("KCC", "<html><head/><body><p><span style=\" font-size:12pt;\">Output format.</span></p></body></html>", None))
|
||||||
self.ConvertButton.setText(_translate("KCC", "Convert", None))
|
self.ConvertButton.setText(_translate("KCC", "Convert", None))
|
||||||
self.DirectoryButton.setText(_translate("KCC", "Add directory", None))
|
self.DirectoryButton.setText(_translate("KCC", "Add directory", None))
|
||||||
self.FileButton.setText(_translate("KCC", "Add file", None))
|
self.FileButton.setText(_translate("KCC", "Add file", None))
|
||||||
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-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\">Unchecked - Normal quality mode<br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-style:italic;\">Use it when Panel View support is not needed.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt;\">- Maximum quality when zoom is not enabled.<br/>- Poor quality when zoom is enabled.<br/>- Lowest file size.</span></p><p><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\">Indeterminate - High quality mode<br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-style:italic;\">Not zoomed image </span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; font-style:italic;\">might </span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-style:italic;\">be a little blurry.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt;\">- Medium/High quality when zoom is not enabled.<br/>- Maximum quality when zoom is enabled.</span></p><p><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\">Checked - Ultra quality mode<br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-style:italic;\">Maximum possible quality.</span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt; font-weight:600; text-decoration: underline;\"><br/></span><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:14pt;\">- 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.</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 page spliting.<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 MIGHT improve readability.</span></p></body></html>", 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.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;\">Do not 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))
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
__version__ = '3.2.1'
|
__version__ = '3.3'
|
||||||
__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'
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
# Copyright (c) 2012 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
|
# Copyright (c) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -21,6 +22,7 @@ __docformat__ = 'restructuredtext en'
|
|||||||
import os
|
import os
|
||||||
import zipfile
|
import zipfile
|
||||||
import rarfile
|
import rarfile
|
||||||
|
from subprocess import Popen, STDOUT, PIPE
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyBroadException
|
# noinspection PyBroadException
|
||||||
@@ -31,6 +33,8 @@ class CBxArchive:
|
|||||||
self.compressor = 'zip'
|
self.compressor = 'zip'
|
||||||
elif rarfile.is_rarfile(origFileName):
|
elif rarfile.is_rarfile(origFileName):
|
||||||
self.compressor = 'rar'
|
self.compressor = 'rar'
|
||||||
|
elif origFileName.endswith('.7z') or origFileName.endswith('.cb7'):
|
||||||
|
self.compressor = '7z'
|
||||||
else:
|
else:
|
||||||
self.compressor = None
|
self.compressor = None
|
||||||
|
|
||||||
@@ -67,12 +71,24 @@ class CBxArchive:
|
|||||||
filelist.append(f)
|
filelist.append(f)
|
||||||
cbrFile.extractall(targetdir, filelist)
|
cbrFile.extractall(targetdir, filelist)
|
||||||
|
|
||||||
|
def extractCB7(self, targetdir):
|
||||||
|
output = Popen('7za x "' + self.origFileName + '" -xr!__MACOSX -xr!.DS_Store -xr!thumbs.db -o"' + targetdir +
|
||||||
|
'"', stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
|
extracted = False
|
||||||
|
for line in output.stdout:
|
||||||
|
if "Everything is Ok" in line:
|
||||||
|
extracted = True
|
||||||
|
if not extracted:
|
||||||
|
raise OSError
|
||||||
|
|
||||||
def extract(self, targetdir):
|
def extract(self, targetdir):
|
||||||
print "\n" + targetdir + "\n"
|
print "\n" + targetdir + "\n"
|
||||||
if self.compressor == 'rar':
|
if self.compressor == 'rar':
|
||||||
self.extractCBR(targetdir)
|
self.extractCBR(targetdir)
|
||||||
elif self.compressor == 'zip':
|
elif self.compressor == 'zip':
|
||||||
self.extractCBZ(targetdir)
|
self.extractCBZ(targetdir)
|
||||||
|
elif self.compressor == '7z':
|
||||||
|
self.extractCB7(targetdir)
|
||||||
adir = os.listdir(targetdir)
|
adir = os.listdir(targetdir)
|
||||||
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
|
import shutil
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
|
# Copyright (c) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -17,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.2.1'
|
__version__ = '3.3'
|
||||||
__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'
|
||||||
@@ -44,11 +45,18 @@ import pdfjpgextract
|
|||||||
def buildHTML(path, imgfile):
|
def buildHTML(path, imgfile):
|
||||||
filename = getImageFileName(imgfile)
|
filename = getImageFileName(imgfile)
|
||||||
if filename is not None:
|
if filename is not None:
|
||||||
# All files marked with this sufix need horizontal Panel View.
|
if "_kccrot" in str(filename):
|
||||||
if "_kccrotated" in str(filename):
|
rotatedPage = True
|
||||||
rotate = True
|
|
||||||
else:
|
else:
|
||||||
rotate = False
|
rotatedPage = False
|
||||||
|
if "_kccnh" in str(filename):
|
||||||
|
noHorizontalPV = True
|
||||||
|
else:
|
||||||
|
noHorizontalPV = False
|
||||||
|
if "_kccnv" in str(filename):
|
||||||
|
noVerticalPV = True
|
||||||
|
else:
|
||||||
|
noVerticalPV = False
|
||||||
htmlpath = ''
|
htmlpath = ''
|
||||||
postfix = ''
|
postfix = ''
|
||||||
backref = 1
|
backref = 1
|
||||||
@@ -79,88 +87,82 @@ def buildHTML(path, imgfile):
|
|||||||
imgfile, "\" class=\"singlePage\"/></div>\n"
|
imgfile, "\" class=\"singlePage\"/></div>\n"
|
||||||
])
|
])
|
||||||
if options.panelview:
|
if options.panelview:
|
||||||
if rotate:
|
if not noHorizontalPV and not noVerticalPV:
|
||||||
if options.righttoleft:
|
if rotatedPage:
|
||||||
f.writelines(["<div id=\"BoxTL\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
if options.righttoleft:
|
||||||
"'{\"targetId\":\"BoxTL-Panel-Parent\", \"ordinal\":1}'></a></div>\n",
|
order = [1, 3, 2, 4]
|
||||||
"<div id=\"BoxTR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
else:
|
||||||
"'{\"targetId\":\"BoxTR-Panel-Parent\", \"ordinal\":3}'></a></div>\n",
|
order = [2, 4, 1, 3]
|
||||||
"<div id=\"BoxBL\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
|
||||||
"'{\"targetId\":\"BoxBL-Panel-Parent\", \"ordinal\":2}'></a></div>\n",
|
|
||||||
"<div id=\"BoxBR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify="
|
|
||||||
"'{\"targetId\":\"BoxBR-Panel-Parent\", \"ordinal\":4}'></a></div>\n"
|
|
||||||
])
|
|
||||||
else:
|
else:
|
||||||
f.writelines(["<div id=\"BoxTL\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
if options.righttoleft:
|
||||||
"'{\"targetId\":\"BoxTL-Panel-Parent\", \"ordinal\":2}'></a></div>\n",
|
order = [2, 1, 4, 3]
|
||||||
"<div id=\"BoxTR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
else:
|
||||||
"'{\"targetId\":\"BoxTR-Panel-Parent\", \"ordinal\":4}'></a></div>\n",
|
order = [1, 2, 3, 4]
|
||||||
"<div id=\"BoxBL\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
boxes = ["BoxTL", "BoxTR", "BoxBL", "BoxBR"]
|
||||||
"'{\"targetId\":\"BoxBL-Panel-Parent\", \"ordinal\":1}'></a></div>\n",
|
elif noHorizontalPV and not noVerticalPV:
|
||||||
"<div id=\"BoxBR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify="
|
if rotatedPage:
|
||||||
"'{\"targetId\":\"BoxBR-Panel-Parent\", \"ordinal\":3}'></a></div>\n"
|
if options.righttoleft:
|
||||||
])
|
order = [2, 1]
|
||||||
|
else:
|
||||||
|
order = [1, 2]
|
||||||
|
else:
|
||||||
|
order = [1, 2]
|
||||||
|
boxes = ["BoxT", "BoxB"]
|
||||||
|
elif not noHorizontalPV and noVerticalPV:
|
||||||
|
if rotatedPage:
|
||||||
|
order = [1, 2]
|
||||||
|
else:
|
||||||
|
if options.righttoleft:
|
||||||
|
order = [2, 1]
|
||||||
|
else:
|
||||||
|
order = [1, 2]
|
||||||
|
boxes = ["BoxL", "BoxR"]
|
||||||
else:
|
else:
|
||||||
if options.righttoleft:
|
order = [1]
|
||||||
f.writelines(["<div id=\"BoxTL\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
boxes = ["BoxC"]
|
||||||
"'{\"targetId\":\"BoxTL-Panel-Parent\", \"ordinal\":2}'></a></div>\n",
|
for i in range(0, len(boxes)):
|
||||||
"<div id=\"BoxTR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
f.writelines(["<div id=\"" + boxes[i] + "\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
||||||
"'{\"targetId\":\"BoxTR-Panel-Parent\", \"ordinal\":1}'></a></div>\n",
|
"'{\"targetId\":\"" + boxes[i] + "-Panel-Parent\", \"ordinal\":" + str(order[i]),
|
||||||
"<div id=\"BoxBL\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
"}'></a></div>\n"])
|
||||||
"'{\"targetId\":\"BoxBL-Panel-Parent\", \"ordinal\":4}'></a></div>\n",
|
|
||||||
"<div id=\"BoxBR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify="
|
|
||||||
"'{\"targetId\":\"BoxBR-Panel-Parent\", \"ordinal\":3}'></a></div>\n"
|
|
||||||
])
|
|
||||||
else:
|
|
||||||
f.writelines(["<div id=\"BoxTL\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
|
||||||
"'{\"targetId\":\"BoxTL-Panel-Parent\", \"ordinal\":1}'></a></div>\n",
|
|
||||||
"<div id=\"BoxTR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
|
||||||
"'{\"targetId\":\"BoxTR-Panel-Parent\", \"ordinal\":2}'></a></div>\n",
|
|
||||||
"<div id=\"BoxBL\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify=",
|
|
||||||
"'{\"targetId\":\"BoxBL-Panel-Parent\", \"ordinal\":3}'></a></div>\n",
|
|
||||||
"<div id=\"BoxBR\"><a class=\"app-amzn-magnify\" data-app-amzn-magnify="
|
|
||||||
"'{\"targetId\":\"BoxBR-Panel-Parent\", \"ordinal\":4}'></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] += "_kcchq"
|
imgfilepv[0] += "_kcchq"
|
||||||
imgfilepv = string.join(imgfilepv, ".")
|
imgfilepv = string.join(imgfilepv, ".")
|
||||||
else:
|
else:
|
||||||
imgfilepv = imgfile
|
imgfilepv = imgfile
|
||||||
f.writelines(["<div id=\"BoxTL-Panel-Parent\" class=\"target-mag-parent\"><div id=\"BoxTL-Panel\" class=\"",
|
xy = string.split(filename[0], "_kccx")[1]
|
||||||
"target-mag\"><img src=\"", "../" * backref, "Images/", postfix, imgfilepv, "\" alt=\"",
|
x = string.split(xy, "_kccy")[0].lstrip("0")
|
||||||
imgfilepv, "\"/></div></div>\n",
|
y = string.split(xy, "_kccy")[1].lstrip("0")
|
||||||
"<div id=\"BoxTR-Panel-Parent\" class=\"target-mag-parent\"><div id=\"BoxTR-Panel\" class=\"",
|
if x != "":
|
||||||
"target-mag\"><img src=\"", "../" * backref, "Images/", postfix, imgfilepv, "\" alt=\"",
|
x = "-" + str(float(x)/100) + "%"
|
||||||
imgfilepv, "\"/></div></div>\n",
|
else:
|
||||||
"<div id=\"BoxBL-Panel-Parent\" class=\"target-mag-parent\"><div id=\"BoxBL-Panel\" class=\"",
|
x = "0%"
|
||||||
"target-mag\"><img src=\"", "../" * backref, "Images/", postfix, imgfilepv, "\" alt=\"",
|
if y != "":
|
||||||
imgfilepv, "\"/></div></div>\n",
|
y = "-" + str(float(y)/100) + "%"
|
||||||
"<div id=\"BoxBR-Panel-Parent\" class=\"target-mag-parent\"><div id=\"BoxBR-Panel\" class=\"",
|
else:
|
||||||
"target-mag\"><img src=\"", "../" * backref, "Images/", postfix, imgfilepv, "\" alt=\"",
|
y = "0%"
|
||||||
imgfilepv, "\"/></div></div>\n"
|
boxStyles = {"BoxTL": "left:" + x + ";top:" + y + ";",
|
||||||
])
|
"BoxTR": "right:" + x + ";top:" + y + ";",
|
||||||
|
"BoxBL": "left:" + x + ";bottom:" + y + ";",
|
||||||
|
"BoxBR": "right:" + x + ";bottom:" + y + ";",
|
||||||
|
"BoxT": "left:-25%;top:" + y + ";",
|
||||||
|
"BoxB": "left:-25%;bottom:" + y + ";",
|
||||||
|
"BoxL": "left:" + x + ";top:-25%;",
|
||||||
|
"BoxR": "right:" + x + ";top:-25%;",
|
||||||
|
"BoxC": "right:-25%;top:-25%;"
|
||||||
|
}
|
||||||
|
for box in boxes:
|
||||||
|
f.writelines(["<div id=\"" + box + "-Panel-Parent\" class=\"target-mag-parent\"><div id=\"",
|
||||||
|
"Generic-Panel\" class=\"target-mag\"><img style=\"" + boxStyles[box] + "\" src=\"",
|
||||||
|
"../" * backref, "Images/", postfix, imgfilepv, "\" alt=\"" + imgfilepv,
|
||||||
|
"\"/></div></div>\n",
|
||||||
|
])
|
||||||
f.writelines(["</div>\n</body>\n</html>"])
|
f.writelines(["</div>\n</body>\n</html>"])
|
||||||
f.close()
|
f.close()
|
||||||
return path, imgfile
|
return path, imgfile
|
||||||
|
|
||||||
|
|
||||||
def buildBlankHTML(path):
|
|
||||||
f = open(os.path.join(path, 'blank.html'), "w")
|
|
||||||
f.writelines(["<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" ",
|
|
||||||
"\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n",
|
|
||||||
"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n",
|
|
||||||
"<head>\n",
|
|
||||||
"<title></title>\n",
|
|
||||||
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n",
|
|
||||||
"</head>\n",
|
|
||||||
"<body>\n",
|
|
||||||
"</body>\n",
|
|
||||||
"</html>"])
|
|
||||||
f.close()
|
|
||||||
return path
|
|
||||||
|
|
||||||
|
|
||||||
def buildNCX(dstdir, title, chapters):
|
def buildNCX(dstdir, title, chapters):
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
options.uuid = str(uuid4())
|
options.uuid = str(uuid4())
|
||||||
@@ -173,16 +175,18 @@ def buildNCX(dstdir, title, chapters):
|
|||||||
"<ncx version=\"2005-1\" xml:lang=\"en-US\" xmlns=\"http://www.daisy.org/z3986/2005/ncx/\">\n",
|
"<ncx version=\"2005-1\" xml:lang=\"en-US\" xmlns=\"http://www.daisy.org/z3986/2005/ncx/\">\n",
|
||||||
"<head>\n",
|
"<head>\n",
|
||||||
"<meta name=\"dtb:uid\" content=\"", options.uuid, "\"/>\n",
|
"<meta name=\"dtb:uid\" content=\"", options.uuid, "\"/>\n",
|
||||||
"<meta name=\"dtb:depth\" content=\"2\"/>\n",
|
"<meta name=\"dtb:depth\" content=\"1\"/>\n",
|
||||||
"<meta name=\"dtb:totalPageCount\" content=\"0\"/>\n",
|
"<meta name=\"dtb:totalPageCount\" content=\"0\"/>\n",
|
||||||
"<meta name=\"dtb:maxPageNumber\" content=\"0\"/>\n",
|
"<meta name=\"dtb:maxPageNumber\" content=\"0\"/>\n",
|
||||||
|
"<meta name=\"generated\" content=\"true\"/>\n",
|
||||||
"</head>\n",
|
"</head>\n",
|
||||||
"<docTitle><text>", title, "</text></docTitle>\n",
|
"<docTitle><text>", title, "</text></docTitle>\n",
|
||||||
"<navMap>"
|
"<navMap>"
|
||||||
])
|
])
|
||||||
for chapter in chapters:
|
for chapter in chapters:
|
||||||
folder = chapter[0].replace(os.path.join(dstdir, 'OEBPS'), '').lstrip('/').lstrip('\\\\')
|
folder = chapter[0].replace(os.path.join(dstdir, 'OEBPS'), '').lstrip('/').lstrip('\\\\')
|
||||||
title = os.path.basename(folder)
|
if os.path.basename(folder) != "Text":
|
||||||
|
title = os.path.basename(folder)
|
||||||
filename = getImageFileName(os.path.join(folder, chapter[1]))
|
filename = getImageFileName(os.path.join(folder, chapter[1]))
|
||||||
f.write("<navPoint id=\"" + folder.replace('/', '_').replace('\\', '_') + "\"><navLabel><text>" + title
|
f.write("<navPoint id=\"" + folder.replace('/', '_').replace('\\', '_') + "\"><navLabel><text>" + title
|
||||||
+ "</text></navLabel><content src=\"" + filename[0].replace("\\", "/") + ".html\"/></navPoint>\n")
|
+ "</text></navLabel><content src=\"" + filename[0].replace("\\", "/") + ".html\"/></navPoint>\n")
|
||||||
@@ -197,38 +201,33 @@ def buildOPF(dstdir, title, filelist, cover=None):
|
|||||||
imgres = str(deviceres[0]) + "x" + str(deviceres[1])
|
imgres = str(deviceres[0]) + "x" + str(deviceres[1])
|
||||||
if options.righttoleft:
|
if options.righttoleft:
|
||||||
writingmode = "horizontal-rl"
|
writingmode = "horizontal-rl"
|
||||||
facing = "right"
|
|
||||||
facing1 = "right"
|
|
||||||
facing2 = "left"
|
|
||||||
else:
|
else:
|
||||||
writingmode = "horizontal-lr"
|
writingmode = "horizontal-lr"
|
||||||
facing = "left"
|
|
||||||
facing1 = "left"
|
|
||||||
facing2 = "right"
|
|
||||||
f = open(opffile, "w")
|
f = open(opffile, "w")
|
||||||
f.writelines(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
|
f.writelines(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
|
||||||
"<package version=\"2.0\" unique-identifier=\"BookID\" xmlns=\"http://www.idpf.org/2007/opf\">\n",
|
"<package version=\"2.0\" unique-identifier=\"BookID\" ",
|
||||||
"<metadata xmlns:dc=\"http://purl.org/dc/elements/1.1/\" ",
|
"xmlns=\"http://www.idpf.org/2007/opf\">\n",
|
||||||
"xmlns:opf=\"http://www.idpf.org/2007/opf\">\n",
|
"<metadata xmlns:opf=\"http://www.idpf.org/2007/opf\" ",
|
||||||
|
"xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n",
|
||||||
"<dc:title>", title, "</dc:title>\n",
|
"<dc:title>", title, "</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",
|
||||||
|
"<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=\"cover\" content=\"cover\"/>\n",
|
"<meta name=\"cover\" content=\"cover\"/>\n",
|
||||||
"<meta name=\"book-type\" content=\"comic\"/>\n",
|
"<meta name=\"book-type\" content=\"comic\"/>\n",
|
||||||
|
"<meta name=\"rendition:layout\" content=\"pre-paginated\"/>\n",
|
||||||
"<meta name=\"zero-gutter\" content=\"true\"/>\n",
|
"<meta name=\"zero-gutter\" content=\"true\"/>\n",
|
||||||
"<meta name=\"zero-margin\" content=\"true\"/>\n",
|
"<meta name=\"zero-margin\" content=\"true\"/>\n",
|
||||||
"<meta name=\"fixed-layout\" content=\"true\"/>\n"
|
"<meta name=\"fixed-layout\" content=\"true\"/>\n"
|
||||||
])
|
"<meta name=\"rendition:orientation\" content=\"portrait\"/>\n",
|
||||||
if options.landscapemode:
|
"<meta name=\"orientation-lock\" content=\"portrait\"/>\n",
|
||||||
f.writelines(["<meta name=\"rendition:orientation\" content=\"auto\"/>\n",
|
"<meta name=\"original-resolution\" content=\"", imgres, "\"/>\n",
|
||||||
"<meta name=\"orientation-lock\" content=\"none\"/>\n"])
|
|
||||||
else:
|
|
||||||
f.writelines(["<meta name=\"rendition:orientation\" content=\"portrait\"/>\n",
|
|
||||||
"<meta name=\"orientation-lock\" content=\"portrait\"/>\n"])
|
|
||||||
f.writelines(["<meta name=\"original-resolution\" content=\"", imgres, "\"/>\n",
|
|
||||||
"<meta name=\"primary-writing-mode\" content=\"", writingmode, "\"/>\n",
|
"<meta name=\"primary-writing-mode\" content=\"", writingmode, "\"/>\n",
|
||||||
"<meta name=\"rendition:layout\" content=\"pre-paginated\"/>\n",
|
"<meta name=\"ke-border-color\" content=\"#ffffff\"/>\n",
|
||||||
|
"<meta name=\"ke-border-width\" content=\"0\"/>\n",
|
||||||
"</metadata>\n<manifest>\n<item id=\"ncx\" href=\"toc.ncx\" ",
|
"</metadata>\n<manifest>\n<item id=\"ncx\" href=\"toc.ncx\" ",
|
||||||
"media-type=\"application/x-dtbncx+xml\"/>\n"])
|
"media-type=\"application/x-dtbncx+xml\"/>\n"])
|
||||||
if cover is not None:
|
if cover is not None:
|
||||||
@@ -253,44 +252,10 @@ def buildOPF(dstdir, title, filelist, cover=None):
|
|||||||
mt = 'image/jpeg'
|
mt = 'image/jpeg'
|
||||||
f.write("<item id=\"img_" + uniqueid + "\" href=\"" + folder + "/" + path[1] + "\" media-type=\""
|
f.write("<item id=\"img_" + uniqueid + "\" href=\"" + folder + "/" + path[1] + "\" media-type=\""
|
||||||
+ mt + "\"/>\n")
|
+ mt + "\"/>\n")
|
||||||
if options.landscapemode and splitCount > 0:
|
|
||||||
splitCountUsed = 1
|
|
||||||
while splitCountUsed <= splitCount:
|
|
||||||
f.write("<item id=\"blank-page" + str(splitCountUsed) +
|
|
||||||
"\" href=\"Text/blank.html\" media-type=\"application/xhtml+xml\"/>\n")
|
|
||||||
splitCountUsed += 1
|
|
||||||
f.write("<item id=\"css\" href=\"Text/style.css\" media-type=\"text/css\"/>\n")
|
f.write("<item id=\"css\" href=\"Text/style.css\" media-type=\"text/css\"/>\n")
|
||||||
f.write("</manifest>\n<spine toc=\"ncx\">\n")
|
f.write("</manifest>\n<spine toc=\"ncx\">\n")
|
||||||
splitCountUsed = 1
|
|
||||||
for entry in reflist:
|
for entry in reflist:
|
||||||
if "_kcca" in str(entry):
|
f.write("<itemref idref=\"page_" + entry + "\"/>\n")
|
||||||
# noinspection PyRedundantParentheses
|
|
||||||
if ((options.righttoleft and facing == 'left') or (not options.righttoleft and facing == 'right')) and\
|
|
||||||
options.landscapemode:
|
|
||||||
f.write("<itemref idref=\"blank-page" + str(splitCountUsed) + "\" properties=\"layout-blank\"/>\n")
|
|
||||||
splitCountUsed += 1
|
|
||||||
if options.landscapemode:
|
|
||||||
f.write("<itemref idref=\"page_" + entry + "\" properties=\"page-spread-" + facing1 + "\"/>\n")
|
|
||||||
else:
|
|
||||||
f.write("<itemref idref=\"page_" + entry + "\"/>\n")
|
|
||||||
elif "_kccb" in str(entry):
|
|
||||||
if options.landscapemode:
|
|
||||||
f.write("<itemref idref=\"page_" + entry + "\" properties=\"page-spread-" + facing2 + "\"/>\n")
|
|
||||||
else:
|
|
||||||
f.write("<itemref idref=\"page_" + entry + "\"/>\n")
|
|
||||||
if options.righttoleft:
|
|
||||||
facing = "right"
|
|
||||||
else:
|
|
||||||
facing = "left"
|
|
||||||
else:
|
|
||||||
if options.landscapemode:
|
|
||||||
f.write("<itemref idref=\"page_" + entry + "\" properties=\"page-spread-" + facing + "\"/>\n")
|
|
||||||
else:
|
|
||||||
f.write("<itemref idref=\"page_" + entry + "\"/>\n")
|
|
||||||
if facing == 'right':
|
|
||||||
facing = 'left'
|
|
||||||
else:
|
|
||||||
facing = 'right'
|
|
||||||
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'))
|
||||||
@@ -322,24 +287,22 @@ def getImageFileName(imgfile):
|
|||||||
return filename
|
return filename
|
||||||
|
|
||||||
|
|
||||||
def applyImgOptimization(img, isSplit, toRight, options, overrideQuality=5):
|
def applyImgOptimization(img, opt, overrideQuality=5):
|
||||||
if not options.webtoon:
|
img.getImageFill(opt.webtoon)
|
||||||
|
if not opt.webtoon:
|
||||||
img.cropWhiteSpace(10.0)
|
img.cropWhiteSpace(10.0)
|
||||||
if options.cutpagenumbers and not options.webtoon:
|
if opt.cutpagenumbers and not opt.webtoon:
|
||||||
img.cutPageNumber()
|
img.cutPageNumber()
|
||||||
img.optimizeImage(options.gamma)
|
img.optimizeImage(opt.gamma)
|
||||||
if overrideQuality != 5:
|
if overrideQuality != 5:
|
||||||
img.resizeImage(options.upscale, options.stretch, options.black_borders, isSplit, toRight,
|
img.resizeImage(opt.upscale, opt.stretch, opt.bordersColor, overrideQuality)
|
||||||
options.landscapemode, overrideQuality)
|
|
||||||
else:
|
else:
|
||||||
img.resizeImage(options.upscale, options.stretch, options.black_borders, isSplit, toRight,
|
img.resizeImage(opt.upscale, opt.stretch, opt.bordersColor, opt.quality)
|
||||||
options.landscapemode, options.quality)
|
if opt.forcepng and not opt.forcecolor:
|
||||||
if options.forcepng and not options.forcecolor:
|
|
||||||
img.quantizeImage()
|
img.quantizeImage()
|
||||||
|
|
||||||
|
|
||||||
def dirImgProcess(path):
|
def dirImgProcess(path):
|
||||||
global options, splitCount
|
|
||||||
work = []
|
work = []
|
||||||
pagenumber = 0
|
pagenumber = 0
|
||||||
pagenumbermodifier = 0
|
pagenumbermodifier = 0
|
||||||
@@ -378,7 +341,6 @@ def dirImgProcess(path):
|
|||||||
splitpages.sort()
|
splitpages.sort()
|
||||||
for page in splitpages:
|
for page in splitpages:
|
||||||
if (page + pagenumbermodifier) % 2 == 0:
|
if (page + pagenumbermodifier) % 2 == 0:
|
||||||
splitCount += 1
|
|
||||||
pagenumbermodifier += 1
|
pagenumbermodifier += 1
|
||||||
pagenumbermodifier += 1
|
pagenumbermodifier += 1
|
||||||
else:
|
else:
|
||||||
@@ -386,9 +348,9 @@ def dirImgProcess(path):
|
|||||||
raise UserWarning("Source directory is empty.")
|
raise UserWarning("Source directory is empty.")
|
||||||
|
|
||||||
|
|
||||||
def fileImgProcess_init(queue, options):
|
def fileImgProcess_init(queue, opt):
|
||||||
fileImgProcess.queue = queue
|
fileImgProcess.queue = queue
|
||||||
fileImgProcess.options = options
|
fileImgProcess.options = opt
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
@@ -396,59 +358,53 @@ def fileImgProcess(work):
|
|||||||
afile = work[0]
|
afile = work[0]
|
||||||
dirpath = work[1]
|
dirpath = work[1]
|
||||||
pagenumber = work[2]
|
pagenumber = work[2]
|
||||||
options = fileImgProcess.options
|
opt = fileImgProcess.options
|
||||||
output = None
|
output = None
|
||||||
if options.verbose:
|
if opt.verbose:
|
||||||
print "Optimizing " + afile + " for " + options.profile
|
print "Optimizing " + afile + " for " + opt.profile
|
||||||
else:
|
else:
|
||||||
print ".",
|
print ".",
|
||||||
fileImgProcess.queue.put(".")
|
fileImgProcess.queue.put(".")
|
||||||
img = image.ComicPage(os.path.join(dirpath, afile), options.profileData)
|
img = image.ComicPage(os.path.join(dirpath, afile), opt.profileData)
|
||||||
if options.quality == 2:
|
if opt.quality == 2:
|
||||||
wipe = False
|
wipe = False
|
||||||
else:
|
else:
|
||||||
wipe = True
|
wipe = True
|
||||||
if options.nosplitrotate:
|
if opt.nosplitrotate:
|
||||||
split = None
|
split = None
|
||||||
else:
|
else:
|
||||||
split = img.splitPage(dirpath, options.righttoleft, options.rotate)
|
split = img.splitPage(dirpath, opt.righttoleft, opt.rotate)
|
||||||
if split is not None and split is not "R":
|
if split is not None:
|
||||||
if options.verbose:
|
if opt.verbose:
|
||||||
print "Splitted " + afile
|
print "Splitted " + afile
|
||||||
if options.righttoleft:
|
|
||||||
toRight1 = False
|
|
||||||
toRight2 = True
|
|
||||||
else:
|
|
||||||
toRight1 = True
|
|
||||||
toRight2 = False
|
|
||||||
output = pagenumber
|
output = pagenumber
|
||||||
img0 = image.ComicPage(split[0], options.profileData)
|
img0 = image.ComicPage(split[0], opt.profileData)
|
||||||
applyImgOptimization(img0, True, toRight1, options)
|
applyImgOptimization(img0, opt)
|
||||||
img0.saveToDir(dirpath, options.forcepng, options.forcecolor, wipe)
|
img0.saveToDir(dirpath, opt.forcepng, opt.forcecolor, wipe)
|
||||||
img1 = image.ComicPage(split[1], options.profileData)
|
img1 = image.ComicPage(split[1], opt.profileData)
|
||||||
applyImgOptimization(img1, True, toRight2, options)
|
applyImgOptimization(img1, opt)
|
||||||
img1.saveToDir(dirpath, options.forcepng, options.forcecolor, wipe)
|
img1.saveToDir(dirpath, opt.forcepng, opt.forcecolor, wipe)
|
||||||
if options.quality == 2:
|
if opt.quality == 2:
|
||||||
img3 = image.ComicPage(split[0], options.profileData)
|
img3 = image.ComicPage(split[0], opt.profileData)
|
||||||
applyImgOptimization(img3, True, toRight1, options, 0)
|
applyImgOptimization(img3, opt, 0)
|
||||||
img3.saveToDir(dirpath, options.forcepng, options.forcecolor, True)
|
img3.saveToDir(dirpath, opt.forcepng, opt.forcecolor, True)
|
||||||
img4 = image.ComicPage(split[1], options.profileData)
|
img4 = image.ComicPage(split[1], opt.profileData)
|
||||||
applyImgOptimization(img4, True, toRight2, options, 0)
|
applyImgOptimization(img4, opt, 0)
|
||||||
img4.saveToDir(dirpath, options.forcepng, options.forcecolor, True)
|
img4.saveToDir(dirpath, opt.forcepng, opt.forcecolor, True)
|
||||||
else:
|
else:
|
||||||
applyImgOptimization(img, False, False, options)
|
applyImgOptimization(img, opt)
|
||||||
img.saveToDir(dirpath, options.forcepng, options.forcecolor, wipe, split)
|
img.saveToDir(dirpath, opt.forcepng, opt.forcecolor, wipe)
|
||||||
if options.quality == 2:
|
if opt.quality == 2:
|
||||||
img2 = image.ComicPage(os.path.join(dirpath, afile), options.profileData)
|
img2 = image.ComicPage(os.path.join(dirpath, afile), opt.profileData)
|
||||||
if split == "R":
|
if img.rotated:
|
||||||
img2.image = img2.image.rotate(90)
|
img2.image = img2.image.rotate(90)
|
||||||
applyImgOptimization(img2, False, False, options, 0)
|
img2.rotated = True
|
||||||
img2.saveToDir(dirpath, options.forcepng, options.forcecolor, True, split)
|
applyImgOptimization(img2, opt, 0)
|
||||||
|
img2.saveToDir(dirpath, opt.forcepng, opt.forcecolor, True)
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
def genEpubStruct(path):
|
def genEpubStruct(path):
|
||||||
global options
|
|
||||||
filelist = []
|
filelist = []
|
||||||
chapterlist = []
|
chapterlist = []
|
||||||
cover = None
|
cover = None
|
||||||
@@ -508,6 +464,36 @@ def genEpubStruct(path):
|
|||||||
"height: ", str(panelviewsize[1]), "px;\n",
|
"height: ", str(panelviewsize[1]), "px;\n",
|
||||||
"width: ", str(panelviewsize[0]), "px;\n",
|
"width: ", str(panelviewsize[0]), "px;\n",
|
||||||
"}\n",
|
"}\n",
|
||||||
|
"#Generic-Panel {\n",
|
||||||
|
"top: 0;\n",
|
||||||
|
"height: 100%;\n",
|
||||||
|
"width: 100%;\n",
|
||||||
|
"}\n",
|
||||||
|
"#BoxC {\n",
|
||||||
|
"top: 0;\n",
|
||||||
|
"height: 100%;\n",
|
||||||
|
"width: 100%;\n",
|
||||||
|
"}\n",
|
||||||
|
"#BoxT {\n",
|
||||||
|
"top: 0;\n",
|
||||||
|
"height: 50%;\n",
|
||||||
|
"width: 100%;\n",
|
||||||
|
"}\n",
|
||||||
|
"#BoxB {\n",
|
||||||
|
"bottom: 0;\n",
|
||||||
|
"height: 50%;\n",
|
||||||
|
"width: 100%;\n",
|
||||||
|
"}\n",
|
||||||
|
"#BoxL {\n",
|
||||||
|
"left: 0;\n",
|
||||||
|
"height: 100%;\n",
|
||||||
|
"width: 50%;\n",
|
||||||
|
"}\n",
|
||||||
|
"#BoxR {\n",
|
||||||
|
"right: 0;\n",
|
||||||
|
"height: 100%;\n",
|
||||||
|
"width: 50%;\n",
|
||||||
|
"}\n",
|
||||||
"#BoxTL {\n",
|
"#BoxTL {\n",
|
||||||
"top: 0;\n",
|
"top: 0;\n",
|
||||||
"left: 0;\n",
|
"left: 0;\n",
|
||||||
@@ -531,47 +517,7 @@ def genEpubStruct(path):
|
|||||||
"right: 0;\n",
|
"right: 0;\n",
|
||||||
"height: 50%;\n",
|
"height: 50%;\n",
|
||||||
"width: 50%;\n",
|
"width: 50%;\n",
|
||||||
"}\n",
|
"}",
|
||||||
"#BoxTL-Panel {\n",
|
|
||||||
"top: 0;\n",
|
|
||||||
"left: 0;\n",
|
|
||||||
"height: 100%;\n",
|
|
||||||
"width: 100%;\n",
|
|
||||||
"}\n",
|
|
||||||
"#BoxTL-Panel img {\n",
|
|
||||||
"top: 0%;\n",
|
|
||||||
"left: 0%;\n",
|
|
||||||
"}\n",
|
|
||||||
"#BoxTR-Panel {\n",
|
|
||||||
"top: 0;\n",
|
|
||||||
"right: 0;\n",
|
|
||||||
"height: 100%;\n",
|
|
||||||
"width: 100%;\n",
|
|
||||||
"}\n",
|
|
||||||
"#BoxTR-Panel img {\n",
|
|
||||||
"top: 0%;\n",
|
|
||||||
"right: 0%;\n",
|
|
||||||
"}\n",
|
|
||||||
"#BoxBL-Panel {\n",
|
|
||||||
"bottom: 0;\n",
|
|
||||||
"left: 0;\n",
|
|
||||||
"height: 100%;\n",
|
|
||||||
"width: 100%;\n",
|
|
||||||
"}\n",
|
|
||||||
"#BoxBL-Panel img {\n",
|
|
||||||
"bottom: 0%;\n",
|
|
||||||
"left: 0%;\n",
|
|
||||||
"}\n",
|
|
||||||
"#BoxBR-Panel {\n",
|
|
||||||
"bottom: 0;\n",
|
|
||||||
"right: 0;\n",
|
|
||||||
"height: 100%;\n",
|
|
||||||
"width: 100%;\n",
|
|
||||||
"}\n",
|
|
||||||
"#BoxBR-Panel img {\n",
|
|
||||||
"bottom: 0%;\n",
|
|
||||||
"right: 0%;\n",
|
|
||||||
"}"
|
|
||||||
])
|
])
|
||||||
f.close()
|
f.close()
|
||||||
for (dirpath, dirnames, filenames) in os.walk(os.path.join(path, 'OEBPS', 'Images')):
|
for (dirpath, dirnames, filenames) in os.walk(os.path.join(path, 'OEBPS', 'Images')):
|
||||||
@@ -588,13 +534,11 @@ def genEpubStruct(path):
|
|||||||
'cover' + getImageFileName(filelist[-1][1])[1])
|
'cover' + getImageFileName(filelist[-1][1])[1])
|
||||||
copyfile(os.path.join(filelist[-1][0], filelist[-1][1]), cover)
|
copyfile(os.path.join(filelist[-1][0], filelist[-1][1]), cover)
|
||||||
buildNCX(path, options.title, chapterlist)
|
buildNCX(path, options.title, chapterlist)
|
||||||
# ensure we're sorting files alphabetically
|
# Ensure we're sorting files alphabetically
|
||||||
convert = lambda text: int(text) if text.isdigit() else text
|
convert = lambda text: int(text) if text.isdigit() else text
|
||||||
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
|
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
|
||||||
filelist.sort(key=lambda name: (alphanum_key(name[0].lower()), alphanum_key(name[1].lower())))
|
filelist.sort(key=lambda name: (alphanum_key(name[0].lower()), alphanum_key(name[1].lower())))
|
||||||
buildOPF(path, options.title, filelist, cover)
|
buildOPF(path, options.title, filelist, cover)
|
||||||
if options.landscapemode and splitCount > 0:
|
|
||||||
filelist.append(buildBlankHTML(os.path.join(path, 'OEBPS', 'Text')))
|
|
||||||
|
|
||||||
|
|
||||||
def getWorkFolder(afile):
|
def getWorkFolder(afile):
|
||||||
@@ -625,8 +569,7 @@ def getWorkFolder(afile):
|
|||||||
path = cbx.extract(workdir)
|
path = cbx.extract(workdir)
|
||||||
except OSError:
|
except OSError:
|
||||||
rmtree(workdir)
|
rmtree(workdir)
|
||||||
print 'Unrar not found, please download from ' + \
|
print 'UnRAR/7za not found or file failed to extract!'
|
||||||
'http://www.rarlab.com/download.htm and put into your PATH.'
|
|
||||||
sys.exit(21)
|
sys.exit(21)
|
||||||
else:
|
else:
|
||||||
rmtree(workdir)
|
rmtree(workdir)
|
||||||
@@ -637,9 +580,9 @@ def getWorkFolder(afile):
|
|||||||
|
|
||||||
|
|
||||||
def slugify(value):
|
def slugify(value):
|
||||||
# Normalizes string, converts to lowercase, removes non-alpha characters,
|
# Normalizes string, converts to lowercase, removes non-alpha characters and converts spaces to hyphens.
|
||||||
# and converts spaces to hyphens.
|
|
||||||
import unicodedata
|
import unicodedata
|
||||||
|
#noinspection PyArgumentList
|
||||||
value = unicodedata.normalize('NFKD', unicode(value, 'latin1')).encode('ascii', 'ignore')
|
value = unicodedata.normalize('NFKD', unicode(value, 'latin1')).encode('ascii', 'ignore')
|
||||||
value = re.sub('[^\w\s\.-]', '', value).strip().lower()
|
value = re.sub('[^\w\s\.-]', '', value).strip().lower()
|
||||||
value = re.sub('[-\.\s]+', '-', value)
|
value = re.sub('[-\.\s]+', '-', value)
|
||||||
@@ -689,6 +632,7 @@ def getDirectorySize(start_path='.'):
|
|||||||
return total_size
|
return total_size
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyUnusedLocal
|
||||||
def createNewTome(parentPath):
|
def createNewTome(parentPath):
|
||||||
tomePathRoot = tempfile.mkdtemp('', 'KCC-TMP-')
|
tomePathRoot = tempfile.mkdtemp('', 'KCC-TMP-')
|
||||||
#tomePathRoot = tempfile.mkdtemp('', 'KCC-TMP-', parentPath)
|
#tomePathRoot = tempfile.mkdtemp('', 'KCC-TMP-', parentPath)
|
||||||
@@ -843,21 +787,22 @@ def Usage():
|
|||||||
|
|
||||||
|
|
||||||
def main(argv=None, qtGUI=None):
|
def main(argv=None, qtGUI=None):
|
||||||
global parser, options, epub_path, splitCount, GUI
|
global parser, options, GUI
|
||||||
parser = OptionParser(usage="Usage: %prog [options] comic_file|comic_folder", add_help_option=False)
|
parser = OptionParser(usage="Usage: %prog [options] comic_file|comic_folder", add_help_option=False)
|
||||||
mainOptions = OptionGroup(parser, "MAIN")
|
mainOptions = OptionGroup(parser, "MAIN")
|
||||||
experimentalOptions = OptionGroup(parser, "EXPERIMENTAL")
|
|
||||||
processingOptions = OptionGroup(parser, "PROCESSING")
|
processingOptions = OptionGroup(parser, "PROCESSING")
|
||||||
outputOptions = OptionGroup(parser, "OUTPUT SETTINGS")
|
outputOptions = OptionGroup(parser, "OUTPUT SETTINGS")
|
||||||
customProfileOptions = OptionGroup(parser, "CUSTOM PROFILE")
|
customProfileOptions = OptionGroup(parser, "CUSTOM PROFILE")
|
||||||
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, K3, K4NT, K4T, KDX, KDXG, KHD, KF, KFHD,"
|
help="Device profile (Choose one among K1, K2, K345, KDX, KDXG, KHD, KF, KFHD, KFHD8, KFHDX,"
|
||||||
" KFHD8, KFA) [Default=KHD]")
|
" KFHDX8, KFA) [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,
|
||||||
help="Manga style (Right-to-left reading and splitting)")
|
help="Manga style (Right-to-left reading and splitting)")
|
||||||
|
mainOptions.add_option("-w", "--webtoon", action="store_true", dest="webtoon", default=False,
|
||||||
|
help="Webtoon processing mode"),
|
||||||
outputOptions.add_option("-o", "--output", action="store", dest="output", default=None,
|
outputOptions.add_option("-o", "--output", action="store", dest="output", default=None,
|
||||||
help="Output generated file to specified directory or file")
|
help="Output generated file to specified directory or file")
|
||||||
outputOptions.add_option("-t", "--title", action="store", dest="title", default="defaulttitle",
|
outputOptions.add_option("-t", "--title", action="store", dest="title", default="defaulttitle",
|
||||||
@@ -866,10 +811,10 @@ def main(argv=None, qtGUI=None):
|
|||||||
help="Outputs a CBZ archive and does not generate EPUB")
|
help="Outputs a CBZ archive and does not generate EPUB")
|
||||||
outputOptions.add_option("--batchsplit", action="store_true", dest="batchsplit", default=False,
|
outputOptions.add_option("--batchsplit", action="store_true", dest="batchsplit", default=False,
|
||||||
help="Split output into multiple files"),
|
help="Split output into multiple files"),
|
||||||
experimentalOptions.add_option("-w", "--webtoon", action="store_true", dest="webtoon", default=False,
|
|
||||||
help="Webtoon processing mode"),
|
|
||||||
processingOptions.add_option("--blackborders", action="store_true", dest="black_borders", default=False,
|
processingOptions.add_option("--blackborders", action="store_true", dest="black_borders", default=False,
|
||||||
help="Use black borders instead of white ones")
|
help="Disable autodetection and force black borders")
|
||||||
|
processingOptions.add_option("--whiteborders", action="store_true", dest="white_borders", default=False,
|
||||||
|
help="Disable autodetection and force white borders")
|
||||||
processingOptions.add_option("--forcecolor", action="store_true", dest="forcecolor", default=False,
|
processingOptions.add_option("--forcecolor", action="store_true", dest="forcecolor", default=False,
|
||||||
help="Don't convert images to grayscale")
|
help="Don't convert images to grayscale")
|
||||||
processingOptions.add_option("--forcepng", action="store_true", dest="forcepng", default=False,
|
processingOptions.add_option("--forcepng", action="store_true", dest="forcepng", default=False,
|
||||||
@@ -897,7 +842,6 @@ def main(argv=None, qtGUI=None):
|
|||||||
otherOptions.add_option("-h", "--help", action="help",
|
otherOptions.add_option("-h", "--help", action="help",
|
||||||
help="Show this help message and exit")
|
help="Show this help message and exit")
|
||||||
parser.add_option_group(mainOptions)
|
parser.add_option_group(mainOptions)
|
||||||
parser.add_option_group(experimentalOptions)
|
|
||||||
parser.add_option_group(outputOptions)
|
parser.add_option_group(outputOptions)
|
||||||
parser.add_option_group(processingOptions)
|
parser.add_option_group(processingOptions)
|
||||||
parser.add_option_group(customProfileOptions)
|
parser.add_option_group(customProfileOptions)
|
||||||
@@ -920,7 +864,6 @@ def main(argv=None, qtGUI=None):
|
|||||||
comic2panel.main(['-y ' + str(options.customheight), '-i', path], qtGUI)
|
comic2panel.main(['-y ' + str(options.customheight), '-i', 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', path], qtGUI)
|
||||||
splitCount = 0
|
|
||||||
if options.imgproc:
|
if options.imgproc:
|
||||||
print "\nProcessing images..."
|
print "\nProcessing images..."
|
||||||
if GUI:
|
if GUI:
|
||||||
@@ -984,45 +927,29 @@ def getOutputFilename(srcpath, wantedname, ext, tomeNumber):
|
|||||||
|
|
||||||
def checkOptions():
|
def checkOptions():
|
||||||
global options
|
global options
|
||||||
# Webtoon mode mandatory options
|
options.panelview = True
|
||||||
if options.webtoon:
|
options.bordersColor = None
|
||||||
options.nosplitrotate = True
|
if options.white_borders:
|
||||||
options.black_borders = False
|
options.bordersColor = "white"
|
||||||
options.quality = 0
|
if options.black_borders:
|
||||||
# Landscape mode is only supported by Kindle Touch and Paperwhite.
|
options.bordersColor = "black"
|
||||||
if options.profile == 'K4T' or options.profile == 'KHD':
|
|
||||||
options.landscapemode = True
|
|
||||||
else:
|
|
||||||
options.landscapemode = False
|
|
||||||
# Older Kindle don't support Virtual Panel View. We providing them configuration that will fake that feature.
|
|
||||||
# Ultra quality mode require Real Panel View. Landscape mode don't work correcly without Virtual Panel View.
|
|
||||||
if options.profile == 'K3' or options.profile == 'K4NT' or options.quality == 2:
|
|
||||||
# Real Panel View
|
|
||||||
options.panelview = True
|
|
||||||
options.landscapemode = False
|
|
||||||
else:
|
|
||||||
# Virtual Panel View
|
|
||||||
options.panelview = False
|
|
||||||
# Disabling grayscale conversion for Kindle Fire family.
|
# Disabling grayscale conversion for Kindle Fire family.
|
||||||
if options.profile == 'KF' or options.profile == 'KFHD' or options.profile == 'KFHD8' or options.forcecolor:
|
if options.profile == 'KF' or options.profile == 'KFHD' or options.profile == 'KFHD8' or options.profile == 'KFHDX'\
|
||||||
|
or options.profile == 'KFHDX8' or options.forcecolor:
|
||||||
options.forcecolor = True
|
options.forcecolor = True
|
||||||
else:
|
else:
|
||||||
options.forcecolor = False
|
options.forcecolor = False
|
||||||
# Mixing vertical and horizontal pages require real Panel View.
|
|
||||||
# Landscape mode don't work correcly without Virtual Panel View.
|
|
||||||
if options.rotate:
|
|
||||||
options.panelview = True
|
|
||||||
options.landscapemode = False
|
|
||||||
# Older Kindle don't need higher resolution files due lack of Panel View.
|
# Older Kindle don't need higher resolution files due lack of Panel View.
|
||||||
# Kindle Fire family have very high resolution. Bigger images are not needed.
|
if options.profile == 'K1' or options.profile == 'K2' or options.profile == 'KDX' or options.profile == 'KDXG':
|
||||||
if options.profile == 'K1' or options.profile == 'K2' or options.profile == 'KDX' or options.profile == 'KDXG'\
|
|
||||||
or options.profile == 'KF' or options.profile == 'KFHD' or options.profile == 'KFHD8':
|
|
||||||
options.quality = 0
|
options.quality = 0
|
||||||
if options.profile == 'K1' or options.profile == 'K2' or options.profile == 'KDX' or options.profile == 'KDXG':
|
options.panelview = False
|
||||||
options.panelview = False
|
# Webtoon mode mandatory options
|
||||||
# Disable all Kindle features
|
if options.webtoon:
|
||||||
|
options.nosplitrotate = True
|
||||||
|
options.quality = 0
|
||||||
|
options.panelview = False
|
||||||
|
# Disable all Kindle features for other e-readers
|
||||||
if options.profile == 'OTHER':
|
if options.profile == 'OTHER':
|
||||||
options.landscapemode = False
|
|
||||||
options.panelview = False
|
options.panelview = False
|
||||||
options.quality = 0
|
options.quality = 0
|
||||||
# Kindle for Android profile require target resolution.
|
# Kindle for Android profile require target resolution.
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
|
# Copyright (c) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -17,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.2.1'
|
__version__ = '3.3'
|
||||||
__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'
|
||||||
@@ -28,7 +29,7 @@ from shutil import rmtree, copytree, move
|
|||||||
from optparse import OptionParser, OptionGroup
|
from optparse import OptionParser, OptionGroup
|
||||||
from multiprocessing import Pool, Queue, freeze_support
|
from multiprocessing import Pool, Queue, freeze_support
|
||||||
try:
|
try:
|
||||||
# noinspection PyUnresolvedReferences,PyPackageRequirements
|
# noinspection PyUnresolvedReferences
|
||||||
from PIL import Image, ImageStat
|
from PIL import Image, ImageStat
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print "ERROR: Pillow is not installed!"
|
print "ERROR: Pillow is not installed!"
|
||||||
@@ -53,48 +54,9 @@ def getImageFileName(imgfile):
|
|||||||
return filename
|
return filename
|
||||||
|
|
||||||
|
|
||||||
def getImageHistogram(image):
|
def sanitizePanelSize(panel, opt):
|
||||||
histogram = image.histogram()
|
|
||||||
RBGW = []
|
|
||||||
for i in range(256):
|
|
||||||
RBGW.append(histogram[i] + histogram[256 + i] + histogram[512 + i])
|
|
||||||
white = 0
|
|
||||||
black = 0
|
|
||||||
for i in range(245, 256):
|
|
||||||
white += RBGW[i]
|
|
||||||
for i in range(11):
|
|
||||||
black += RBGW[i]
|
|
||||||
if white > black:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def getImageFill(image):
|
|
||||||
imageSize = image.size
|
|
||||||
imageT = image.crop((0, 0, imageSize[0], 1))
|
|
||||||
imageB = image.crop((0, imageSize[1]-1, imageSize[0], imageSize[1]))
|
|
||||||
fill = 0
|
|
||||||
fill += getImageHistogram(imageT)
|
|
||||||
fill += getImageHistogram(imageB)
|
|
||||||
if fill == 2:
|
|
||||||
return 'KCCFB'
|
|
||||||
elif fill == 0:
|
|
||||||
return 'KCCFW'
|
|
||||||
else:
|
|
||||||
imageL = image.crop((0, 0, 1, imageSize[1]))
|
|
||||||
imageR = image.crop((imageSize[0]-1, 0, imageSize[0], imageSize[1]))
|
|
||||||
fill += getImageHistogram(imageL)
|
|
||||||
fill += getImageHistogram(imageR)
|
|
||||||
if fill >= 2:
|
|
||||||
return 'KCCFB'
|
|
||||||
else:
|
|
||||||
return 'KCCFW'
|
|
||||||
|
|
||||||
|
|
||||||
def sanitizePanelSize(panel, options):
|
|
||||||
newPanels = []
|
newPanels = []
|
||||||
if panel[2] > 8 * options.height:
|
if panel[2] > 8 * opt.height:
|
||||||
diff = (panel[2] / 8)
|
diff = (panel[2] / 8)
|
||||||
newPanels.append([panel[0], panel[1] - diff*7, diff])
|
newPanels.append([panel[0], panel[1] - diff*7, diff])
|
||||||
newPanels.append([panel[1] - diff*7, panel[1] - diff*6, diff])
|
newPanels.append([panel[1] - diff*7, panel[1] - diff*6, diff])
|
||||||
@@ -104,13 +66,13 @@ def sanitizePanelSize(panel, options):
|
|||||||
newPanels.append([panel[1] - diff*3, panel[1] - diff*2, diff])
|
newPanels.append([panel[1] - diff*3, panel[1] - diff*2, diff])
|
||||||
newPanels.append([panel[1] - diff*2, panel[1] - diff, diff])
|
newPanels.append([panel[1] - diff*2, panel[1] - diff, diff])
|
||||||
newPanels.append([panel[1] - diff, panel[1], diff])
|
newPanels.append([panel[1] - diff, panel[1], diff])
|
||||||
elif panel[2] > 4 * options.height:
|
elif panel[2] > 4 * opt.height:
|
||||||
diff = (panel[2] / 4)
|
diff = (panel[2] / 4)
|
||||||
newPanels.append([panel[0], panel[1] - diff*3, diff])
|
newPanels.append([panel[0], panel[1] - diff*3, diff])
|
||||||
newPanels.append([panel[1] - diff*3, panel[1] - diff*2, diff])
|
newPanels.append([panel[1] - diff*3, panel[1] - diff*2, diff])
|
||||||
newPanels.append([panel[1] - diff*2, panel[1] - diff, diff])
|
newPanels.append([panel[1] - diff*2, panel[1] - diff, diff])
|
||||||
newPanels.append([panel[1] - diff, panel[1], diff])
|
newPanels.append([panel[1] - diff, panel[1], diff])
|
||||||
elif panel[2] > 2 * options.height:
|
elif panel[2] > 2 * opt.height:
|
||||||
newPanels.append([panel[0], panel[1] - (panel[2] / 2), (panel[2] / 2)])
|
newPanels.append([panel[0], panel[1] - (panel[2] / 2), (panel[2] / 2)])
|
||||||
newPanels.append([panel[1] - (panel[2] / 2), panel[1], (panel[2] / 2)])
|
newPanels.append([panel[1] - (panel[2] / 2), panel[1], (panel[2] / 2)])
|
||||||
else:
|
else:
|
||||||
@@ -118,17 +80,17 @@ def sanitizePanelSize(panel, options):
|
|||||||
return newPanels
|
return newPanels
|
||||||
|
|
||||||
|
|
||||||
def splitImage_init(queue, options):
|
def splitImage_init(queue, opt):
|
||||||
splitImage.queue = queue
|
splitImage.queue = queue
|
||||||
splitImage.options = options
|
splitImage.options = opt
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
def splitImage(work):
|
def splitImage(work):
|
||||||
path = work[0]
|
path = work[0]
|
||||||
name = work[1]
|
name = work[1]
|
||||||
options = splitImage.options
|
opt = splitImage.options
|
||||||
# Harcoded options
|
# Harcoded opttions
|
||||||
threshold = 1.0
|
threshold = 1.0
|
||||||
delta = 15
|
delta = 15
|
||||||
print ".",
|
print ".",
|
||||||
@@ -137,7 +99,7 @@ def splitImage(work):
|
|||||||
filePath = os.path.join(path, name)
|
filePath = os.path.join(path, name)
|
||||||
# Detect corrupted files
|
# Detect corrupted files
|
||||||
try:
|
try:
|
||||||
image = Image.open(filePath)
|
Image.open(filePath)
|
||||||
except IOError:
|
except IOError:
|
||||||
raise RuntimeError('Cannot read image file %s' % filePath)
|
raise RuntimeError('Cannot read image file %s' % filePath)
|
||||||
try:
|
try:
|
||||||
@@ -153,8 +115,8 @@ def splitImage(work):
|
|||||||
image = Image.open(filePath)
|
image = Image.open(filePath)
|
||||||
image = image.convert('RGB')
|
image = image.convert('RGB')
|
||||||
widthImg, heightImg = image.size
|
widthImg, heightImg = image.size
|
||||||
if heightImg > options.height:
|
if heightImg > opt.height:
|
||||||
if options.debug:
|
if opt.debug:
|
||||||
from PIL import ImageDraw
|
from PIL import ImageDraw
|
||||||
debugImage = Image.open(filePath)
|
debugImage = Image.open(filePath)
|
||||||
draw = ImageDraw.Draw(debugImage)
|
draw = ImageDraw.Draw(debugImage)
|
||||||
@@ -176,23 +138,23 @@ def splitImage(work):
|
|||||||
if y1 + delta >= heightImg:
|
if y1 + delta >= heightImg:
|
||||||
y1 = heightImg - 1
|
y1 = heightImg - 1
|
||||||
y2Temp = y1
|
y2Temp = y1
|
||||||
if options.debug:
|
if opt.debug:
|
||||||
draw.line([(0, y1Temp), (widthImg, y1Temp)], fill=(0, 255, 0))
|
draw.line([(0, y1Temp), (widthImg, y1Temp)], fill=(0, 255, 0))
|
||||||
draw.line([(0, y2Temp), (widthImg, y2Temp)], fill=(255, 0, 0))
|
draw.line([(0, y2Temp), (widthImg, y2Temp)], fill=(255, 0, 0))
|
||||||
panelHeight = y2Temp - y1Temp
|
panelHeight = y2Temp - y1Temp
|
||||||
if panelHeight > delta:
|
if panelHeight > delta:
|
||||||
# Panels that can't be cut nicely will be forcefully splitted
|
# Panels that can't be cut nicely will be forcefully splitted
|
||||||
panelsCleaned = sanitizePanelSize([y1Temp, y2Temp, panelHeight], options)
|
panelsCleaned = sanitizePanelSize([y1Temp, y2Temp, panelHeight], opt)
|
||||||
for panel in panelsCleaned:
|
for panel in panelsCleaned:
|
||||||
panels.append(panel)
|
panels.append(panel)
|
||||||
if options.debug:
|
if opt.debug:
|
||||||
# noinspection PyUnboundLocalVariable
|
# noinspection PyUnboundLocalVariable
|
||||||
debugImage.save(os.path.join(path, fileExpanded[0] + '-debug.png'), 'PNG')
|
debugImage.save(os.path.join(path, fileExpanded[0] + '-debug.png'), 'PNG')
|
||||||
|
|
||||||
# Create virtual pages
|
# Create virtual pages
|
||||||
pages = []
|
pages = []
|
||||||
currentPage = []
|
currentPage = []
|
||||||
pageLeft = options.height
|
pageLeft = opt.height
|
||||||
panelNumber = 0
|
panelNumber = 0
|
||||||
for panel in panels:
|
for panel in panels:
|
||||||
if pageLeft - panel[2] > 0:
|
if pageLeft - panel[2] > 0:
|
||||||
@@ -202,7 +164,7 @@ def splitImage(work):
|
|||||||
else:
|
else:
|
||||||
if len(currentPage) > 0:
|
if len(currentPage) > 0:
|
||||||
pages.append(currentPage)
|
pages.append(currentPage)
|
||||||
pageLeft = options.height - panel[2]
|
pageLeft = opt.height - panel[2]
|
||||||
currentPage = [panelNumber]
|
currentPage = [panelNumber]
|
||||||
panelNumber += 1
|
panelNumber += 1
|
||||||
if len(currentPage) > 0:
|
if len(currentPage) > 0:
|
||||||
@@ -222,7 +184,7 @@ def splitImage(work):
|
|||||||
newPage.paste(panelImg, (0, targetHeight))
|
newPage.paste(panelImg, (0, targetHeight))
|
||||||
targetHeight += panels[panel][2]
|
targetHeight += panels[panel][2]
|
||||||
newPage.save(os.path.join(path, fileExpanded[0] + '-' +
|
newPage.save(os.path.join(path, fileExpanded[0] + '-' +
|
||||||
str(pageNumber) + '-' + getImageFill(newPage) + '.png'), 'PNG')
|
str(pageNumber) + '.png'), 'PNG')
|
||||||
pageNumber += 1
|
pageNumber += 1
|
||||||
os.remove(filePath)
|
os.remove(filePath)
|
||||||
|
|
||||||
|
|||||||
215
kcc/image.py
215
kcc/image.py
@@ -1,6 +1,7 @@
|
|||||||
# Copyright (C) 2010 Alex Yatskov
|
# Copyright (C) 2010 Alex Yatskov
|
||||||
# Copyright (C) 2011 Stanislav (proDOOMman) Kosolapov <prodoomman@gmail.com>
|
# Copyright (C) 2011 Stanislav (proDOOMman) Kosolapov <prodoomman@gmail.com>
|
||||||
# Copyright (C) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (C) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
|
# 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
|
||||||
@@ -21,7 +22,7 @@ __docformat__ = 'restructuredtext en'
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
try:
|
try:
|
||||||
# noinspection PyUnresolvedReferences,PyPackageRequirements
|
# noinspection PyUnresolvedReferences
|
||||||
from PIL import Image, ImageOps, ImageStat, ImageChops
|
from PIL import Image, ImageOps, ImageStat, ImageChops
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print "ERROR: Pillow is not installed!"
|
print "ERROR: Pillow is not installed!"
|
||||||
@@ -29,6 +30,9 @@ except ImportError:
|
|||||||
|
|
||||||
|
|
||||||
class ProfileData:
|
class ProfileData:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
Palette4 = [
|
Palette4 = [
|
||||||
0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00,
|
||||||
0x55, 0x55, 0x55,
|
0x55, 0x55, 0x55,
|
||||||
@@ -73,38 +77,60 @@ class ProfileData:
|
|||||||
0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
PalleteNull = [
|
||||||
|
]
|
||||||
|
|
||||||
Profiles = {
|
Profiles = {
|
||||||
'K1': ("Kindle 1", (600, 800), Palette4, 1.8, (900, 1200)),
|
'K1': ("Kindle 1", (600, 670), Palette4, 1.8, (900, 1005)),
|
||||||
'K2': ("Kindle 2", (600, 800), Palette15, 1.8, (900, 1200)),
|
'K2': ("Kindle 2", (600, 670), Palette15, 1.8, (900, 1005)),
|
||||||
'K3': ("Kindle Keyboard", (600, 800), Palette16, 1.8, (900, 1200)),
|
'K345': ("Kindle", (600, 800), Palette16, 1.8, (900, 1200)),
|
||||||
'K4NT': ("Kindle Non-Touch", (600, 800), Palette16, 1.8, (900, 1200)),
|
|
||||||
'K4T': ("Kindle Touch", (600, 800), Palette16, 1.8, (900, 1200)),
|
|
||||||
'KHD': ("Kindle Paperwhite", (758, 1024), Palette16, 1.8, (1137, 1536)),
|
'KHD': ("Kindle Paperwhite", (758, 1024), Palette16, 1.8, (1137, 1536)),
|
||||||
'KDX': ("Kindle DX", (824, 1200), Palette15, 1.8, (1236, 1800)),
|
'KDX': ("Kindle DX", (824, 1000), Palette15, 1.8, (1236, 1500)),
|
||||||
'KDXG': ("Kindle DXG", (824, 1200), Palette16, 1.8, (1236, 1800)),
|
'KDXG': ("Kindle DXG", (824, 1000), Palette16, 1.8, (1236, 1500)),
|
||||||
'KF': ("Kindle Fire", (600, 1024), Palette16, 1.0, (900, 1536)),
|
'KF': ("Kindle Fire", (600, 1024), PalleteNull, 1.0, (900, 1536)),
|
||||||
'KFHD': ("Kindle Fire HD 7\"", (800, 1280), Palette16, 1.0, (1200, 1920)),
|
'KFHD': ("K. Fire HD 7\"", (800, 1280), PalleteNull, 1.0, (1200, 1920)),
|
||||||
'KFHD8': ("Kindle Fire HD 8.9\"", (1200, 1920), Palette16, 1.0, (1800, 2880)),
|
'KFHD8': ("K. Fire HD 8.9\"", (1200, 1920), PalleteNull, 1.0, (1800, 2880)),
|
||||||
'KFA': ("Kindle for Android", (0, 0), Palette16, 1.0, (0, 0)),
|
'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)),
|
||||||
|
'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 = {
|
ProfileLabels = {
|
||||||
"Kindle 1": 'K1',
|
"Kindle 1": 'K1',
|
||||||
"Kindle 2": 'K2',
|
"Kindle 2": 'K2',
|
||||||
"Kindle 3/Keyboard": 'K3',
|
"Kindle": 'K345',
|
||||||
"Kindle 4/Non-Touch": 'K4NT',
|
|
||||||
"Kindle 4/Touch": 'K4T',
|
|
||||||
"Kindle Paperwhite": 'KHD',
|
"Kindle Paperwhite": 'KHD',
|
||||||
"Kindle DX": 'KDX',
|
"Kindle DX": 'KDX',
|
||||||
"Kindle DXG": 'KDXG',
|
"Kindle DXG": 'KDXG',
|
||||||
"Kindle Fire": 'KF',
|
"Kindle Fire": 'KF',
|
||||||
"Kindle Fire HD 7\"": 'KFHD',
|
"K. Fire HD 7\"": 'KFHD',
|
||||||
"Kindle Fire HD 8.9\"": 'KFHD8',
|
"K. Fire HD 8.9\"": 'KFHD8',
|
||||||
|
"K. Fire HDX 7\"": 'KFHDX',
|
||||||
|
"K. Fire HDX 8.9\"": 'KFHDX8',
|
||||||
"Kindle for Android": 'KFA',
|
"Kindle for Android": 'KFA',
|
||||||
"Other": 'OTHER'
|
"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",
|
||||||
|
"Kindle DXG",
|
||||||
|
"Kindle Fire"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class ComicPage:
|
class ComicPage:
|
||||||
def __init__(self, source, device):
|
def __init__(self, source, device):
|
||||||
@@ -133,19 +159,29 @@ class ComicPage:
|
|||||||
raise RuntimeError('Image file %s is corrupted' % source)
|
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.border = None
|
||||||
|
self.noHPV = None
|
||||||
|
self.noVPV = None
|
||||||
|
self.fill = None
|
||||||
|
|
||||||
def saveToDir(self, targetdir, forcepng, color, wipe, suffix=None):
|
def saveToDir(self, targetdir, forcepng, color, wipe):
|
||||||
try:
|
try:
|
||||||
|
suffix = ""
|
||||||
if not color:
|
if not color:
|
||||||
self.image = self.image.convert('L') # convert to grayscale
|
self.image = self.image.convert('L') # convert to grayscale
|
||||||
if suffix == "R":
|
if self.rotated:
|
||||||
suffix = "_kccrotated"
|
suffix += "_kccrot"
|
||||||
else:
|
|
||||||
suffix = ""
|
|
||||||
if wipe:
|
if wipe:
|
||||||
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:
|
||||||
|
suffix += "_kccnh"
|
||||||
|
if self.noVPV:
|
||||||
|
suffix += "_kccnv"
|
||||||
|
if self.border:
|
||||||
|
suffix += "_kccx" + str(self.border[0]) + "_kccy" + str(self.border[1])
|
||||||
if forcepng:
|
if forcepng:
|
||||||
self.image.save(os.path.join(targetdir, os.path.splitext(self.filename)[0] + suffix + ".png"), "PNG")
|
self.image.save(os.path.join(targetdir, os.path.splitext(self.filename)[0] + suffix + ".png"), "PNG")
|
||||||
else:
|
else:
|
||||||
@@ -171,72 +207,98 @@ class ComicPage:
|
|||||||
palImg.putpalette(self.palette)
|
palImg.putpalette(self.palette)
|
||||||
self.image = self.image.quantize(palette=palImg)
|
self.image = self.image.quantize(palette=palImg)
|
||||||
|
|
||||||
def resizeImage(self, upscale=False, stretch=False, black_borders=False, isSplit=False, toRight=False,
|
def resizeImage(self, upscale=False, stretch=False, bordersColor=None, qualityMode=0):
|
||||||
landscapeMode=False, qualityMode=0):
|
|
||||||
method = Image.ANTIALIAS
|
method = Image.ANTIALIAS
|
||||||
if '-KCCFW' in str(self.filename):
|
if bordersColor:
|
||||||
fill = 'white'
|
fill = bordersColor
|
||||||
elif '-KCCFB' in str(self.filename):
|
|
||||||
fill = 'black'
|
|
||||||
else:
|
else:
|
||||||
if black_borders:
|
fill = self.fill
|
||||||
fill = 'black'
|
|
||||||
else:
|
|
||||||
fill = 'white'
|
|
||||||
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])
|
||||||
# Kindle Paperwhite/Touch - Force upscale of splited pages to increase readability
|
generateBorder = False
|
||||||
if isSplit and landscapeMode:
|
|
||||||
upscale = True
|
|
||||||
if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]:
|
if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]:
|
||||||
if not upscale:
|
if not upscale:
|
||||||
borderw = (self.size[0] - self.image.size[0]) / 2
|
borderw = (self.size[0] - self.image.size[0]) / 2
|
||||||
borderh = (self.size[1] - self.image.size[1]) / 2
|
borderh = (self.size[1] - self.image.size[1]) / 2
|
||||||
self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=fill)
|
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
|
return self.image
|
||||||
else:
|
else:
|
||||||
method = Image.BILINEAR
|
method = Image.BILINEAR
|
||||||
if stretch: # if stretching call directly resize() without other considerations.
|
if stretch: # If stretching call directly resize() without other considerations.
|
||||||
self.image = self.image.resize(size, method)
|
self.image = self.image.resize(size, method)
|
||||||
|
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
|
||||||
ratioDev = float(self.size[0]) / float(self.size[1])
|
ratioDev = float(self.size[0]) / float(self.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:
|
||||||
if isSplit and landscapeMode:
|
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)
|
|
||||||
tempImg = Image.new(self.image.mode, (self.image.size[0] + diff, self.image.size[1]), fill)
|
|
||||||
if toRight:
|
|
||||||
tempImg.paste(self.image, (diff, 0))
|
|
||||||
else:
|
|
||||||
tempImg.paste(self.image, (0, 0))
|
|
||||||
self.image = tempImg
|
|
||||||
else:
|
|
||||||
diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
|
|
||||||
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)
|
||||||
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):
|
||||||
width, height = self.image.size
|
width, height = self.image.size
|
||||||
dstwidth, dstheight = self.size
|
dstwidth, dstheight = self.size
|
||||||
#print "Image is %d x %d" % (width,height)
|
# Only split if origin is not oriented the same as target
|
||||||
# only split if origin is not oriented the same as target
|
|
||||||
if (width > height) != (dstwidth > dstheight):
|
if (width > height) != (dstwidth > dstheight):
|
||||||
if rotate:
|
if rotate:
|
||||||
self.image = self.image.rotate(90)
|
self.image = self.image.rotate(90)
|
||||||
return "R"
|
self.rotated = True
|
||||||
|
return None
|
||||||
else:
|
else:
|
||||||
|
self.rotated = False
|
||||||
if width > height:
|
if width > height:
|
||||||
# source is landscape, so split by the width
|
# Source is landscape, so split by the width
|
||||||
leftbox = (0, 0, width / 2, height)
|
leftbox = (0, 0, width / 2, height)
|
||||||
rightbox = (width / 2, 0, width, height)
|
rightbox = (width / 2, 0, width, height)
|
||||||
else:
|
else:
|
||||||
# source is portrait and target is landscape, so split by the height
|
# Source is portrait and target is landscape, so split by the height
|
||||||
leftbox = (0, 0, width, height / 2)
|
leftbox = (0, 0, width, height / 2)
|
||||||
rightbox = (0, height / 2, width, height)
|
rightbox = (0, height / 2, width, height)
|
||||||
filename = os.path.splitext(self.filename)
|
filename = os.path.splitext(self.filename)
|
||||||
@@ -256,6 +318,7 @@ class ComicPage:
|
|||||||
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
|
raise RuntimeError('Cannot write image in directory %s: %s' % (targetdir, e))
|
||||||
return fileone, filetwo
|
return fileone, filetwo
|
||||||
else:
|
else:
|
||||||
|
self.rotated = False
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def cutPageNumber(self):
|
def cutPageNumber(self):
|
||||||
@@ -351,4 +414,48 @@ class ComicPage:
|
|||||||
# print "Right crop: %s"%diff
|
# print "Right crop: %s"%diff
|
||||||
self.image = self.image.crop((0, 0, widthImg - diff, heightImg))
|
self.image = self.image.crop((0, 0, widthImg - diff, heightImg))
|
||||||
# print "New size: %sx%s"%(self.image.size[0],self.image.size[1])
|
# print "New size: %sx%s"%(self.image.size[0],self.image.size[1])
|
||||||
return self.image
|
return self.image
|
||||||
|
|
||||||
|
def getImageHistogram(self, image):
|
||||||
|
histogram = image.histogram()
|
||||||
|
RBGW = []
|
||||||
|
pixelCount = 0
|
||||||
|
for i in range(256):
|
||||||
|
pixelCount += histogram[i] + histogram[256 + i] + histogram[512 + i]
|
||||||
|
RBGW.append(histogram[i] + histogram[256 + i] + histogram[512 + i])
|
||||||
|
white = 0
|
||||||
|
black = 0
|
||||||
|
for i in range(245, 256):
|
||||||
|
white += RBGW[i]
|
||||||
|
for i in range(11):
|
||||||
|
black += RBGW[i]
|
||||||
|
if black > white and black > pixelCount*0.5:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def getImageFill(self, isWebToon):
|
||||||
|
fill = 0
|
||||||
|
if isWebToon or self.rotated:
|
||||||
|
fill += self.getImageHistogram(self.image.crop((0, 0, self.image.size[0], 5)))
|
||||||
|
fill += self.getImageHistogram(self.image.crop((0, self.image.size[1]-5, self.image.size[0],
|
||||||
|
self.image.size[1])))
|
||||||
|
else:
|
||||||
|
fill += self.getImageHistogram(self.image.crop((0, 0, 5, self.image.size[1])))
|
||||||
|
fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, 0, self.image.size[0],
|
||||||
|
self.image.size[1])))
|
||||||
|
if fill == 2:
|
||||||
|
self.fill = 'black'
|
||||||
|
elif fill == 0:
|
||||||
|
self.fill = 'white'
|
||||||
|
else:
|
||||||
|
fill = 0
|
||||||
|
fill += self.getImageHistogram(self.image.crop((0, 0, 5, 5)))
|
||||||
|
fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, 0, self.image.size[0], 5)))
|
||||||
|
fill += self.getImageHistogram(self.image.crop((0, self.image.size[1]-5, 5, self.image.size[1])))
|
||||||
|
fill += self.getImageHistogram(self.image.crop((self.image.size[0]-5, self.image.size[1]-5,
|
||||||
|
self.image.size[0], self.image.size[1])))
|
||||||
|
if fill > 1:
|
||||||
|
self.fill = 'black'
|
||||||
|
else:
|
||||||
|
self.fill = 'white'
|
||||||
384
kcc/kindlesplit.py
Normal file
384
kcc/kindlesplit.py
Normal file
@@ -0,0 +1,384 @@
|
|||||||
|
# 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
|
||||||
|
# Copyright (C) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# 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
|
||||||
|
# from uuid import uuid4
|
||||||
|
|
||||||
|
# important pdb header offsets
|
||||||
|
unique_id_seed = 68
|
||||||
|
number_of_pdb_records = 76
|
||||||
|
|
||||||
|
# important palmdoc header offsets
|
||||||
|
book_length = 4
|
||||||
|
book_record_count = 8
|
||||||
|
first_pdb_record = 78
|
||||||
|
|
||||||
|
# important rec0 offsets
|
||||||
|
length_of_book = 4
|
||||||
|
mobi_header_base = 16
|
||||||
|
mobi_header_length = 20
|
||||||
|
mobi_type = 24
|
||||||
|
mobi_version = 36
|
||||||
|
first_non_text = 80
|
||||||
|
title_offset = 84
|
||||||
|
first_image_record = 108
|
||||||
|
first_content_index = 192
|
||||||
|
last_content_index = 194
|
||||||
|
kf8_last_content_index = 192 # for KF8 mobi headers
|
||||||
|
fcis_index = 200
|
||||||
|
flis_index = 208
|
||||||
|
srcs_index = 224
|
||||||
|
srcs_count = 228
|
||||||
|
primary_index = 244
|
||||||
|
datp_index = 256
|
||||||
|
huffoff = 112
|
||||||
|
hufftbloff = 120
|
||||||
|
|
||||||
|
|
||||||
|
def getint(datain, ofs, sz='L'):
|
||||||
|
i, = struct.unpack_from('>'+sz, datain, ofs)
|
||||||
|
return i
|
||||||
|
|
||||||
|
|
||||||
|
def writeint(datain, ofs, n, length='L'):
|
||||||
|
if length == 'L':
|
||||||
|
return datain[:ofs]+struct.pack('>L', n)+datain[ofs+4:]
|
||||||
|
else:
|
||||||
|
return datain[:ofs]+struct.pack('>H', n)+datain[ofs+2:]
|
||||||
|
|
||||||
|
|
||||||
|
def getsecaddr(datain, secno):
|
||||||
|
nsec = getint(datain, number_of_pdb_records, 'H')
|
||||||
|
assert secno >= 0 & secno < nsec, 'secno %d out of range (nsec=%d)' % (secno, nsec)
|
||||||
|
secstart = getint(datain, first_pdb_record+secno*8)
|
||||||
|
if secno == nsec-1:
|
||||||
|
secend = len(datain)
|
||||||
|
else:
|
||||||
|
secend = getint(datain, first_pdb_record+(secno+1)*8)
|
||||||
|
return secstart, secend
|
||||||
|
|
||||||
|
|
||||||
|
def readsection(datain, secno):
|
||||||
|
secstart, secend = getsecaddr(datain, secno)
|
||||||
|
return datain[secstart:secend]
|
||||||
|
|
||||||
|
|
||||||
|
def writesection(datain, secno, secdata): # overwrite, accounting for different length
|
||||||
|
dataout = deletesectionrange(datain, secno, secno)
|
||||||
|
return insertsection(dataout, secno, secdata)
|
||||||
|
|
||||||
|
|
||||||
|
def nullsection(datain, secno): # make it zero-length without deleting it
|
||||||
|
datalst = []
|
||||||
|
nsec = getint(datain, number_of_pdb_records, 'H')
|
||||||
|
secstart, secend = getsecaddr(datain, secno)
|
||||||
|
zerosecstart, zerosecend = getsecaddr(datain, 0)
|
||||||
|
dif = secend-secstart
|
||||||
|
datalst.append(datain[:first_pdb_record])
|
||||||
|
for i in range(0, secno+1):
|
||||||
|
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||||
|
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||||
|
for i in range(secno+1, nsec):
|
||||||
|
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||||
|
ofs -= dif
|
||||||
|
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||||
|
lpad = zerosecstart - (first_pdb_record + 8*nsec)
|
||||||
|
if lpad > 0:
|
||||||
|
datalst.append('\0' * lpad)
|
||||||
|
datalst.append(datain[zerosecstart: secstart])
|
||||||
|
datalst.append(datain[secend:])
|
||||||
|
dataout = "".join(datalst)
|
||||||
|
return dataout
|
||||||
|
|
||||||
|
|
||||||
|
def deletesectionrange(datain, firstsec, lastsec): # delete a range of sections
|
||||||
|
datalst = []
|
||||||
|
firstsecstart, firstsecend = getsecaddr(datain, firstsec)
|
||||||
|
lastsecstart, lastsecend = getsecaddr(datain, lastsec)
|
||||||
|
zerosecstart, zerosecend = getsecaddr(datain, 0)
|
||||||
|
dif = lastsecend - firstsecstart + 8*(lastsec-firstsec+1)
|
||||||
|
nsec = getint(datain, number_of_pdb_records, 'H')
|
||||||
|
datalst.append(datain[:unique_id_seed])
|
||||||
|
datalst.append(struct.pack('>L', 2*(nsec-(lastsec-firstsec+1))+1))
|
||||||
|
datalst.append(datain[unique_id_seed+4:number_of_pdb_records])
|
||||||
|
datalst.append(struct.pack('>H', nsec-(lastsec-firstsec+1)))
|
||||||
|
newstart = zerosecstart - 8*(lastsec-firstsec+1)
|
||||||
|
for i in range(0, firstsec):
|
||||||
|
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||||
|
ofs -= 8 * (lastsec - firstsec + 1)
|
||||||
|
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||||
|
for i in range(lastsec+1, nsec):
|
||||||
|
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||||
|
ofs -= dif
|
||||||
|
flgval = 2*(i-(lastsec-firstsec+1))
|
||||||
|
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||||
|
lpad = newstart - (first_pdb_record + 8*(nsec - (lastsec - firstsec + 1)))
|
||||||
|
if lpad > 0:
|
||||||
|
datalst.append('\0' * lpad)
|
||||||
|
datalst.append(datain[zerosecstart:firstsecstart])
|
||||||
|
datalst.append(datain[lastsecend:])
|
||||||
|
dataout = "".join(datalst)
|
||||||
|
return dataout
|
||||||
|
|
||||||
|
|
||||||
|
def insertsection(datain, secno, secdata): # insert a new section
|
||||||
|
datalst = []
|
||||||
|
nsec = getint(datain, number_of_pdb_records, 'H')
|
||||||
|
secstart, secend = getsecaddr(datain, secno)
|
||||||
|
zerosecstart, zerosecend = getsecaddr(datain, 0)
|
||||||
|
dif = len(secdata)
|
||||||
|
datalst.append(datain[:unique_id_seed])
|
||||||
|
datalst.append(struct.pack('>L', 2*(nsec+1)+1))
|
||||||
|
datalst.append(datain[unique_id_seed+4:number_of_pdb_records])
|
||||||
|
datalst.append(struct.pack('>H', nsec+1))
|
||||||
|
newstart = zerosecstart + 8
|
||||||
|
for i in range(0, secno):
|
||||||
|
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||||
|
ofs += 8
|
||||||
|
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||||
|
datalst.append(struct.pack('>L', secstart + 8) + struct.pack('>L', (2*secno)))
|
||||||
|
for i in range(secno, nsec):
|
||||||
|
ofs, flgval = struct.unpack_from('>2L', datain, first_pdb_record+i*8)
|
||||||
|
ofs = ofs + dif + 8
|
||||||
|
flgval = 2*(i+1)
|
||||||
|
datalst.append(struct.pack('>L', ofs) + struct.pack('>L', flgval))
|
||||||
|
lpad = newstart - (first_pdb_record + 8*(nsec + 1))
|
||||||
|
if lpad > 0:
|
||||||
|
datalst.append('\0' * lpad)
|
||||||
|
datalst.append(datain[zerosecstart:secstart])
|
||||||
|
datalst.append(secdata)
|
||||||
|
datalst.append(datain[secstart:])
|
||||||
|
dataout = "".join(datalst)
|
||||||
|
return dataout
|
||||||
|
|
||||||
|
|
||||||
|
def insertsectionrange(sectionsource, firstsec, lastsec, sectiontarget, targetsec): # insert a range of sections
|
||||||
|
dataout = sectiontarget
|
||||||
|
for idx in range(lastsec, firstsec-1, -1):
|
||||||
|
dataout = insertsection(dataout, targetsec, readsection(sectionsource, idx))
|
||||||
|
return dataout
|
||||||
|
|
||||||
|
|
||||||
|
def get_exth_params(rec0):
|
||||||
|
ebase = mobi_header_base + getint(rec0, mobi_header_length)
|
||||||
|
elen = getint(rec0, ebase+4)
|
||||||
|
enum = getint(rec0, ebase+8)
|
||||||
|
return ebase, elen, enum
|
||||||
|
|
||||||
|
|
||||||
|
def add_exth(rec0, exth_num, exth_bytes):
|
||||||
|
ebase, elen, enum = get_exth_params(rec0)
|
||||||
|
newrecsize = 8+len(exth_bytes)
|
||||||
|
newrec0 = rec0[0:ebase+4]+struct.pack('>L', elen+newrecsize)+struct.pack('>L', enum+1) +\
|
||||||
|
struct.pack('>L', exth_num) + struct.pack('>L', newrecsize)+exth_bytes+rec0[ebase+12:]
|
||||||
|
newrec0 = writeint(newrec0, title_offset, getint(newrec0, title_offset)+newrecsize)
|
||||||
|
return newrec0
|
||||||
|
|
||||||
|
|
||||||
|
def read_exth(rec0, exth_num):
|
||||||
|
exth_values = []
|
||||||
|
ebase, elen, enum = get_exth_params(rec0)
|
||||||
|
ebase += 12
|
||||||
|
while enum > 0:
|
||||||
|
exth_id = getint(rec0, ebase)
|
||||||
|
if exth_id == exth_num:
|
||||||
|
# We might have multiple exths, so build a list.
|
||||||
|
exth_values.append(rec0[ebase+8:ebase+getint(rec0, ebase+4)])
|
||||||
|
enum -= 1
|
||||||
|
ebase = ebase+getint(rec0, ebase+4)
|
||||||
|
return exth_values
|
||||||
|
|
||||||
|
|
||||||
|
def write_exth(rec0, exth_num, exth_bytes):
|
||||||
|
ebase, elen, enum = get_exth_params(rec0)
|
||||||
|
ebase_idx = ebase+12
|
||||||
|
enum_idx = enum
|
||||||
|
while enum_idx > 0:
|
||||||
|
exth_id = getint(rec0, ebase_idx)
|
||||||
|
if exth_id == exth_num:
|
||||||
|
dif = len(exth_bytes)+8-getint(rec0, ebase_idx+4)
|
||||||
|
newrec0 = rec0
|
||||||
|
if dif != 0:
|
||||||
|
newrec0 = writeint(newrec0, title_offset, getint(newrec0, title_offset)+dif)
|
||||||
|
return newrec0[:ebase+4]+struct.pack('>L', elen+len(exth_bytes)+8-getint(rec0, ebase_idx+4)) +\
|
||||||
|
struct.pack('>L', enum)+rec0[ebase+12:ebase_idx+4] +\
|
||||||
|
struct.pack('>L', len(exth_bytes)+8)+exth_bytes +\
|
||||||
|
rec0[ebase_idx+getint(rec0, ebase_idx+4):]
|
||||||
|
enum_idx -= 1
|
||||||
|
ebase_idx = ebase_idx+getint(rec0, ebase_idx+4)
|
||||||
|
return rec0
|
||||||
|
|
||||||
|
|
||||||
|
def del_exth(rec0, exth_num):
|
||||||
|
ebase, elen, enum = get_exth_params(rec0)
|
||||||
|
ebase_idx = ebase+12
|
||||||
|
enum_idx = 0
|
||||||
|
while enum_idx < enum:
|
||||||
|
exth_id = getint(rec0, ebase_idx)
|
||||||
|
exth_size = getint(rec0, ebase_idx+4)
|
||||||
|
if exth_id == exth_num:
|
||||||
|
newrec0 = rec0
|
||||||
|
newrec0 = writeint(newrec0, title_offset, getint(newrec0, title_offset)-exth_size)
|
||||||
|
newrec0 = newrec0[:ebase_idx]+newrec0[ebase_idx+exth_size:]
|
||||||
|
newrec0 = newrec0[0:ebase+4]+struct.pack('>L', elen-exth_size)+struct.pack('>L', enum-1)+newrec0[ebase+12:]
|
||||||
|
return newrec0
|
||||||
|
enum_idx += 1
|
||||||
|
ebase_idx = ebase_idx+exth_size
|
||||||
|
return rec0
|
||||||
|
|
||||||
|
|
||||||
|
class mobi_split:
|
||||||
|
def __init__(self, infile, newKindle):
|
||||||
|
try:
|
||||||
|
datain = open(infile, 'rb').read()
|
||||||
|
datain_rec0 = readsection(datain, 0)
|
||||||
|
ver = getint(datain_rec0, mobi_version)
|
||||||
|
# fake_asin = str(uuid4())
|
||||||
|
self.combo = (ver != 8)
|
||||||
|
if not self.combo:
|
||||||
|
return
|
||||||
|
exth121 = read_exth(datain_rec0, 121)
|
||||||
|
if len(exth121) == 0:
|
||||||
|
self.combo = False
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
# only pay attention to first exth121
|
||||||
|
# (there should only be one)
|
||||||
|
datain_kf8, = struct.unpack_from('>L', exth121[0], 0)
|
||||||
|
if datain_kf8 == 0xffffffff:
|
||||||
|
self.combo = False
|
||||||
|
return
|
||||||
|
datain_kfrec0 = readsection(datain, datain_kf8)
|
||||||
|
firstimage = getint(datain_rec0, first_image_record)
|
||||||
|
lastimage = getint(datain_rec0, last_content_index, 'H')
|
||||||
|
|
||||||
|
if not newKindle:
|
||||||
|
# create the standalone mobi7
|
||||||
|
num_sec = getint(datain, number_of_pdb_records, 'H')
|
||||||
|
# remove BOUNDARY up to but not including ELF record
|
||||||
|
self.result_file = deletesectionrange(datain, datain_kf8-1, num_sec-2)
|
||||||
|
# check if there are SRCS records and delete them
|
||||||
|
srcs = getint(datain_rec0, srcs_index)
|
||||||
|
num_srcs = getint(datain_rec0, srcs_count)
|
||||||
|
if srcs != 0xffffffff and num_srcs > 0:
|
||||||
|
self.result_file = deletesectionrange(self.result_file, srcs, srcs+num_srcs-1)
|
||||||
|
datain_rec0 = writeint(datain_rec0, srcs_index, 0xffffffff)
|
||||||
|
datain_rec0 = writeint(datain_rec0, srcs_count, 0)
|
||||||
|
# reset the EXTH 121 KF8 Boundary meta data to 0xffffffff
|
||||||
|
datain_rec0 = write_exth(datain_rec0, 121, struct.pack('>L', 0xffffffff))
|
||||||
|
# datain_rec0 = del_exth(datain_rec0,121)
|
||||||
|
# datain_rec0 = del_exth(datain_rec0,534)
|
||||||
|
# don't remove the EXTH 125 KF8 Count of Resources, seems to be present in mobi6 files as well
|
||||||
|
# set the EXTH 129 KF8 Masthead / Cover Image string to the null string
|
||||||
|
datain_rec0 = write_exth(datain_rec0, 129, '')
|
||||||
|
# don't remove the EXTH 131 KF8 Unidentified Count, seems to be present in mobi6 files as well
|
||||||
|
|
||||||
|
# Make sure we have an ASIN & cdeType set...
|
||||||
|
# if len(read_exth(datain_rec0, 113)) == 0:
|
||||||
|
# datain_rec0 = add_exth(datain_rec0, 113, fake_asin)
|
||||||
|
# if len(read_exth(datain_rec0, 504)) == 0:
|
||||||
|
# datain_rec0 = add_exth(datain_rec0, 504, fake_asin)
|
||||||
|
if len(read_exth(datain_rec0, 501)) == 0:
|
||||||
|
datain_rec0 = add_exth(datain_rec0, 501, b'EBOK')
|
||||||
|
|
||||||
|
# need to reset flags stored in 0x80-0x83
|
||||||
|
# old mobi with exth: 0x50, mobi7 part with exth: 0x1850, mobi8 part with exth: 0x1050
|
||||||
|
# Bit Flags
|
||||||
|
# 0x1000 = Bit 12 indicates if embedded fonts are used or not
|
||||||
|
# 0x0800 = means this Header points to *shared* images/resource/fonts ??
|
||||||
|
# 0x0080 = unknown new flag, why is this now being set by Kindlegen 2.8?
|
||||||
|
# 0x0040 = exth exists
|
||||||
|
# 0x0010 = Not sure but this is always set so far
|
||||||
|
fval, = struct.unpack_from('>L', datain_rec0, 0x80)
|
||||||
|
# need to remove flag 0x0800 for KindlePreviewer 2.8 and unset Bit 12 for embedded fonts
|
||||||
|
fval &= 0x07FF
|
||||||
|
datain_rec0 = datain_rec0[:0x80] + struct.pack('>L', fval) + datain_rec0[0x84:]
|
||||||
|
self.result_file = writesection(self.result_file, 0, datain_rec0)
|
||||||
|
if lastimage == 0xffff:
|
||||||
|
# find the lowest of the next sections and copy up to that.
|
||||||
|
ofs_list = [(kf8_last_content_index, 'L'), (fcis_index, 'L'), (flis_index, 'L'), (datp_index, 'L'),
|
||||||
|
(hufftbloff, 'L')]
|
||||||
|
for ofs, sz in ofs_list:
|
||||||
|
n = getint(datain_kfrec0, ofs, sz)
|
||||||
|
if 0 < n < lastimage:
|
||||||
|
lastimage = n-1
|
||||||
|
|
||||||
|
# Try to null out FONT and RES, but leave the (empty) PDB record so image refs remain valid
|
||||||
|
for i in range(firstimage, lastimage):
|
||||||
|
imgsec = readsection(self.result_file, i)
|
||||||
|
if imgsec[0:4] in ['RESC', 'FONT']:
|
||||||
|
self.result_file = nullsection(self.result_file, i)
|
||||||
|
# mobi7 finished
|
||||||
|
else:
|
||||||
|
# create standalone mobi8
|
||||||
|
self.result_file = deletesectionrange(datain, 0, datain_kf8-1)
|
||||||
|
target = getint(datain_kfrec0, first_image_record)
|
||||||
|
self.result_file = insertsectionrange(datain, firstimage, lastimage, self.result_file, target)
|
||||||
|
datain_kfrec0 = readsection(self.result_file, 0)
|
||||||
|
|
||||||
|
# Only keep the correct EXTH 116 StartOffset, KG 2.5 carries over the one from the mobi7 part,
|
||||||
|
# which then points at garbage in the mobi8 part, and confuses FW 3.4
|
||||||
|
kf8starts = read_exth(datain_kfrec0, 116)
|
||||||
|
# If we have multiple StartOffset, keep only the last one
|
||||||
|
kf8start_count = len(kf8starts)
|
||||||
|
while kf8start_count > 1:
|
||||||
|
kf8start_count -= 1
|
||||||
|
datain_kfrec0 = del_exth(datain_kfrec0, 116)
|
||||||
|
|
||||||
|
# update the EXTH 125 KF8 Count of Images/Fonts/Resources
|
||||||
|
datain_kfrec0 = write_exth(datain_kfrec0, 125, struct.pack('>L', lastimage-firstimage+1))
|
||||||
|
|
||||||
|
# Same dance for the KF8, we want an ASIN & cdeType :)
|
||||||
|
# if len(read_exth(datain_kfrec0, 113)) == 0:
|
||||||
|
# datain_kfrec0 = add_exth(datain_kfrec0, 113, fake_asin)
|
||||||
|
# if len(read_exth(datain_kfrec0, 504)) == 0:
|
||||||
|
# datain_kfrec0 = add_exth(datain_kfrec0, 504, fake_asin)
|
||||||
|
if len(read_exth(datain_kfrec0, 501)) == 0:
|
||||||
|
datain_kfrec0 = add_exth(datain_kfrec0, 501, b'EBOK')
|
||||||
|
|
||||||
|
# need to reset flags stored in 0x80-0x83
|
||||||
|
# old mobi with exth: 0x50, mobi7 part with exth: 0x1850, mobi8 part with exth: 0x1050
|
||||||
|
# standalone mobi8 with exth: 0x0050
|
||||||
|
# Bit Flags
|
||||||
|
# 0x1000 = Bit 12 indicates if embedded fonts are used or not
|
||||||
|
# 0x0800 = means this Header points to *shared* images/resource/fonts ??
|
||||||
|
# 0x0080 = unknown new flag, why is this now being set by Kindlegen 2.8?
|
||||||
|
# 0x0040 = exth exists
|
||||||
|
# 0x0010 = Not sure but this is always set so far
|
||||||
|
fval, = struct.unpack_from('>L', datain_kfrec0, 0x80)
|
||||||
|
fval &= 0x1FFF
|
||||||
|
fval |= 0x0800
|
||||||
|
datain_kfrec0 = datain_kfrec0[:0x80] + struct.pack('>L', fval) + datain_kfrec0[0x84:]
|
||||||
|
|
||||||
|
# properly update other index pointers that have been shifted by the insertion of images
|
||||||
|
ofs_list = [(kf8_last_content_index, 'L'), (fcis_index, 'L'), (flis_index, 'L'), (datp_index, 'L'),
|
||||||
|
(hufftbloff, 'L')]
|
||||||
|
for ofs, sz in ofs_list:
|
||||||
|
n = getint(datain_kfrec0, ofs, sz)
|
||||||
|
if n != 0xffffffff:
|
||||||
|
datain_kfrec0 = writeint(datain_kfrec0, ofs, n+lastimage-firstimage+1, sz)
|
||||||
|
self.result_file = writesection(self.result_file, 0, datain_kfrec0)
|
||||||
|
# mobi8 finished
|
||||||
|
except Exception:
|
||||||
|
raise
|
||||||
|
|
||||||
|
def getResult(self):
|
||||||
|
return self.result_file
|
||||||
@@ -1,236 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
|
||||||
#
|
|
||||||
# This is a python script. You need a Python interpreter to run it.
|
|
||||||
# For example, ActiveState Python, which exists for windows.
|
|
||||||
#
|
|
||||||
# This script strips the penultimate record from a Mobipocket file.
|
|
||||||
# This is useful because the current KindleGen add a compressed copy
|
|
||||||
# of the source files used in this record, making the ebook produced
|
|
||||||
# about twice as big as it needs to be.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# This is free and unencumbered software released into the public domain.
|
|
||||||
#
|
|
||||||
# Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
||||||
# distribute this software, either in source code form or as a compiled
|
|
||||||
# binary, for any purpose, commercial or non-commercial, and by any
|
|
||||||
# means.
|
|
||||||
#
|
|
||||||
# In jurisdictions that recognize copyright laws, the author or authors
|
|
||||||
# of this software dedicate any and all copyright interest in the
|
|
||||||
# software to the public domain. We make this dedication for the benefit
|
|
||||||
# of the public at large and to the detriment of our heirs and
|
|
||||||
# successors. We intend this dedication to be an overt act of
|
|
||||||
# relinquishment in perpetuity of all present and future rights to this
|
|
||||||
# software under copyright law.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
||||||
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
||||||
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||||
# OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
#
|
|
||||||
# For more information, please refer to <http://unlicense.org/>
|
|
||||||
#
|
|
||||||
# Written by Paul Durrant, 2010-2011, paul@durrant.co.uk, pdurrant on mobileread.com
|
|
||||||
# With enhancements by Kevin Hendricks, KevinH on mobileread.com
|
|
||||||
#
|
|
||||||
# Changelog
|
|
||||||
# 1.00 - Initial version
|
|
||||||
# 1.10 - Added an option to output the stripped data
|
|
||||||
# 1.20 - Added check for source files section (thanks Piquan)
|
|
||||||
# 1.30 - Added prelim Support for K8 style mobis
|
|
||||||
# 1.31 - removed the SRCS section but kept a 0 size entry for it
|
|
||||||
# 1.32 - removes the SRCS section and its entry, now updates metadata 121 if needed
|
|
||||||
# 1.33 - now uses and modifies mobiheader SRCS and CNT
|
|
||||||
# 1.34 - added credit for Kevin Hendricks
|
|
||||||
# 1.35 - fixed bug when more than one compilation (SRCS/CMET) records
|
|
||||||
|
|
||||||
__version__ = '1.35'
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import struct
|
|
||||||
import binascii
|
|
||||||
|
|
||||||
class Unbuffered:
|
|
||||||
def __init__(self, stream):
|
|
||||||
self.stream = stream
|
|
||||||
def write(self, data):
|
|
||||||
self.stream.write(data)
|
|
||||||
self.stream.flush()
|
|
||||||
def __getattr__(self, attr):
|
|
||||||
return getattr(self.stream, attr)
|
|
||||||
|
|
||||||
|
|
||||||
class StripException(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class SectionStripper:
|
|
||||||
def loadSection(self, section):
|
|
||||||
if (section + 1 == self.num_sections):
|
|
||||||
endoff = len(self.data_file)
|
|
||||||
else:
|
|
||||||
endoff = self.sections[section + 1][0]
|
|
||||||
off = self.sections[section][0]
|
|
||||||
return self.data_file[off:endoff]
|
|
||||||
|
|
||||||
def patch(self, off, new):
|
|
||||||
self.data_file = self.data_file[:off] + new + self.data_file[off+len(new):]
|
|
||||||
|
|
||||||
def strip(self, off, len):
|
|
||||||
self.data_file = self.data_file[:off] + self.data_file[off+len:]
|
|
||||||
|
|
||||||
def patchSection(self, section, new, in_off = 0):
|
|
||||||
if (section + 1 == self.num_sections):
|
|
||||||
endoff = len(self.data_file)
|
|
||||||
else:
|
|
||||||
endoff = self.sections[section + 1][0]
|
|
||||||
off = self.sections[section][0]
|
|
||||||
assert off + in_off + len(new) <= endoff
|
|
||||||
self.patch(off + in_off, new)
|
|
||||||
|
|
||||||
def updateEXTH121(self, srcs_secnum, srcs_cnt, mobiheader):
|
|
||||||
mobi_length, = struct.unpack('>L',mobiheader[0x14:0x18])
|
|
||||||
exth_flag, = struct.unpack('>L', mobiheader[0x80:0x84])
|
|
||||||
exth = 'NONE'
|
|
||||||
try:
|
|
||||||
if exth_flag & 0x40:
|
|
||||||
exth = mobiheader[16 + mobi_length:]
|
|
||||||
if (len(exth) >= 4) and (exth[:4] == 'EXTH'):
|
|
||||||
nitems, = struct.unpack('>I', exth[8:12])
|
|
||||||
pos = 12
|
|
||||||
for i in xrange(nitems):
|
|
||||||
type, size = struct.unpack('>II', exth[pos: pos + 8])
|
|
||||||
# print type, size
|
|
||||||
if type == 121:
|
|
||||||
boundaryptr, =struct.unpack('>L',exth[pos+8: pos + size])
|
|
||||||
if srcs_secnum <= boundaryptr:
|
|
||||||
boundaryptr -= srcs_cnt
|
|
||||||
prefix = mobiheader[0:16 + mobi_length + pos + 8]
|
|
||||||
suffix = mobiheader[16 + mobi_length + pos + 8 + 4:]
|
|
||||||
nval = struct.pack('>L',boundaryptr)
|
|
||||||
mobiheader = prefix + nval + suffix
|
|
||||||
pos += size
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return mobiheader
|
|
||||||
|
|
||||||
def __init__(self, datain):
|
|
||||||
if datain[0x3C:0x3C+8] != 'BOOKMOBI':
|
|
||||||
raise StripException("invalid file format")
|
|
||||||
self.num_sections, = struct.unpack('>H', datain[76:78])
|
|
||||||
|
|
||||||
# get mobiheader and check SRCS section number and count
|
|
||||||
offset0, = struct.unpack_from('>L', datain, 78)
|
|
||||||
offset1, = struct.unpack_from('>L', datain, 86)
|
|
||||||
mobiheader = datain[offset0:offset1]
|
|
||||||
srcs_secnum, srcs_cnt = struct.unpack_from('>2L', mobiheader, 0xe0)
|
|
||||||
if srcs_secnum == 0xffffffff or srcs_cnt == 0:
|
|
||||||
raise StripException("File doesn't contain the sources section.")
|
|
||||||
|
|
||||||
print "Found SRCS section number %d, and count %d" % (srcs_secnum, srcs_cnt)
|
|
||||||
# find its offset and length
|
|
||||||
next = srcs_secnum + srcs_cnt
|
|
||||||
srcs_offset, flgval = struct.unpack_from('>2L', datain, 78+(srcs_secnum*8))
|
|
||||||
next_offset, flgval = struct.unpack_from('>2L', datain, 78+(next*8))
|
|
||||||
srcs_length = next_offset - srcs_offset
|
|
||||||
if datain[srcs_offset:srcs_offset+4] != 'SRCS':
|
|
||||||
raise StripException("SRCS section num does not point to SRCS.")
|
|
||||||
print " beginning at offset %0x and ending at offset %0x" % (srcs_offset, srcs_length)
|
|
||||||
|
|
||||||
# it appears bytes 68-71 always contain (2*num_sections) + 1
|
|
||||||
# this is not documented anyplace at all but it appears to be some sort of next
|
|
||||||
# available unique_id used to identify specific sections in the palm db
|
|
||||||
self.data_file = datain[:68] + struct.pack('>L',((self.num_sections-srcs_cnt)*2+1))
|
|
||||||
self.data_file += datain[72:76]
|
|
||||||
|
|
||||||
# write out the number of sections reduced by srtcs_cnt
|
|
||||||
self.data_file = self.data_file + struct.pack('>H',self.num_sections-srcs_cnt)
|
|
||||||
|
|
||||||
# we are going to remove srcs_cnt SRCS sections so the offset of every entry in the table
|
|
||||||
# up to the srcs secnum must begin 8 bytes earlier per section removed (each table entry is 8 )
|
|
||||||
delta = -8 * srcs_cnt
|
|
||||||
for i in xrange(srcs_secnum):
|
|
||||||
offset, flgval = struct.unpack_from('>2L', datain, 78+(i*8))
|
|
||||||
offset += delta
|
|
||||||
self.data_file += struct.pack('>L',offset) + struct.pack('>L',flgval)
|
|
||||||
|
|
||||||
# for every record after the srcs_cnt SRCS records we must start it
|
|
||||||
# earlier by 8*srcs_cnt + the length of the srcs sections themselves)
|
|
||||||
delta = delta - srcs_length
|
|
||||||
for i in xrange(srcs_secnum+srcs_cnt,self.num_sections):
|
|
||||||
offset, flgval = struct.unpack_from('>2L', datain, 78+(i*8))
|
|
||||||
offset += delta
|
|
||||||
flgval = 2 * (i - srcs_cnt)
|
|
||||||
self.data_file += struct.pack('>L',offset) + struct.pack('>L',flgval)
|
|
||||||
|
|
||||||
# now pad it out to begin right at the first offset
|
|
||||||
# typically this is 2 bytes of nulls
|
|
||||||
first_offset, flgval = struct.unpack_from('>2L', self.data_file, 78)
|
|
||||||
self.data_file += '\0' * (first_offset - len(self.data_file))
|
|
||||||
|
|
||||||
# now finally add on every thing up to the original src_offset
|
|
||||||
self.data_file += datain[offset0: srcs_offset]
|
|
||||||
|
|
||||||
# and everything afterwards
|
|
||||||
self.data_file += datain[srcs_offset+srcs_length:]
|
|
||||||
|
|
||||||
#store away the SRCS section in case the user wants it output
|
|
||||||
self.stripped_data_header = datain[srcs_offset:srcs_offset+16]
|
|
||||||
self.stripped_data = datain[srcs_offset+16:srcs_offset+srcs_length]
|
|
||||||
|
|
||||||
# update the number of sections count
|
|
||||||
self.num_section = self.num_sections - srcs_cnt
|
|
||||||
|
|
||||||
# update the srcs_secnum and srcs_cnt in the mobiheader
|
|
||||||
offset0, flgval0 = struct.unpack_from('>2L', self.data_file, 78)
|
|
||||||
offset1, flgval1 = struct.unpack_from('>2L', self.data_file, 86)
|
|
||||||
mobiheader = self.data_file[offset0:offset1]
|
|
||||||
mobiheader = mobiheader[:0xe0]+ struct.pack('>L', 0xffffffff) + struct.pack('>L', 0) + mobiheader[0xe8:]
|
|
||||||
|
|
||||||
# if K8 mobi, handle metadata 121 in old mobiheader
|
|
||||||
mobiheader = self.updateEXTH121(srcs_secnum, srcs_cnt, mobiheader)
|
|
||||||
self.data_file = self.data_file[0:offset0] + mobiheader + self.data_file[offset1:]
|
|
||||||
print "done"
|
|
||||||
|
|
||||||
def getResult(self):
|
|
||||||
return self.data_file
|
|
||||||
|
|
||||||
def getStrippedData(self):
|
|
||||||
return self.stripped_data
|
|
||||||
|
|
||||||
def getHeader(self):
|
|
||||||
return self.stripped_data_header
|
|
||||||
|
|
||||||
def main(argv=None):
|
|
||||||
infile = argv[0]
|
|
||||||
outfile = argv[1]
|
|
||||||
data_file = file(infile, 'rb').read()
|
|
||||||
try:
|
|
||||||
strippedFile = SectionStripper(data_file)
|
|
||||||
file(outfile, 'wb').write(strippedFile.getResult())
|
|
||||||
print "Header Bytes: " + binascii.b2a_hex(strippedFile.getHeader())
|
|
||||||
if len(argv)==3:
|
|
||||||
file(argv[2], 'wb').write(strippedFile.getStrippedData())
|
|
||||||
except StripException, e:
|
|
||||||
print "Error: %s" % e
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sys.stdout=Unbuffered(sys.stdout)
|
|
||||||
print ('KindleStrip v%(__version__)s. '
|
|
||||||
'Written 2010-2012 by Paul Durrant and Kevin Hendricks.' % globals())
|
|
||||||
if len(sys.argv)<3 or len(sys.argv)>4:
|
|
||||||
print "Strips the Sources record from Mobipocket ebooks"
|
|
||||||
print "For ebooks generated using KindleGen 1.1 and later that add the source"
|
|
||||||
print "Usage:"
|
|
||||||
print " %s <infile> <outfile> <strippeddatafile>" % sys.argv[0]
|
|
||||||
print "<strippeddatafile> is optional."
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
main(sys.argv[1:])
|
|
||||||
sys.exit(0)
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
# Copyright (c) 2012 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2013 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
|
# Copyright (c) 2013 Pawel Jastrzebski <pawelj@vulturis.eu>
|
||||||
#
|
#
|
||||||
# Based upon the code snippet by Ned Batchelder
|
# Based upon the code snippet by Ned Batchelder
|
||||||
# (http://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html)
|
# (http://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html)
|
||||||
|
|||||||
91
other/Additional-LICENSE.txt
Normal file
91
other/Additional-LICENSE.txt
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
****** ***** ****** UnRAR - free utility for RAR archives
|
||||||
|
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
****** ******* ****** License for use and distribution of
|
||||||
|
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
** ** ** ** ** ** FREEWARE version
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The UnRAR utility is freeware. This means:
|
||||||
|
|
||||||
|
1. All copyrights to RAR and the utility UnRAR are exclusively
|
||||||
|
owned by the author - Alexander Roshal.
|
||||||
|
|
||||||
|
2. The UnRAR utility may be freely distributed. It is allowed
|
||||||
|
to distribute UnRAR inside of other software packages.
|
||||||
|
|
||||||
|
3. THE RAR ARCHIVER AND THE UnRAR UTILITY ARE DISTRIBUTED "AS IS".
|
||||||
|
NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT
|
||||||
|
YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS,
|
||||||
|
DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING
|
||||||
|
OR MISUSING THIS SOFTWARE.
|
||||||
|
|
||||||
|
4. Neither RAR binary code, WinRAR binary code, UnRAR source or UnRAR
|
||||||
|
binary code may be used or reverse engineered to re-create the RAR
|
||||||
|
compression algorithm, which is proprietary, without written
|
||||||
|
permission of the author.
|
||||||
|
|
||||||
|
5. If you don't agree with terms of the license you must remove
|
||||||
|
UnRAR files from your storage devices and cease to use the
|
||||||
|
utility.
|
||||||
|
|
||||||
|
Thank you for your interest in RAR and UnRAR.
|
||||||
|
|
||||||
|
|
||||||
|
Alexander L. Roshal
|
||||||
|
|
||||||
|
7-Zip
|
||||||
|
~~~~~
|
||||||
|
License for use and distribution
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
7-Zip Copyright (C) 1999-2012 Igor Pavlov.
|
||||||
|
|
||||||
|
Licenses for files are:
|
||||||
|
|
||||||
|
1) 7z.dll: GNU LGPL + unRAR restriction
|
||||||
|
2) All other files: GNU LGPL
|
||||||
|
|
||||||
|
The GNU LGPL + unRAR restriction means that you must follow both
|
||||||
|
GNU LGPL rules and unRAR restriction rules.
|
||||||
|
|
||||||
|
|
||||||
|
Note:
|
||||||
|
You can use 7-Zip on any computer, including a computer in a commercial
|
||||||
|
organization. You don't need to register or pay for 7-Zip.
|
||||||
|
|
||||||
|
|
||||||
|
GNU LGPL information
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You can receive a copy of the GNU Lesser General Public License from
|
||||||
|
http://www.gnu.org/
|
||||||
|
|
||||||
|
|
||||||
|
unRAR restriction
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
The decompression engine for RAR archives was developed using source
|
||||||
|
code of unRAR program.
|
||||||
|
All copyrights to original unRAR code are owned by Alexander Roshal.
|
||||||
|
|
||||||
|
The license for original unRAR code has the following restriction:
|
||||||
|
|
||||||
|
The unRAR sources cannot be used to re-create the RAR compression algorithm,
|
||||||
|
which is proprietary. Distribution of modified unRAR sources in separate form
|
||||||
|
or as a part of other software is permitted, provided that it is clearly
|
||||||
|
stated in the documentation and source comments that the code may
|
||||||
|
not be used to develop a RAR (WinRAR) compatible archiver.
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
Igor Pavlov
|
||||||
8
setup.py
8
setup.py
@@ -10,7 +10,7 @@ Usage (Windows):
|
|||||||
from sys import platform
|
from sys import platform
|
||||||
|
|
||||||
NAME = "KindleComicConverter"
|
NAME = "KindleComicConverter"
|
||||||
VERSION = "3.2.1"
|
VERSION = "3.3"
|
||||||
MAIN = "kcc.py"
|
MAIN = "kcc.py"
|
||||||
|
|
||||||
if platform == "darwin":
|
if platform == "darwin":
|
||||||
@@ -41,7 +41,11 @@ elif platform == "win32":
|
|||||||
from cx_Freeze import setup, Executable
|
from cx_Freeze import setup, Executable
|
||||||
base = "Win32GUI"
|
base = "Win32GUI"
|
||||||
extra_options = dict(
|
extra_options = dict(
|
||||||
options={"build_exe": {"include_files": ['LICENSE.txt'], "compressed": True}},
|
options={"build_exe": {"include_files": ['LICENSE.txt',
|
||||||
|
['other/UnRAR.exe', 'UnRAR.exe'],
|
||||||
|
['other/7za.exe', '7za.exe'],
|
||||||
|
['other/Additional-LICENSE.txt', 'Additional-LICENSE.txt']
|
||||||
|
], "compressed": True}},
|
||||||
executables=[Executable(MAIN,
|
executables=[Executable(MAIN,
|
||||||
base=base,
|
base=base,
|
||||||
targetName="KCC.exe",
|
targetName="KCC.exe",
|
||||||
|
|||||||
Reference in New Issue
Block a user