1
0
mirror of https://github.com/ciromattia/kcc synced 2026-04-15 21:48:44 +00:00

Compare commits

...

323 Commits
5.4 ... v6.2.1

Author SHA1 Message Date
Alex Xu
1131bab41f bump 6.2.1 2024-10-23 21:21:27 -07:00
Alex Xu
8d204668a7 add kindle 12th gen, including colorsoft (#762)
* add kindle colorsoft

* fix typo
2024-10-23 21:17:22 -07:00
Alex Xu
99d94ceaa7 fix _cffi_backend 2024-10-16 19:24:01 -07:00
Alex Xu
8ff401cc3a remove fastnumbers from armv7 2024-10-04 09:04:56 -07:00
Alex Xu
fb7d92d737 fix Docker linux arm (#746)
* fix linux arm64

* Update Dockerfile-base

* Update Dockerfile

* Update Dockerfile-base

* ENV PATH="/opt/venv/bin:$PATH"

* fix docker armv7

* Update Dockerfile-base

* Update Dockerfile-base
2024-09-29 10:21:35 -07:00
Alex Xu
1ca8b2c11b Update README.md 2024-09-15 11:49:49 -07:00
Alex Xu
40e0b4853b add flatpak note 2024-09-08 22:23:23 -07:00
Alex Xu
005313f978 flatpak mobi conversion stuck 2024-09-08 21:22:56 -07:00
Alex Xu
add2ef9faa fix image file is corrupt for real 2024-09-07 22:17:30 -07:00
Alex Xu
0c98acd606 bump to 6.2.0 2024-09-06 23:05:02 -07:00
Alex Xu
fe902ec213 fix corrupt 2024-09-06 23:04:32 -07:00
Alex Xu
4e9714e6f8 add packaging for Python 3.12 2024-08-30 10:02:44 -07:00
Alex Xu
1337ad7fe3 Python 3.12 supported 2024-08-28 14:32:23 -07:00
dependabot[bot]
511c7c1580 Bump python from 3.11-slim-bullseye to 3.12-slim-bullseye
Bumps python from 3.11-slim-bullseye to 3.12-slim-bullseye.

---
updated-dependencies:
- dependency-name: python
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-28 14:28:16 -07:00
Alex Xu
16dd034af4 add Python 3.12 support 2024-08-28 14:26:54 -07:00
Alex Xu
d22794555f bump to 6.1.1 2024-08-09 17:13:02 -07:00
Alex Xu
ab089adbca fix no such file or directory 7z (#728)
* refactor archive code

* simplify code

* Revert "simplify code"

This reverts commit 3e90dd66c3.

* add link to missing extraction software

* fix tar

* fix wording
2024-08-09 17:08:13 -07:00
Alex Xu
2c770f4562 search for kindlegen in %UserProfile% 2024-08-09 17:05:44 -07:00
Alex Xu
4c73006bd8 add APFS to external drive 2024-08-06 16:04:45 -07:00
Alex Xu
1093dbf65a Update README.md 2024-07-27 08:26:44 -07:00
Alex Xu
df9990c692 add python 3.12 unsupported note 2024-07-25 13:54:31 -07:00
Alex Xu
114f4c9e57 add macOS minimums 2024-07-21 10:19:49 -07:00
Alex Xu
c2c477475d combine files/chapters in readme 2024-07-20 12:37:20 -07:00
Alex Xu
a0f8d0b5cf add kcc 6.1 7z note 2024-07-01 08:55:20 -07:00
Alex Xu
2fc32bae58 Update __init__.py 2024-06-29 08:52:09 -07:00
Alex Xu
db25a0939c Build windows gui version normally. 2024-06-25 22:03:10 -07:00
Alex Xu
1bd7506140 remove unar macOS 2024-06-25 21:04:52 -07:00
Alex Xu
4fc5cc9dfb remove GUI windows docker 2024-06-25 20:45:32 -07:00
Alex Xu
89289412a3 Revert "add hiddenimports=['pkg_resources.extern']"
This reverts commit 193297c8fc.
2024-06-25 19:29:17 -07:00
Alex Xu
193297c8fc add hiddenimports=['pkg_resources.extern'] 2024-06-25 19:15:34 -07:00
Alex Xu
367d71e4ad fix typo 2024-06-25 12:52:41 -07:00
Alex Xu
cdde0f18cd update prereq readme (#714)
* update prereq readme

* Update README.md

* Update README.md

* Revert "Update README.md"

This reverts commit ceb35b03b6.

* Revert "Update README.md"

This reverts commit a24e818c0e.

* add other OS note
2024-06-25 12:42:38 -07:00
Alex Xu
9fe82a9dd4 improve kindlegen detection windows (#688)
* improve kindlegen detection windows

* add C:\Apps folders
2024-06-25 12:21:48 -07:00
detournemint
e958edd135 Update package-linux.yml to include libxcb-cursor0
Including libxcb-cursor0 for linux
2024-06-25 12:15:33 -07:00
Alex Xu
6738b70487 don't display upscale warning on kindle scribe 2024-06-09 08:00:55 -07:00
Dominik Gedon
44094bdb21 Add Kobo Libra/Clara colour (#703)
* fix: trailing whitespaces

* Add color toggle mode

* Add Kobo Libra Colour

Signed-off-by: Dominik Gedon <dominik@gedon.org>

* Add Kobo Clara Colour

Signed-off-by: Dominik Gedon <dominik@gedon.org>

* Address suggestions

* Address more suggestions

---------

Signed-off-by: Dominik Gedon <dominik@gedon.org>
2024-06-09 08:00:25 -07:00
Alex Xu
a9a2f47e30 fix 1860 width 2024-05-28 09:55:59 -07:00
Bruno Resende
c35dd137ea Add de-dupe cover option for landscape alignment (#561)
* Adds --author argument to CLI

* Add --prefercoverfile and --nocoveraspage arguments to CLI

* cover checks only run once

* Revert "cover checks only run once"

This reverts commit ad7b3cc106.

* split off author portion

* split off author

* remove prefercover

* whitespace fixes

* rename to duplicatecover

* whitespace fixes

* rename to dedupecover

* add dedupe to UI

---------

Co-authored-by: Alex Xu <alexkurosakimh3@gmail.com>
2024-05-17 09:56:22 -07:00
Alex Xu
1ea008c8f3 reduce dependency on 7z, unar, homebrew by using builtin tar (#693)
* reduce dependency on 7z, unar, homebrew by using builtin tar

* update readme

* fix typo

* add editor text

* remove unar

* Revert "remove unar"

This reverts commit 2c4b239d67.

* Revert "fix typo"

This reverts commit 79752c7f38.

* Revert "update readme"

This reverts commit 4f5c727a2d.
2024-05-17 09:56:04 -07:00
Alex Xu
cbc1ed5db4 Kindle Scribe 1860 max width (#691)
* Kindle Scribe 1860 max width

* create kindle_scribe_azw3 var

* clean up code
2024-05-17 09:55:43 -07:00
Alex Xu
6bf662bea3 add faq 2024-05-15 10:15:08 -07:00
Alex Xu
cfae306731 macos-latest is now macos-14 (m1) 2024-04-27 12:56:49 -07:00
Alex Xu
f6475f4c61 Close and re-open KCC note 2024-04-19 21:15:48 -07:00
Alex Xu
9646518575 shorten 7z/kindlegen notes 2024-04-18 20:58:12 -07:00
Alex Xu
937dd3984a kindlegen note 2024-04-18 18:07:06 -07:00
Alex Xu
4e6f6ec8e8 clarify 7z/kindlegen windows 2024-04-18 17:35:51 -07:00
Alex Xu
4b36fdbfa2 update C drive notes 2024-04-18 16:08:10 -07:00
Alex Xu
d8141af4eb update c drive notes 2024-04-18 15:45:34 -07:00
Alex Xu
cf38c4d445 Revert "fix package-windows-with-docker.yml (#579)"
This reverts commit 424118b7cd.
2024-04-16 15:46:44 -07:00
Alex Xu
283b2da1a0 bump to 6.0.0 2024-04-16 15:09:03 -07:00
Alex Xu
4a9f693574 Adds --author argument to CLI (#683) 2024-04-16 14:59:54 -07:00
Alex Xu
9a48887edc update C drive notes 2024-04-15 21:16:14 -07:00
Alex Xu
0981ec3c6d add more 7z Windows locations 2024-03-24 18:40:50 -07:00
dependabot[bot]
e0e6606736 Bump softprops/action-gh-release from 1 to 2
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 1 to 2.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v1...v2)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-21 21:58:00 -07:00
Alex Xu
518e67c132 move install from source instructions 2024-03-16 20:12:30 -07:00
Alex Xu
6c593dac1f add gen_ui_files note 2024-03-16 14:04:35 -07:00
Alex Xu
9d065676db add install from source and qt creator instructions 2024-03-16 13:54:40 -07:00
Alex Xu
9520e59a29 Add C drive notes 2024-03-15 12:08:46 -07:00
Alex Xu
461a7fda88 add C drive note 2024-03-12 12:44:07 -07:00
Alex Xu
5ccbb770a6 do not change default install location for 7z/KP 2024-03-09 10:04:01 -08:00
Alex Xu
49bf80f5d8 LOAD_TRUNCATED_IMAGES = True 2024-03-04 21:36:07 -08:00
Alex Xu
33cc324381 prepare m1 build pipeline (#669) 2024-01-31 11:49:27 -08:00
Alex Xu
6ba5539813 Revert "docker arm install from requirements.txt" 2024-01-29 10:54:13 -08:00
Alex Xu
f725196106 reset saved settings 2024-01-29 10:29:45 -08:00
Alex Xu
c8ff88ed0f Update Dockerfile-base 2024-01-28 22:27:03 -08:00
darodi
33fed662fe Merge pull request #666
* fix dependencies
2024-01-12 23:22:09 +00:00
Alex Xu
bc7cd17916 rename kp3 2024-01-12 12:41:51 -08:00
Alex Xu
c5e1e18ac2 Revert "rename pw to paperwhite"
This reverts commit 48541404ee.
2024-01-02 14:26:53 -08:00
Alex Xu
ee31b784cb Add native Apple Silicon support by upgrading qt5 to qt6 (#523)
* initial upgrade

* fix epub icon

* pyside6

* fix tray icon

* add spaces

* add comment back

* change exec

* edit shared

* Add CheckState enums

* add mozJpeg

* fix batch

* import CheckedState

* remove references to qt5

* add mozJpeg warning

* Update package-linux.yml

* Update package-linux.yml

* Update Dockerfile-base

* Update README.md

* Update package-linux.yml

* Update README.md

* Update README.md

* add mozjpeg to gitignore

* add warning text

* fix state issue

* use same settings save location as qt5

* remove space

* remove mozJpeg

* update Dockerfile-base file version

* use getattr instead of eval

* undo readme changes

* undo conda

* undo gitignore

---------

Co-authored-by: Alexander Xu <alexanderx@qualtrics.com>
Co-authored-by: darodi <4682830+darodi@users.noreply.github.com>
2024-01-02 14:08:39 -08:00
Alex Xu
48541404ee rename pw to paperwhite 2024-01-02 12:14:51 -08:00
Alex Xu
acbebcfd40 rename kindle labels by gen 2024-01-02 12:14:51 -08:00
VampiroMedicado
dd6273b864 add missing parameter output to options 2024-01-02 10:11:38 -08:00
VampiroMedicado
e8502f008a hide subprocess consoles on Windows (#656) 2024-01-01 18:11:55 -08:00
inganault
169a41e7d2 Add missing dependencies to setup.py (#653) 2023-12-29 19:00:24 -08:00
Alex Xu
57cf669cdd add to credits 2023-12-28 18:55:08 -08:00
Alex Xu
0b4f089b8e add .DS_Store to .gitignore 2023-12-23 09:35:12 -08:00
Alex Xu
7eb985337c add requests to setup.py 2023-12-23 09:10:31 -08:00
Alex Xu
d62690e8bf import subprocess 2023-12-21 13:40:48 -08:00
Alex Xu
3988f2012f fix p7zip-rar error and files with ' or " by using arg lists instead of strings (#633)
* Revert "Revert "fix files with ' or " by using arg lists instead of strings (#581)" (#628)"

This reverts commit b528dab711.

* handle FileNotFoundError

* modify unar handling

* remove unneeded utf-8 encoding

* dont uft-8 encode 7z

* remove utf-8 encoding from 7z calls

* don't extract stderr

* add extraction error

* edit error message

* remove debug

* remove kindlegen location from GUI

* remove comment
2023-12-21 12:52:35 -08:00
Alex Xu
6cdd9d5909 change kobo epub filenames (#616) 2023-12-21 12:51:26 -08:00
Alex Xu
c29a4beac9 use requests library 2023-12-21 12:44:29 -08:00
Alex Xu
5f7bdef325 bump to 5.6.5 2023-12-21 09:50:34 -08:00
Alex Xu
54b5d698ee fix access denied 2023-12-21 09:43:33 -08:00
Alex Xu
a99c63acea use os_sorted over natsorted 2023-12-21 09:43:07 -08:00
dependabot[bot]
251df2e7ba Bump github/codeql-action from 2 to 3
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-21 09:42:20 -08:00
dependabot[bot]
b1379b7c59 Bump actions/upload-artifact from 3 to 4
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-21 09:42:11 -08:00
Alex Xu
983bde1691 add fat to list of drives 2023-12-21 09:41:18 -08:00
dependabot[bot]
e79e5a311c Bump actions/setup-python from 4 to 5
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-10 20:02:36 -08:00
jaroslawjanas
39c73dbc0f Added natsort to the dependency list in environment.yml 2023-12-10 19:59:33 -08:00
Alex Xu
915c9389ef remove kindlegen location UI 2023-12-09 17:39:01 -08:00
Alex Xu
89d887710e fix typo 2023-12-07 18:57:46 -08:00
Alex Xu
2e9bc5381a add PREREQUISITES 2023-12-07 18:56:57 -08:00
Alex Xu
ab1ce158c7 rename to prerequisites 2023-12-04 09:33:08 -08:00
Ciro Mattia Gonano
6278adfb25 Update issue templates 2023-11-29 12:40:11 +01:00
Alex Xu
6e6c13047e bump to 5.6.4 2023-11-28 08:32:34 -08:00
Alex Xu
b528dab711 Revert "fix files with ' or " by using arg lists instead of strings (#581)" (#628)
This reverts commit 431862a2e9.
2023-11-28 08:20:14 -08:00
Alex Xu
2ffefee928 link to readme not wiki for 7z kindlegen (#627)
* link to readme not wiki for 7z kindlegen

* update 7z link
2023-11-28 08:15:59 -08:00
Alex Xu
a5e5407363 streamline downloads and installation readme (#623)
* streamline downloads and installation

move linux stuff into wiki

* Update README.md

* update labels

* simplify
2023-11-28 07:38:46 -08:00
Alex Xu
da1ba64bd2 skip bookmarks if split (#620) 2023-11-28 06:54:47 -08:00
Alex Xu
6dcaf9a6d1 fix unsupported archive error (#619) 2023-11-28 06:53:58 -08:00
Alex Xu
3090a47f20 change mac pyinstaller -F to -D (#621) 2023-11-28 06:52:39 -08:00
Alex Xu
1e537915d4 make c2e and c2p versions first in file order 2023-11-28 06:50:55 -08:00
dependabot[bot]
7273ca25b8 Bump actions/setup-node from 3 to 4 (#609)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3 to 4.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-09 23:06:46 +00:00
Alex Xu
68da853e42 fix page order in pdf and more by using natural sort instead of python sort (#589)
* use natsorted

* Add fast
2023-11-09 23:00:44 +00:00
Alex Xu
431862a2e9 fix files with ' or " by using arg lists instead of strings (#581)
* replace popen with subprocess run

* add splitlines

* remove stdin

* fix xml

* fix error logging and 7zip
2023-11-09 22:27:09 +00:00
Alex Xu
65062f8984 add Kindle 4/5/7/8/10 label (#614) 2023-11-09 22:15:34 +00:00
Alex Xu
8122fa1e45 add c2e and c2p note (#606) 2023-10-26 19:29:16 +00:00
Alex Xu
13fedff77b lower auto crop threshold (#598) 2023-10-26 19:20:26 +00:00
dependabot[bot]
61b1207a3e Bump actions/checkout from 3 to 4 (#592)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-16 12:10:53 +00:00
Alex Xu
60e9f075b8 replace exit() with sys.exit() (#590) 2023-09-08 20:18:32 +00:00
darodi
424118b7cd fix package-windows-with-docker.yml (#579) 2023-08-11 19:00:30 +00:00
Alex Xu
4e45402b8f add download instructions (#577)
* add download instructions

* fix spacing

* fix capitalization
2023-08-10 16:16:55 +00:00
Alex Xu
615790c278 remove old windows 7z binaries and Inno Setup Script ISS (#575)
* Delete 7z.dll

* Delete 7z.exe

* Delete Additional-LICENSE.txt

* Delete InstallWarning.rtf

* Update kcc.iss

* Update kcc.py

* Update .dockerignore

* Delete kcc.iss
2023-08-09 16:24:26 +00:00
Alex Xu
0d417b8e11 prioritize KC2 over KP3 kindlegen version (#574)
* prioritize KC2 over KP3

* remove link to buggy KP3 kindlegen

* prioritize KC2 since KP3 version is buggy as of v3.72

* add kindlegen install link

* update comments
2023-08-08 20:25:03 +00:00
Alex Xu
6836c20377 Fix page order and bookmarks by renaming numerically (#507)
* disable slugify

* rename to digits

* add -kcc

* add ABC checks

* remove kobo

* don't use if statements

* rename to suffix

* re-order check

* only slugify directories

* add break

* add sorted

* fix kcc-b logic

* add kcc to front of filename

---------

Co-authored-by: Alexander Xu <alexanderx@qualtrics.com>
2023-08-07 18:22:46 +00:00
swaggy-p-jp
f75ea6dfe8 enable double spread on kindle (#567) 2023-08-07 18:07:00 +00:00
Alex Xu
77afa77d32 Display kindlegen path (#571)
* add %LOCALAPPDATA%\\Amazon\\KC2

* fix kindlegen link

* expandvars

* remove link

* print where kindlegen

* adjust where command

* remove platform
2023-08-07 17:53:38 +00:00
Alex Xu
f73d889b6e fix damaged 2023-08-06 20:11:00 +00:00
darodi
8e04ccde18 Fix Mac CBZ, CBR, damaged, cover upload 2023-08-06 21:53:37 +02:00
darodi
cc1e5db0aa Merge pull request #566 from axu2/mac
Fix Mac CBZ, CBR, damaged, cover upload
2023-08-06 19:43:54 +00:00
Alex Xu
c5c88095ee bump to 5.6.3 2023-08-06 21:39:40 +02:00
Alex Xu
1318b9c0f2 Fix Mac CBZ, CBR, damaged, cover upload
.decode("utf-8")

edit kindlegen text

adjust 7z text

add unar

delete spec

remove 7z binaries

change path priorities

add 7z location for m1

delete plist

fix mac cover upload
2023-08-06 21:39:40 +02:00
Alex Xu
9339abb267 skip single pixel images in PDF (#546)
* skip pixels hopefully

* add comments and reorder

* add constant
2023-08-05 15:37:00 +00:00
Alex Xu
154707a412 Merge pull request #559
* make scribe default to no upscale with manga mode
2023-08-05 15:18:25 +00:00
darodi
217f571f3d refactor display when kindlegen is missing (#555)
display_kindlegen_missing
2023-07-25 19:31:02 +00:00
Alex Xu
531cea88e6 Add 7z and Kindle Previewer 3 to PATH in all scenarios (#560)
* add 7z and KP3 to path
---------

Co-authored-by: darodi <4682830+darodi@users.noreply.github.com>
2023-07-25 19:27:56 +00:00
Alex Xu
a5202458dc Merge pull request #553
* warn p7zip-rar

* replace strerror
2023-07-05 16:54:24 +00:00
Alex Xu
5902d88d98 remove dead download links (#544)
* remove old links
2023-07-04 10:48:04 +00:00
Alex Xu
e7e41715d0 rename binary releases to downloads (#545) 2023-06-27 16:59:33 +00:00
Alex Xu
62d1c7c488 add 7z wiki link (#543) 2023-06-12 20:16:26 +00:00
darodi
95678adfd6 change format labels in gui (#538) 2023-06-12 18:28:21 +00:00
Alex Xu
4923dac8f0 explicitly name disabled archives (#531)
* explicitly name disabled archives
2023-06-10 11:14:41 +00:00
Vinh Quang Tran
935727c1db Override book's title if Title is set in XML (#532)
* Allow overriding title if it is set in XML
2023-06-10 09:13:01 +00:00
Jaroslaw Janas
b0e38a700a Bump conda python to 3.11 (#524) 2023-05-22 19:46:51 +00:00
darodi
23961243b6 CHANGELOG.md 2023-05-14 19:25:07 +02:00
darodi
c98d6179c3 docker update (#521) 2023-05-14 17:10:40 +00:00
Alex Xu
37200bdca0 Crop images within 3% of device aspect ratio (#495)
* Crop images within 3% of device aspect ratio

* use pad instead of expand+fit

* reafactor threshold check

* remove default val
2023-05-14 16:34:11 +00:00
Jaroslaw Janas
0193bcd00a conda environment (#520) 2023-05-14 16:32:06 +00:00
darodi
0bbe9348a2 OptionParser to ArgumentParser (#517) 2023-05-14 16:31:45 +00:00
darodi
d16628dc59 last version check (#518) 2023-05-14 16:31:31 +00:00
darodi
85c1801417 change version 2023-05-13 18:40:24 +02:00
darodi
b28ee08d01 Merge pull request #515 from darodi/unrar_for_fedora
use unrar for fedora only
2023-05-13 16:25:06 +00:00
darodi
dba927c351 use unrar for fedora only 2023-05-13 18:24:18 +02:00
cookie99999
dd5fd621db Update README.md
Recommend to install p7zip-rar on Debian based systems, as it is needed to properly decompress rar files (As explained under "supported formats" on https://packages.debian.org/sid/p7zip-full).

(cherry picked from commit f3ee9b770b)
2023-05-13 18:20:01 +02:00
darodi
21a167b3ee limit kindle scribe image size to (1440, 1920) when using kindlegen (#516) 2023-05-13 15:50:27 +00:00
darodi
1c9eeee52d use unrar for fedora only 2023-05-13 14:11:50 +02:00
darodi
611ee31526 Merge pull request #513 from axu2/patch-3
add 7z to PATH
2023-05-13 01:46:01 +00:00
darodi
7c4fdf9d1a Merge pull request #514 from darodi/limit_kindle_scribe_size_with_kindlegen
limit kindle scribe image size to (1440, 1920) when using kindlegen
2023-05-13 01:44:12 +00:00
darodi
b14f59e77a limit kindle scribe image size to (1440, 1920) when using kindlegen 2023-05-13 03:40:52 +02:00
Alex Xu
b4ec0b4a74 update wording 2023-05-12 14:17:18 -07:00
Alex Xu
a90b4c82c5 add UI 7z path 2023-05-12 13:06:09 -07:00
Alex Xu
390d58bf08 add 7z to PATH 2023-05-12 12:20:37 -07:00
darodi
e1aa6cd0af Merge pull request #503 from darodi/epub_200MB_above_200MB
Even with EPUB-200MB option selected, created file is above 200MB
2023-04-17 17:50:42 +00:00
darodi
718fda2f0c Even with EPUB-200MB option selected, created file is above 200MB 2023-04-17 19:49:14 +02:00
darodi
9d7904f63b Merge pull request #502 from darodi/master_revert_499
revert #499
2023-04-17 17:46:57 +00:00
darodi
ec58964c7c Revert "Disable Panel View for kindle scribe"
This reverts commit 9bc1f92c8c.
2023-04-17 19:45:20 +02:00
darodi
0b687ebadc Merge pull request #499 from darodi/disable_panel_view_kindle_scribe
Disable Panel View for kindle scribe
2023-04-06 17:21:31 +00:00
darodi
9bc1f92c8c Disable Panel View for kindle scribe 2023-04-06 19:13:56 +02:00
darodi
56f6c6962f Merge pull request #491 from thatrobotdev/brew-gui-change
Updates GUI text for new Homebrew version
2023-03-27 22:48:27 +00:00
darodi
dfd15ab572 Updates GUI text for new Homebrew version 2023-03-28 00:46:25 +02:00
James Kerrane
5588ad9250 Updates GUI text for new Homebrew version 2023-03-28 00:46:25 +02:00
dependabot[bot]
0c2adb517e Update python-slugify requirement from <8.0.0,>=1.2.1 to >=1.2.1,<9.0.0 (#473)
Updates the requirements on [python-slugify](https://github.com/un33k/python-slugify) to permit the latest version.
- [Release notes](https://github.com/un33k/python-slugify/releases)
- [Changelog](https://github.com/un33k/python-slugify/blob/master/CHANGELOG.md)
- [Commits](https://github.com/un33k/python-slugify/compare/1.2.1...v8.0.0)

---
updated-dependencies:
- dependency-name: python-slugify
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-27 22:16:07 +00:00
Alex Xu
9ab1cd359c remove transparency from image info 2023-03-27 22:04:35 +00:00
darodi
41d24e77e1 GUI delete option checkBox 2023-03-02 23:42:11 +01:00
Constantin Hong
17206ddf8b GUI delete option checkBox (closes #458) (#488)
* gui/func: add delete button (closes ciromattia#458)

* Update KCC_ui.py

fix typo

* GUI delete option checkBox

---------

Co-authored-by: darodi <4682830+darodi@users.noreply.github.com>
2023-03-02 23:38:27 +01:00
darodi
896c05a72f Add command line executables to CI/pipelines (#487) 2023-03-02 21:07:45 +01:00
darodi
f83106f35b Merge pull request #485 from Constantin1489/master
comic2ebook/func: Add a delete option
2023-03-02 17:34:16 +01:00
darodi
dfca136a2d comic2ebook/func: Add a delete option and function (closes #458) 2023-03-02 17:31:33 +01:00
Constantin Hong
92ced5f415 comic2ebook/func: Add a delete option and function (closes #458) 2023-03-02 17:12:46 +01:00
darodi
d18275d525 supporting Kindle Previewer (#486) 2023-03-02 17:09:45 +01:00
dependabot[bot]
c049adc3a1 Bump actions/checkout from 2 to 3 (#484)
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-27 21:31:42 +01:00
darodi
a3ce26983e new AppImage (#483) 2023-02-23 18:26:05 +01:00
dependabot[bot]
fe8195cfed Bump actions/upload-artifact from 2 to 3 (#468)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-15 20:38:25 +01:00
darodi
3a1737e8d0 supporting Kindle Previewer 2023-01-22 18:27:50 +01:00
darodi
fb0c0231f3 build pipeline : drop pypi 2023-01-22 17:42:09 +01:00
darodi
2e807e23e1 update README.md 2023-01-22 14:25:37 +01:00
darodi
27841abb83 Update README.md 2023-01-22 14:08:44 +01:00
darodi
b71d056559 prepare pipeline for signing 2023-01-22 10:30:06 +01:00
darodi
a822dfa3ae Version bump 2023-01-21 11:57:55 +01:00
clach04
70de379987 Document CLI tools debian quick install
Command Line Tools can be used with pre-built dependencies.
2023-01-21 11:36:52 +01:00
Frédéric Brière
16e275bb1f Added --croppingminimum option to set a cropping minimum area ratio
Closes #342
2023-01-21 11:30:30 +01:00
darodi
b225de7b97 Enable Synthetic Spreads for the Kobo Forma. 2023-01-21 11:20:14 +01:00
Michael Shavit
4a89446914 Enable Synthetic Spreads for the Kobo Forma.
Rotating the device into landscape mode will cause it to display two
pages side by side. This is particularly useful for input comics whose
spreads are already split into two files.

See https://github.com/kobolabs/epub-spec#synthetic-spreads for
additional information on synthetic spreads.

(Tiny drive-by: Add Kobo format to list of profiles for which the AUTO
format is EPUB)
2023-01-21 11:20:14 +01:00
StudioEtrange
64521de577 replace move with copyfile 2023-01-21 11:03:39 +01:00
catsout
38b14fd734 Using communicate instead of terminate (#459)
Fix kindlegen not clear temp files
2023-01-21 11:00:04 +01:00
Alice Charatonik
4fa72780a1 fix in fedora: 7z doesn't support rar archives, use unrar (#370)
see 
https://github.com/ttys3/fedora-rpm-p7zip
https://sourceforge.net/p/sevenzip/discussion/45798/thread/dc2d0438/#8f9f
2023-01-21 10:54:11 +01:00
Cory Kleinschmidt
c979486e28 Fix pillow backwards compatibility, add mozjpeg-lossless-optimization to setup.py (#461)
- Fix pillow backwards compatibility
- Add mozjpeg-lossless-optimization to setup.py
2023-01-21 00:35:59 +01:00
darodi
03bd67cf2f Update README.md 2023-01-20 13:08:20 +01:00
darodi
b44af66484 pipeline python-package.yml python-package-test.yml 2023-01-19 21:15:54 +01:00
darodi
754395f1b3 pipeline python-package.yml python-package-test.yml 2023-01-19 21:08:34 +01:00
darodi
95e73ea1dd update README.md 2023-01-19 01:54:32 +01:00
darodi
f466701b5d Version bump 2023-01-19 01:28:21 +01:00
darodi
bc6b26862f update README.md 2023-01-19 01:04:45 +01:00
darodi
b4d86fed7f update README.md 2023-01-19 00:39:54 +01:00
darodi
b5806ece0e Update README.md 2023-01-19 00:33:54 +01:00
darodi
85a99f0b05 update README.md 2023-01-19 00:28:37 +01:00
Busindre
4fea796763 Update README
Dependency qt5dxcb-plugin required for KCC added. The kindlegen tool is no longer available through amazon, the link was replaced by a link to archive.org.
2023-01-14 20:31:19 +01:00
darodi
ca8bdf7e1f Update README.md 2023-01-14 17:38:59 +01:00
darodi
33d57d5025 Merge pull request #457 from ciromattia/beta_release_merge_rebased
Beta release merge rebased
2023-01-14 16:45:23 +01:00
darodi
cceb9cf61f change pipeline to publish to PyPi 2023-01-14 01:44:16 +01:00
darodi
9ee375c6e4 change repository to ciromattia 2023-01-14 01:44:16 +01:00
darodi
a50345a26d update version 2023-01-14 01:44:16 +01:00
darodi
be4b35b705 update to python 3.11 2023-01-14 00:31:12 +01:00
dependabot[bot]
608e79a9fc Bump python from 3.8-slim-buster to 3.11-slim-buster
Bumps python from 3.8-slim-buster to 3.11-slim-buster.

---
updated-dependencies:
- dependency-name: python
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-14 00:31:12 +01:00
Fabrizio Pietrucci
7468512ec8 More precise type in slugify dependency check 2023-01-14 00:31:12 +01:00
Fabrizio Pietrucci
2256df0785 Fix 'slugify' dependency check
New versions of slugify moved version informations to a standalone
module (__verrsion__.py). Added a check to see if the imported version
is indeed a string (as previously expected). If not, get the
`__version__` variable in the `__version__` module.
2023-01-14 00:31:12 +01:00
dependabot[bot]
378a3caccc Update python-slugify requirement from <3.0.0,>=1.2.1 to >=1.2.1,<8.0.0
Updates the requirements on [python-slugify](https://github.com/un33k/python-slugify) to permit the latest version.
- [Release notes](https://github.com/un33k/python-slugify/releases)
- [Changelog](https://github.com/un33k/python-slugify/blob/master/CHANGELOG.md)
- [Commits](https://github.com/un33k/python-slugify/compare/1.2.1...v7.0.0)

---
updated-dependencies:
- dependency-name: python-slugify
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-14 00:31:12 +01:00
dependabot[bot]
ab7d629ba9 Bump actions/setup-python from 3 to 4
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 3 to 4.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-14 00:31:12 +01:00
dependabot[bot]
b54299ff76 Bump actions/setup-node from 2 to 3
* Bump actions/setup-node from 2 to 3

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 2 to 3.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump actions/setup-node from 2 to 3

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: darodi <4682830+darodi@users.noreply.github.com>
2023-01-14 00:31:12 +01:00
darodi
1d3fc9cc92 Update dependabot.yml 2023-01-14 00:31:11 +01:00
darodi
49313ce030 Create dependabot.yml 2023-01-14 00:31:11 +01:00
darodi
c0d17c1803 Update README.md 2023-01-14 00:31:11 +01:00
darodi
7f883f98ba Fix Docker 7z missing 2023-01-14 00:31:11 +01:00
darodi
2c19898952 Fix spread splitter not keeping aspect ratio 2023-01-14 00:31:11 +01:00
darodi
12c663bc05 Update README.md 2023-01-14 00:31:11 +01:00
darodi
d8957dc4a6 replace version in Info.plist 2023-01-14 00:31:11 +01:00
darodi
9b45633279 activate batchsplit only for EPUB-200 2023-01-14 00:31:11 +01:00
darodi
b5a0126051 targetsize and EPUB-200MB 2023-01-14 00:31:11 +01:00
rourien
182a292f70 Merge 0c152cf targetsize option 2023-01-14 00:31:11 +01:00
rourien
7ab96c5573 Add backwards compatibility for Pillow >9.1.0 from 4b127b1 2023-01-14 00:31:11 +01:00
rourien
1fbfaeae01 Update deprecated pillow filters
See https://pillow.readthedocs.io/en/stable/deprecations.html#constants
2023-01-14 00:31:11 +01:00
darodi
2462d11b5e appImage with ubuntu-20.04 2023-01-14 00:31:10 +01:00
darodi
44e6ffe4e3 Adding a switch on GUI interface in order to control cropping options 2023-01-14 00:31:10 +01:00
darodi
9be2a4a492 profiles: add Kindle11 and Kindle Scribe - update README.md and CHANGELOG.md 2023-01-14 00:31:10 +01:00
darodi
3ea9a486bf profiles: add Kindle11 and Kindle Scribe 2023-01-14 00:31:10 +01:00
lennie420
95f138887e Update with new Kobo models
* Update Kobo profile list

Update the Kobo models to the current models available from Kobo. I have kept Kobo Forma as this is a popular device amongst manga readers even though it's currently unlisted from Kobo UK's site.

Co-authored-by: darodi <4682830+darodi@users.noreply.github.com>
2023-01-14 00:31:10 +01:00
darodi
a7a01f8269 keep epub file when selecting another type of output file
* Keep epub file when selecting another type of output file
2023-01-14 00:31:10 +01:00
darodi
6987c8b1cd KFX Output in GUI 2023-01-14 00:31:09 +01:00
darodi
6e10636356 Adding Dockerfile 2023-01-14 00:27:53 +01:00
darodi
63bd55313f Update README.md 2023-01-14 00:27:53 +01:00
darodi
324047bebc Fix type error in autocontrastImage 2023-01-14 00:27:53 +01:00
darodi
842a729c75 turn 1x4 strips into 2x2 2023-01-14 00:27:53 +01:00
darodi
27d3eab8d5 Update README.md
clarify requirements for pillow
2023-01-14 00:27:53 +01:00
darodi
8035dedae8 force PNG checkbox 2023-01-14 00:27:53 +01:00
darodi
b39076a9f4 pipelines 2023-01-14 00:27:52 +01:00
darodi
237f343e62 * fix Using 'Disable processing' option using my processed image get an error 2023-01-13 22:48:53 +01:00
darodi
ab60d67ab7 add --mozjpeg option and GUI checkBox 2023-01-13 22:48:53 +01:00
darodi
79715c6a06 add --mozjpeg option and GUI checkBox 2023-01-13 22:48:53 +01:00
StudioEtrange
6cd073809e add GUI option to disable processing 2023-01-13 22:48:53 +01:00
StudioEtrange
9dac000a04 add --noprocessing option 2023-01-13 22:48:53 +01:00
StudioEtrange
674121620f file selector add All *.* 2023-01-13 22:22:11 +01:00
clach04
f6e2ceae91 Clarify Pillow version requirement
Pillow version requirement in code is 5.2.0+ since support for WebP was added for issue #240 
Clarify optional GUI dependencies, kcc-c2p.py/kcc-c2e.py does not need pyqt nor raven.
2023-01-13 22:20:12 +01:00
StudioEtrange
143f6eb0f9 sync requirements between setup.py and requirements.txt 2023-01-13 22:17:40 +01:00
darodi
7cac6d4008 Merge pull request #405 from darodi/kindle_signature
Add profile for Kindle Paperwhite 5 (Signature Edition) - fixed for panel view 4/2/HQ
2023-01-13 21:55:30 +01:00
darodi
aa4456bdb1 Add profile for Kindle PW5/Signature 2021-11-27 23:57:45 +01:00
Einlar
c91be77588 Add profile for Kindle PW5/Signature 2021-11-13 13:50:56 +01:00
Einlar
65a42c1063 Merge branch 'add_profiles_kobo' 2021-11-13 13:32:06 +01:00
Fulya
6519eb0453 Fixed the skipped/missed images and/or panels 2021-05-15 14:08:36 -04:00
Frédéric Brière
9fdbf095d3 Add profiles for the Kobo Clara HD and Libra H2O
Note: I omitted the "HD" and "H2O" suffixes from the labels to keep
things simple, since they do not denote a variation of a preexisting
model, as was the case with the Aura.
2019-11-12 11:59:22 -05:00
Paweł Jastrzębski
4ec4c9966c Merge pull request #329 from C0rn3j/master
Do not recommend running pip as root
2019-10-29 11:25:48 +01:00
C0rn3j
5a51c5234e Recommend running pip as user, not root 2019-10-28 14:38:48 +01:00
C0rn3j
b7c6fd30e4 Fix typo 2019-10-28 14:37:56 +01:00
Paweł Jastrzębski
515b83637f Merge pull request #326 from ciromattia/dev
5.5.2
2019-10-21 17:27:38 +02:00
Paweł Jastrzębski
c3dad087d3 Update build scripts 2019-10-21 16:12:03 +02:00
Paweł Jastrzębski
67e913ed9e Version bump 2019-10-21 13:50:53 +02:00
Paweł Jastrzębski
6ce0f76fe0 Fixed KindleGen detection on macOS 2019-10-21 13:44:49 +02:00
Paweł Jastrzębski
5f5157c1d4 No longer modify header field 504 2019-08-04 09:29:03 +02:00
Paweł Jastrzębski
4c13ef0f6c Fixed handling filenames that start with dot (close #310) 2019-08-04 09:25:32 +02:00
Paweł Jastrzębski
50dc7fbffe Added profile label for Oasis 3
New profile is unnecessary.
2019-08-04 08:40:48 +02:00
Paweł Jastrzębski
a060498ac7 Fixed Windows autoupdater 2019-03-08 09:04:12 +01:00
Paweł Jastrzębski
35bba68a72 Merge pull request #308 from ciromattia/dev
5.5.1
2019-03-08 08:44:48 +01:00
Paweł Jastrzębski
0b056a8fa8 Stabilise multiprocessing on OSX 2019-03-08 08:16:53 +01:00
Paweł Jastrzębski
a6f9e84251 Tweaks for OSX binary 2019-03-07 16:24:41 +01:00
Paweł Jastrzębski
259800e48b Tweaks for Windows binary 2019-03-07 11:36:56 +01:00
Paweł Jastrzębski
28e170f1d2 Merge pull request #306 from ciromattia/dev
5.5.0
2019-03-07 08:39:57 +01:00
Paweł Jastrzębski
7120c76025 Updated changelog 2019-03-07 08:38:22 +01:00
Paweł Jastrzębski
4891913b5c Added additional cleanup 2019-03-07 08:26:31 +01:00
Paweł Jastrzębski
cd83b2899c Fixed bookmark parsing (close #229) 2019-03-07 08:21:56 +01:00
Paweł Jastrzębski
535c2c220b Added RAR5 support 2019-03-06 20:12:11 +01:00
Paweł Jastrzębski
409f077c3e Bye, bye DEBs 2019-03-06 19:50:17 +01:00
Paweł Jastrzębski
3ecb2ba877 Fixed metadata encoding (close #281) 2019-03-06 16:37:26 +01:00
Paweł Jastrzębski
c07a9657ef Removed MCD support 2019-03-06 16:16:26 +01:00
Paweł Jastrzębski
7f719a22ad Added PW4 profile (close #293) 2019-03-06 16:01:18 +01:00
Paweł Jastrzębski
332d3d455e Version bump 2019-03-06 15:47:18 +01:00
Paweł Jastrzębski
2070a977ae Updated build enviroment 2019-03-06 10:56:44 +01:00
Paweł Jastrzębski
8f8d0d68a3 Fixed possible glob issues 2019-02-27 13:49:47 +01:00
Paweł Jastrzębski
5a8deb4623 Merge pull request #295 from murphytsai/feature/support-kobo-forma
Support Kobo Forma (close #294)
2019-01-04 10:09:25 +01:00
MurphyTsai
a7ea795df5 support kobo forma. 2019-01-03 14:52:28 +08:00
Paweł Jastrzębski
a2ffd259b8 Code cleanup 2018-07-10 09:00:13 +02:00
Paweł Jastrzębski
93e6b51466 Expanded output of corruption error (close #272) 2018-07-10 08:42:15 +02:00
Paweł Jastrzębski
7904662f25 Let 7-Zip handle all archive operations 2018-07-10 08:09:04 +02:00
Paweł Jastrzębski
6792c2d366 Bump MAX_IMAGE_PIXELS (close #273) 2018-07-09 08:30:12 +02:00
Paweł Jastrzębski
ef4a91e44d WebP support (close #263) 2018-07-08 08:42:34 +02:00
Paweł Jastrzębski
a2a405e5f5 Merge branch 'Gokuroro-master' into dev 2018-04-21 09:26:48 +02:00
Hugo
a63a46a741 Use more standard __version__ rather than PILLOW_VERSION 2018-04-18 11:42:56 +03:00
Carlos Rosa
2591b53a09 Make file type error more informative (display file name) 2018-04-04 11:05:13 -03:00
Carlos Rosa
1c615ffc20 Make format checking more straightforward 2018-04-04 11:04:31 -03:00
Carlos Rosa
6eb05b3a8f Allow for multiple file arguments on startup 2018-04-04 10:12:30 -03:00
Paweł Jastrzębski
968b083fb2 Updated build enviroment 2018-03-10 08:41:12 +01:00
Paweł Jastrzębski
205907ef1e Merge branch 'master' of https://github.com/ciromattia/kcc 2018-03-10 08:27:16 +01:00
Paweł Jastrzębski
33ef8275c3 Fixed non-Kindle EPUB ouput (close #262) 2018-03-10 08:26:55 +01:00
Paweł Jastrzębski
eec2099515 Fixed unrar detection 2018-03-10 08:26:14 +01:00
Paweł Jastrzębski
9027265b7c Update README.md 2018-03-09 20:45:37 +01:00
Paweł Jastrzębski
34e2af3389 Merge pull request #261 from ciromattia/dev
5.4.4
2018-03-08 16:15:42 +01:00
Paweł Jastrzębski
5ecddaceab Version bump 2018-03-08 16:12:56 +01:00
Paweł Jastrzębski
fe554c20aa Fixed dot procesing for real this time 2017-11-10 19:54:07 +01:00
Paweł Jastrzębski
6acf1a1802 Updated build enviroment 2017-11-10 19:10:23 +01:00
Paweł Jastrzębski
ac81a6be4b Fixed dot processing in directory names 2017-11-10 17:32:34 +01:00
Paweł Jastrzębski
829a5f25e7 Experimental KFX output 2017-11-05 18:54:11 +01:00
Paweł Jastrzębski
a695a4c151 Code cleanup 2017-11-02 10:28:43 +01:00
Paweł Jastrzębski
7c0b78350d Updated build enviroment 2017-10-14 22:13:09 +02:00
Paweł Jastrzębski
aa978ab246 Disabled old multiprocessing hack 2017-10-14 22:10:31 +02:00
Paweł Jastrzębski
7524c50657 Merge pull request #250 from ciromattia/dev
5.4.2
2017-10-14 18:01:32 +02:00
Paweł Jastrzębski
9d8663a925 Updated README + version bump 2017-10-14 18:00:39 +02:00
Paweł Jastrzębski
08ed304f8e Allow metadata editor to embed directories 2017-10-14 17:57:00 +02:00
Paweł Jastrzębski
658d2f3281 Fixed directory sorting (close #235) 2017-10-13 11:56:51 +02:00
Paweł Jastrzębski
f44bf5993e Fixed HQ mode upscaling (close #248) 2017-10-13 10:41:45 +02:00
Paweł Jastrzębski
458c28281f Added Oasis 2 profile (close #249) 2017-10-13 09:12:17 +02:00
Paweł Jastrzębski
968a1afa1d Updated build enviroment 2017-10-13 08:57:58 +02:00
Paweł Jastrzębski
2c875673bd Merge pull request #244 from ciromattia/dev
5.4.1
2017-08-22 15:32:18 +02:00
Paweł Jastrzębski
1a0be83d63 Updated README + version bump 2017-08-22 15:31:45 +02:00
Paweł Jastrzębski
36a7dc49ec Fixed some typos 2017-08-20 18:06:09 +02:00
Paweł Jastrzębski
40d1ae63da Tweaked build process 2017-08-20 17:10:28 +02:00
Paweł Jastrzębski
3d3621c6ec Merge pull request #243 from AcidWeb/master
Implemented new build environments
2017-08-20 12:29:28 +02:00
Paweł Jastrzębski
d77f04a84e Implemented new build enviroments 2017-08-20 12:21:21 +02:00
Paweł Jastrzębski
ec51d6fc51 Merge pull request #242 from AcidWeb/master
Travis update
2017-08-19 20:58:38 +02:00
Paweł Jastrzębski
b7861d9d9e Travis update 2017-08-19 20:45:49 +02:00
Paweł Jastrzębski
0b4503af21 Merge pull request #241 from ciromattia/dev
5.4.1 preparation
2017-08-19 20:31:28 +02:00
Paweł Jastrzębski
437ffb9b10 Updated Docker recipe 2017-08-19 20:26:18 +02:00
Paweł Jastrzębski
066d1401bd Cleaned profile list 2017-08-17 10:11:24 +02:00
Paweł Jastrzębski
9babe68d2a Start using Travis CI as OS X binary builder 2017-08-16 18:55:20 +02:00
Paweł Jastrzębski
67de77538c Disable Panel View for Kindle Keyboard (#238) 2017-07-15 12:00:19 +02:00
Paweł Jastrzębski
c3e950f2ec Split README file 2017-04-09 16:50:11 +02:00
64 changed files with 15495 additions and 15857 deletions

13
.dockerignore Normal file
View File

@@ -0,0 +1,13 @@
.git
.github
build
dist
KindleComicConverter.egg-info
.dockerignore
.gitignore
.travis.yml
Dockerfile
venv
*.md
LICENSE.txt
MANIFEST.in

31
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,31 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
Add a screenshot of your KCC settings.
**Desktop (please complete the following information):**
- OS: [e.g. macOS, Linux, Windows 11]
- Device [e.g. Kindle Paperwhite 3rd gen, Kobo Libra 2]
**Additional context**
Add any other context about the problem here.

25
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
# Enable version updates for Docker
- package-ecosystem: "docker"
# Look for a `Dockerfile` in the `root` directory
directory: "/"
# Check for updates once a week
schedule:
interval: "weekly"
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

74
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,74 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ "beta_release" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "beta_release" ]
schedule:
- cron: '42 22 * * 3'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

View File

@@ -0,0 +1,34 @@
name: Docker base
on:
workflow_dispatch:
push:
tags: [ 'docker-base-*' ]
# Don't trigger if it's just a documentation update
paths-ignore:
- '**.md'
- '**.MD'
- '**.yml'
- 'docs/**'
- 'LICENSE'
- '.gitattributes'
- '.gitignore'
- '.dockerignore'
jobs:
build_and_push:
uses: sdr-enthusiasts/common-github-workflows/.github/workflows/build_and_push_image.yml@main
with:
docker_build_file: ./Dockerfile-base
platform_linux_arm32v7_enabled: true
platform_linux_arm64v8_enabled: true
platform_linux_amd64_enabled: true
push_enabled: true
build_nohealthcheck: false
ghcr_repo_owner: ${{ github.repository_owner }}
ghcr_repo: ${{ github.repository }}
build_latest: false
secrets:
ghcr_token: ${{ secrets.GITHUB_TOKEN }}

33
.github/workflows/docker-publish.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: Docker
on:
workflow_dispatch:
push:
# Publish semver tags as releases.
tags: [ 'v*.*.*' ]
# Don't trigger if it's just a documentation update
paths-ignore:
- '**.md'
- '**.MD'
- '**.yml'
- 'docs/**'
- 'LICENSE'
- '.gitattributes'
- '.gitignore'
- '.dockerignore'
jobs:
build_and_push:
uses: sdr-enthusiasts/common-github-workflows/.github/workflows/build_and_push_image.yml@main
with:
platform_linux_arm32v7_enabled: true
platform_linux_arm64v8_enabled: true
platform_linux_amd64_enabled: true
push_enabled: true
build_nohealthcheck: false
ghcr_repo_owner: ${{ github.repository_owner }}
ghcr_repo: ${{ github.repository }}
secrets:
ghcr_token: ${{ secrets.GITHUB_TOKEN }}

75
.github/workflows/package-linux.yml vendored Normal file
View File

@@ -0,0 +1,75 @@
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
name: build KCC for Linux
on:
workflow_dispatch:
push:
tags:
- "v*.*.*"
# Don't trigger if it's just a documentation update
paths-ignore:
- '**.md'
- '**.MD'
- '**.yml'
- '**.sh'
- 'docs/**'
- 'Dockerfile'
- 'LICENSE'
- '.gitattributes'
- '.gitignore'
- '.dockerignore'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.11
cache: 'pip'
- name: Install python dependencies
run: |
sudo apt-get update
sudo apt-get install -y libpng-dev libjpeg-dev p7zip-full p7zip-rar python3-pip squashfs-tools libfuse2 libxcb-cursor0
python -m pip install --upgrade pip setuptools wheel certifi pyinstaller --no-binary pyinstaller
python -m pip install -r requirements.txt
- name: build binary
run: |
python setup.py build_binary
chmod +x dist/kcc_linux*
# issue with this action, disabled and commented out
# see https://github.com/AppImageCrafters/build-appimage/issues/5
# see https://appimage-builder.readthedocs.io/en/latest/intro/install.html#install-appimagetool
# - name: Build AppImage
# uses: AppImageCrafters/build-appimage-action@master
# env:
# UPDATE_INFO: gh-releases-zsync|ciromattia|kcc|latest|*x86_64.AppImage.zsync
# with:
# recipe: AppImageBuilder.yml
- name: Build AppImage
run: |
wget -O appimage-builder-x86_64.AppImage https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0-x86_64.AppImage
chmod +x appimage-builder-x86_64.AppImage
sudo mv appimage-builder-x86_64.AppImage /usr/local/bin/appimage-builder
appimage-builder --recipe AppImageBuilder.yml --skip-test
env:
UPDATE_INFO: gh-releases-zsync|ciromattia|kcc|latest|*x86_64.AppImage.zsync
- name: upload artifact
uses: actions/upload-artifact@v4
with:
name: AppImage
path: './*.AppImage*'
- name: Release
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
prerelease: true
generate_release_notes: true
files: |
CHANGELOG.md
LICENSE.txt
*.AppImage*

101
.github/workflows/package-macos.yml vendored Normal file
View File

@@ -0,0 +1,101 @@
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
name: build KCC for mac os
on:
workflow_dispatch:
push:
tags:
- "v*.*.*"
# Don't trigger if it's just a documentation update
paths-ignore:
- '**.md'
- '**.MD'
- '**.yml'
- '**.sh'
- 'docs/**'
- 'Dockerfile'
- 'LICENSE'
- '.gitattributes'
- '.gitignore'
- '.dockerignore'
jobs:
build:
strategy:
matrix:
os: [ macos-12, macos-14 ]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.11
cache: 'pip'
- name: Install python dependencies
run: |
python -m pip install --upgrade pip setuptools wheel pyinstaller certifi
pip install -r requirements.txt
- name: Install the Apple certificate and provisioning profile
# TODO signing
# https://federicoterzi.com/blog/automatic-code-signing-and-notarization-for-macos-apps-using-github-actions/
if: ${{ false }}
env:
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
# create variables
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
# import certificate and provisioning profile from secrets
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH
echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH
# create temporary keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# import certificate to keychain
security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
# apply provisioning profile
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
- uses: actions/setup-node@v4
with:
node-version: 16
- run: npm install -g appdmg
- name: build binary
# TODO /usr/bin/codesign --force -s "$MACOS_CERTIFICATE_NAME" --options runtime dist/Applications/Kindle\ Comic\ Converter.app -v
run: |
python setup.py build_binary
- name: upload build
uses: actions/upload-artifact@v4
with:
name: mac-os-build-${{ runner.arch }}
path: dist/*.dmg
- name: Release
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
prerelease: true
generate_release_notes: true
files: |
CHANGELOG.md
LICENSE.txt
dist/*.dmg
- name: Clean up keychain and provisioning profile
# TODO signing
if: ${{ false }}
# if: ${{ always() }}
run: |
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
rm ~/Library/MobileDevice/Provisioning\ Profiles/build_pp.mobileprovision

View File

@@ -0,0 +1,57 @@
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
name: build KCC for windows with docker
on:
workflow_dispatch:
push:
tags:
- "v*.*.*"
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# - name: Set up Python
# uses: actions/setup-python@v4
# with:
# python-version: 3.11
# cache: 'pip'
# - name: Install python dependencies
# run: |
# python -m pip install --upgrade pip setuptools wheel pyinstaller
# pip install -r requirements.txt
# - name: build binary
# run: |
# pyi-makespec -F -i icons\\comic2ebook.ico -n KCC_test -w --noupx kcc.py
- name: Package Application
uses: JackMcKew/pyinstaller-action-windows@main
with:
path: .
spec: ./kcc-c2e.spec
- name: Package Application
uses: JackMcKew/pyinstaller-action-windows@main
with:
path: .
spec: ./kcc-c2p.spec
- name: rename binaries
run: |
version_built=$(cat kindlecomicconverter/__init__.py | grep version | awk '{print $3}' | sed "s/[^.0-9b]//g")
mv dist/windows/kcc-c2e.exe dist/windows/KCC_c2e_${version_built}.exe
mv dist/windows/kcc-c2p.exe dist/windows/KCC_c2p_${version_built}.exe
- name: upload build
uses: actions/upload-artifact@v4
with:
name: windows-build
path: dist/windows/*.exe
- name: Release
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
prerelease: true
generate_release_notes: true
files: |
CHANGELOG.md
LICENSE.txt
dist/windows/*.exe

58
.github/workflows/package-windows.yml vendored Normal file
View File

@@ -0,0 +1,58 @@
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
name: build KCC for windows
on:
workflow_dispatch:
push:
tags:
- "v*.*.*"
# Don't trigger if it's just a documentation update
paths-ignore:
- '**.md'
- '**.MD'
- '**.yml'
- '**.sh'
- 'docs/**'
- 'Dockerfile'
- 'LICENSE'
- '.gitattributes'
- '.gitignore'
- '.dockerignore'
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.11
cache: 'pip'
- name: Install dependencies
env:
PYINSTALLER_COMPILE_BOOTLOADER: 1
run: |
python -m pip install --upgrade pip setuptools wheel
pip install -r requirements.txt
pip install certifi pyinstaller --no-binary pyinstaller
- name: build binary
run: |
python setup.py build_binary
- name: upload build
uses: actions/upload-artifact@v4
with:
name: windows-build
path: dist/*.exe
- name: Release
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
prerelease: true
generate_release_notes: true
files: |
CHANGELOG.md
LICENSE.txt
dist/*.exe

24
.gitignore vendored
View File

@@ -1,18 +1,14 @@
*.pyc
*.cbz
*.cbr
.idea
.DS_Store
Thumbs.db
dist
Output
test
solaio
kindlegen*
*.spec
Pipfile
Pipfile.lock
setup.bat
setup.sh
kindlecomicconverter/sentry.py
other/windows/kindlegen.exe
dist/
build/
.python-version
KindleComicConverter.egg-info/
KindleComicConverter*.egg-info/
.idea/
/venv/
/kindlegen*
/kcc.bat
.DS_Store

30
.travis.yml Normal file
View File

@@ -0,0 +1,30 @@
matrix:
include:
- os: osx
language: generic
osx_image: xcode11.1
before_install:
- pip3 install --upgrade pip setuptools wheel
install:
- pip3 install -r requirements.txt
- pip3 install certifi https://github.com/pyinstaller/pyinstaller/archive/develop.zip
- npm install -g appdmg
script: python3 setup.py build_binary
before_deploy:
- shopt -s extglob
- rm -r dist/!(*.deb|*.dmg)
deploy:
provider: gcs
access_key_id: GOOG1EC62457RKUYFR2TIZUWV4EFSV2EP5LVLPPFXUAKADWJFDYPFW63BQSLA
secret_access_key:
secure: sxYjeho7U3im0Ezf6cz6TjYDiLvf0kAM2ETQHYoFNbD1VVvhJJyymDCnPH80zpFKmhc1MWTB6ndwsrPfcyZDLR2meSdWGPjZfFPY3RcrfImndKi7ln+mYQDBQ7W1lGit4YcH3Ju7LHceaTbRA7fVTX8pWKOcbXL2oM+lQxTJHH32+crVma+ChhbjzTWsSLRoakt3Nhiveec5p/qSW7AFe4Zq+b3C85IgwjSJI/xVwzaWrs6p915h1zZi7KL7YCMIxfQFrvRPFR2KTbh/DoLCCrqfbD4qh0PVy1li51Ac3hd/u3foiNnTNchzgE3Nv/nbKmtFU6huuLNgzkQGuLA+yn7mKYzBwA3ZmFgoimdH9+yRCMkZ8B5VHpvfN1hgpJcyEl1T98Kv4cdtRYNB4w9iAMy1qSVxhjeI+2rjuWGoXro0lU6L4LIRCOruY3AuLCAKG8Qw5Ak9ksmIKBhZ9soxpoIwu/TYDUQkFj29IrUQucg9TEp7uAoxu8/7EHxB7hWnBRaBAAQbMuIRg7yysT3FT0Os6SB0t9+RBsVMSPuIti9JJZ2Lu0uRI1+Se+g7ItzYtJoPhBJAzAa+J9OONj0RNj2z8Vq2oIBhH4z6b6zTRMVroos3cdfYl5qIKs9SQ7rmeHoPRROcqpCznsUZ/ESa4f2MewFU/7AYcEnCesZV4xg=
bucket: kcc-deploy
local-dir: dist
skip_cleanup: true
on:
repo: AcidWeb/KCC

67
AppImageBuilder.yml Normal file
View File

@@ -0,0 +1,67 @@
# appimage-builder recipe see https://appimage-builder.readthedocs.io for details
version: 1
script:
- rm -rf AppDir || true
- mkdir -p AppDir/usr/share/icons/hicolor/64x64/apps/
- cp -a dist/kcc_linux* AppDir/ && mv AppDir/kcc_linux* AppDir/kcc_linux
- cp icons/comic2ebook.png AppDir/usr/share/icons/hicolor/64x64/apps/
AppDir:
path: AppDir
app_info:
id: com.github.ciromattia.kcc
name: kindleComicConverter
icon: comic2ebook
version: latest
exec: ./kcc_linux
exec_args: $@
apt:
arch:
- amd64
allow_unauthenticated: true
sources:
- sourceline: deb http://archive.ubuntu.com/ubuntu jammy main restricted
- sourceline: deb http://archive.ubuntu.com/ubuntu jammy-updates main restricted
- sourceline: deb http://archive.ubuntu.com/ubuntu jammy universe
- sourceline: deb http://archive.ubuntu.com/ubuntu jammy-updates universe
- sourceline: deb http://archive.ubuntu.com/ubuntu jammy multiverse
- sourceline: deb http://archive.ubuntu.com/ubuntu jammy-updates multiverse
- sourceline: deb http://archive.ubuntu.com/ubuntu jammy-backports main restricted
universe multiverse
- sourceline: deb http://security.ubuntu.com/ubuntu jammy-security main restricted
- sourceline: deb http://security.ubuntu.com/ubuntu jammy-security universe
- sourceline: deb http://security.ubuntu.com/ubuntu jammy-security multiverse
include:
- libc6:amd64
files:
include: []
exclude:
- usr/share/man
- usr/share/doc/*/README.*
- usr/share/doc/*/changelog.*
- usr/share/doc/*/NEWS.*
- usr/share/doc/*/TODO.*
test:
fedora-30:
image: appimagecrafters/tests-env:fedora-30
command: ./AppRun
use_host_x: true
debian-stable:
image: appimagecrafters/tests-env:debian-stable
command: ./AppRun
use_host_x: true
archlinux-latest:
image: appimagecrafters/tests-env:archlinux-latest
command: ./AppRun
use_host_x: true
centos-7:
image: appimagecrafters/tests-env:centos-7
command: ./AppRun
use_host_x: true
ubuntu-xenial:
image: appimagecrafters/tests-env:ubuntu-xenial
command: ./AppRun
use_host_x: true
AppImage:
arch: x86_64
update-information: !ENV ${UPDATE_INFO}
sign-key: None

433
CHANGELOG.md Normal file
View File

@@ -0,0 +1,433 @@
# CHANGELOG
#### 5.6.2:
* build pipeline : drop pypi by @darodi in [#465](https://github.com/ciromattia/kcc/pull/465)
* supporting Kindle Previewer by @darodi in [#466](https://github.com/ciromattia/kcc/pull/466)
* Bump actions/upload-artifact from 2 to 3 by @dependabot in [#468](https://github.com/ciromattia/kcc/pull/468)
* new appImage by @darodi in [#483](https://github.com/ciromattia/kcc/pull/483)
* Bump actions/checkout from 2 to 3 by @dependabot in [#484](https://github.com/ciromattia/kcc/pull/484)
* supporting Kindle Previewer by @darodi in [#486](https://github.com/ciromattia/kcc/pull/486)
* comic2ebook/func: Add a delete option (closes #458) by @Constantin1489 in [#485](https://github.com/ciromattia/kcc/pull/485)
* Add command line executables to CI/pipelines by @darodi in [#487](https://github.com/ciromattia/kcc/pull/487)
* gui/func: Add a 'delete after conversion' button (closes #458) by @Constantin1489 in [#488](https://github.com/ciromattia/kcc/pull/488)
* fix crashes on png transparency by @axu2 in [#494](https://github.com/ciromattia/kcc/pull/494)
* Update python-slugify requirement from <8.0.0,>=1.2.1 to >=1.2.1,<9.0.0 by @dependabot in [#473](https://github.com/ciromattia/kcc/pull/473)
* Updates GUI text for new Homebrew version by @thatrobotdev in [#491](https://github.com/ciromattia/kcc/pull/491)
* Even with EPUB-200MB option selected, created file is above 200MB by @darodi in [#503](https://github.com/ciromattia/kcc/pull/503)
* limit kindle scribe image size to (1440, 1920) when using kindlegen by @darodi in [#514](https://github.com/ciromattia/kcc/pull/514)
* add 7z to PATH by @axu2 in [#513](https://github.com/ciromattia/kcc/pull/513)
* use unrar for fedora only by @darodi in [#515](https://github.com/ciromattia/kcc/pull/515)
#### 5.6.1:
* Fix pillow backwards compatibility, add mozjpeg-lossless-optimization to setup.py by @corylk in #461
* fix in fedora: 7z doesn't support rar archives, use unrar by @AlicesReflexion in #370
* Using communicate instead of terminate by @catsout in #459
* use copyfile and delete instead of shutil.move fix #386 by @StudioEtrange in #387
#### 5.6.0:
* Fix Docker 7z missing [darodi/kcc#31](https://github.com/darodi/kcc/issues/31), thanks [@darodi](https://github.com/darodi)
* update to python 3.11, thanks [@darodi](https://github.com/darodi)
* Bump python from 3.8-slim-buster to 3.11-slim-buster dependabot[bot]
* More precise type in slugify dependency check, thanks [@bamless](https://github.com/bamless)
* Fix 'slugify' dependency check, thanks [@bamless](https://github.com/bamless)
* Update python-slugify requirement from <3.0.0,>=1.2.1 to >=1.2.1,<8.0.0 dependabot[bot]
* Bump actions/setup-python from 3 to 4 [darodi/kcc#32](https://github.com/darodi/kcc/issues/32) dependabot[bot]
* Bump actions/setup-node from 2 to 3 [darodi/kcc#34](https://github.com/darodi/kcc/issues/34) dependabot[bot]
* Fix Docker 7z missing [darodi/kcc#31](https://github.com/darodi/kcc/issues/31), thanks [@darodi](https://github.com/darodi)
* Spread splitter not keeping aspect ratio [darodi/kcc#27](https://github.com/darodi/kcc/issues/27), thanks [@darodi](https://github.com/darodi)
* activate batchsplit only for EPUB-200 [darodi/kcc#24](https://github.com/darodi/kcc/issues/24), thanks [@darodi](https://github.com/darodi)
* Feature Request: allow split for epub and set target (email, web upload) [darodi/kcc#21](https://github.com/darodi/kcc/issues/21), thanks [@darodi](https://github.com/darodi)
* Adding a switch on GUI interface in order to control cropping options [darodi/kcc#18](https://github.com/darodi/kcc/issues/18), thanks [@darodi](https://github.com/darodi)
* profiles: add Kindle11 and Kindle Scribe [darodi/kcc#16](https://github.com/darodi/kcc/issues/16), thanks [@darodi](https://github.com/darodi)
* Update with new Kobo models [darodi/kcc#15](https://github.com/darodi/kcc/issues/15), thanks [@lennie420](https://github.com/lennie420)
* Keep epub file when selecting another type of output file [darodi/kcc#12](https://github.com/darodi/kcc/issues/12), thanks [@darodi](https://github.com/darodi)
* fix Using 'Disable processing' option using my processed image get an error [darodi/kcc#1](https://github.com/darodi/kcc/issues/1), thanks [@darodi](https://github.com/darodi)
* KFX Output in GUI [darodi/kcc#9](https://github.com/darodi/kcc/issues/9), thanks [@darodi](https://github.com/darodi)
* Linux version and appImage [darodi/kcc#6](https://github.com/darodi/kcc/issues/6), thanks [@darodi](https://github.com/darodi)
* docker image for command line [darodi/kcc#5](https://github.com/darodi/kcc/issues/5), thanks [@darodi](https://github.com/darodi)
* Fix type error in autocontrastImage [ciromattia/kcc#432](https://github.com/ciromattia/kcc/issues/432), thanks [@darodi](https://github.com/darodi)
* Option to turn 1x4 strips into 2x2 strips [ciromattia/kcc#439](https://github.com/ciromattia/kcc/issues/439), thanks [@darodi](https://github.com/darodi)
* Option in GUI to have PNG instead of jpg images [darodi/kcc#3](https://github.com/darodi/kcc/issues/3), thanks [@darodi](https://github.com/darodi)
* Use MozJPEG as the JPEG encoder : cli and GUI option [ciromattia/kcc#416](https://github.com/ciromattia/kcc/pull/416), thanks [@darodi](https://github.com/darodi)
* Disable all image transformation : cli and GUI option [ciromattia/kcc#388](https://github.com/ciromattia/kcc/pull/388), thanks [@StudioEtrange](https://github.com/StudioEtrange)
* file selector add All `*.*` [ciromattia/kcc#412](https://github.com/ciromattia/kcc/pull/412), thanks [@StudioEtrange](https://github.com/StudioEtrange)
* Clarify Pillow version requirement [ciromattia/kcc#366](https://github.com/ciromattia/kcc/pull/366), thanks [@clach04](https://github.com/clach04)
* sync requirements between setup.py and requirements.txt [ciromattia/kcc#411](https://github.com/ciromattia/kcc/pull/411), thanks [@StudioEtrange](https://github.com/StudioEtrange)
* Add profile for Kindle PW5/Signature [ciromattia/kcc#405](https://github.com/ciromattia/kcc/pull/405), thanks [@Einlar](https://github.com/Einlar), [@darodi](https://github.com/darodi)
* Fixed the skipped/missed images and/or panels [ciromattia/kcc#393](https://github.com/ciromattia/kcc/pull/393), thanks [@FulyaDemirkan](https://github.com/FulyaDemirkan)
* Add profiles for the Kobo Clara HD and Libra H2O [ciromattia/kcc#331](https://github.com/ciromattia/kcc/pull/331), thanks [@fbriere](https://github.com/fbriere)
#### 5.5.2:
* Fixed KindleGen detection on macOS 10.15
* Fixed multiple smaller issues
#### 5.5.1:
* Fixes some stability issues
#### 5.5.0:
* Added support for WebP format
* Added profiles for Kindle Paperwhite 4 and Kobo Forma
* All archives are now handled by 7z
* Removed MCD support
* Fixed multiple smaller issues
#### 5.4.5:
* Fixed EPUB output for non-Kindle devices
#### 5.4.4:
* Minor bug fixes
#### 5.4.3:
* Fixed conversion crash on Windows
#### 5.4.2:
* Added Kindle Oasis 2 profile
* Allowed metadata editor to edit directories
* Fixed image stretching when HQ Panel View option was enabled
* Fixed possible problem with directory sort order
#### 5.4.1:
* Minor bug fixes and tweaks
* Implemented new binary build pipeline
#### 5.4:
* Reimplemented high quality Panel View option
* Improved webtoon splitter
* Fixed page splitter
#### 5.3.1:
* Small increase of output quality
* Improved error reporting
* Internal changes and tweaks
#### 5.3:
* Vastly improved output compatibility for non-Kindle devices
* Enabled old pinch zoom for Kindle devices
* Re-enabled Panel View support for Kindle Keyboard
* Partially re-enabled OS X file association mechanism
* Fixed multiple smaller issues
#### 5.2.1:
* Improved directory parsing
* Tweaked margin detection algorithm
* Improved error reporting
#### 5.2:
* Added new Panel View options
* Implemented new margin detection algorithm
* Removed HQ Panel View mode
* Fixed multiple smaller issues
#### 5.1.3:
* Added Kobo Aura ONE profile
* Fixed few small bugs
#### 5.1.2:
* Fixed error reporting
#### 5.1.1:
* Fixed multiple GUI bugs
#### 5.1:
* GUI now can be resized and high DPI support was somewhat improved
* Added profile for Kindle Oasis
* Implemented new error reporting mechanism
* CLI version now support additional cropping options
* Fixed permission issues on Windows
* Fixed multiple smaller issues
#### 5.0.1:
* Fixed Panel View placement issues
* Decreased application startup time
* Fixed multiple smaller issues
#### 5.0:
* Major overhaul of internal mechanisms and GUI
* Added cover upload feature
* Tweaked Webtoon parsing mode
* Fixed multiple smaller issues
* Migrated build enviroment to PyInstaller
#### 4.6.5:
* Fixed multiple Windows and OS X issues
* Allowed Linux release to use older PyQT5 version
#### 4.6.4:
* Fixed multiple Windows specific problems
* Improved error handling
* Improved color detection algorithm
* New, slimmer OS X release
#### 4.6.3:
* Implemented remote bug reporting
* Minor bug fixes and GUI tweaks
#### 4.6.2:
* Fixed critical MOBI header bug
* Fixed metadata encoding error
#### 4.6.1:
* Fixed KEPUB TOC generator
* Added warning about too small input files
* ComicRack Summary metadata field is now parsed
* Small tweaks of KEPUB output
#### 4.6:
* KEPUB is now default output for all Kobo profiles
* EPUB output now produce fully valid EPUB 3.0.1
* Added profile for Kindle Paperwhite 3
* Dropped official support of all Kindle Fire models and Kindle for Android
* Other minor tweaks
#### 4.5.1:
* Added Kobo Glo HD profile
* Fixed RAR/CBR parsing anomalies
* Minor bug fixes and tweaks
#### 4.5:
* Added simple ComicRack metadata editor
* Re-enabled Manga Cover Database support
* ComicRack bookmarks are now parsed
* Fixed glitches in Kindle Voyage profile
* Fixed problems with directory locks on Windows
* Fixed sorting anomalies
* Improved conversion speed
#### 4.4.1:
* Fixed problems with OSX GUI
* Added one missing DLL to Windows installer
#### 4.4:
* Improved speed and quality of conversion
* Added RAR5 support
* Dropped BMP and TIFF support
* Fixed some WebToon mode bugs
* Fixed CBR parsing on OSX
#### 4.3.1:
* Fixed Kindle Voyage profile
* Fixed some bugs in OS X release
* CLI version now support multiple input files at once
* Disabled MCB support
* Other minor tweaks
#### 4.3:
* Added profiles for Kindle Voyage and Kobo Aura H2O
* Added missing features to CLI version
* Other minor bug fixes
#### 4.2.1:
* Improved margin color detection
* Fixed random crashes of MOBI processing step
* Fixed resizing problems in high quality mode
* Fixed some MCD support bugs
* Default output format for Kindle DX is now CBZ
#### 4.2:
* Added [Manga Cover Database](http://manga.joentjuh.nl/) support
* Officially dropped Windows XP support
* Fixed _Other_ profile
* Fixed problems with page order on stock KOBO CBZ reader
* Many other small bug fixes and tweaks
#### 4.1:
* Thanks to code contributed by Kevin Hendricks speed of MOBI creation was greatly increased
* Improved performance on Windows
* Improved MOBI splitting and changed maximal size of output file
* Fixed _No optimization_ mode
* Multiple small tweaks nad minor bug fixes
#### 4.0.2:
* Fixed some Windows and OSX specific bugs
* Fixed problem with marigns when using HQ mode
#### 4.0.1:
* Fixed file lock problems that plagued some Windows users
* Fixed content server failing to start on Windows
* Improved performance of WebToon splitter
* Tweaked margin color detection
#### 4.0:
* KCC now use Python 3.3 and Qt 5.2
* Full UTF-8 awareness
* CBZ output now support Manga mode
* Improved Panel View support and margin color detection
* Added drag&drop support
* Output directory can be now selected
* Windows release now have auto-updater
* Names of chapters on Kindle should be now more user friendly
* Fixed OSX file association support
* Many extensive internal changes and tweaks
#### 3.7.2:
* Fixed problems with HQ mode
#### 3.7.1:
* Hotfixed Kobo profiles
#### 3.7:
* Added profiles for KOBO devices
* Improved Panel View support
* Improved WebToon splitter
* Improved margin color autodetection
* Tweaked EPUB output
* Fixed stretching option
* GUI tweaks and minor bugfixes
#### 3.6.2:
* Fixed previous PNG output fix
* Fixed Panel View anomalies
#### 3.6.1:
* Fixed PNG output
#### 3.6:
* Increased quality of Panel View zoom
* Creation of multipart MOBI output is now faster on machines with 4GB+ RAM
* Automatic gamma correction now distinguishes color and grayscale images
* Added ComicRack metadata parser
* Implemented new method to detect border color in non-webtoon comics
* Upscaling is now enabled by default for Kindle Fire HD/HDX
* Windows nad Linux releases now have tray icon
* Fixed Kindle Fire HDX 7" output
* Increased target resolution for Kindle DX/DXG CBZ output
#### 3.5:
* Added simple content server - Converted files can be now delivered wireless
* Added proper Windows installer
* Improved multiprocessing speed
* GUI tweaks and minor bug fixes
#### 3.4:
* Improved PNG output
* Increased quality of upscaling
* Added support of file association - KCC can now open CBZ, CBR, CB7, ZIP, RAR, 7Z and PDF files directly
* Paths that contain UTF-8 characters are now supported
* Migrated to new version of Pillow library
* Merged DX and DXG profiles
* Many other minor bug fixes and GUI tweaks
#### 3.3:
* Margins are now automatically omitted in Panel View mode
* Margin color fill is now autodetected
* Created MOBI files are not longer marked as _Personal_ on newer Kindle models
* 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
#### 3.2:
* Too big EPUB files are now splitted before conversion to MOBI
* Added experimental parser of manga webtoons
* Improved error handling
#### 3.2.1:
* Hotfixed crash occurring on OS with Russian locale
#### 3.1:
* Added profile: Kindle for Android
* Add file/directory dialogs now support multiselect
* Many small fixes and tweaks
#### 3.0:
* New QT GUI
* Merge with AWKCC
* Added ultra quality mode
* Added support for custom width/height
* Added option to disable color conversion
#### 2.10:
* Multiprocessing support
* Kindle Fire support (color EPUB/MOBI)
* Panel View support for horizontal content
* Fixed panel order for horizontal pages when --rotate is enabled
* Disabled cropping and page number cutting for blank pages
* Fixed some slugify issues with specific file naming conventions (#50, #51)
#### 2.9
* Added support for generating a plain CBZ (skipping all the EPUB/MOBI generation) (#45)
* Prevent output file overwriting the source one: if a duplicate name is detected, append _kcc to the name
* Rarfile library updated to 2.6
* Added GIF, TIFF and BMP to supported formats (#42)
* Filenames slugifications (#28, #31, #9, #8)
#### 2.8
* Updated rarfile library
* Panel View support + HQ support (#36) - new option: --nopanelviewhq
* Split profiles for K4NT and K4T
* Rewrite of Landscape Mode support (huge readability improvement for KPW)
* Upscale use now BILINEAR method
* Added generic CSS file
* Optimized archive extraction for zip/rar files (#40)
#### 2.7
* Lots of GUI improvements (#27, #13)
* Added gamma support within --gamma option (defaults to profile-specified gamma) (#26, #27)
* Added --nodithering option to prevent dithering optimizations (#27)
* EPUB margins support (#30)
* Fixed no file added if file has no spaces on Windows (#25)
* Gracefully exit if unrar missing (#15)
* Do not call kindlegen if source EPUB is bigger than 320MB (#17)
* Get filetype from magic number (#14)
* PDF conversion works again
#### 2.6
* Added --rotate option to rotate landscape images instead of splitting them (#16, #24)
* Added --output option to customize EPUB output dir/file (#22)
* Add rendition:layout and rendition:orientation EPUB meta tags (supported by new kindlegen 2.8)
* Fixed natural sorting for files (#18)
#### 2.5
* Added --black-borders option to set added borders black when page's ratio is not the device's one (#11).
* Fixes EPUB containing zipped itself (#10)
#### 2.4
* Use temporary directory as workdir (fixes converting from external volumes and zipfiles renaming)
* Fixed "add folders" from GUI.
#### 2.3
* Fixed win32 EPUB generation, folder handling, filenames with spaces and subfolders
#### 2.2:
* Added (valid!) EPUB 2.0 output
* Rename .zip files to .cbz to avoid overwriting
#### 2.1
* Added basic error reporting
#### 2.0
* GUI! AppleScript is gone and Tk is used to provide cross-platform GUI support.
#### 1.5
* Added subfolder support for multiple chapters.
#### 1.4.1
* Fixed a serious bug on resizing when img ratio was bigger than device one
#### 1.4
* Added some options for controlling image optimization
* Further optimization (ImageOps, page numbering cut, autocontrast)
#### 1.3
* Fixed an issue in OPF generation for device resolution
* Reworked options system (call with -h option to get the inline help)
#### 1.2
* Comic optimizations! Split pages not target-oriented (landscape with portrait target or portrait with landscape target), add palette and other image optimizations from Mangle. WARNING: PIL is required for all image mangling!
#### 1.1.1
* Added support for CBZ/CBR files in Kindle Comic Converter
#### 1.1
* Added support for CBZ/CBR files in comic2ebook.py
#### 1.0
* Initial version

19
Dockerfile Normal file
View File

@@ -0,0 +1,19 @@
# Select final stage based on TARGETARCH ARG
FROM ghcr.io/ciromattia/kcc:docker-base-20240928
LABEL com.kcc.name="Kindle Comic Converter"
LABEL com.kcc.author="Ciro Mattia Gonano, Paweł Jastrzębski and Darodi"
LABEL org.opencontainers.image.description='Kindle Comic Converter'
LABEL org.opencontainers.image.documentation='https://github.com/ciromattia/kcc'
LABEL org.opencontainers.image.source='https://github.com/ciromattia/kcc'
LABEL org.opencontainers.image.authors='darodi'
LABEL org.opencontainers.image.url='https://github.com/ciromattia/kcc'
LABEL org.opencontainers.image.documentation='https://github.com/ciromattia/kcc'
LABEL org.opencontainers.image.vendor='ciromattia'
LABEL org.opencontainers.image.licenses='ISC'
LABEL org.opencontainers.image.title="Kindle Comic Converter"
COPY . /opt/kcc
RUN cat /opt/kcc/kindlecomicconverter/__init__.py | grep version | awk '{print $3}' | sed "s/'//g" > /IMAGE_VERSION
ENTRYPOINT ["/opt/kcc/kcc-c2e.py"]
CMD ["-h"]

164
Dockerfile-base Normal file
View File

@@ -0,0 +1,164 @@
FROM --platform=linux/amd64 python:3.12-slim-bullseye as compile-amd64
ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
RUN echo "I'm building for $TARGETOS/$TARGETARCH/$TARGETVARIANT"
COPY requirements.txt /opt/kcc/
ENV PATH="/opt/venv/bin:$PATH"
RUN DEBIAN_FRONTEND=noninteractive apt-get update -y && apt-get -yq upgrade && \
apt-get install -y libpng-dev libjpeg-dev p7zip-full unrar-free libgl1 && \
python -m pip install --upgrade pip && \
python -m venv /opt/venv && \
python -m pip install -r /opt/kcc/requirements.txt
######################################################################################
FROM --platform=linux/arm64 python:3.12-slim-bullseye as compile-arm64
ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
RUN echo "I'm building for $TARGETOS/$TARGETARCH/$TARGETVARIANT"
ENV LC_ALL=C.UTF-8 \
LANG=C.UTF-8 \
LANGUAGE=en_US:en
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
COPY requirements.txt /opt/kcc/
ENV PATH="/opt/venv/bin:$PATH"
RUN set -x && \
TEMP_PACKAGES=() && \
KEPT_PACKAGES=() && \
# Packages only required during build
TEMP_PACKAGES+=(build-essential) && \
TEMP_PACKAGES+=(cmake) && \
TEMP_PACKAGES+=(libfreetype6-dev) && \
TEMP_PACKAGES+=(libfontconfig1-dev) && \
TEMP_PACKAGES+=(libpng-dev) && \
TEMP_PACKAGES+=(libjpeg-dev) && \
TEMP_PACKAGES+=(libssl-dev) && \
TEMP_PACKAGES+=(libxft-dev) && \
TEMP_PACKAGES+=(make) && \
TEMP_PACKAGES+=(python3-dev) && \
TEMP_PACKAGES+=(python3-setuptools) && \
TEMP_PACKAGES+=(python3-wheel) && \
# Packages kept in the image
KEPT_PACKAGES+=(bash) && \
KEPT_PACKAGES+=(ca-certificates) && \
KEPT_PACKAGES+=(chrpath) && \
KEPT_PACKAGES+=(locales) && \
KEPT_PACKAGES+=(locales-all) && \
KEPT_PACKAGES+=(libfreetype6) && \
KEPT_PACKAGES+=(libfontconfig1) && \
KEPT_PACKAGES+=(p7zip-full) && \
KEPT_PACKAGES+=(python3) && \
KEPT_PACKAGES+=(python3-pip) && \
KEPT_PACKAGES+=(unrar-free) && \
# Install packages
DEBIAN_FRONTEND=noninteractive apt-get update -y && apt-get -yq upgrade && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
${KEPT_PACKAGES[@]} \
${TEMP_PACKAGES[@]} \
&& \
# Install required python modules
python -m pip install --upgrade pip && \
python -m venv /opt/venv && \
python -m pip install -r /opt/kcc/requirements.txt
######################################################################################
FROM --platform=linux/arm/v7 python:3.12-slim-bullseye as compile-armv7
ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
RUN echo "I'm building for $TARGETOS/$TARGETARCH/$TARGETVARIANT"
ENV LC_ALL=C.UTF-8 \
LANG=C.UTF-8 \
LANGUAGE=en_US:en
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
COPY requirements.txt /opt/kcc/
ENV PATH="/opt/venv/bin:$PATH"
RUN set -x && \
TEMP_PACKAGES=() && \
KEPT_PACKAGES=() && \
# Packages only required during build
TEMP_PACKAGES+=(build-essential) && \
TEMP_PACKAGES+=(cmake) && \
TEMP_PACKAGES+=(libffi-dev) && \
TEMP_PACKAGES+=(libfreetype6-dev) && \
TEMP_PACKAGES+=(libfontconfig1-dev) && \
TEMP_PACKAGES+=(libpng-dev) && \
TEMP_PACKAGES+=(libjpeg-dev) && \
TEMP_PACKAGES+=(libssl-dev) && \
TEMP_PACKAGES+=(libxft-dev) && \
TEMP_PACKAGES+=(make) && \
TEMP_PACKAGES+=(python3-dev) && \
TEMP_PACKAGES+=(python3-setuptools) && \
TEMP_PACKAGES+=(python3-wheel) && \
# Packages kept in the image
KEPT_PACKAGES+=(bash) && \
KEPT_PACKAGES+=(ca-certificates) && \
KEPT_PACKAGES+=(chrpath) && \
KEPT_PACKAGES+=(locales) && \
KEPT_PACKAGES+=(locales-all) && \
KEPT_PACKAGES+=(libfreetype6) && \
KEPT_PACKAGES+=(libfontconfig1) && \
KEPT_PACKAGES+=(p7zip-full) && \
KEPT_PACKAGES+=(python3) && \
KEPT_PACKAGES+=(python3-pip) && \
KEPT_PACKAGES+=(unrar-free) && \
# Install packages
DEBIAN_FRONTEND=noninteractive apt-get update -y && apt-get -yq upgrade && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
${KEPT_PACKAGES[@]} \
${TEMP_PACKAGES[@]} \
&& \
# Install required python modules
python -m pip install --upgrade pip && \
python -m venv /opt/venv && \
python -m pip install --upgrade pillow psutil requests python-slugify raven packaging mozjpeg-lossless-optimization natsort distro
######################################################################################
FROM --platform=linux/amd64 python:3.12-slim-bullseye as build-amd64
COPY --from=compile-amd64 /opt/venv /opt/venv
FROM --platform=linux/arm64 python:3.12-slim-bullseye as build-arm64
COPY --from=compile-arm64 /opt/venv /opt/venv
FROM --platform=linux/arm/v7 python:3.12-slim-bullseye as build-armv7
COPY --from=compile-armv7 /opt/venv /opt/venv
######################################################################################
# Select final stage based on TARGETARCH ARG
FROM build-${TARGETARCH}${TARGETVARIANT}
LABEL com.kcc.name="Kindle Comic Converter base image"
LABEL com.kcc.author="Ciro Mattia Gonano, Paweł Jastrzębski and Darodi"
LABEL org.opencontainers.image.description='Kindle Comic Converter base image'
LABEL org.opencontainers.image.documentation='https://github.com/ciromattia/kcc'
LABEL org.opencontainers.image.source='https://github.com/ciromattia/kcc'
LABEL org.opencontainers.image.authors='darodi'
LABEL org.opencontainers.image.url='https://github.com/ciromattia/kcc'
LABEL org.opencontainers.image.documentation='https://github.com/ciromattia/kcc'
LABEL org.opencontainers.image.vendor='ciromattia'
LABEL org.opencontainers.image.licenses='ISC'
LABEL org.opencontainers.image.title="Kindle Comic Converter"
ENV PATH="/opt/venv/bin:$PATH"
WORKDIR /app
RUN DEBIAN_FRONTEND=noninteractive apt-get update -y && apt-get -yq upgrade && \
apt-get install -y p7zip-full unrar-free && \
ln -s /app/kindlegen /bin/kindlegen && \
echo docker-base-20240928 > /IMAGE_VERSION

View File

@@ -1,7 +1,8 @@
ISC LICENSE
Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
Copyright (c) 2013-2017 Paweł Jastrzębski <pawelj@iosphe.re>
Copyright (c) 2013-2019 Paweł Jastrzębski <pawelj@iosphe.re>
Copyright (c) 2021-2023 Darodi
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the

657
README.md
View File

@@ -1,6 +1,10 @@
# KCC
[![GitHub release](https://img.shields.io/github/release/ciromattia/kcc.svg)](https://github.com/ciromattia/kcc/releases) [![PyPI](https://img.shields.io/pypi/v/KindleComicConverter.svg)](https://pypi.python.org/pypi/KindleComicConverter) [![AUR](https://img.shields.io/aur/version/kcc.svg)](https://aur.archlinux.org/packages/kcc/)
[![GitHub release](https://img.shields.io/github/release/ciromattia/kcc.svg)](https://github.com/ciromattia/kcc/releases)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/ciromattia/kcc/docker-publish.yml?label=docker%20build)](https://github.com/ciromattia/kcc/pkgs/container/kcc)
**Kindle Comic Converter** is a Python app to convert comic/manga files or folders to EPUB, Panel View MOBI or E-Ink optimized CBZ.
It was initially developed for Kindle but since version 4.6 it outputs valid EPUB 3.0 so _**despite its name, KCC is
@@ -10,7 +14,7 @@ It can also optionally optimize images by applying a number of transformations.
### A word of warning
**KCC** _is not_ [Amazon's Kindle Comic Creator](http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1001103761) nor is in any way endorsed by Amazon.
Amazon's tool is for comic publishers and involves a lot of manual effort, while **KCC** is for comic/manga readers.
_KC2_ in no way is a replacement for **KCC** so you can be quite confident we'll going to carry on developing our little monster ;-)
_KC2_ in no way is a replacement for **KCC** so you can be quite confident we are going to carry on developing our little monster ;-)
### Issues / new features / donations
If you have general questions about usage, feedback etc. please [post it here](http://www.mobileread.com/forums/showthread.php?t=207461).
@@ -18,507 +22,276 @@ If you have some **technical** problems using KCC please [file an issue here](ht
If you can fix an open issue, fork & make a pull request.
If you find **KCC** valuable you can consider donating to the authors:
- Ciro Mattia Gonano:
- Ciro Mattia Gonano (founder, active 2013-2014):
- [![Donate PayPal](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=D8WNYNPBGDAS2)
- [![Donate Flattr](https://img.shields.io/badge/Donate-Flattr-green.svg)](http://flattr.com/thing/2260449/ciromattiakcc-on-GitHub)
- Paweł Jastrzębski:
- Paweł Jastrzębski (active 2013-2019):
- [![Donate PayPal](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YTTJ4LK2JDHPS)
- [![Donate Bitcoin](https://img.shields.io/badge/Donate-Bitcoin-green.svg)](https://jastrzeb.ski/donate/)
- Alex Xu (active 2023-Present)
- [![Donate PayPal](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/donate/?business=QFJVE7A6LCP6U&no_recurring=0&item_name=Kindle+Comic+Converter&currency_code=USD)
## BINARY RELEASES
You can find the latest released binary at the following links:
- **Windows (64-bit only):** [http://kcc.iosphe.re/Windows/](http://kcc.iosphe.re/Windows/)
- **Linux (Glibc 2.19+):** [http://kcc.iosphe.re/Linux/](http://kcc.iosphe.re/Linux/)
- **OS X (10.9+):** [http://kcc.iosphe.re/OSX/](http://kcc.iosphe.re/OSX/)
## PYPI
**KCC** is also available on PyPI.
```
pip install KindleComicConverter
```
## DOWNLOADS
## DEPENDENCIES
Following software is required to run Linux version of **KCC** and/or bare sources:
- Python 3.3+
- [PyQt5](https://pypi.python.org/pypi/PyQt5) 5.6.0+
- [Pillow](https://pypi.python.org/pypi/Pillow/) 4.0.0+
- [psutil](https://pypi.python.org/pypi/psutil) 5.0.0+
- [python-slugify](https://pypi.python.org/pypi/python-slugify) 1.2.1+
- [raven](https://pypi.python.org/pypi/raven) 6.0.0+
- **https://github.com/ciromattia/kcc/releases**
On Debian based distributions these two commands should install all needed dependencies:
```
sudo apt-get install python3 python3-dev python3-pip libpng-dev libjpeg-dev p7zip-full unrar
sudo pip3 install --upgrade pillow python-slugify psutil pyqt5 raven
```
Click on **Assets** of the latest release.
### Optional dependencies
- [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)*
- [7za](http://www.7-zip.org/download.html) *(For 7z/CB7 support)*
You probably want either
- `KCC_*.*.*.exe` (Windows)
- `kcc_macos_arm_*.*.*.dmg` (recent Mac with Apple Silicon M1 chip or later)
- `kcc_macos_i386_*.*.*.dmg` (older Mac with Intel chip)
The `c2e` and `c2p` versions are command line tools for power users.
On Windows 11, you may need to run in compatibility mode for an older Windows version.
On Mac, right click open to get past the security warning.
For flatpak, Docker, and AppImage versions, refer to the wiki: https://github.com/ciromattia/kcc/wiki/Installation
## FAQ
- [Kindle Scribe cover guide](https://github.com/ciromattia/kcc/issues/508) (also works for older Kindles)
- [Windows 7 support](https://github.com/ciromattia/kcc/issues/678)
- [Combine files/chapters](https://github.com/ciromattia/kcc/issues/612#issuecomment-2117985011)
- [Flatpak mobi conversion stuck](https://github.com/ciromattia/kcc/wiki/Installation#linux)
## PREREQUISITES
You'll need to install various tools to access important but optional features. Close and re-open KCC to get KCC to detect them.
### KindleGen
On Windows and macOS, install [Kindle Previewer](https://www.amazon.com/Kindle-Previewer/b?ie=UTF8&node=21381691011) and `kindlegen` will be autodetected from it.
If you have issues detecting it, get stuck on the MOBI conversion step, or use Linux AppImage or Flatpak, refer to the wiki: https://github.com/ciromattia/kcc/wiki/Installation#kindlegen
### 7-Zip
This is no longer required as of KCC 6.1.
If you still need it, refer to the wiki: https://github.com/ciromattia/kcc/wiki/Installation#7-zip
## INPUT FORMATS
**KCC** can understand and convert, at the moment, the following input types:
- Folders containing: PNG, JPG or GIF files
- CBZ, ZIP
- CBR, RAR *(With `unrar` executable)*
- CB7, 7Z *(With `7za` executable)*
- Folders containing: PNG, JPG, GIF or WebP files
- CBZ, ZIP *(With `7z` executable)*
- CBR, RAR *(With `7z` executable)*
- CB7, 7Z *(With `7z` executable)*
- PDF *(Only extracting JPG images)*
## USAGE
Should be pretty self-explanatory. All options have detailed informations in tooltips.
After completed conversion you should find ready file alongside the original input file (same directory).
Should be pretty self-explanatory. All options have detailed information in tooltips.
After completed conversion, you should find ready file alongside the original input file (same directory).
Please check [our wiki](https://github.com/ciromattia/kcc/wiki/) for more details.
CLI version of **KCC** is intended for power users. It allow to use options that might not be compatible and decrease quality of output.
CLI version of **KCC** is intended for power users. It allows using options that might not be compatible and decrease the quality of output.
CLI version has reduced dependencies, on Debian based distributions this commands should install all needed dependencies:
```
sudo apt-get install python3 p7zip-full python3-pil python3-psutil python3-slugify
```
### Profiles:
```
'K1': ("Kindle 1", (600, 670), Palette4, 1.8),
'K11': ("Kindle 11/12", (1072, 1448), Palette16, 1.8),
'K2': ("Kindle 2", (600, 670), Palette15, 1.8),
'K34': ("Kindle Keyboard/Touch", (600, 800), Palette16, 1.8),
'K578': ("Kindle", (600, 800), Palette16, 1.8),
'KDX': ("Kindle DX/DXG", (824, 1000), Palette16, 1.8),
'KPW': ("Kindle Paperwhite 1/2", (758, 1024), Palette16, 1.8),
'KV': ("Kindle Paperwhite 3/4/Voyage/Oasis", (1072, 1448), Palette16, 1.8),
'KPW5': ("Kindle Paperwhite 5/Signature Edition", (1236, 1648), Palette16, 1.8),
'KPW6': ("Kindle Paperwhite 6", (1264, 1680), Palette16, 1.8),
'KCS12': ("Kindle Colorsoft", (1264, 1680), Palette16, 1.8),
'KO': ("Kindle Oasis 2/3", (1264, 1680), Palette16, 1.8),
'KS': ("Kindle Scribe", (1860, 2480), Palette16, 1.8),
'KoMT': ("Kobo Mini/Touch", (600, 800), Palette16, 1.8),
'KoG': ("Kobo Glo", (768, 1024), Palette16, 1.8),
'KoGHD': ("Kobo Glo HD", (1072, 1448), Palette16, 1.8),
'KoA': ("Kobo Aura", (758, 1024), Palette16, 1.8),
'KoAHD': ("Kobo Aura HD", (1080, 1440), Palette16, 1.8),
'KoAH2O': ("Kobo Aura H2O", (1080, 1430), Palette16, 1.8),
'KoAO': ("Kobo Aura ONE", (1404, 1872), Palette16, 1.8),
'KoN': ("Kobo Nia", (758, 1024), Palette16, 1.8),
'KoC': ("Kobo Clara HD/Kobo Clara 2E", (1072, 1448), Palette16, 1.8),
'KoCC': ("Kobo Clara Colour", (1072, 1448), Palette16, 1.8),
'KoL': ("Kobo Libra H2O/Kobo Libra 2", (1264, 1680), Palette16, 1.8),
'KoLC': ("Kobo Libra Colour", (1264, 1680), Palette16, 1.8),
'KoF': ("Kobo Forma", (1440, 1920), Palette16, 1.8),
'KoS': ("Kobo Sage", (1440, 1920), Palette16, 1.8),
'KoE': ("Kobo Elipsa", (1404, 1872), Palette16, 1.8),
'OTHER': ("Other", (0, 0), Palette16, 1.8),
```
### Standalone `kcc-c2e.py` usage:
```
Usage: kcc-c2e [options] comic_file|comic_folder
usage: kcc-c2e [options] [input]
Options:
MAIN:
-p PROFILE, --profile=PROFILE
Device profile (Available options: K1, K2, K3, K45,
KDX, KPW, KV, KoMT, KoG, KoGHD, KoA, KoAHD, KoAH2O,
KoAO) [Default=KV]
-m, --manga-style Manga style (right-to-left reading and splitting)
-q, --hq Try to increase the quality of magnification
-2, --two-panel Display two not four panels in Panel View mode
-w, --webtoon Webtoon processing mode
MANDATORY:
input Full path to comic folder or file(s) to be processed.
OUTPUT SETTINGS:
-o OUTPUT, --output=OUTPUT
Output generated file to specified directory or file
-t TITLE, --title=TITLE
Comic title [Default=filename or directory name]
-f FORMAT, --format=FORMAT
Output format (Available options: Auto, MOBI, EPUB,
CBZ) [Default=Auto]
-b BATCHSPLIT, --batchsplit=BATCHSPLIT
Split output into multiple files. 0: Don't split 1:
Automatic mode 2: Consider every subdirectory as
separate volume [Default=0]
MAIN:
-p PROFILE, --profile PROFILE
Device profile (Available options: K1, K2, K34, K578, KDX, KPW, KPW5, KV, KO, K11, KS, KoMT, KoG, KoGHD, KoA, KoAHD, KoAH2O, KoAO, KoN, KoC, KoL, KoF, KoS, KoE) [Default=KV]
-m, --manga-style Manga style (right-to-left reading and splitting)
-q, --hq Try to increase the quality of magnification
-2, --two-panel Display two not four panels in Panel View mode
-w, --webtoon Webtoon processing mode
--ts TARGETSIZE, --targetsize TARGETSIZE
the maximal size of output file in MB. [Default=100MB for webtoon and 400MB for others]
PROCESSING:
-u, --upscale Resize images smaller than device's resolution
-s, --stretch Stretch images to device's resolution
-r SPLITTER, --splitter=SPLITTER
Double page parsing mode. 0: Split 1: Rotate 2: Both
[Default=0]
-g GAMMA, --gamma=GAMMA
Apply gamma correction to linearize the image
[Default=Auto]
-c CROPPING, --cropping=CROPPING
Set cropping mode. 0: Disabled 1: Margins 2: Margins +
page numbers [Default=2]
--cp=CROPPINGP, --croppingpower=CROPPINGP
PROCESSING:
-n, --noprocessing Do not modify image and ignore any profil or processing option
-u, --upscale Resize images smaller than device's resolution
-s, --stretch Stretch images to device's resolution
-r SPLITTER, --splitter SPLITTER
Double page parsing mode. 0: Split 1: Rotate 2: Both [Default=0]
-g GAMMA, --gamma GAMMA
Apply gamma correction to linearize the image [Default=Auto]
-c CROPPING, --cropping CROPPING
Set cropping mode. 0: Disabled 1: Margins 2: Margins + page numbers [Default=2]
--cp CROPPINGP, --croppingpower CROPPINGP
Set cropping power [Default=1.0]
--blackborders Disable autodetection and force black borders
--whiteborders Disable autodetection and force white borders
--forcecolor Don't convert images to grayscale
--forcepng Create PNG files instead JPEG
--cm CROPPINGM, --croppingminimum CROPPINGM
Set cropping minimum area ratio [Default=0.0]
--blackborders Disable autodetection and force black borders
--whiteborders Disable autodetection and force white borders
--forcecolor Don't convert images to grayscale
--forcepng Create PNG files instead JPEG
--mozjpeg Create JPEG files using mozJpeg
--maximizestrips Turn 1x4 strips to 2x2 strips
-d, --delete Delete source file(s) or a directory. It's not recoverable.
CUSTOM PROFILE:
--customwidth=CUSTOMWIDTH
OUTPUT SETTINGS:
-o OUTPUT, --output OUTPUT
Output generated file to specified directory or file
-t TITLE, --title TITLE
Comic title [Default=filename or directory name]
-f FORMAT, --format FORMAT
Output format (Available options: Auto, MOBI, EPUB, CBZ, KFX, MOBI+EPUB) [Default=Auto]
-b BATCHSPLIT, --batchsplit BATCHSPLIT
Split output into multiple files. 0: Don't split 1: Automatic mode 2: Consider every subdirectory as separate volume [Default=0]
CUSTOM PROFILE:
--customwidth CUSTOMWIDTH
Replace screen width provided by device profile
--customheight=CUSTOMHEIGHT
--customheight CUSTOMHEIGHT
Replace screen height provided by device profile
OTHER:
-h, --help Show this help message and exit
OTHER:
-h, --help Show this help message and exit
```
### Standalone `kcc-c2p.py` usage:
```
Usage: kcc-c2p [options] comic_folder
usage: kcc-c2p [options] [input]
Options:
MANDATORY:
-y HEIGHT, --height=HEIGHT
MANDATORY:
input Full path to comic folder(s) to be processed. Separate multiple inputs with spaces.
MAIN:
-y HEIGHT, --height HEIGHT
Height of the target device screen
-i, --in-place Overwrite source directory
-m, --merge Combine every directory into a single image before splitting
-i, --in-place Overwrite source directory
-m, --merge Combine every directory into a single image before splitting
OTHER:
-d, --debug Create debug file for every splitted image
-h, --help Show this help message and exit
OTHER:
-d, --debug Create debug file for every split image
-h, --help Show this help message and exit
```
## INSTALL FROM SOURCE
This section is for developers who want to contribute to KCC or power users who want to run the latest code without waiting for an official release.
Easiest to use [GitHub Desktop](https://desktop.github.com) to clone the KCC repo. From GitHub Desktop, click on `Repository` in the toolbar, then `Command Prompt` (Windows)/`Terminal` (Mac) to open a window in the KCC repo.
Depending on your system [Python](https://www.python.org) may be called either `python` or `python3`. We use virtual environments (venv) to manage dependencies.
If you want to edit the code, a good code editor is [VS Code](https://code.visualstudio.com).
If you want to edit the `.ui` files, use [Qt Creator](https://www.qt.io/download-qt-installer-oss), included in **Qt for desktop development**.
Then use the `gen_ui_files` scripts to autogenerate the python UI.
### Windows install from source
One time setup and running for the first time:
```
python -m venv venv
venv\Scripts\activate.bat
pip install -r requirements.txt
python kcc.py
```
Every time you close Command Prompt, you will need to re-activate the virtual environment and re-run:
```
venv\Scripts\activate.bat
python kcc.py
```
### macOS install from source
One time setup and running for the first time:
```
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python kcc.py
```
Every time you close Terminal, you will need to reactivate the virtual environment and re-run:
```
source venv/bin/activate
python kcc.py
```
## CREDITS
**KCC** is made by [Ciro Mattia Gonano](http://github.com/ciromattia) and [Paweł Jastrzębski](http://github.com/AcidWeb).
**KCC** is made by
- [Ciro Mattia Gonano](http://github.com/ciromattia)
- [Paweł Jastrzębski](http://github.com/AcidWeb)
- [Darodi](http://github.com/darodi)
- [Alex Xu](http://github.com/axu2)
This script born as a cross-platform alternative to `KindleComicParser` by **Dc5e** (published [here](http://www.mobileread.com/forums/showthread.php?t=192783)).
The app relies and includes the following scripts:
- `DualMetaFix` script by **K. Hendricks**. Released with GPL-3 License.
- `rarfile.py` script &copy; 2005-2014 **Marko Kreen** <markokr@gmail.com>. Released with ISC License.
- `image.py` class from **Alex Yatskov**'s [Mangle](https://github.com/FooSoft/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.
## SAMPLE FILES CREATED BY KCC
* [Kindle Paperwhite 3 / Voyage / Oasis](http://kcc.iosphe.re/Samples/Ubunchu!-KV.mobi)
* [Kindle Oasis 2 / 3](http://kcc.iosphe.re/Samples/Ubunchu!-KO.mobi)
* [Kindle Paperwhite 3 / 4 / Voyage / Oasis](http://kcc.iosphe.re/Samples/Ubunchu!-KV.mobi)
* [Kindle Paperwhite 1 / 2](http://kcc.iosphe.re/Samples/Ubunchu!-KPW.mobi)
* [Kindle](http://kcc.iosphe.re/Samples/Ubunchu!-K45.mobi)
* [Kindle](http://kcc.iosphe.re/Samples/Ubunchu!-K578.mobi)
* [Kobo Aura](http://kcc.iosphe.re/Samples/Ubunchu-KoA.kepub.epub)
* [Kobo Aura HD](http://kcc.iosphe.re/Samples/Ubunchu-KoAHD.kepub.epub)
* [Kobo Aura H2O](http://kcc.iosphe.re/Samples/Ubunchu-KoAH2O.kepub.epub)
* [Kobo Aura ONE](http://kcc.iosphe.re/Samples/Ubunchu-KoAO.kepub.epub)
## CHANGELOG
#### 5.4:
* Reimplemented high quality Panel View option
* Improved webtoon splitter
* Fixed page splitter
#### 5.3.1:
* Small increase of output quality
* Improved error reporting
* Internal changes and tweaks
#### 5.3:
* Vastly improved output compatibility for non-Kindle devices
* Enabled old pinch zoom for Kindle devices
* Re-enabled Panel View support for Kindle Keyboard
* Partially re-enabled OS X file association mechanism
* Fixed multiple smaller issues
#### 5.2.1:
* Improved directory parsing
* Tweaked margin detection algorithm
* Improved error reporting
#### 5.2:
* Added new Panel View options
* Implemented new margin detection algorithm
* Removed HQ Panel View mode
* Fixed multiple smaller issues
#### 5.1.3:
* Added Kobo Aura ONE profile
* Fixed few small bugs
#### 5.1.2:
* Fixed error reporting
#### 5.1.1:
* Fixed multiple GUI bugs
#### 5.1:
* GUI now can be resized and high DPI support was somewhat improved
* Added profile for Kindle Oasis
* Implemented new error reporting mechanism
* CLI version now support additional cropping options
* Fixed permission issues on Windows
* Fixed multiple smaller issues
#### 5.0.1:
* Fixed Panel View placement issues
* Decreased application startup time
* Fixed multiple smaller issues
#### 5.0:
* Major overhaul of internal mechanisms and GUI
* Added cover upload feature
* Tweaked Webtoon parsing mode
* Fixed multiple smaller issues
* Migrated build enviroment to PyInstaller
#### 4.6.5:
* Fixed multiple Windows and OS X issues
* Allowed Linux release to use older PyQT5 version
#### 4.6.4:
* Fixed multiple Windows specific problems
* Improved error handling
* Improved color detection algorithm
* New, slimmer OS X release
#### 4.6.3:
* Implemented remote bug reporting
* Minor bug fixes and GUI tweaks
#### 4.6.2:
* Fixed critical MOBI header bug
* Fixed metadata encoding error
#### 4.6.1:
* Fixed KEPUB TOC generator
* Added warning about too small input files
* ComicRack Summary metadata field is now parsed
* Small tweaks of KEPUB output
#### 4.6:
* KEPUB is now default output for all Kobo profiles
* EPUB output now produce fully valid EPUB 3.0.1
* Added profile for Kindle Paperwhite 3
* Dropped official support of all Kindle Fire models and Kindle for Android
* Other minor tweaks
#### 4.5.1:
* Added Kobo Glo HD profile
* Fixed RAR/CBR parsing anomalies
* Minor bug fixes and tweaks
#### 4.5:
* Added simple ComicRack metadata editor
* Re-enabled Manga Cover Database support
* ComicRack bookmarks are now parsed
* Fixed glitches in Kindle Voyage profile
* Fixed problems with directory locks on Windows
* Fixed sorting anomalies
* Improved conversion speed
#### 4.4.1:
* Fixed problems with OSX GUI
* Added one missing DLL to Windows installer
#### 4.4:
* Improved speed and quality of conversion
* Added RAR5 support
* Dropped BMP and TIFF support
* Fixed some WebToon mode bugs
* Fixed CBR parsing on OSX
#### 4.3.1:
* Fixed Kindle Voyage profile
* Fixed some bugs in OS X release
* CLI version now support multiple input files at once
* Disabled MCB support
* Other minor tweaks
#### 4.3:
* Added profiles for Kindle Voyage and Kobo Aura H2O
* Added missing features to CLI version
* Other minor bug fixes
#### 4.2.1:
* Improved margin color detection
* Fixed random crashes of MOBI processing step
* Fixed resizing problems in high quality mode
* Fixed some MCD support bugs
* Default output format for Kindle DX is now CBZ
#### 4.2:
* Added [Manga Cover Database](http://manga.joentjuh.nl/) support
* Officially dropped Windows XP support
* Fixed _Other_ profile
* Fixed problems with page order on stock KOBO CBZ reader
* Many other small bug fixes and tweaks
#### 4.1:
* Thanks to code contributed by Kevin Hendricks speed of MOBI creation was greatly increased
* Improved performance on Windows
* Improved MOBI splitting and changed maximal size of output file
* Fixed _No optimization_ mode
* Multiple small tweaks nad minor bug fixes
#### 4.0.2:
* Fixed some Windows and OSX specific bugs
* Fixed problem with marigns when using HQ mode
#### 4.0.1:
* Fixed file lock problems that plagued some Windows users
* Fixed content server failing to start on Windows
* Improved performance of WebToon splitter
* Tweaked margin color detection
#### 4.0:
* KCC now use Python 3.3 and Qt 5.2
* Full UTF-8 awareness
* CBZ output now support Manga mode
* Improved Panel View support and margin color detection
* Added drag&drop support
* Output directory can be now selected
* Windows release now have auto-updater
* Names of chapters on Kindle should be now more user friendly
* Fixed OSX file association support
* Many extensive internal changes and tweaks
#### 3.7.2:
* Fixed problems with HQ mode
#### 3.7.1:
* Hotfixed Kobo profiles
#### 3.7:
* Added profiles for KOBO devices
* Improved Panel View support
* Improved WebToon splitter
* Improved margin color autodetection
* Tweaked EPUB output
* Fixed stretching option
* GUI tweaks and minor bugfixes
#### 3.6.2:
* Fixed previous PNG output fix
* Fixed Panel View anomalies
#### 3.6.1:
* Fixed PNG output
#### 3.6:
* Increased quality of Panel View zoom
* Creation of multipart MOBI output is now faster on machines with 4GB+ RAM
* Automatic gamma correction now distinguishes color and grayscale images
* Added ComicRack metadata parser
* Implemented new method to detect border color in non-webtoon comics
* Upscaling is now enabled by default for Kindle Fire HD/HDX
* Windows nad Linux releases now have tray icon
* Fixed Kindle Fire HDX 7" output
* Increased target resolution for Kindle DX/DXG CBZ output
#### 3.5:
* Added simple content server - Converted files can be now delivered wireless
* Added proper Windows installer
* Improved multiprocessing speed
* GUI tweaks and minor bug fixes
#### 3.4:
* Improved PNG output
* Increased quality of upscaling
* Added support of file association - KCC can now open CBZ, CBR, CB7, ZIP, RAR, 7Z and PDF files directly
* Paths that contain UTF-8 characters are now supported
* Migrated to new version of Pillow library
* Merged DX and DXG profiles
* Many other minor bug fixes and GUI tweaks
#### 3.3:
* Margins are now automatically omitted in Panel View mode
* Margin color fill is now autodetected
* Created MOBI files are not longer marked as _Personal_ on newer Kindle models
* 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
#### 3.2:
* Too big EPUB files are now splitted before conversion to MOBI
* Added experimental parser of manga webtoons
* Improved error handling
#### 3.2.1:
* Hotfixed crash occurring on OS with Russian locale
#### 3.1:
* Added profile: Kindle for Android
* Add file/directory dialogs now support multiselect
* Many small fixes and tweaks
#### 3.0:
* New QT GUI
* Merge with AWKCC
* Added ultra quality mode
* Added support for custom width/height
* Added option to disable color conversion
#### 2.10:
* Multiprocessing support
* Kindle Fire support (color EPUB/MOBI)
* Panel View support for horizontal content
* Fixed panel order for horizontal pages when --rotate is enabled
* Disabled cropping and page number cutting for blank pages
* Fixed some slugify issues with specific file naming conventions (#50, #51)
#### 2.9
* Added support for generating a plain CBZ (skipping all the EPUB/MOBI generation) (#45)
* Prevent output file overwriting the source one: if a duplicate name is detected, append _kcc to the name
* Rarfile library updated to 2.6
* Added GIF, TIFF and BMP to supported formats (#42)
* Filenames slugifications (#28, #31, #9, #8)
#### 2.8
* Updated rarfile library
* Panel View support + HQ support (#36) - new option: --nopanelviewhq
* Split profiles for K4NT and K4T
* Rewrite of Landscape Mode support (huge readability improvement for KPW)
* Upscale use now BILINEAR method
* Added generic CSS file
* Optimized archive extraction for zip/rar files (#40)
#### 2.7
* Lots of GUI improvements (#27, #13)
* Added gamma support within --gamma option (defaults to profile-specified gamma) (#26, #27)
* Added --nodithering option to prevent dithering optimizations (#27)
* EPUB margins support (#30)
* Fixed no file added if file has no spaces on Windows (#25)
* Gracefully exit if unrar missing (#15)
* Do not call kindlegen if source EPUB is bigger than 320MB (#17)
* Get filetype from magic number (#14)
* PDF conversion works again
#### 2.6
* Added --rotate option to rotate landscape images instead of splitting them (#16, #24)
* Added --output option to customize EPUB output dir/file (#22)
* Add rendition:layout and rendition:orientation EPUB meta tags (supported by new kindlegen 2.8)
* Fixed natural sorting for files (#18)
#### 2.5
* Added --black-borders option to set added borders black when page's ratio is not the device's one (#11).
* Fixes EPUB containing zipped itself (#10)
#### 2.4
* Use temporary directory as workdir (fixes converting from external volumes and zipfiles renaming)
* Fixed "add folders" from GUI.
#### 2.3
* Fixed win32 EPUB generation, folder handling, filenames with spaces and subfolders
#### 2.2:
* Added (valid!) EPUB 2.0 output
* Rename .zip files to .cbz to avoid overwriting
#### 2.1
* Added basic error reporting
#### 2.0
* GUI! AppleScript is gone and Tk is used to provide cross-platform GUI support.
#### 1.5
* Added subfolder support for multiple chapters.
#### 1.4.1
* Fixed a serious bug on resizing when img ratio was bigger than device one
#### 1.4
* Added some options for controlling image optimization
* Further optimization (ImageOps, page numbering cut, autocontrast)
#### 1.3
* Fixed an issue in OPF generation for device resolution
* Reworked options system (call with -h option to get the inline help)
#### 1.2
* Comic optimizations! Split pages not target-oriented (landscape with portrait target or portrait with landscape target), add palette and other image optimizations from Mangle. WARNING: PIL is required for all image mangling!
#### 1.1.1
* Added support for CBZ/CBR files in Kindle Comic Converter
#### 1.1
* Added support for CBZ/CBR files in comic2ebook.py
#### 1.0
* Initial version
* [Kobo Forma](http://kcc.iosphe.re/Samples/Ubunchu-KoF.kepub.epub)
## PRIVACY
**KCC** is initiating internet connections in three cases:
* During startup - Version check
* When MCD metadata are used - Cover download
* When error occurs - Automatic reporting
**KCC** is initiating internet connections in two cases:
* During startup - Version check.
* When error occurs - Automatic reporting on Windows and macOS.
## KNOWN ISSUES
Please check [wiki page](https://github.com/ciromattia/kcc/wiki/Known-issues).
## COPYRIGHT
Copyright (c) 2012-2017 Ciro Mattia Gonano and Paweł Jastrzębski.
**KCC** is released under ISC LICENSE; see LICENSE.txt for further details.
Copyright (c) 2012-2023 Ciro Mattia Gonano, Paweł Jastrzębski and Darodi.
**KCC** is released under ISC LICENSE; see [LICENSE.txt](./LICENSE.txt) for further details.

View File

@@ -0,0 +1,320 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48px"
height="48px"
id="svg3832"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="appimage-assistant_alt3.svg">
<defs
id="defs3834">
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3308-4-6-931-761-0"
id="linearGradient2975"
gradientUnits="userSpaceOnUse"
x1="24.3125"
y1="22.96875"
x2="24.3125"
y2="41.03125" />
<linearGradient
id="linearGradient3308-4-6-931-761-0">
<stop
id="stop2919-2"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop2921-76"
style="stop-color:#ffffff;stop-opacity:0"
offset="1" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4222"
id="linearGradient2979"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0,0.3704967,-0.3617496,0,33.508315,6.1670925)"
x1="7.6485429"
y1="26.437023"
x2="41.861729"
y2="26.437023" />
<linearGradient
id="linearGradient4222">
<stop
id="stop4224"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop4226"
style="stop-color:#ffffff;stop-opacity:0"
offset="1" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3308-4-6-931-761"
id="linearGradient2982"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0,0.9999987)"
x1="23.99999"
y1="4.999989"
x2="23.99999"
y2="43" />
<linearGradient
id="linearGradient3308-4-6-931-761">
<stop
id="stop2919"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop2921"
style="stop-color:#ffffff;stop-opacity:0"
offset="1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3575"
id="radialGradient2985"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0,1.0262008,-1.6561124,9.4072203e-4,-56.097482,-45.332325)"
cx="48.42384"
cy="-48.027504"
fx="48.42384"
fy="-48.027504"
r="38.212933" />
<linearGradient
id="linearGradient3575">
<stop
id="stop3577"
style="stop-color:#fafafa;stop-opacity:1"
offset="0" />
<stop
id="stop3579"
style="stop-color:#e6e6e6;stop-opacity:1"
offset="1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3993"
id="radialGradient2990"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0,2.0478765,-2.7410544,-8.6412258e-8,47.161382,-8.837436)"
cx="9.3330879"
cy="8.4497671"
fx="9.3330879"
fy="8.4497671"
r="19.99999" />
<linearGradient
id="linearGradient3993">
<stop
offset="0"
style="stop-color:#a3c0d0;stop-opacity:1"
id="stop3995" />
<stop
offset="1"
style="stop-color:#427da1;stop-opacity:1"
id="stop4001" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2508"
id="linearGradient2992"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0,0.9674382)"
x1="14.048676"
y1="44.137306"
x2="14.048676"
y2="4.0000005" />
<linearGradient
id="linearGradient2508">
<stop
offset="0"
style="stop-color:#2e4a5a;stop-opacity:1"
id="stop2510" />
<stop
offset="1"
style="stop-color:#6e8796;stop-opacity:1"
id="stop2512" />
</linearGradient>
<radialGradient
cx="4.9929786"
cy="43.5"
r="2.5"
fx="4.9929786"
fy="43.5"
id="radialGradient2873-966-168"
xlink:href="#linearGradient3688-166-749"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.003784,0,0,1.4,27.98813,-17.4)" />
<linearGradient
id="linearGradient3688-166-749">
<stop
id="stop2883"
style="stop-color:#181818;stop-opacity:1"
offset="0" />
<stop
id="stop2885"
style="stop-color:#181818;stop-opacity:0"
offset="1" />
</linearGradient>
<radialGradient
cx="4.9929786"
cy="43.5"
r="2.5"
fx="4.9929786"
fy="43.5"
id="radialGradient2875-742-326"
xlink:href="#linearGradient3688-464-309"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.003784,0,0,1.4,-20.01187,-104.4)" />
<linearGradient
id="linearGradient3688-464-309">
<stop
id="stop2889"
style="stop-color:#181818;stop-opacity:1"
offset="0" />
<stop
id="stop2891"
style="stop-color:#181818;stop-opacity:0"
offset="1" />
</linearGradient>
<linearGradient
x1="25.058096"
y1="47.027729"
x2="25.058096"
y2="39.999443"
id="linearGradient2877-634-617"
xlink:href="#linearGradient3702-501-757"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3702-501-757">
<stop
id="stop2895"
style="stop-color:#181818;stop-opacity:0"
offset="0" />
<stop
id="stop2897"
style="stop-color:#181818;stop-opacity:1"
offset="0.5" />
<stop
id="stop2899"
style="stop-color:#181818;stop-opacity:0"
offset="1" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="7"
inkscape:cx="24"
inkscape:cy="24"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="603"
inkscape:window-height="484"
inkscape:window-x="417"
inkscape:window-y="162"
inkscape:window-maximized="0" />
<metadata
id="metadata3837">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
style="display:inline"
id="g2036"
transform="matrix(1.1,0,0,0.4444449,-2.4000022,25.11107)">
<g
style="opacity:0.4"
id="g3712"
transform="matrix(1.052632,0,0,1.285713,-1.263158,-13.42854)">
<rect
style="fill:url(#radialGradient2873-966-168);fill-opacity:1;stroke:none"
id="rect2801"
y="40"
x="38"
height="7"
width="5" />
<rect
style="fill:url(#radialGradient2875-742-326);fill-opacity:1;stroke:none"
id="rect3696"
transform="scale(-1,-1)"
y="-47"
x="-10"
height="7"
width="5" />
<rect
style="fill:url(#linearGradient2877-634-617);fill-opacity:1;stroke:none"
id="rect3700"
y="40"
x="10"
height="7.0000005"
width="28" />
</g>
</g>
<rect
style="fill:url(#radialGradient2990);fill-opacity:1;stroke:url(#linearGradient2992);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect5505"
y="5.4674392"
x="4.5"
ry="2.2322156"
rx="2.2322156"
height="39"
width="39" />
<path
style="opacity:0.05;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00178742;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path4294-1"
d="m 21,6.9687498 a 2.0165107,2.0165107 0 0 0 -2.03125,2.03125 l 0,3.9687502 -1.15625,0 a 2.0165107,2.0165107 0 0 0 -1.5,3.375 l 5.0625,5.75 c -0.06312,0.110777 -0.178724,0.246032 -0.21875,0.34375 -0.195898,0.478256 -0.25,0.83653 -0.25,1.21875 l 0,0.125 L 20.8125,23.6875 C 20.534322,23.409323 20.213169,23.162739 19.71875,22.96875 19.47154,22.87176 19.185456,22.791748 18.75,22.8125 c -0.435456,0.02075 -1.054055,0.210302 -1.46875,0.625 L 15.75,24.96875 c -0.414689,0.414689 -0.604245,1.033294 -0.625,1.46875 -0.02075,0.435456 0.05925,0.721537 0.15625,0.96875 C 15.475241,27.900677 15.721817,28.221821 16,28.5 l 0.09375,0.09375 -0.125,0 c -0.382218,0 -0.740493,0.0541 -1.21875,0.25 -0.239128,0.09795 -0.538285,0.214988 -0.84375,0.53125 -0.305465,0.316262 -0.625,0.914788 -0.625,1.53125 l 0,2.1875 c 0,0.616465 0.319536,1.214989 0.625,1.53125 0.305464,0.316261 0.604622,0.433301 0.84375,0.53125 0.478256,0.195898 0.83653,0.25 1.21875,0.25 l 0.125,0 L 16,35.5 c -0.278175,0.278176 -0.52476,0.599329 -0.71875,1.09375 -0.09699,0.24721 -0.177003,0.533292 -0.15625,0.96875 0.02075,0.435458 0.210304,1.054058 0.625,1.46875 l 1.53125,1.53125 c 0.414691,0.414697 1.033292,0.604245 1.46875,0.625 0.435458,0.02076 0.721537,-0.05926 0.96875,-0.15625 0.494425,-0.19399 0.81557,-0.440568 1.09375,-0.71875 l 0.09375,-0.09375 0,0.125 c 0,0.38222 0.0541,0.740495 0.25,1.21875 0.09795,0.239127 0.214989,0.538285 0.53125,0.84375 0.316261,0.305465 0.914783,0.625 1.53125,0.625 l 2.1875,0 c 0.616466,0 1.214989,-0.319534 1.53125,-0.625 0.316261,-0.305466 0.433302,-0.604622 0.53125,-0.84375 0.195896,-0.478255 0.25,-0.836532 0.25,-1.21875 l 0,-0.125 0.09375,0.09375 c 0.278176,0.278175 0.599329,0.52476 1.09375,0.71875 0.24721,0.09699 0.533292,0.177003 0.96875,0.15625 0.435458,-0.02075 1.054058,-0.210304 1.46875,-0.625 L 32.875,39.03125 C 33.289697,38.616559 33.479245,37.997958 33.5,37.5625 33.52076,37.127042 33.44074,36.840963 33.34375,36.59375 33.14976,36.099325 32.903182,35.77818 32.625,35.5 l -0.09375,-0.09375 0.125,0 c 0.38222,0 0.740494,-0.0541 1.21875,-0.25 0.239128,-0.09795 0.538286,-0.214988 0.84375,-0.53125 0.305464,-0.316262 0.625,-0.914787 0.625,-1.53125 l 0,-2.1875 c 0,-0.61646 -0.319535,-1.214987 -0.625,-1.53125 -0.305465,-0.316263 -0.604621,-0.433301 -0.84375,-0.53125 -0.478257,-0.195898 -0.836532,-0.25 -1.21875,-0.25 l -0.125,0 L 32.625,28.5 c 0.278177,-0.278177 0.52476,-0.599329 0.71875,-1.09375 C 33.44074,27.15904 33.520753,26.872957 33.5,26.4375 33.47925,26.002043 33.289697,25.383443 32.875,24.96875 L 31.34375,23.4375 c -0.414688,-0.414694 -1.03329,-0.604245 -1.46875,-0.625 -0.43546,-0.02076 -0.721537,0.05925 -0.96875,0.15625 -0.494426,0.193991 -0.815572,0.44057 -1.09375,0.71875 l -0.09375,0.09375 0,-0.125 c 0,-0.382218 -0.0541,-0.740493 -0.25,-1.21875 -0.09112,-0.22245 -0.228127,-0.500183 -0.5,-0.78125 l 4.71875,-5.3125 a 2.0165107,2.0165107 0 0 0 -1.5,-3.375 l -1.15625,0 0,-3.9687502 A 2.0165107,2.0165107 0 0 0 27,6.9687498 l -6,0 z M 24.3125,31.25 c 0.427097,0 0.75,0.322904 0.75,0.75 0,0.427096 -0.322903,0.75 -0.75,0.75 -0.427094,0 -0.75,-0.322906 -0.75,-0.75 0,-0.427094 0.322906,-0.75 0.75,-0.75 z" />
<path
style="opacity:0.05;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00178742;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path4294"
d="m 20.90625,8.0312498 a 0.96385067,0.96385067 0 0 0 -0.875,0.96875 l 0,5.0312502 -2.21875,0 A 0.96385067,0.96385067 0 0 0 17.09375,15.625 l 5.78125,6.53125 c -0.158814,0.0616 -0.341836,0.0951 -0.4375,0.1875 -0.169161,0.163386 -0.252971,0.323419 -0.3125,0.46875 -0.119058,0.290663 -0.15625,0.566746 -0.15625,0.84375 l 0,1.65625 C 21.718163,25.40233 21.485871,25.509772 21.25,25.625 l -1.1875,-1.1875 c -0.199651,-0.19965 -0.421433,-0.352095 -0.71875,-0.46875 -0.148659,-0.05833 -0.329673,-0.104846 -0.5625,-0.09375 -0.232827,0.0111 -0.53583,0.09833 -0.75,0.3125 L 16.5,25.71875 c -0.214168,0.214168 -0.301403,0.517173 -0.3125,0.75 -0.0111,0.232827 0.03542,0.41384 0.09375,0.5625 0.116655,0.297321 0.269096,0.519099 0.46875,0.71875 l 1.1875,1.1875 c -0.115228,0.235871 -0.222668,0.468163 -0.3125,0.71875 l -1.65625,0 c -0.277003,0 -0.553087,0.03719 -0.84375,0.15625 -0.145332,0.05953 -0.305363,0.143338 -0.46875,0.3125 -0.163387,0.169162 -0.3125,0.46403 -0.3125,0.78125 l 0,2.1875 c 0,0.317221 0.149114,0.612089 0.3125,0.78125 0.163386,0.169161 0.323419,0.252971 0.46875,0.3125 0.290663,0.119058 0.566746,0.15625 0.84375,0.15625 l 1.65625,0 c 0.08983,0.250587 0.197272,0.482879 0.3125,0.71875 L 16.75,36.25 c -0.199649,0.19965 -0.352095,0.421432 -0.46875,0.71875 -0.05833,0.148659 -0.104846,0.329672 -0.09375,0.5625 0.0111,0.232828 0.09833,0.535831 0.3125,0.75 l 1.53125,1.53125 c 0.214168,0.214172 0.517172,0.301403 0.75,0.3125 0.232828,0.0111 0.41384,-0.03542 0.5625,-0.09375 0.29732,-0.116655 0.519098,-0.269096 0.71875,-0.46875 L 21.25,38.375 c 0.235871,0.115228 0.468164,0.222668 0.71875,0.3125 l 0,1.65625 c 0,0.277003 0.03719,0.553087 0.15625,0.84375 0.05953,0.145331 0.143339,0.305364 0.3125,0.46875 0.169161,0.163386 0.464028,0.3125 0.78125,0.3125 l 2.1875,0 c 0.317221,0 0.612089,-0.149113 0.78125,-0.3125 0.169161,-0.163387 0.252971,-0.323419 0.3125,-0.46875 0.119057,-0.290663 0.15625,-0.566748 0.15625,-0.84375 l 0,-1.65625 c 0.250586,-0.08983 0.482879,-0.197272 0.71875,-0.3125 l 1.1875,1.1875 c 0.19965,0.199649 0.421432,0.352095 0.71875,0.46875 0.148659,0.05833 0.329672,0.104846 0.5625,0.09375 0.232828,-0.0111 0.535831,-0.09833 0.75,-0.3125 L 32.125,38.28125 c 0.214172,-0.214168 0.301403,-0.517172 0.3125,-0.75 0.0111,-0.232828 -0.03542,-0.41384 -0.09375,-0.5625 C 32.227095,36.67143 32.074654,36.449652 31.875,36.25 L 30.6875,35.0625 C 30.802728,34.82663 30.910168,34.594337 31,34.34375 l 1.65625,0 c 0.277004,0 0.553087,-0.03719 0.84375,-0.15625 0.145332,-0.05953 0.305364,-0.143339 0.46875,-0.3125 0.163386,-0.169161 0.3125,-0.46403 0.3125,-0.78125 l 0,-2.1875 c 0,-0.317219 -0.149114,-0.612088 -0.3125,-0.78125 C 33.805364,29.955838 33.645332,29.872029 33.5,29.8125 33.209336,29.693442 32.933253,29.65625 32.65625,29.65625 l -1.65625,0 C 30.91017,29.405663 30.802728,29.17337 30.6875,28.9375 L 31.875,27.75 c 0.19965,-0.19965 0.352095,-0.421432 0.46875,-0.71875 0.05833,-0.148659 0.104846,-0.329672 0.09375,-0.5625 -0.0111,-0.232828 -0.09833,-0.535831 -0.3125,-0.75 L 30.59375,24.1875 c -0.214167,-0.21417 -0.517171,-0.301403 -0.75,-0.3125 -0.232829,-0.0111 -0.41384,0.03542 -0.5625,0.09375 -0.29732,0.116656 -0.519099,0.269097 -0.71875,0.46875 L 27.375,25.625 c -0.235871,-0.115228 -0.468163,-0.222668 -0.71875,-0.3125 l 0,-1.65625 c 0,-0.277003 -0.03719,-0.553087 -0.15625,-0.84375 -0.05953,-0.145332 -0.143338,-0.305363 -0.3125,-0.46875 -0.169162,-0.163387 -0.46403,-0.3125 -0.78125,-0.3125 l -0.15625,0 5.65625,-6.40625 A 0.96385067,0.96385067 0 0 0 30.1875,14.03125 l -2.21875,0 0,-5.0312502 A 0.96385067,0.96385067 0 0 0 27,8.0312498 l -6,0 a 0.96385067,0.96385067 0 0 0 -0.09375,0 z M 24.3125,30.1875 c 1.002113,0 1.8125,0.810388 1.8125,1.8125 0,1.002112 -0.810387,1.8125 -1.8125,1.8125 C 23.31039,33.8125 22.5,33.002111 22.5,32 c 0,-1.002111 0.81039,-1.8125 1.8125,-1.8125 z" />
<path
style="fill:url(#radialGradient2985);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00178742;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path2317"
d="M 21,8.9999996 21,15 17.8125,15 24,22 30.1875,15 27,15 l 0,-6.0000004 -6,0 z M 23.21875,23 c -0.172892,0 -0.28125,0.294922 -0.28125,0.65625 l 0,2.28125 C 22.24145,26.095996 21.585954,26.379869 21,26.75 l -1.625,-1.625 c -0.255498,-0.255497 -0.533998,-0.372253 -0.65625,-0.25 l -1.53125,1.53125 c -0.122254,0.122254 -0.0055,0.400753 0.25,0.65625 l 1.625,1.625 c -0.37013,0.585953 -0.654003,1.24145 -0.8125,1.9375 l -2.28125,0 c -0.361328,0 -0.65625,0.108357 -0.65625,0.28125 l 0,2.1875 c 0,0.172892 0.294922,0.28125 0.65625,0.28125 l 2.28125,0 c 0.158497,0.69605 0.44237,1.351546 0.8125,1.9375 l -1.625,1.625 c -0.255497,0.255498 -0.372254,0.533997 -0.25,0.65625 l 1.53125,1.53125 c 0.122252,0.122254 0.400752,0.0055 0.65625,-0.25 L 21,37.25 c 0.585954,0.37013 1.24145,0.654002 1.9375,0.8125 l 0,2.28125 C 22.9375,40.705077 23.045858,41 23.21875,41 l 2.1875,0 c 0.172893,0 0.28125,-0.294924 0.28125,-0.65625 l 0,-2.28125 c 0.69605,-0.158498 1.351546,-0.44237 1.9375,-0.8125 l 1.625,1.625 c 0.255498,0.255497 0.533997,0.372254 0.65625,0.25 l 1.53125,-1.53125 c 0.122254,-0.122252 0.0055,-0.400752 -0.25,-0.65625 l -1.625,-1.625 c 0.370129,-0.585954 0.654003,-1.24145 0.8125,-1.9375 l 2.28125,0 c 0.361329,0 0.65625,-0.108358 0.65625,-0.28125 l 0,-2.1875 c 0,-0.172893 -0.294921,-0.28125 -0.65625,-0.28125 l -2.28125,0 c -0.158497,-0.69605 -0.442371,-1.351547 -0.8125,-1.9375 l 1.625,-1.625 c 0.255497,-0.255497 0.372254,-0.533997 0.25,-0.65625 L 29.90625,24.875 C 29.783997,24.752745 29.505498,24.8695 29.25,25.125 l -1.625,1.625 c -0.585954,-0.370131 -1.24145,-0.654004 -1.9375,-0.8125 l 0,-2.28125 C 25.6875,23.294922 25.579143,23 25.40625,23 l -2.1875,0 z m 1.09375,6.21875 c 1.528616,0 2.78125,1.252635 2.78125,2.78125 0,1.528615 -1.252634,2.78125 -2.78125,2.78125 -1.528614,0 -2.78125,-1.252635 -2.78125,-2.78125 0,-1.528615 1.252636,-2.78125 2.78125,-2.78125 z" />
<rect
style="opacity:0.4;fill:none;stroke:url(#linearGradient2982);stroke-width:0.99999976;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect6741"
y="6.4999886"
x="5.4999981"
ry="1.365193"
rx="1.365193"
height="37.000011"
width="36.999985" />
<path
style="fill:none;stroke:url(#linearGradient2979);stroke-width:0.99829447;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
id="path2777"
d="M 28.926376,15.466668 24,21.177578 18.963089,15.5 21.5,15.5 l 0,-6.0000004 5,0 0,6.0000004 2.426376,-0.03333 z" />
<path
style="fill:none;stroke:url(#linearGradient2975);stroke-width:1;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path4243"
d="m 23.4375,23.46875 c -0.01166,0.05381 -0.03125,0.100205 -0.03125,0.1875 l 0,2.28125 a 0.48185467,0.48185467 0 0 1 -0.375,0.46875 c -0.638467,0.145384 -1.238423,0.407111 -1.78125,0.75 a 0.48185467,0.48185467 0 0 1 -0.59375,-0.0625 l -1.625,-1.625 C 18.9779,25.4154 18.9477,25.40242 18.90625,25.375 l -1.21875,1.21875 c 0.02742,0.04145 0.0404,0.07165 0.09375,0.125 l 1.625,1.625 a 0.48185467,0.48185467 0 0 1 0.0625,0.59375 c -0.342888,0.542826 -0.604615,1.142782 -0.75,1.78125 a 0.48185467,0.48185467 0 0 1 -0.46875,0.375 l -2.28125,0 c -0.08729,0 -0.133695,0.01959 -0.1875,0.03125 l 0,1.75 c 0.05381,0.01166 0.100205,0.03125 0.1875,0.03125 l 2.28125,0 a 0.48185467,0.48185467 0 0 1 0.46875,0.375 c 0.145385,0.638468 0.407112,1.238423 0.75,1.78125 a 0.48185467,0.48185467 0 0 1 -0.0625,0.59375 l -1.625,1.625 c -0.05335,0.05335 -0.06633,0.08355 -0.09375,0.125 l 1.21875,1.21875 c 0.04145,-0.02742 0.07165,-0.0404 0.125,-0.09375 l 1.625,-1.625 A 0.48185467,0.48185467 0 0 1 21.25,36.84375 c 0.542827,0.342888 1.142781,0.604614 1.78125,0.75 a 0.48185467,0.48185467 0 0 1 0.375,0.46875 l 0,2.28125 c 0,0.08729 0.01959,0.133695 0.03125,0.1875 l 1.75,0 c 0.01166,-0.0538 0.03125,-0.100206 0.03125,-0.1875 l 0,-2.28125 a 0.48185467,0.48185467 0 0 1 0.375,-0.46875 c 0.638469,-0.145386 1.238423,-0.407112 1.78125,-0.75 a 0.48185467,0.48185467 0 0 1 0.59375,0.0625 l 1.625,1.625 c 0.05335,0.05335 0.08355,0.06633 0.125,0.09375 l 1.21875,-1.21875 c -0.02742,-0.04145 -0.0404,-0.07165 -0.09375,-0.125 l -1.625,-1.625 a 0.48185467,0.48185467 0 0 1 -0.0625,-0.59375 c 0.342888,-0.542828 0.604615,-1.142783 0.75,-1.78125 a 0.48185467,0.48185467 0 0 1 0.46875,-0.375 l 2.28125,0 c 0.08729,0 0.133695,-0.01959 0.1875,-0.03125 l 0,-1.75 c -0.0538,-0.01166 -0.100204,-0.03125 -0.1875,-0.03125 l -2.28125,0 a 0.48185467,0.48185467 0 0 1 -0.46875,-0.375 c -0.145385,-0.638467 -0.407113,-1.238424 -0.75,-1.78125 a 0.48185467,0.48185467 0 0 1 0.0625,-0.59375 l 1.625,-1.625 c 0.05335,-0.05335 0.06633,-0.08355 0.09375,-0.125 L 29.71875,25.375 c -0.04145,0.02742 -0.07165,0.0404 -0.125,0.09375 l -1.625,1.625 a 0.48185467,0.48185467 0 0 1 -0.59375,0.0625 c -0.542827,-0.342889 -1.142783,-0.604616 -1.78125,-0.75 a 0.48185467,0.48185467 0 0 1 -0.375,-0.46875 l 0,-2.28125 c 0,-0.0873 -0.01959,-0.133695 -0.03125,-0.1875 l -1.75,0 z m 0.875,5.28125 c 1.791829,0 3.25,1.458172 3.25,3.25 0,1.791828 -1.458171,3.25 -3.25,3.25 -1.791827,0 -3.25,-1.458172 -3.25,-3.25 0,-1.791828 1.458173,-3.25 3.25,-3.25 z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

14
appveyor.yml Normal file
View File

@@ -0,0 +1,14 @@
environment:
PYTHON: "C:\\Python37-x64"
install:
- set PATH="%PYTHON%\\Scripts";%PATH%
- "%PYTHON%\\python.exe -m pip install --upgrade pip setuptools wheel"
- "%PYTHON%\\python.exe -m pip install -r requirements.txt"
- "%PYTHON%\\python.exe -m pip install certifi https://github.com/pyinstaller/pyinstaller/archive/develop.zip"
build_script:
- "%PYTHON%\\python.exe setup.py build_binary"
artifacts:
- path: dist\KCC*

View File

@@ -1,18 +0,0 @@
#!/bin/bash
set -e
pip3 install --upgrade pip setuptools wheel
pip3 install pillow python-slugify psutil pyinstaller raven pyqt5 certifi
gem install fpm
cd /app
pyinstaller -F -s kcc.py
mkdir -p dist/usr/bin dist/usr/share/applications dist/usr/share/doc/kindlecomicconverter dist/usr/share/kindlecomicconverter dist/usr/share/lintian/overrides
mv dist/kcc dist/usr/bin
cp icons/comic2ebook.png dist/usr/share/kindlecomicconverter
cp LICENSE.txt dist/usr/share/doc/kindlecomicconverter/copyright
cp other/linux/kindlecomicconverter.desktop dist/usr/share/applications
cp other/linux/kindlecomicconverter dist/usr/share/lintian/overrides
cd /app/dist
fpm -f -s dir -t deb -n kindlecomicconverter -v $KCCVER -m "Paweł Jastrzębski <pawelj@iosphe.re>" --license "ISC" --description "$(printf "Comic and Manga converter for e-book readers.\nThis app allows you to transform your PNG, JPG, GIF, CBZ, CBR and CB7 files\ninto EPUB or MOBI format e-books.")" --url "https://kcc.iosphe.re/" --deb-priority "optional" --vendor "" --category "graphics" -d "unrar | unrar-free" -d "p7zip-full" -d "libc6" usr

View File

@@ -1,12 +0,0 @@
# acidweb/kcc
FROM debian:stretch
MAINTAINER Paweł Jastrzębski <pawelj@iosphe.re>
ADD ./Build /Build
RUN apt-get update && apt-get -y dist-upgrade
RUN apt-get -y install build-essential curl ruby ruby-dev libpng-dev libjpeg-dev python3 python3-dev python3-pyqt5
RUN curl https://bootstrap.pypa.io/get-pip.py | python3
RUN apt-get clean -y && apt-get autoclean -y && apt-get autoremove -y && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
CMD /Build

16
environment.yml Normal file
View File

@@ -0,0 +1,16 @@
name: kcc
channels:
- conda-forge
- defaults
dependencies:
- python=3.11
- Pillow>=5.2.0
- psutil>=5.9.5
- python-slugify>=1.2.1
- raven>=6.0.0
- distro
- natsort[fast]>=8.4.0
- pip
- pip:
- mozjpeg-lossless-optimization>=1.1.2
- pyside6>=6.5.1

3
gen_ui_files.bat Normal file
View File

@@ -0,0 +1,3 @@
pyside6-uic gui/KCC.ui > kindlecomicconverter/KCC_ui.py
pyside6-uic gui/MetaEditor.ui > kindlecomicconverter/KCC_ui_editor.py
pyside6-rcc gui/KCC.qrc > kindlecomicconverter/KCC_rc.py

5
gen_ui_files.sh Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/sh
pyside6-uic gui/KCC.ui --from-imports > kindlecomicconverter/KCC_ui.py
pyside6-uic gui/MetaEditor.ui --from-imports > kindlecomicconverter/KCC_ui_editor.py
pyside6-rcc gui/KCC.qrc > kindlecomicconverter/KCC_rc.py

View File

@@ -11,6 +11,7 @@
<file>../icons/CBZ.png</file>
<file>../icons/EPUB.png</file>
<file>../icons/MOBI.png</file>
<file>../icons/KFX.png</file>
</qresource>
<qresource prefix="Status">
<file>../icons/error.png</file>

View File

@@ -22,118 +22,7 @@
<property name="bottomMargin">
<number>5</number>
</property>
<item row="1" column="0" colspan="2">
<widget class="QProgressBar" name="progressBar">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="visible">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QListWidget" name="jobList">
<property name="styleSheet">
<string notr="true">QListWidget#jobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;color:rgb(0,0,0);}</string>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QWidget" name="customWidget" native="true">
<property name="visible">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="2">
<widget class="QLabel" name="hLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Custom height:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="widthBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="maximum">
<number>2160</number>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="wLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Custom width:</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QSpinBox" name="heightBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="maximum">
<number>3840</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="4" column="0" colspan="2">
<item row="5" column="0" colspan="2">
<widget class="QWidget" name="optionWidget" native="true">
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
@@ -148,36 +37,56 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QCheckBox" name="mangaBox">
<item row="0" column="2">
<widget class="QCheckBox" name="qualityBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Enable right-to-left reading.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - 4 panels&lt;br/&gt;&lt;/span&gt;Zoom each corner separately.&lt;/p&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - 2 panels&lt;br/&gt;&lt;/span&gt;Zoom only the top and bottom of the page.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - 4 high-quality panels&lt;br/&gt;&lt;/span&gt;Zoom each corner separately. Try to increase the quality of magnification. Check wiki for more details.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Manga mode</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="rotateBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Split&lt;br/&gt;&lt;/span&gt;Double page spreads will be cut into two separate pages.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - Rotate and split&lt;br/&gt;&lt;/span&gt;Double page spreads will be displayed twice. First rotated and then split. &lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Rotate&lt;br/&gt;&lt;/span&gt;Double page spreads will be rotated.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Spread splitter</string>
<string>Panel View 4/2/HQ</string>
</property>
<property name="tristate">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="qualityBox">
<item row="4" column="1">
<widget class="QCheckBox" name="deleteBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - 4 panels&lt;br/&gt;&lt;/span&gt;Zoom each corner separately.&lt;/p&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - 2 panels&lt;br/&gt;&lt;/span&gt;Zoom only the top and bottom of the page.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - 4 high quality panels&lt;br/&gt;&lt;/span&gt;Zoom each corner separately. Try to increase the quality of magnification. Check wiki for more details.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>Delete input file(s) or directory. It's not recoverable!</string>
</property>
<property name="text">
<string>Panel View 4/2/HQ</string>
<string>Delete input</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="maximizeStrips">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - 1x4&lt;br/&gt;&lt;/span&gt;Keep format 1x4 panels strips.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - 2x2&lt;br/&gt;&lt;/span&gt;Turn 1x4 strips to 2x2 to maximize screen usage.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>1x4 to 2x2 strips</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="gammaBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Disable automatic gamma correction.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Custom gamma</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="borderBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Autodetection&lt;br/&gt;&lt;/span&gt;The color of margins fill will be detected automatically.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - White&lt;br/&gt;&lt;/span&gt;Margins will be filled with white color.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Black&lt;br/&gt;&lt;/span&gt;Margins will be filled with black color.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>W/B margins</string>
</property>
<property name="tristate">
<bool>true</bool>
@@ -207,23 +116,36 @@
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="gammaBox">
<item row="0" column="0">
<widget class="QCheckBox" name="mangaBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Disable automatic gamma correction.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Enable right-to-left reading.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Custom gamma</string>
<string>Manga mode</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="borderBox">
<item row="0" column="1">
<widget class="QCheckBox" name="rotateBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Autodetection&lt;br/&gt;&lt;/span&gt;Color of margins fill will be detected automatically.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - White&lt;br/&gt;&lt;/span&gt;Margins will be filled with white color.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Black&lt;br/&gt;&lt;/span&gt;Margins will be filled with black color.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Split&lt;br/&gt;&lt;/span&gt;Double page spreads will be cut into two separate pages.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - Rotate and split&lt;br/&gt;&lt;/span&gt;Double page spreads will be displayed twice. First rotated and then split. &lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Rotate&lt;br/&gt;&lt;/span&gt;Double page spreads will be rotated.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>W/B margins</string>
<string>Spread splitter</string>
</property>
<property name="tristate">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QCheckBox" name="croppingBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Disabled&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Disabled&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - Margins&lt;br/&gt;&lt;/span&gt;Margins&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Margins + page numbers&lt;br/&gt;&lt;/span&gt;Margins +page numbers&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Cropping mode</string>
</property>
<property name="tristate">
<bool>true</bool>
@@ -233,13 +155,26 @@
<item row="2" column="1">
<widget class="QCheckBox" name="outputSplit">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Automatic mode&lt;br/&gt;&lt;/span&gt;Output will be splitted automatically.&lt;/p&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Volume mode&lt;br/&gt;&lt;/span&gt;Every subdirectory will be considered as separate volume.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - Automatic mode&lt;br/&gt;&lt;/span&gt;The output will be split automatically.&lt;/p&gt;&lt;p style='white-space:pre'&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - Volume mode&lt;br/&gt;&lt;/span&gt;Every subdirectory will be considered as a separate volume.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Output split</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="mozJpegBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - JPEG&lt;br/&gt;&lt;/span&gt;Use JPEG files&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - force PNG&lt;br/&gt;&lt;/span&gt;Create PNG files instead JPEG&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - mozJpeg&lt;br/&gt;&lt;/span&gt;10-20% smaller JPEG file, with the same image quality, but processing time multiplied by 2&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>JPEG/PNG/mozJpeg</string>
</property>
<property name="tristate">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QCheckBox" name="colorBox">
<property name="toolTip">
@@ -250,10 +185,30 @@
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QCheckBox" name="disableProcessingBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;pre style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Do not process any image, ignore profile and processing options&lt;/pre&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Disable processing</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="dedupeCoverBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Don't duplicate the first page as the cover. Useful for 2 page spread alignment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>De-dupe cover</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="5" column="0" colspan="2">
<item row="6" column="0" colspan="2">
<widget class="QWidget" name="gammaWidget" native="true">
<property name="visible">
<bool>false</bool>
@@ -294,9 +249,12 @@
</layout>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QWidget" name="toolWidget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<item row="8" column="0" colspan="2">
<widget class="QWidget" name="croppingWidget" native="true">
<property name="visible">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
@@ -310,36 +268,22 @@
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="editorButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<widget class="QLabel" name="croppingPowerLabel">
<property name="text">
<string>Editor</string>
</property>
<property name="icon">
<iconset resource="KCC.qrc">
<normaloff>:/Other/icons/editor.png</normaloff>:/Other/icons/editor.png</iconset>
<string>Cropping power:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="wikiButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
<widget class="QSlider" name="croppingPowerSlider">
<property name="maximum">
<number>200</number>
</property>
<property name="text">
<string>Wiki</string>
<property name="singleStep">
<number>1</number>
</property>
<property name="icon">
<iconset resource="KCC.qrc">
<normaloff>:/Other/icons/wiki.png</normaloff>:/Other/icons/wiki.png</iconset>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
@@ -418,9 +362,6 @@
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
</property>
</widget>
</item>
<item row="1" column="3">
@@ -434,9 +375,6 @@
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Output format.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
</property>
</widget>
</item>
<item row="1" column="2">
@@ -449,12 +387,11 @@
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Shift+Click to select the output directory.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Shift+Click to select the output directory.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Convert</string>
@@ -491,6 +428,171 @@
<zorder>formatBox</zorder>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QWidget" name="toolWidget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="editorButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Shift+Click to edit directory.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Editor</string>
</property>
<property name="icon">
<iconset resource="KCC.qrc">
<normaloff>:/Other/icons/editor.png</normaloff>:/Other/icons/editor.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="wikiButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>Wiki</string>
</property>
<property name="icon">
<iconset resource="KCC.qrc">
<normaloff>:/Other/icons/wiki.png</normaloff>:/Other/icons/wiki.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QListWidget" name="jobList">
<property name="styleSheet">
<string notr="true">QListWidget#jobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;color:rgb(0,0,0);}</string>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QProgressBar" name="progressBar">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="font">
<font>
<bold>true</bold>
</font>
</property>
<property name="visible">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="7" column="0" colspan="2">
<widget class="QWidget" name="customWidget" native="true">
<property name="visible">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="2">
<widget class="QLabel" name="hLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of the target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Custom height:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="widthBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of the target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="maximum">
<number>2160</number>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="wLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of the target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Custom width:</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QSpinBox" name="heightBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p style='white-space:pre'&gt;Resolution of the target device.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="maximum">
<number>3840</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QStatusBar" name="statusBar">
@@ -515,12 +617,18 @@
<tabstop>borderBox</tabstop>
<tabstop>outputSplit</tabstop>
<tabstop>colorBox</tabstop>
<tabstop>croppingBox</tabstop>
<tabstop>mozJpegBox</tabstop>
<tabstop>maximizeStrips</tabstop>
<tabstop>deleteBox</tabstop>
<tabstop>disableProcessingBox</tabstop>
<tabstop>editorButton</tabstop>
<tabstop>wikiButton</tabstop>
<tabstop>jobList</tabstop>
<tabstop>gammaSlider</tabstop>
<tabstop>widthBox</tabstop>
<tabstop>heightBox</tabstop>
<tabstop>croppingPowerSlider</tabstop>
</tabstops>
<resources>
<include location="KCC.qrc"/>

View File

@@ -112,19 +112,6 @@
<item row="6" column="1">
<widget class="QLineEdit" name="coloristLine"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/ciromattia/kcc/wiki/Manga-Cover-Database-support&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;MUid:&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="muidLine"/>
</item>
</layout>
</widget>
</item>

BIN
icons/KFX.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
#
# Permission to use, copy, modify, and/or distribute this software for
# any purpose with or without fee is hereby granted, provided that the
@@ -19,13 +19,15 @@
# PERFORMANCE OF THIS SOFTWARE.
import sys
if sys.version_info[0] != 3:
print('ERROR: This is Python 3 script!')
exit(1)
from multiprocessing import freeze_support
if sys.version_info < (3, 8, 0):
print('ERROR: This is a Python 3.8+ script!')
sys.exit(1)
from multiprocessing import freeze_support, set_start_method
from kindlecomicconverter.startup import startC2E
if __name__ == "__main__":
set_start_method('spawn')
freeze_support()
startC2E()

39
kcc-c2e.spec Normal file
View File

@@ -0,0 +1,39 @@
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['kcc-c2e.py'],
pathex=['.'],
binaries=[],
datas=[],
hiddenimports=['_cffi_backend'],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='kcc-c2e',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=False,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None , icon='icons\\comic2ebook.ico')

View File

@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
#
# Permission to use, copy, modify, and/or distribute this software for
# any purpose with or without fee is hereby granted, provided that the
@@ -19,13 +19,15 @@
# PERFORMANCE OF THIS SOFTWARE.
import sys
if sys.version_info[0] != 3:
print('ERROR: This is Python 3 script!')
exit(1)
from multiprocessing import freeze_support
if sys.version_info < (3, 8, 0):
print('ERROR: This is a Python 3.8+ script!')
sys.exit(1)
from multiprocessing import freeze_support, set_start_method
from kindlecomicconverter.startup import startC2P
if __name__ == "__main__":
set_start_method('spawn')
freeze_support()
startC2P()

39
kcc-c2p.spec Normal file
View File

@@ -0,0 +1,39 @@
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['kcc-c2p.py'],
pathex=['.'],
binaries=[],
datas=[],
hiddenimports=['_cffi_backend'],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='kcc-c2p',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=False,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None , icon='icons\\comic2ebook.ico')

125
kcc.iss
View File

@@ -1,125 +0,0 @@
#define MyAppName "Kindle Comic Converter"
#define MyAppVersion "5.4"
#define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
#define MyAppURL "http://kcc.iosphe.re/"
#define MyAppExeName "KCC.exe"
[Setup]
AppId={{7D279A59-C65E-4DA7-B165-56DD06596216}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
AppCopyright=Copyright (C) 2012-2017 Ciro Mattia Gonano and Paweł Jastrzębski
ArchitecturesAllowed=x64
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName={#MyAppName}
AllowNoIcons=yes
LicenseFile=LICENSE.txt
OutputBaseFilename=KindleComicConverter_win_{#MyAppVersion}
SetupIconFile=icons\comic2ebook.ico
SolidCompression=yes
ShowLanguageDialog=no
LanguageDetectionMethod=none
WizardImageFile=icons\Wizard.bmp
WizardSmallImageFile=icons\Wizard-Small.bmp
UninstallDisplayName={#MyAppName}
UninstallDisplayIcon={app}\{#MyAppExeName}
ChangesAssociations=True
InfoAfterFile=other\windows\InstallWarning.rtf
SignTool=SignTool /d $q{#MyAppName}$q /du $q{#MyAppURL}$q $f
MinVersion=0,6.0
OutputDir=dist
ArchitecturesInstallIn64BitMode=x64
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
Name: "CBZassociation"; Description: "CBZ"; GroupDescription: "File associations:"
Name: "CBRassociation"; Description: "CBR"; GroupDescription: "File associations:"
Name: "CB7association"; Description: "CB7"; GroupDescription: "File associations:"
[Files]
Source: "dist\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: "LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion solidbreak
Source: "other\windows\Additional-LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "other\windows\UnRAR.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "other\windows\7za.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "other\windows\vc_redist.x64.exe"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall
[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{group}\Readme"; Filename: "https://github.com/ciromattia/kcc#kcc"
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
[Run]
Filename: "{tmp}\vc_redist.x64.exe"; Parameters: "/install /passive /norestart"; StatusMsg: "Installing Microsoft Visual C++ 2015 Redistributable Package..."
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall
[Messages]
WelcomeLabel1=Welcome to the KCC Setup Wizard
FinishedHeadingLabel=Completing the KCC Setup Wizard
[Registry]
Root: HKCR; SubKey: ".cbz"; ValueType: string; ValueData: "KCCZIP"; Flags: uninsdeletekey; Tasks: CBZassociation
Root: HKCR; SubKey: "KCCZIP"; ValueType: string; ValueData: "KCC ZIP Archive"; Flags: uninsdeletekey; Tasks: CBZassociation
Root: HKCR; SubKey: "KCCZIP\Shell\Open\Command"; ValueType: string; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey; Tasks: CBZassociation
Root: HKCR; Subkey: "KCCZIP\DefaultIcon"; ValueType: string; ValueData: "{app}\{#MyAppExeName},0"; Flags: uninsdeletevalue; Tasks: CBZassociation
Root: HKCR; SubKey: ".cbr"; ValueType: string; ValueData: "KCCRAR"; Flags: uninsdeletekey; Tasks: CBRassociation
Root: HKCR; SubKey: "KCCRAR"; ValueType: string; ValueData: "KCC RAR Archive"; Flags: uninsdeletekey; Tasks: CBRassociation
Root: HKCR; SubKey: "KCCRAR\Shell\Open\Command"; ValueType: string; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey; Tasks: CBRassociation
Root: HKCR; Subkey: "KCCRAR\DefaultIcon"; ValueType: string; ValueData: "{app}\{#MyAppExeName},0"; Flags: uninsdeletevalue; Tasks: CBRassociation
Root: HKCR; SubKey: ".cb7"; ValueType: string; ValueData: "KCCCB7"; Flags: uninsdeletekey; Tasks: CB7association
Root: HKCR; SubKey: "KCCCB7"; ValueType: string; ValueData: "KCC 7z Archive"; Flags: uninsdeletekey; Tasks: CB7association
Root: HKCR; SubKey: "KCCCB7\Shell\Open\Command"; ValueType: string; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey; Tasks: CB7association
Root: HKCR; Subkey: "KCCCB7\DefaultIcon"; ValueType: string; ValueData: "{app}\{#MyAppExeName},0"; Flags: uninsdeletevalue; Tasks: CB7association
[Code]
function GetUninstallString(): String;
var
sUnInstPath: String;
sUnInstallString: String;
begin
sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
sUnInstallString := '';
if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
Result := sUnInstallString;
end;
function IsUpgrade(): Boolean;
begin
Result := (GetUninstallString() <> '');
end;
function UnInstallOldVersion(): Integer;
var
sUnInstallString: String;
iResultCode: Integer;
begin
Result := 0;
sUnInstallString := GetUninstallString();
if sUnInstallString <> '' then begin
sUnInstallString := RemoveQuotes(sUnInstallString);
if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
Result := 3
else
Result := 2;
end else
Result := 1;
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if (CurStep=ssInstall) then
begin
if (IsUpgrade()) then
begin
UnInstallOldVersion();
end;
end;
end;

81
kcc.py
View File

@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
#
# Permission to use, copy, modify, and/or distribute this software for
# any purpose with or without fee is hereby granted, provided that the
@@ -19,54 +19,63 @@
# PERFORMANCE OF THIS SOFTWARE.
import sys
if sys.version_info[0] != 3:
print('ERROR: This is Python 3 script!')
exit(1)
if sys.version_info < (3, 8, 0):
print('ERROR: This is a Python 3.8+ script!')
sys.exit(1)
# OS specific workarounds
import os
if sys.platform.startswith('darwin'):
# prioritize KC2 since it optionally also installs KP3
mac_paths = [
'/Applications/Kindle Comic Creator/Kindle Comic Creator.app/Contents/MacOS',
'/Applications/Kindle Previewer 3.app/Contents/lib/fc/bin/',
]
if getattr(sys, 'frozen', False):
os.environ['PATH'] = os.path.dirname(os.path.abspath(sys.executable)) + \
'/../Resources:/usr/local/bin:/usr/bin:/bin'
os.system('defaults write com.kindlecomicconverter.KindleComicConverter ApplePersistenceIgnoreState YES')
os.system('defaults write com.kindlecomicconverter.KindleComicConverter NSInitialToolTipDelay -int 1000')
else:
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/osx/:' + os.environ['PATH']
elif sys.platform.startswith('win'):
import multiprocessing.popen_spawn_win32 as forking
class _Popen(forking.Popen):
def __init__(self, *args, **kw):
if hasattr(sys, 'frozen'):
# noinspection PyUnresolvedReferences,PyProtectedMember
os.putenv('_MEIPASS2', sys._MEIPASS)
try:
super(_Popen, self).__init__(*args, **kw)
finally:
if hasattr(sys, 'frozen'):
if hasattr(os, 'unsetenv'):
os.unsetenv('_MEIPASS2')
else:
os.putenv('_MEIPASS2', '')
forking.Popen = _Popen
if getattr(sys, 'frozen', False):
os.environ['PATH'] += os.pathsep + os.pathsep.join(mac_paths +
[
'/opt/homebrew/bin',
'/usr/local/bin',
'/usr/bin',
'/bin',
]
)
os.chdir(os.path.dirname(os.path.abspath(sys.executable)))
else:
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/windows/;' + os.environ['PATH']
os.environ['PATH'] += os.pathsep + os.pathsep.join(mac_paths)
os.chdir(os.path.dirname(os.path.abspath(__file__)))
elif sys.platform.startswith('win'):
# prioritize KC2 since it optionally also installs KP3
win_paths = [
os.path.expandvars('%LOCALAPPDATA%\\Amazon\\KC2'),
os.path.expandvars('%LOCALAPPDATA%\\Amazon\\Kindle Previewer 3\\lib\\fc\\bin\\'),
os.path.expandvars('%UserProfile%\\Kindle Previewer 3\\lib\\fc\\bin\\'),
'C:\\Apps\\Kindle Previewer 3\\lib\\fc\\bin',
'D:\\Apps\\Kindle Previewer 3\\lib\\fc\\bin',
'E:\\Apps\\Kindle Previewer 3\\lib\\fc\\bin',
'C:\\Program Files\\7-Zip',
'D:\\Program Files\\7-Zip',
'E:\\Program Files\\7-Zip',
]
if getattr(sys, 'frozen', False):
os.environ['PATH'] += os.pathsep + os.pathsep.join(win_paths)
os.chdir(os.path.dirname(os.path.abspath(sys.executable)))
else:
os.environ['PATH'] += os.pathsep + os.pathsep.join(win_paths)
os.chdir(os.path.dirname(os.path.abspath(__file__)))
# Load additional Sentry configuration
if getattr(sys, 'frozen', False):
try:
import kindlecomicconverter.sentry
except:
pass
# if getattr(sys, 'frozen', False):
# try:
# import kindlecomicconverter.sentry
# except ImportError:
# pass
from multiprocessing import freeze_support
from multiprocessing import freeze_support, set_start_method
from kindlecomicconverter.startup import start
if __name__ == "__main__":
set_start_method('spawn')
freeze_support()
start()

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,272 +1,463 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'gui\KCC.ui'
#
# Created by: PyQt5 UI code generator 5.8.1
#
# WARNING! All changes made in this file will be lost!
################################################################################
## Form generated from reading UI file 'KCC.ui'
##
## Created by: Qt User Interface Compiler version 6.5.2
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PyQt5 import QtCore, QtGui, QtWidgets
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QAbstractItemView, QApplication, QCheckBox, QComboBox,
QGridLayout, QHBoxLayout, QLabel, QListWidget,
QListWidgetItem, QMainWindow, QProgressBar, QPushButton,
QSizePolicy, QSlider, QSpinBox, QStatusBar,
QWidget)
from . import KCC_rc
class Ui_mainWindow(object):
def setupUi(self, mainWindow):
mainWindow.setObjectName("mainWindow")
if not mainWindow.objectName():
mainWindow.setObjectName(u"mainWindow")
mainWindow.resize(450, 400)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/Icon/icons/comic2ebook.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
icon = QIcon()
icon.addFile(u":/Icon/icons/comic2ebook.png", QSize(), QIcon.Normal, QIcon.Off)
mainWindow.setWindowIcon(icon)
self.centralWidget = QtWidgets.QWidget(mainWindow)
self.centralWidget.setObjectName("centralWidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralWidget)
self.centralWidget = QWidget(mainWindow)
self.centralWidget.setObjectName(u"centralWidget")
self.gridLayout = QGridLayout(self.centralWidget)
self.gridLayout.setObjectName(u"gridLayout")
self.gridLayout.setContentsMargins(-1, -1, -1, 5)
self.gridLayout.setObjectName("gridLayout")
self.progressBar = QtWidgets.QProgressBar(self.centralWidget)
self.progressBar.setMinimumSize(QtCore.QSize(0, 30))
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.progressBar.setFont(font)
self.progressBar.setVisible(False)
self.progressBar.setAlignment(QtCore.Qt.AlignJustify|QtCore.Qt.AlignVCenter)
self.progressBar.setObjectName("progressBar")
self.gridLayout.addWidget(self.progressBar, 1, 0, 1, 2)
self.jobList = QtWidgets.QListWidget(self.centralWidget)
self.jobList.setStyleSheet("QListWidget#jobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;color:rgb(0,0,0);}")
self.jobList.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
self.jobList.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
self.jobList.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
self.jobList.setObjectName("jobList")
self.gridLayout.addWidget(self.jobList, 2, 0, 1, 2)
self.customWidget = QtWidgets.QWidget(self.centralWidget)
self.customWidget.setVisible(False)
self.customWidget.setObjectName("customWidget")
self.gridLayout_3 = QtWidgets.QGridLayout(self.customWidget)
self.gridLayout_3.setContentsMargins(0, 0, 0, 0)
self.gridLayout_3.setObjectName("gridLayout_3")
self.hLabel = QtWidgets.QLabel(self.customWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.hLabel.sizePolicy().hasHeightForWidth())
self.hLabel.setSizePolicy(sizePolicy)
self.hLabel.setObjectName("hLabel")
self.gridLayout_3.addWidget(self.hLabel, 0, 2, 1, 1)
self.widthBox = QtWidgets.QSpinBox(self.customWidget)
self.widthBox.setMaximum(2160)
self.widthBox.setObjectName("widthBox")
self.gridLayout_3.addWidget(self.widthBox, 0, 1, 1, 1)
self.wLabel = QtWidgets.QLabel(self.customWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.wLabel.sizePolicy().hasHeightForWidth())
self.wLabel.setSizePolicy(sizePolicy)
self.wLabel.setObjectName("wLabel")
self.gridLayout_3.addWidget(self.wLabel, 0, 0, 1, 1)
self.heightBox = QtWidgets.QSpinBox(self.customWidget)
self.heightBox.setMaximum(3840)
self.heightBox.setObjectName("heightBox")
self.gridLayout_3.addWidget(self.heightBox, 0, 3, 1, 1)
self.gridLayout.addWidget(self.customWidget, 6, 0, 1, 2)
self.optionWidget = QtWidgets.QWidget(self.centralWidget)
self.optionWidget.setObjectName("optionWidget")
self.gridLayout_2 = QtWidgets.QGridLayout(self.optionWidget)
self.optionWidget = QWidget(self.centralWidget)
self.optionWidget.setObjectName(u"optionWidget")
self.gridLayout_2 = QGridLayout(self.optionWidget)
self.gridLayout_2.setObjectName(u"gridLayout_2")
self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
self.gridLayout_2.setObjectName("gridLayout_2")
self.mangaBox = QtWidgets.QCheckBox(self.optionWidget)
self.mangaBox.setObjectName("mangaBox")
self.gridLayout_2.addWidget(self.mangaBox, 0, 0, 1, 1)
self.rotateBox = QtWidgets.QCheckBox(self.optionWidget)
self.rotateBox.setTristate(True)
self.rotateBox.setObjectName("rotateBox")
self.gridLayout_2.addWidget(self.rotateBox, 0, 1, 1, 1)
self.qualityBox = QtWidgets.QCheckBox(self.optionWidget)
self.qualityBox = QCheckBox(self.optionWidget)
self.qualityBox.setObjectName(u"qualityBox")
self.qualityBox.setTristate(True)
self.qualityBox.setObjectName("qualityBox")
self.gridLayout_2.addWidget(self.qualityBox, 0, 2, 1, 1)
self.webtoonBox = QtWidgets.QCheckBox(self.optionWidget)
self.webtoonBox.setObjectName("webtoonBox")
self.gridLayout_2.addWidget(self.webtoonBox, 1, 0, 1, 1)
self.upscaleBox = QtWidgets.QCheckBox(self.optionWidget)
self.upscaleBox.setTristate(True)
self.upscaleBox.setObjectName("upscaleBox")
self.gridLayout_2.addWidget(self.upscaleBox, 1, 1, 1, 1)
self.gammaBox = QtWidgets.QCheckBox(self.optionWidget)
self.gammaBox.setObjectName("gammaBox")
self.deleteBox = QCheckBox(self.optionWidget)
self.deleteBox.setObjectName(u"deleteBox")
self.gridLayout_2.addWidget(self.deleteBox, 4, 1, 1, 1)
self.maximizeStrips = QCheckBox(self.optionWidget)
self.maximizeStrips.setObjectName(u"maximizeStrips")
self.gridLayout_2.addWidget(self.maximizeStrips, 3, 1, 1, 1)
self.gammaBox = QCheckBox(self.optionWidget)
self.gammaBox.setObjectName(u"gammaBox")
self.gridLayout_2.addWidget(self.gammaBox, 1, 2, 1, 1)
self.borderBox = QtWidgets.QCheckBox(self.optionWidget)
self.borderBox = QCheckBox(self.optionWidget)
self.borderBox.setObjectName(u"borderBox")
self.borderBox.setTristate(True)
self.borderBox.setObjectName("borderBox")
self.gridLayout_2.addWidget(self.borderBox, 2, 0, 1, 1)
self.outputSplit = QtWidgets.QCheckBox(self.optionWidget)
self.outputSplit.setObjectName("outputSplit")
self.webtoonBox = QCheckBox(self.optionWidget)
self.webtoonBox.setObjectName(u"webtoonBox")
self.gridLayout_2.addWidget(self.webtoonBox, 1, 0, 1, 1)
self.upscaleBox = QCheckBox(self.optionWidget)
self.upscaleBox.setObjectName(u"upscaleBox")
self.upscaleBox.setTristate(True)
self.gridLayout_2.addWidget(self.upscaleBox, 1, 1, 1, 1)
self.mangaBox = QCheckBox(self.optionWidget)
self.mangaBox.setObjectName(u"mangaBox")
self.gridLayout_2.addWidget(self.mangaBox, 0, 0, 1, 1)
self.rotateBox = QCheckBox(self.optionWidget)
self.rotateBox.setObjectName(u"rotateBox")
self.rotateBox.setTristate(True)
self.gridLayout_2.addWidget(self.rotateBox, 0, 1, 1, 1)
self.croppingBox = QCheckBox(self.optionWidget)
self.croppingBox.setObjectName(u"croppingBox")
self.croppingBox.setTristate(True)
self.gridLayout_2.addWidget(self.croppingBox, 3, 2, 1, 1)
self.outputSplit = QCheckBox(self.optionWidget)
self.outputSplit.setObjectName(u"outputSplit")
self.gridLayout_2.addWidget(self.outputSplit, 2, 1, 1, 1)
self.colorBox = QtWidgets.QCheckBox(self.optionWidget)
self.colorBox.setObjectName("colorBox")
self.mozJpegBox = QCheckBox(self.optionWidget)
self.mozJpegBox.setObjectName(u"mozJpegBox")
self.mozJpegBox.setTristate(True)
self.gridLayout_2.addWidget(self.mozJpegBox, 3, 0, 1, 1)
self.colorBox = QCheckBox(self.optionWidget)
self.colorBox.setObjectName(u"colorBox")
self.gridLayout_2.addWidget(self.colorBox, 2, 2, 1, 1)
self.gridLayout.addWidget(self.optionWidget, 4, 0, 1, 2)
self.gammaWidget = QtWidgets.QWidget(self.centralWidget)
self.disableProcessingBox = QCheckBox(self.optionWidget)
self.disableProcessingBox.setObjectName(u"disableProcessingBox")
self.gridLayout_2.addWidget(self.disableProcessingBox, 4, 2, 1, 1)
self.dedupeCoverBox = QCheckBox(self.optionWidget)
self.dedupeCoverBox.setObjectName(u"dedupeCoverBox")
self.gridLayout_2.addWidget(self.dedupeCoverBox, 4, 0, 1, 1)
self.gridLayout.addWidget(self.optionWidget, 5, 0, 1, 2)
self.gammaWidget = QWidget(self.centralWidget)
self.gammaWidget.setObjectName(u"gammaWidget")
self.gammaWidget.setVisible(False)
self.gammaWidget.setObjectName("gammaWidget")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.gammaWidget)
self.horizontalLayout_2 = QHBoxLayout(self.gammaWidget)
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.gammaLabel = QtWidgets.QLabel(self.gammaWidget)
self.gammaLabel.setObjectName("gammaLabel")
self.gammaLabel = QLabel(self.gammaWidget)
self.gammaLabel.setObjectName(u"gammaLabel")
self.horizontalLayout_2.addWidget(self.gammaLabel)
self.gammaSlider = QtWidgets.QSlider(self.gammaWidget)
self.gammaSlider = QSlider(self.gammaWidget)
self.gammaSlider.setObjectName(u"gammaSlider")
self.gammaSlider.setMaximum(250)
self.gammaSlider.setSingleStep(5)
self.gammaSlider.setOrientation(QtCore.Qt.Horizontal)
self.gammaSlider.setObjectName("gammaSlider")
self.gammaSlider.setOrientation(Qt.Horizontal)
self.horizontalLayout_2.addWidget(self.gammaSlider)
self.gridLayout.addWidget(self.gammaWidget, 5, 0, 1, 2)
self.toolWidget = QtWidgets.QWidget(self.centralWidget)
self.toolWidget.setObjectName("toolWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.toolWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.editorButton = QtWidgets.QPushButton(self.toolWidget)
self.editorButton.setMinimumSize(QtCore.QSize(0, 30))
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(":/Other/icons/editor.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.editorButton.setIcon(icon1)
self.editorButton.setObjectName("editorButton")
self.horizontalLayout.addWidget(self.editorButton)
self.wikiButton = QtWidgets.QPushButton(self.toolWidget)
self.wikiButton.setMinimumSize(QtCore.QSize(0, 30))
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(":/Other/icons/wiki.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.wikiButton.setIcon(icon2)
self.wikiButton.setObjectName("wikiButton")
self.horizontalLayout.addWidget(self.wikiButton)
self.gridLayout.addWidget(self.toolWidget, 0, 0, 1, 2)
self.buttonWidget = QtWidgets.QWidget(self.centralWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
self.gridLayout.addWidget(self.gammaWidget, 6, 0, 1, 2)
self.croppingWidget = QWidget(self.centralWidget)
self.croppingWidget.setObjectName(u"croppingWidget")
self.croppingWidget.setVisible(False)
self.horizontalLayout_3 = QHBoxLayout(self.croppingWidget)
self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0)
self.croppingPowerLabel = QLabel(self.croppingWidget)
self.croppingPowerLabel.setObjectName(u"croppingPowerLabel")
self.horizontalLayout_3.addWidget(self.croppingPowerLabel)
self.croppingPowerSlider = QSlider(self.croppingWidget)
self.croppingPowerSlider.setObjectName(u"croppingPowerSlider")
self.croppingPowerSlider.setMaximum(200)
self.croppingPowerSlider.setSingleStep(1)
self.croppingPowerSlider.setOrientation(Qt.Horizontal)
self.horizontalLayout_3.addWidget(self.croppingPowerSlider)
self.gridLayout.addWidget(self.croppingWidget, 8, 0, 1, 2)
self.buttonWidget = QWidget(self.centralWidget)
self.buttonWidget.setObjectName(u"buttonWidget")
sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.buttonWidget.sizePolicy().hasHeightForWidth())
self.buttonWidget.setSizePolicy(sizePolicy)
self.buttonWidget.setObjectName("buttonWidget")
self.gridLayout_4 = QtWidgets.QGridLayout(self.buttonWidget)
self.gridLayout_4 = QGridLayout(self.buttonWidget)
self.gridLayout_4.setObjectName(u"gridLayout_4")
self.gridLayout_4.setContentsMargins(0, 0, 0, 0)
self.gridLayout_4.setObjectName("gridLayout_4")
self.directoryButton = QtWidgets.QPushButton(self.buttonWidget)
self.directoryButton.setMinimumSize(QtCore.QSize(0, 30))
icon3 = QtGui.QIcon()
icon3.addPixmap(QtGui.QPixmap(":/Other/icons/folder_new.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.directoryButton.setIcon(icon3)
self.directoryButton.setObjectName("directoryButton")
self.directoryButton = QPushButton(self.buttonWidget)
self.directoryButton.setObjectName(u"directoryButton")
self.directoryButton.setMinimumSize(QSize(0, 30))
icon1 = QIcon()
icon1.addFile(u":/Other/icons/folder_new.png", QSize(), QIcon.Normal, QIcon.Off)
self.directoryButton.setIcon(icon1)
self.gridLayout_4.addWidget(self.directoryButton, 0, 0, 1, 1)
self.fileButton = QtWidgets.QPushButton(self.buttonWidget)
self.fileButton.setMinimumSize(QtCore.QSize(0, 30))
icon4 = QtGui.QIcon()
icon4.addPixmap(QtGui.QPixmap(":/Other/icons/document_new.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.fileButton.setIcon(icon4)
self.fileButton.setObjectName("fileButton")
self.fileButton = QPushButton(self.buttonWidget)
self.fileButton.setObjectName(u"fileButton")
self.fileButton.setMinimumSize(QSize(0, 30))
icon2 = QIcon()
icon2.addFile(u":/Other/icons/document_new.png", QSize(), QIcon.Normal, QIcon.Off)
self.fileButton.setIcon(icon2)
self.gridLayout_4.addWidget(self.fileButton, 0, 3, 1, 1)
self.deviceBox = QtWidgets.QComboBox(self.buttonWidget)
self.deviceBox.setMinimumSize(QtCore.QSize(0, 28))
self.deviceBox.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToMinimumContentsLength)
self.deviceBox.setObjectName("deviceBox")
self.deviceBox = QComboBox(self.buttonWidget)
self.deviceBox.setObjectName(u"deviceBox")
self.deviceBox.setMinimumSize(QSize(0, 28))
self.gridLayout_4.addWidget(self.deviceBox, 1, 0, 1, 1)
self.formatBox = QtWidgets.QComboBox(self.buttonWidget)
self.formatBox.setMinimumSize(QtCore.QSize(0, 28))
self.formatBox.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToMinimumContentsLength)
self.formatBox.setObjectName("formatBox")
self.formatBox = QComboBox(self.buttonWidget)
self.formatBox.setObjectName(u"formatBox")
self.formatBox.setMinimumSize(QSize(0, 28))
self.gridLayout_4.addWidget(self.formatBox, 1, 3, 1, 1)
self.convertButton = QtWidgets.QPushButton(self.buttonWidget)
self.convertButton.setMinimumSize(QtCore.QSize(0, 30))
font = QtGui.QFont()
self.convertButton = QPushButton(self.buttonWidget)
self.convertButton.setObjectName(u"convertButton")
self.convertButton.setMinimumSize(QSize(0, 30))
font = QFont()
font.setBold(True)
font.setWeight(75)
self.convertButton.setFont(font)
icon5 = QtGui.QIcon()
icon5.addPixmap(QtGui.QPixmap(":/Other/icons/convert.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.convertButton.setIcon(icon5)
self.convertButton.setObjectName("convertButton")
icon3 = QIcon()
icon3.addFile(u":/Other/icons/convert.png", QSize(), QIcon.Normal, QIcon.Off)
self.convertButton.setIcon(icon3)
self.gridLayout_4.addWidget(self.convertButton, 1, 2, 1, 1)
self.clearButton = QtWidgets.QPushButton(self.buttonWidget)
self.clearButton.setMinimumSize(QtCore.QSize(0, 30))
icon6 = QtGui.QIcon()
icon6.addPixmap(QtGui.QPixmap(":/Other/icons/clear.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.clearButton.setIcon(icon6)
self.clearButton.setObjectName("clearButton")
self.clearButton = QPushButton(self.buttonWidget)
self.clearButton.setObjectName(u"clearButton")
self.clearButton.setMinimumSize(QSize(0, 30))
icon4 = QIcon()
icon4.addFile(u":/Other/icons/clear.png", QSize(), QIcon.Normal, QIcon.Off)
self.clearButton.setIcon(icon4)
self.gridLayout_4.addWidget(self.clearButton, 0, 2, 1, 1)
self.directoryButton.raise_()
self.clearButton.raise_()
self.fileButton.raise_()
self.deviceBox.raise_()
self.convertButton.raise_()
self.formatBox.raise_()
self.gridLayout.addWidget(self.buttonWidget, 3, 0, 1, 2)
self.toolWidget = QWidget(self.centralWidget)
self.toolWidget.setObjectName(u"toolWidget")
self.horizontalLayout = QHBoxLayout(self.toolWidget)
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.editorButton = QPushButton(self.toolWidget)
self.editorButton.setObjectName(u"editorButton")
self.editorButton.setMinimumSize(QSize(0, 30))
icon5 = QIcon()
icon5.addFile(u":/Other/icons/editor.png", QSize(), QIcon.Normal, QIcon.Off)
self.editorButton.setIcon(icon5)
self.horizontalLayout.addWidget(self.editorButton)
self.wikiButton = QPushButton(self.toolWidget)
self.wikiButton.setObjectName(u"wikiButton")
self.wikiButton.setMinimumSize(QSize(0, 30))
icon6 = QIcon()
icon6.addFile(u":/Other/icons/wiki.png", QSize(), QIcon.Normal, QIcon.Off)
self.wikiButton.setIcon(icon6)
self.horizontalLayout.addWidget(self.wikiButton)
self.gridLayout.addWidget(self.toolWidget, 0, 0, 1, 2)
self.jobList = QListWidget(self.centralWidget)
self.jobList.setObjectName(u"jobList")
self.jobList.setStyleSheet(u"QListWidget#jobList {background:#ffffff;background-image:url(:/Other/icons/list_background.png);background-position:center center;background-repeat:no-repeat;color:rgb(0,0,0);}")
self.jobList.setSelectionMode(QAbstractItemView.NoSelection)
self.jobList.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
self.jobList.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
self.gridLayout.addWidget(self.jobList, 2, 0, 1, 2)
self.progressBar = QProgressBar(self.centralWidget)
self.progressBar.setObjectName(u"progressBar")
self.progressBar.setMinimumSize(QSize(0, 30))
self.progressBar.setFont(font)
self.progressBar.setVisible(False)
self.progressBar.setAlignment(Qt.AlignJustify|Qt.AlignVCenter)
self.gridLayout.addWidget(self.progressBar, 1, 0, 1, 2)
self.customWidget = QWidget(self.centralWidget)
self.customWidget.setObjectName(u"customWidget")
self.customWidget.setVisible(False)
self.gridLayout_3 = QGridLayout(self.customWidget)
self.gridLayout_3.setObjectName(u"gridLayout_3")
self.gridLayout_3.setContentsMargins(0, 0, 0, 0)
self.hLabel = QLabel(self.customWidget)
self.hLabel.setObjectName(u"hLabel")
sizePolicy1 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
sizePolicy1.setHorizontalStretch(0)
sizePolicy1.setVerticalStretch(0)
sizePolicy1.setHeightForWidth(self.hLabel.sizePolicy().hasHeightForWidth())
self.hLabel.setSizePolicy(sizePolicy1)
self.gridLayout_3.addWidget(self.hLabel, 0, 2, 1, 1)
self.widthBox = QSpinBox(self.customWidget)
self.widthBox.setObjectName(u"widthBox")
self.widthBox.setMaximum(2160)
self.gridLayout_3.addWidget(self.widthBox, 0, 1, 1, 1)
self.wLabel = QLabel(self.customWidget)
self.wLabel.setObjectName(u"wLabel")
sizePolicy1.setHeightForWidth(self.wLabel.sizePolicy().hasHeightForWidth())
self.wLabel.setSizePolicy(sizePolicy1)
self.gridLayout_3.addWidget(self.wLabel, 0, 0, 1, 1)
self.heightBox = QSpinBox(self.customWidget)
self.heightBox.setObjectName(u"heightBox")
self.heightBox.setMaximum(3840)
self.gridLayout_3.addWidget(self.heightBox, 0, 3, 1, 1)
self.gridLayout.addWidget(self.customWidget, 7, 0, 1, 2)
mainWindow.setCentralWidget(self.centralWidget)
self.statusBar = QtWidgets.QStatusBar(mainWindow)
self.statusBar = QStatusBar(mainWindow)
self.statusBar.setObjectName(u"statusBar")
self.statusBar.setSizeGripEnabled(False)
self.statusBar.setObjectName("statusBar")
mainWindow.setStatusBar(self.statusBar)
QWidget.setTabOrder(self.convertButton, self.clearButton)
QWidget.setTabOrder(self.clearButton, self.directoryButton)
QWidget.setTabOrder(self.directoryButton, self.fileButton)
QWidget.setTabOrder(self.fileButton, self.deviceBox)
QWidget.setTabOrder(self.deviceBox, self.formatBox)
QWidget.setTabOrder(self.formatBox, self.mangaBox)
QWidget.setTabOrder(self.mangaBox, self.rotateBox)
QWidget.setTabOrder(self.rotateBox, self.qualityBox)
QWidget.setTabOrder(self.qualityBox, self.webtoonBox)
QWidget.setTabOrder(self.webtoonBox, self.upscaleBox)
QWidget.setTabOrder(self.upscaleBox, self.gammaBox)
QWidget.setTabOrder(self.gammaBox, self.borderBox)
QWidget.setTabOrder(self.borderBox, self.outputSplit)
QWidget.setTabOrder(self.outputSplit, self.colorBox)
QWidget.setTabOrder(self.colorBox, self.croppingBox)
QWidget.setTabOrder(self.croppingBox, self.mozJpegBox)
QWidget.setTabOrder(self.mozJpegBox, self.maximizeStrips)
QWidget.setTabOrder(self.maximizeStrips, self.deleteBox)
QWidget.setTabOrder(self.deleteBox, self.disableProcessingBox)
QWidget.setTabOrder(self.disableProcessingBox, self.editorButton)
QWidget.setTabOrder(self.editorButton, self.wikiButton)
QWidget.setTabOrder(self.wikiButton, self.jobList)
QWidget.setTabOrder(self.jobList, self.gammaSlider)
QWidget.setTabOrder(self.gammaSlider, self.widthBox)
QWidget.setTabOrder(self.widthBox, self.heightBox)
QWidget.setTabOrder(self.heightBox, self.croppingPowerSlider)
self.retranslateUi(mainWindow)
QtCore.QMetaObject.connectSlotsByName(mainWindow)
mainWindow.setTabOrder(self.convertButton, self.clearButton)
mainWindow.setTabOrder(self.clearButton, self.directoryButton)
mainWindow.setTabOrder(self.directoryButton, self.fileButton)
mainWindow.setTabOrder(self.fileButton, self.deviceBox)
mainWindow.setTabOrder(self.deviceBox, self.formatBox)
mainWindow.setTabOrder(self.formatBox, self.mangaBox)
mainWindow.setTabOrder(self.mangaBox, self.rotateBox)
mainWindow.setTabOrder(self.rotateBox, self.qualityBox)
mainWindow.setTabOrder(self.qualityBox, self.webtoonBox)
mainWindow.setTabOrder(self.webtoonBox, self.upscaleBox)
mainWindow.setTabOrder(self.upscaleBox, self.gammaBox)
mainWindow.setTabOrder(self.gammaBox, self.borderBox)
mainWindow.setTabOrder(self.borderBox, self.outputSplit)
mainWindow.setTabOrder(self.outputSplit, self.colorBox)
mainWindow.setTabOrder(self.colorBox, self.editorButton)
mainWindow.setTabOrder(self.editorButton, self.wikiButton)
mainWindow.setTabOrder(self.wikiButton, self.jobList)
mainWindow.setTabOrder(self.jobList, self.gammaSlider)
mainWindow.setTabOrder(self.gammaSlider, self.widthBox)
mainWindow.setTabOrder(self.widthBox, self.heightBox)
QMetaObject.connectSlotsByName(mainWindow)
# setupUi
def retranslateUi(self, mainWindow):
_translate = QtCore.QCoreApplication.translate
mainWindow.setWindowTitle(_translate("mainWindow", "Kindle Comic Converter"))
self.hLabel.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
self.hLabel.setText(_translate("mainWindow", "Custom height:"))
self.widthBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
self.wLabel.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
self.wLabel.setText(_translate("mainWindow", "Custom width:"))
self.heightBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Resolution of target device.</p></body></html>"))
self.mangaBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Enable right-to-left reading.</p></body></html>"))
self.mangaBox.setText(_translate("mainWindow", "Manga mode"))
self.rotateBox.setToolTip(_translate("mainWindow", "<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Split<br/></span>Double page spreads will be cut into two separate pages.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Rotate and split<br/></span>Double page spreads will be displayed twice. First rotated and then split. </p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Rotate<br/></span>Double page spreads will be rotated.</p></body></html>"))
self.rotateBox.setText(_translate("mainWindow", "Spread splitter"))
self.qualityBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - 4 panels<br/></span>Zoom each corner separately.</p><p style=\'white-space:pre\'><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - 2 panels<br/></span>Zoom only the top and bottom of the page.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - 4 high quality panels<br/></span>Zoom each corner separately. Try to increase the quality of magnification. Check wiki for more details.</p></body></html>"))
self.qualityBox.setText(_translate("mainWindow", "Panel View 4/2/HQ"))
self.webtoonBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Enable special parsing mode for Korean Webtoons.</p></body></html>"))
self.webtoonBox.setText(_translate("mainWindow", "Webtoon mode"))
self.upscaleBox.setToolTip(_translate("mainWindow", "<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>"))
self.upscaleBox.setText(_translate("mainWindow", "Stretch/Upscale"))
self.gammaBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Disable automatic gamma correction.</p></body></html>"))
self.gammaBox.setText(_translate("mainWindow", "Custom gamma"))
self.borderBox.setToolTip(_translate("mainWindow", "<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>"))
self.borderBox.setText(_translate("mainWindow", "W/B margins"))
self.outputSplit.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Automatic mode<br/></span>Output will be splitted automatically.</p><p style=\'white-space:pre\'><span style=\" font-weight:600; text-decoration: underline;\">Checked - Volume mode<br/></span>Every subdirectory will be considered as separate volume.</p></body></html>"))
self.outputSplit.setText(_translate("mainWindow", "Output split"))
self.colorBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Disable conversion to grayscale.</p></body></html>"))
self.colorBox.setText(_translate("mainWindow", "Color mode"))
self.gammaLabel.setText(_translate("mainWindow", "Gamma: Auto"))
self.editorButton.setText(_translate("mainWindow", "Editor"))
self.wikiButton.setText(_translate("mainWindow", "Wiki"))
self.directoryButton.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Add directory containing JPG, PNG or GIF files to queue.<br/><span style=\" font-weight:600;\">CBR, CBZ and CB7 files inside will not be processed!</span></p></body></html>"))
self.directoryButton.setText(_translate("mainWindow", "Add directory"))
self.fileButton.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html>"))
self.fileButton.setText(_translate("mainWindow", "Add file"))
self.deviceBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Target device.</p></body></html>"))
self.formatBox.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Output format.</p></body></html>"))
self.convertButton.setToolTip(_translate("mainWindow", "<html><head/><body><p style=\'white-space:pre\'>Shift+Click to select the output directory.</p></body></html>"))
self.convertButton.setText(_translate("mainWindow", "Convert"))
self.clearButton.setText(_translate("mainWindow", "Clear list"))
mainWindow.setWindowTitle(QCoreApplication.translate("mainWindow", u"Kindle Comic Converter", None))
#if QT_CONFIG(tooltip)
self.qualityBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - 4 panels<br/></span>Zoom each corner separately.</p><p style='white-space:pre'><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - 2 panels<br/></span>Zoom only the top and bottom of the page.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - 4 high-quality panels<br/></span>Zoom each corner separately. Try to increase the quality of magnification. Check wiki for more details.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.qualityBox.setText(QCoreApplication.translate("mainWindow", u"Panel View 4/2/HQ", None))
#if QT_CONFIG(tooltip)
self.deleteBox.setToolTip(QCoreApplication.translate("mainWindow", u"Delete input file(s) or directory. It's not recoverable!", None))
#endif // QT_CONFIG(tooltip)
self.deleteBox.setText(QCoreApplication.translate("mainWindow", u"Delete input", None))
#if QT_CONFIG(tooltip)
self.maximizeStrips.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - 1x4<br/></span>Keep format 1x4 panels strips.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - 2x2<br/></span>Turn 1x4 strips to 2x2 to maximize screen usage.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.maximizeStrips.setText(QCoreApplication.translate("mainWindow", u"1x4 to 2x2 strips", None))
#if QT_CONFIG(tooltip)
self.gammaBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Disable automatic gamma correction.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.gammaBox.setText(QCoreApplication.translate("mainWindow", u"Custom gamma", None))
#if QT_CONFIG(tooltip)
self.borderBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Autodetection<br/></span>The 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))
#endif // QT_CONFIG(tooltip)
self.borderBox.setText(QCoreApplication.translate("mainWindow", u"W/B margins", None))
#if QT_CONFIG(tooltip)
self.webtoonBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Enable special parsing mode for Korean Webtoons.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.webtoonBox.setText(QCoreApplication.translate("mainWindow", u"Webtoon mode", None))
#if QT_CONFIG(tooltip)
self.upscaleBox.setToolTip(QCoreApplication.translate("mainWindow", u"<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))
#endif // QT_CONFIG(tooltip)
self.upscaleBox.setText(QCoreApplication.translate("mainWindow", u"Stretch/Upscale", None))
#if QT_CONFIG(tooltip)
self.mangaBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Enable right-to-left reading.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.mangaBox.setText(QCoreApplication.translate("mainWindow", u"Manga mode", None))
#if QT_CONFIG(tooltip)
self.rotateBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Split<br/></span>Double page spreads will be cut into two separate pages.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Rotate and split<br/></span>Double page spreads will be displayed twice. First rotated and then split. </p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Rotate<br/></span>Double page spreads will be rotated.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.rotateBox.setText(QCoreApplication.translate("mainWindow", u"Spread splitter", None))
#if QT_CONFIG(tooltip)
self.croppingBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Disabled</span></p><p>Disabled</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Margins<br/></span>Margins</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Margins + page numbers<br/></span>Margins +page numbers</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.croppingBox.setText(QCoreApplication.translate("mainWindow", u"Cropping mode", None))
#if QT_CONFIG(tooltip)
self.outputSplit.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Automatic mode<br/></span>The output will be split automatically.</p><p style='white-space:pre'><span style=\" font-weight:600; text-decoration: underline;\">Checked - Volume mode<br/></span>Every subdirectory will be considered as a separate volume.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.outputSplit.setText(QCoreApplication.translate("mainWindow", u"Output split", None))
#if QT_CONFIG(tooltip)
self.mozJpegBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - JPEG<br/></span>Use JPEG files</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - force PNG<br/></span>Create PNG files instead JPEG</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - mozJpeg<br/></span>10-20% smaller JPEG file, with the same image quality, but processing time multiplied by 2</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.mozJpegBox.setText(QCoreApplication.translate("mainWindow", u"JPEG/PNG/mozJpeg", None))
#if QT_CONFIG(tooltip)
self.colorBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Disable conversion to grayscale.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.colorBox.setText(QCoreApplication.translate("mainWindow", u"Color mode", None))
#if QT_CONFIG(tooltip)
self.disableProcessingBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><pre style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Do not process any image, ignore profile and processing options</pre></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.disableProcessingBox.setText(QCoreApplication.translate("mainWindow", u"Disable processing", None))
#if QT_CONFIG(tooltip)
self.dedupeCoverBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p>Don't duplicate the first page as the cover. Useful for 2 page spread alignment.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.dedupeCoverBox.setText(QCoreApplication.translate("mainWindow", u"De-dupe cover", None))
self.gammaLabel.setText(QCoreApplication.translate("mainWindow", u"Gamma: Auto", None))
self.croppingPowerLabel.setText(QCoreApplication.translate("mainWindow", u"Cropping power:", None))
#if QT_CONFIG(tooltip)
self.directoryButton.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Add directory containing JPG, PNG or GIF files to queue.<br/><span style=\" font-weight:600;\">CBR, CBZ and CB7 files inside will not be processed!</span></p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.directoryButton.setText(QCoreApplication.translate("mainWindow", u"Add directory", None))
#if QT_CONFIG(tooltip)
self.fileButton.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.fileButton.setText(QCoreApplication.translate("mainWindow", u"Add file", None))
#if QT_CONFIG(tooltip)
self.deviceBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Target device.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
#if QT_CONFIG(tooltip)
self.formatBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Output format.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
#if QT_CONFIG(tooltip)
self.convertButton.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Shift+Click to select the output directory.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.convertButton.setText(QCoreApplication.translate("mainWindow", u"Convert", None))
self.clearButton.setText(QCoreApplication.translate("mainWindow", u"Clear list", None))
#if QT_CONFIG(tooltip)
self.editorButton.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Shift+Click to edit directory.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.editorButton.setText(QCoreApplication.translate("mainWindow", u"Editor", None))
self.wikiButton.setText(QCoreApplication.translate("mainWindow", u"Wiki", None))
#if QT_CONFIG(tooltip)
self.hLabel.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Resolution of the target device.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.hLabel.setText(QCoreApplication.translate("mainWindow", u"Custom height:", None))
#if QT_CONFIG(tooltip)
self.widthBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Resolution of the target device.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
#if QT_CONFIG(tooltip)
self.wLabel.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Resolution of the target device.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
self.wLabel.setText(QCoreApplication.translate("mainWindow", u"Custom width:", None))
#if QT_CONFIG(tooltip)
self.heightBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Resolution of the target device.</p></body></html>", None))
#endif // QT_CONFIG(tooltip)
# retranslateUi
from . import KCC_rc

View File

@@ -1,124 +1,168 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'gui\MetaEditor.ui'
#
# Created by: PyQt5 UI code generator 5.6
#
# WARNING! All changes made in this file will be lost!
################################################################################
## Form generated from reading UI file 'MetaEditor.ui'
##
## Created by: Qt User Interface Compiler version 6.5.2
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PyQt5 import QtCore, QtGui, QtWidgets
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QDialog, QGridLayout, QHBoxLayout,
QLabel, QLineEdit, QPushButton, QSizePolicy,
QVBoxLayout, QWidget)
from . import KCC_rc
class Ui_editorDialog(object):
def setupUi(self, editorDialog):
editorDialog.setObjectName("editorDialog")
if not editorDialog.objectName():
editorDialog.setObjectName(u"editorDialog")
editorDialog.resize(400, 260)
editorDialog.setMinimumSize(QtCore.QSize(400, 260))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/Icon/icons/comic2ebook.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
editorDialog.setMinimumSize(QSize(400, 260))
icon = QIcon()
icon.addFile(u":/Icon/icons/comic2ebook.png", QSize(), QIcon.Normal, QIcon.Off)
editorDialog.setWindowIcon(icon)
self.verticalLayout = QtWidgets.QVBoxLayout(editorDialog)
self.verticalLayout = QVBoxLayout(editorDialog)
self.verticalLayout.setObjectName(u"verticalLayout")
self.verticalLayout.setContentsMargins(-1, -1, -1, 5)
self.verticalLayout.setObjectName("verticalLayout")
self.editorWidget = QtWidgets.QWidget(editorDialog)
self.editorWidget.setObjectName("editorWidget")
self.gridLayout = QtWidgets.QGridLayout(self.editorWidget)
self.editorWidget = QWidget(editorDialog)
self.editorWidget.setObjectName(u"editorWidget")
self.gridLayout = QGridLayout(self.editorWidget)
self.gridLayout.setObjectName(u"gridLayout")
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
self.label_1 = QtWidgets.QLabel(self.editorWidget)
self.label_1.setObjectName("label_1")
self.label_1 = QLabel(self.editorWidget)
self.label_1.setObjectName(u"label_1")
self.gridLayout.addWidget(self.label_1, 0, 0, 1, 1)
self.seriesLine = QtWidgets.QLineEdit(self.editorWidget)
self.seriesLine.setObjectName("seriesLine")
self.seriesLine = QLineEdit(self.editorWidget)
self.seriesLine.setObjectName(u"seriesLine")
self.gridLayout.addWidget(self.seriesLine, 0, 1, 1, 1)
self.label_2 = QtWidgets.QLabel(self.editorWidget)
self.label_2.setObjectName("label_2")
self.label_2 = QLabel(self.editorWidget)
self.label_2.setObjectName(u"label_2")
self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1)
self.volumeLine = QtWidgets.QLineEdit(self.editorWidget)
self.volumeLine.setObjectName("volumeLine")
self.volumeLine = QLineEdit(self.editorWidget)
self.volumeLine.setObjectName(u"volumeLine")
self.gridLayout.addWidget(self.volumeLine, 1, 1, 1, 1)
self.label_3 = QtWidgets.QLabel(self.editorWidget)
self.label_3.setObjectName("label_3")
self.label_3 = QLabel(self.editorWidget)
self.label_3.setObjectName(u"label_3")
self.gridLayout.addWidget(self.label_3, 2, 0, 1, 1)
self.numberLine = QtWidgets.QLineEdit(self.editorWidget)
self.numberLine.setObjectName("numberLine")
self.numberLine = QLineEdit(self.editorWidget)
self.numberLine.setObjectName(u"numberLine")
self.gridLayout.addWidget(self.numberLine, 2, 1, 1, 1)
self.label_4 = QtWidgets.QLabel(self.editorWidget)
self.label_4.setObjectName("label_4")
self.label_4 = QLabel(self.editorWidget)
self.label_4.setObjectName(u"label_4")
self.gridLayout.addWidget(self.label_4, 3, 0, 1, 1)
self.writerLine = QtWidgets.QLineEdit(self.editorWidget)
self.writerLine.setObjectName("writerLine")
self.writerLine = QLineEdit(self.editorWidget)
self.writerLine.setObjectName(u"writerLine")
self.gridLayout.addWidget(self.writerLine, 3, 1, 1, 1)
self.label_5 = QtWidgets.QLabel(self.editorWidget)
self.label_5.setObjectName("label_5")
self.label_5 = QLabel(self.editorWidget)
self.label_5.setObjectName(u"label_5")
self.gridLayout.addWidget(self.label_5, 4, 0, 1, 1)
self.pencillerLine = QtWidgets.QLineEdit(self.editorWidget)
self.pencillerLine.setObjectName("pencillerLine")
self.pencillerLine = QLineEdit(self.editorWidget)
self.pencillerLine.setObjectName(u"pencillerLine")
self.gridLayout.addWidget(self.pencillerLine, 4, 1, 1, 1)
self.label_6 = QtWidgets.QLabel(self.editorWidget)
self.label_6.setObjectName("label_6")
self.label_6 = QLabel(self.editorWidget)
self.label_6.setObjectName(u"label_6")
self.gridLayout.addWidget(self.label_6, 5, 0, 1, 1)
self.inkerLine = QtWidgets.QLineEdit(self.editorWidget)
self.inkerLine.setObjectName("inkerLine")
self.inkerLine = QLineEdit(self.editorWidget)
self.inkerLine.setObjectName(u"inkerLine")
self.gridLayout.addWidget(self.inkerLine, 5, 1, 1, 1)
self.label_7 = QtWidgets.QLabel(self.editorWidget)
self.label_7.setObjectName("label_7")
self.label_7 = QLabel(self.editorWidget)
self.label_7.setObjectName(u"label_7")
self.gridLayout.addWidget(self.label_7, 6, 0, 1, 1)
self.coloristLine = QtWidgets.QLineEdit(self.editorWidget)
self.coloristLine.setObjectName("coloristLine")
self.coloristLine = QLineEdit(self.editorWidget)
self.coloristLine.setObjectName(u"coloristLine")
self.gridLayout.addWidget(self.coloristLine, 6, 1, 1, 1)
self.label_8 = QtWidgets.QLabel(self.editorWidget)
self.label_8.setOpenExternalLinks(True)
self.label_8.setObjectName("label_8")
self.gridLayout.addWidget(self.label_8, 7, 0, 1, 1)
self.muidLine = QtWidgets.QLineEdit(self.editorWidget)
self.muidLine.setObjectName("muidLine")
self.gridLayout.addWidget(self.muidLine, 7, 1, 1, 1)
self.verticalLayout.addWidget(self.editorWidget)
self.optionWidget = QtWidgets.QWidget(editorDialog)
self.optionWidget.setObjectName("optionWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.optionWidget)
self.optionWidget = QWidget(editorDialog)
self.optionWidget.setObjectName(u"optionWidget")
self.horizontalLayout = QHBoxLayout(self.optionWidget)
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.statusLabel = QtWidgets.QLabel(self.optionWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
self.statusLabel = QLabel(self.optionWidget)
self.statusLabel.setObjectName(u"statusLabel")
sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.statusLabel.sizePolicy().hasHeightForWidth())
self.statusLabel.setSizePolicy(sizePolicy)
self.statusLabel.setText("")
self.statusLabel.setObjectName("statusLabel")
self.horizontalLayout.addWidget(self.statusLabel)
self.okButton = QtWidgets.QPushButton(self.optionWidget)
self.okButton.setMinimumSize(QtCore.QSize(0, 30))
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(":/Other/icons/convert.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.okButton = QPushButton(self.optionWidget)
self.okButton.setObjectName(u"okButton")
self.okButton.setMinimumSize(QSize(0, 30))
icon1 = QIcon()
icon1.addFile(u":/Other/icons/convert.png", QSize(), QIcon.Normal, QIcon.Off)
self.okButton.setIcon(icon1)
self.okButton.setObjectName("okButton")
self.horizontalLayout.addWidget(self.okButton)
self.cancelButton = QtWidgets.QPushButton(self.optionWidget)
self.cancelButton.setMinimumSize(QtCore.QSize(0, 30))
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(":/Other/icons/clear.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.cancelButton = QPushButton(self.optionWidget)
self.cancelButton.setObjectName(u"cancelButton")
self.cancelButton.setMinimumSize(QSize(0, 30))
icon2 = QIcon()
icon2.addFile(u":/Other/icons/clear.png", QSize(), QIcon.Normal, QIcon.Off)
self.cancelButton.setIcon(icon2)
self.cancelButton.setObjectName("cancelButton")
self.horizontalLayout.addWidget(self.cancelButton)
self.verticalLayout.addWidget(self.optionWidget)
self.retranslateUi(editorDialog)
QtCore.QMetaObject.connectSlotsByName(editorDialog)
QMetaObject.connectSlotsByName(editorDialog)
# setupUi
def retranslateUi(self, editorDialog):
_translate = QtCore.QCoreApplication.translate
editorDialog.setWindowTitle(_translate("editorDialog", "Metadata editor"))
self.label_1.setText(_translate("editorDialog", "Series:"))
self.label_2.setText(_translate("editorDialog", "Volume:"))
self.label_3.setText(_translate("editorDialog", "Number:"))
self.label_4.setText(_translate("editorDialog", "Writer:"))
self.label_5.setText(_translate("editorDialog", "Penciller:"))
self.label_6.setText(_translate("editorDialog", "Inker:"))
self.label_7.setText(_translate("editorDialog", "Colorist:"))
self.label_8.setText(_translate("editorDialog", "<html><head/><body><p><a href=\"https://github.com/ciromattia/kcc/wiki/Manga-Cover-Database-support\"><span style=\" text-decoration: underline; color:#0000ff;\">MUid:</span></a></p></body></html>"))
self.okButton.setText(_translate("editorDialog", "Save"))
self.cancelButton.setText(_translate("editorDialog", "Cancel"))
editorDialog.setWindowTitle(QCoreApplication.translate("editorDialog", u"Metadata editor", None))
self.label_1.setText(QCoreApplication.translate("editorDialog", u"Series:", None))
self.label_2.setText(QCoreApplication.translate("editorDialog", u"Volume:", None))
self.label_3.setText(QCoreApplication.translate("editorDialog", u"Number:", None))
self.label_4.setText(QCoreApplication.translate("editorDialog", u"Writer:", None))
self.label_5.setText(QCoreApplication.translate("editorDialog", u"Penciller:", None))
self.label_6.setText(QCoreApplication.translate("editorDialog", u"Inker:", None))
self.label_7.setText(QCoreApplication.translate("editorDialog", u"Colorist:", None))
self.statusLabel.setText("")
self.okButton.setText(QCoreApplication.translate("editorDialog", u"Save", None))
self.cancelButton.setText(QCoreApplication.translate("editorDialog", u"Cancel", None))
# retranslateUi
from . import KCC_rc

View File

@@ -1,4 +1,4 @@
__version__ = '5.4'
__version__ = '6.2.1'
__license__ = 'ISC'
__copyright__ = '2012-2017, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
__copyright__ = '2012-2022, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>, darodi'
__docformat__ = 'restructuredtext en'

View File

@@ -1,90 +0,0 @@
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
#
# Permission to use, copy, modify, and/or distribute this software for
# any purpose with or without fee is hereby granted, provided that the
# above copyright notice and this permission notice appear in all
# copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
# OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
#
import os
from zipfile import is_zipfile, ZipFile
from subprocess import STDOUT, PIPE
from psutil import Popen
from shutil import move
from . import rarfile
from .shared import check7ZFile as is_7zfile
class CBxArchive:
def __init__(self, origFileName):
self.origFileName = origFileName
if is_zipfile(origFileName):
self.compressor = 'zip'
elif rarfile.is_rarfile(origFileName):
self.compressor = 'rar'
elif is_7zfile(origFileName):
self.compressor = '7z'
else:
self.compressor = None
def isCbxFile(self):
return self.compressor is not None
def extractCBZ(self, targetdir):
cbzFile = ZipFile(self.origFileName)
filelist = []
for f in cbzFile.namelist():
if f.startswith('__MACOSX') or f.endswith('.DS_Store') or f.endswith('humbs.db'):
pass
elif f.endswith('/'):
try:
os.makedirs(os.path.join(targetdir, f))
except Exception:
pass
else:
filelist.append(f)
cbzFile.extractall(targetdir, filelist)
def extractCBR(self, targetdir):
cbrFile = rarfile.RarFile(self.origFileName)
cbrFile.extractall(targetdir)
for root, _, filenames in os.walk(targetdir):
for filename in filenames:
if filename.startswith('__MACOSX') or filename.endswith('.DS_Store') or filename.endswith('humbs.db'):
os.remove(os.path.join(root, filename))
def extractCB7(self, targetdir):
output = Popen('7za x "' + self.origFileName + '" -xr!__MACOSX -xr!.DS_Store -xr!thumbs.db -xr!Thumbs.db -o"' +
targetdir + '"', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
extracted = False
for line in output.stdout:
if b"Everything is Ok" in line:
extracted = True
if not extracted:
raise OSError
def extract(self, targetdir):
if self.compressor == 'rar':
self.extractCBR(targetdir)
elif self.compressor == 'zip':
self.extractCBZ(targetdir)
elif self.compressor == '7z':
self.extractCB7(targetdir)
adir = os.listdir(targetdir)
if 'ComicInfo.xml' in adir:
adir.remove('ComicInfo.xml')
if len(adir) == 1 and os.path.isdir(os.path.join(targetdir, adir[0])):
for f in os.listdir(os.path.join(targetdir, adir[0])):
move(os.path.join(targetdir, adir[0], f), targetdir)
os.rmdir(os.path.join(targetdir, adir[0]))
return targetdir

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
#
# Permission to use, copy, modify, and/or distribute this software for
# any purpose with or without fee is hereby granted, provided that the
@@ -20,15 +20,11 @@
import os
import sys
from argparse import ArgumentParser
from shutil import rmtree, copytree, move
from optparse import OptionParser, OptionGroup
from multiprocessing import Pool
from PIL import Image, ImageChops, ImageOps, ImageDraw
from .shared import getImageFileName, walkLevel, walkSort, sanitizeTrace
try:
from PyQt5 import QtCore
except ImportError:
QtCore = None
def mergeDirectoryTick(output):
@@ -57,9 +53,8 @@ def mergeDirectory(work):
if len(images) > 0:
targetWidth = max(set(sizes), key=sizes.count)
for i in images:
if i[1] <= targetWidth:
targetHeight += i[2]
imagesValid.append(i[0])
targetHeight += i[2]
imagesValid.append(i[0])
# Silently drop directories that contain too many images
# 131072 = GIMP_MAX_IMAGE_SIZE / 4
if targetHeight > 131072:
@@ -68,8 +63,10 @@ def mergeDirectory(work):
y = 0
for i in imagesValid:
img = Image.open(i).convert('RGB')
if img.size[0] < targetWidth:
img = ImageOps.fit(img, (targetWidth, img.size[1]), method=Image.BICUBIC, centering=(0.5, 0.5))
if img.size[0] < targetWidth or img.size[0] > targetWidth:
widthPercent = (targetWidth / float(img.size[0]))
heightSize = int((float(img.size[1]) * float(widthPercent)))
img = ImageOps.fit(img, (targetWidth, heightSize), method=Image.BICUBIC, centering=(0.5, 0.5))
result.paste(img, (0, y))
y += img.size[1]
os.remove(i)
@@ -93,12 +90,15 @@ def splitImageTick(output):
splitWorkerPool.terminate()
# noinspection PyUnboundLocalVariable
def splitImage(work):
try:
path = work[0]
name = work[1]
opt = work[2]
filePath = os.path.join(path, name)
Image.warnings.simplefilter('error', Image.DecompressionBombWarning)
Image.MAX_IMAGE_PIXELS = 1000000000
imgOrg = Image.open(filePath).convert('RGB')
imgProcess = Image.open(filePath).convert('1')
widthImg, heightImg = imgOrg.size
@@ -112,11 +112,16 @@ def splitImage(work):
panelDetected = False
panels = []
while yWork < heightImg:
tmpImg = imgProcess.crop([0, yWork, widthImg, yWork + 4])
tmpImg = imgProcess.crop((4, yWork, widthImg-4, yWork + 4))
solid = detectSolid(tmpImg)
if not solid and not panelDetected:
panelDetected = True
panelY1 = yWork - 2
if heightImg - yWork <= 5:
if not solid and panelDetected:
panelY2 = heightImg
panelDetected = False
panels.append((panelY1, panelY2, panelY2 - panelY1))
if solid and panelDetected:
panelDetected = False
panelY2 = yWork + 6
@@ -140,9 +145,7 @@ def splitImage(work):
if opt.debug:
for panel in panelsProcessed:
# noinspection PyUnboundLocalVariable
draw.rectangle([(0, panel[0]), (widthImg, panel[1])], (0, 255, 0, 128), (0, 0, 255, 255))
# noinspection PyUnboundLocalVariable
draw.rectangle(((0, panel[0]), (widthImg, panel[1])), (0, 255, 0, 128), (0, 0, 255, 255))
debugImage = Image.alpha_composite(imgOrg.convert(mode='RGBA'), drawImg)
debugImage.save(os.path.join(path, os.path.splitext(name)[0] + '-debug.png'), 'PNG')
@@ -175,7 +178,7 @@ def splitImage(work):
if pageHeight > 15:
newPage = Image.new('RGB', (widthImg, pageHeight))
for panel in page:
panelImg = imgOrg.crop([0, panelsProcessed[panel][0], widthImg, panelsProcessed[panel][1]])
panelImg = imgOrg.crop((0, panelsProcessed[panel][0], widthImg, panelsProcessed[panel][1]))
newPage.paste(panelImg, (0, targetHeight))
targetHeight += panelsProcessed[panel][2]
newPage.save(os.path.join(path, os.path.splitext(name)[0] + '-' + str(pageNumber) + '.png'), 'PNG')
@@ -185,98 +188,101 @@ def splitImage(work):
return str(sys.exc_info()[1]), sanitizeTrace(sys.exc_info()[2])
def main(argv=None, qtGUI=None):
global options, GUI, splitWorkerPool, splitWorkerOutput, mergeWorkerPool, mergeWorkerOutput
parser = OptionParser(usage="Usage: kcc-c2p [options] comic_folder", add_help_option=False)
mainOptions = OptionGroup(parser, "MANDATORY")
otherOptions = OptionGroup(parser, "OTHER")
mainOptions.add_option("-y", "--height", type="int", dest="height", default=0,
help="Height of the target device screen")
mainOptions.add_option("-i", "--in-place", action="store_true", dest="inPlace", default=False,
help="Overwrite source directory")
mainOptions.add_option("-m", "--merge", action="store_true", dest="merge", default=False,
help="Combine every directory into a single image before splitting")
otherOptions.add_option("-d", "--debug", action="store_true", dest="debug", default=False,
help="Create debug file for every splitted image")
otherOptions.add_option("-h", "--help", action="help",
help="Show this help message and exit")
parser.add_option_group(mainOptions)
parser.add_option_group(otherOptions)
options, args = parser.parse_args(argv)
if qtGUI:
GUI = qtGUI
def main(argv=None, qtgui=None):
global args, GUI, splitWorkerPool, splitWorkerOutput, mergeWorkerPool, mergeWorkerOutput
parser = ArgumentParser(prog="kcc-c2p", usage="kcc-c2p [options] [input]", add_help=False)
mandatory_options = parser.add_argument_group("MANDATORY")
main_options = parser.add_argument_group("MAIN")
other_options = parser.add_argument_group("OTHER")
mandatory_options.add_argument("input", action="extend", nargs="*", default=None,
help="Full path to comic folder(s) to be processed. Separate multiple inputs"
" with spaces.")
main_options.add_argument("-y", "--height", type=int, dest="height", default=0,
help="Height of the target device screen")
main_options.add_argument("-i", "--in-place", action="store_true", dest="inPlace", default=False,
help="Overwrite source directory")
main_options.add_argument("-m", "--merge", action="store_true", dest="merge", default=False,
help="Combine every directory into a single image before splitting")
other_options.add_argument("-d", "--debug", action="store_true", dest="debug", default=False,
help="Create debug file for every split image")
other_options.add_argument("-h", "--help", action="help",
help="Show this help message and exit")
args = parser.parse_args(argv)
if qtgui:
GUI = qtgui
else:
GUI = None
if len(args) != 1:
if not argv or args.input == []:
parser.print_help()
return 1
if options.height > 0:
options.sourceDir = args[0]
options.targetDir = args[0] + "-Splitted"
if os.path.isdir(options.sourceDir):
rmtree(options.targetDir, True)
copytree(options.sourceDir, options.targetDir)
work = []
pagenumber = 1
splitWorkerOutput = []
splitWorkerPool = Pool(maxtasksperchild=10)
if options.merge:
print("Merging images...")
directoryNumer = 1
mergeWork = []
mergeWorkerOutput = []
mergeWorkerPool = Pool(maxtasksperchild=10)
mergeWork.append([options.targetDir])
for root, dirs, files in os.walk(options.targetDir, False):
dirs, files = walkSort(dirs, files)
for directory in dirs:
directoryNumer += 1
mergeWork.append([os.path.join(root, directory)])
if args.height > 0:
for sourceDir in args.input:
targetDir = sourceDir + "-Splitted"
if os.path.isdir(sourceDir):
rmtree(targetDir, True)
copytree(sourceDir, targetDir)
work = []
pagenumber = 1
splitWorkerOutput = []
splitWorkerPool = Pool(maxtasksperchild=10)
if args.merge:
print("Merging images...")
directoryNumer = 1
mergeWork = []
mergeWorkerOutput = []
mergeWorkerPool = Pool(maxtasksperchild=10)
mergeWork.append([targetDir])
for root, dirs, files in os.walk(targetDir, False):
dirs, files = walkSort(dirs, files)
for directory in dirs:
directoryNumer += 1
mergeWork.append([os.path.join(root, directory)])
if GUI:
GUI.progressBarTick.emit('Combining images')
GUI.progressBarTick.emit(str(directoryNumer))
for i in mergeWork:
mergeWorkerPool.apply_async(func=mergeDirectory, args=(i, ), callback=mergeDirectoryTick)
mergeWorkerPool.close()
mergeWorkerPool.join()
if GUI and not GUI.conversionAlive:
rmtree(targetDir, True)
raise UserWarning("Conversion interrupted.")
if len(mergeWorkerOutput) > 0:
rmtree(targetDir, True)
raise RuntimeError("One of workers crashed. Cause: " + mergeWorkerOutput[0][0],
mergeWorkerOutput[0][1])
print("Splitting images...")
for root, _, files in os.walk(targetDir, False):
for name in files:
if getImageFileName(name) is not None:
pagenumber += 1
work.append([root, name, args])
else:
os.remove(os.path.join(root, name))
if GUI:
GUI.progressBarTick.emit('Combining images')
GUI.progressBarTick.emit(str(directoryNumer))
for i in mergeWork:
mergeWorkerPool.apply_async(func=mergeDirectory, args=(i, ), callback=mergeDirectoryTick)
mergeWorkerPool.close()
mergeWorkerPool.join()
if GUI and not GUI.conversionAlive:
rmtree(options.targetDir, True)
raise UserWarning("Conversion interrupted.")
if len(mergeWorkerOutput) > 0:
rmtree(options.targetDir, True)
raise RuntimeError("One of workers crashed. Cause: " + mergeWorkerOutput[0][0],
mergeWorkerOutput[0][1])
print("Splitting images...")
for root, _, files in os.walk(options.targetDir, False):
for name in files:
if getImageFileName(name) is not None:
pagenumber += 1
work.append([root, name, options])
else:
os.remove(os.path.join(root, name))
if GUI:
GUI.progressBarTick.emit('Splitting images')
GUI.progressBarTick.emit(str(pagenumber))
GUI.progressBarTick.emit('tick')
if len(work) > 0:
for i in work:
splitWorkerPool.apply_async(func=splitImage, args=(i, ), callback=splitImageTick)
splitWorkerPool.close()
splitWorkerPool.join()
if GUI and not GUI.conversionAlive:
rmtree(options.targetDir, True)
raise UserWarning("Conversion interrupted.")
if len(splitWorkerOutput) > 0:
rmtree(options.targetDir, True)
raise RuntimeError("One of workers crashed. Cause: " + splitWorkerOutput[0][0],
splitWorkerOutput[0][1])
if options.inPlace:
rmtree(options.sourceDir)
move(options.targetDir, options.sourceDir)
GUI.progressBarTick.emit('Splitting images')
GUI.progressBarTick.emit(str(pagenumber))
GUI.progressBarTick.emit('tick')
if len(work) > 0:
for i in work:
splitWorkerPool.apply_async(func=splitImage, args=(i, ), callback=splitImageTick)
splitWorkerPool.close()
splitWorkerPool.join()
if GUI and not GUI.conversionAlive:
rmtree(targetDir, True)
raise UserWarning("Conversion interrupted.")
if len(splitWorkerOutput) > 0:
rmtree(targetDir, True)
raise RuntimeError("One of workers crashed. Cause: " + splitWorkerOutput[0][0],
splitWorkerOutput[0][1])
if args.inPlace:
rmtree(sourceDir)
move(targetDir, sourceDir)
else:
rmtree(targetDir, True)
raise UserWarning("Source directory is empty.")
else:
rmtree(options.targetDir, True)
raise UserWarning("Source directory is empty.")
else:
raise UserWarning("Provided path is not a directory.")
raise UserWarning("Provided input is not a directory.")
else:
raise UserWarning("Target height is not set.")

View File

@@ -0,0 +1,114 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
#
# Permission to use, copy, modify, and/or distribute this software for
# any purpose with or without fee is hereby granted, provided that the
# above copyright notice and this permission notice appear in all
# copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
# OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
#
from functools import cached_property
import os
import platform
import distro
from subprocess import STDOUT, PIPE, CalledProcessError
from xml.dom.minidom import parseString
from xml.parsers.expat import ExpatError
from .shared import subprocess_run
EXTRACTION_ERROR = 'Failed to extract archive. Try extracting file outside of KCC.'
class ComicArchive:
def __init__(self, filepath):
self.filepath = filepath
if not os.path.isfile(self.filepath):
raise OSError('File not found.')
@cached_property
def type(self):
extraction_commands = [
['7z', 'l', '-y', '-p1', self.filepath],
]
if distro.id() == 'fedora':
extraction_commands.append(
['unrar', 'l', '-y', '-p1', self.filepath],
)
for cmd in extraction_commands:
try:
process = subprocess_run(cmd, capture_output=True, check=True)
for line in process.stdout.splitlines():
if b'Type =' in line:
return line.rstrip().decode().split(' = ')[1].upper()
except FileNotFoundError:
pass
except CalledProcessError:
pass
raise OSError(EXTRACTION_ERROR)
def extract(self, targetdir):
if not os.path.isdir(targetdir):
raise OSError('Target directory doesn\'t exist.')
missing = []
extraction_commands = [
['tar', '--exclude', '__MACOSX', '--exclude', '.DS_Store', '--exclude', 'thumbs.db', '--exclude', 'Thumbs.db', '-xf', self.filepath, '-C', targetdir],
['7z', 'x', '-y', '-xr!__MACOSX', '-xr!.DS_Store', '-xr!thumbs.db', '-xr!Thumbs.db', '-o' + targetdir, self.filepath],
]
if platform.system() == 'Darwin':
extraction_commands.append(
['unar', self.filepath, '-f', '-o', targetdir]
)
if distro.id() == 'fedora':
extraction_commands.append(
['unrar', 'x', '-y', '-x__MACOSX', '-x.DS_Store', '-xthumbs.db', '-xThumbs.db', self.filepath, targetdir]
)
for cmd in extraction_commands:
try:
subprocess_run(cmd, capture_output=True, check=True)
return targetdir
except FileNotFoundError:
missing.append(cmd[0])
except CalledProcessError:
pass
if missing:
raise OSError(f'Extraction failed, install <a href="https://github.com/ciromattia/kcc#7-zip">specialized extraction software.</a> ')
else:
raise OSError(EXTRACTION_ERROR)
def addFile(self, sourcefile):
if self.type in ['RAR', 'RAR5']:
raise NotImplementedError
process = subprocess_run(['7z', 'a', '-y', self.filepath, sourcefile],
stdout=PIPE, stderr=STDOUT)
if process.returncode != 0:
raise OSError('Failed to add the file.')
def extractMetadata(self):
process = subprocess_run(['7z', 'x', '-y', '-so', self.filepath, 'ComicInfo.xml'],
stdout=PIPE, stderr=STDOUT)
if process.returncode != 0:
raise OSError(EXTRACTION_ERROR)
try:
return parseString(process.stdout)
except ExpatError:
return None

View File

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# Based on initial version of DualMetaFix. Copyright (C) 2013 Kevin Hendricks
# Changes for KCC Copyright (C) 2014-2017 Pawel Jastrzebski <pawelj@iosphe.re>
# Changes for KCC Copyright (C) 2014-2019 Pawel Jastrzebski <pawelj@iosphe.re>
#
# 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
@@ -24,6 +24,7 @@ import shutil
class DualMetaFixException(Exception):
pass
# palm database offset constants
number_of_pdb_records = 76
first_pdb_record = 78
@@ -142,14 +143,12 @@ class DualMobiMetaFix:
self.datain_rec0 = readsection(self.datain, 0)
# in the first mobi header
# add 501 to "EBOK", add 113 as asin, add 504 as asin
# add 501 to "EBOK", add 113 as asin
rec0 = self.datain_rec0
rec0 = del_exth(rec0, 501)
rec0 = del_exth(rec0, 113)
rec0 = del_exth(rec0, 504)
rec0 = add_exth(rec0, 501, b'EBOK')
rec0 = add_exth(rec0, 113, asin)
rec0 = add_exth(rec0, 504, asin)
replacesection(self.datain, 0, rec0)
ver = getint(self.datain_rec0, mobi_version)
@@ -171,14 +170,12 @@ class DualMobiMetaFix:
self.datain_kfrec0 = readsection(self.datain, datain_kf8)
# in the second header
# add 501 to "EBOK", add 113 as asin, add 504 as asin
# add 501 to "EBOK", add 113 as asin
rec0 = self.datain_kfrec0
rec0 = del_exth(rec0, 501)
rec0 = del_exth(rec0, 113)
rec0 = del_exth(rec0, 504)
rec0 = add_exth(rec0, 501, b'EBOK')
rec0 = add_exth(rec0, 113, asin)
rec0 = add_exth(rec0, 504, asin)
replacesection(self.datain, datain_kf8, rec0)
self.datain.flush()

View File

@@ -1,8 +1,10 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2010 Alex Yatskov
# Copyright (C) 2011 Stanislav (proDOOMman) Kosolapov <prodoomman@gmail.com>
# Copyright (c) 2016 Alberto Planas <aplanas@gmail.com>
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
#
# 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
@@ -16,14 +18,13 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import io
import os
from io import BytesIO
from urllib.request import Request, urlopen
from urllib.parse import quote
import mozjpeg_lossless_optimization
from PIL import Image, ImageOps, ImageStat, ImageChops, ImageFilter
from .shared import md5Checksum
from . import __version__
AUTO_CROP_THRESHOLD = 0.015
class ProfileData:
@@ -79,12 +80,18 @@ class ProfileData:
Profiles = {
'K1': ("Kindle 1", (600, 670), Palette4, 1.8),
'K11': ("Kindle 11/12", (1072, 1448), Palette16, 1.8),
'K2': ("Kindle 2", (600, 670), Palette15, 1.8),
'K3': ("Kindle", (600, 800), Palette16, 1.8),
'K45': ("Kindle", (600, 800), Palette16, 1.8),
'K34': ("Kindle Keyboard/Touch", (600, 800), Palette16, 1.8),
'K578': ("Kindle", (600, 800), Palette16, 1.8),
'KDX': ("Kindle DX/DXG", (824, 1000), Palette16, 1.8),
'KPW': ("Kindle Paperwhite 1/2", (758, 1024), Palette16, 1.8),
'KV': ("Kindle Paperwhite 3/Voyage/Oasis", (1072, 1448), Palette16, 1.8),
'KV': ("Kindle Paperwhite 3/4/Voyage/Oasis", (1072, 1448), Palette16, 1.8),
'KPW5': ("Kindle Paperwhite 5/Signature Edition", (1236, 1648), Palette16, 1.8),
'KPW6': ("Kindle Paperwhite 6", (1264, 1680), Palette16, 1.8),
'KCS12': ("Kindle Colorsoft", (1264, 1680), Palette16, 1.8),
'KO': ("Kindle Oasis 2/3", (1264, 1680), Palette16, 1.8),
'KS': ("Kindle Scribe", (1860, 2480), Palette16, 1.8),
'KoMT': ("Kobo Mini/Touch", (600, 800), Palette16, 1.8),
'KoG': ("Kobo Glo", (768, 1024), Palette16, 1.8),
'KoGHD': ("Kobo Glo HD", (1072, 1448), Palette16, 1.8),
@@ -92,12 +99,21 @@ class ProfileData:
'KoAHD': ("Kobo Aura HD", (1080, 1440), Palette16, 1.8),
'KoAH2O': ("Kobo Aura H2O", (1080, 1430), Palette16, 1.8),
'KoAO': ("Kobo Aura ONE", (1404, 1872), Palette16, 1.8),
'KoN': ("Kobo Nia", (758, 1024), Palette16, 1.8),
'KoC': ("Kobo Clara HD/Kobo Clara 2E", (1072, 1448), Palette16, 1.8),
'KoCC': ("Kobo Clara Colour", (1072, 1448), Palette16, 1.8),
'KoL': ("Kobo Libra H2O/Kobo Libra 2", (1264, 1680), Palette16, 1.8),
'KoLC': ("Kobo Libra Colour", (1264, 1680), Palette16, 1.8),
'KoF': ("Kobo Forma", (1440, 1920), Palette16, 1.8),
'KoS': ("Kobo Sage", (1440, 1920), Palette16, 1.8),
'KoE': ("Kobo Elipsa", (1404, 1872), Palette16, 1.8),
'OTHER': ("Other", (0, 0), Palette16, 1.8),
}
class ComicPageParser:
def __init__(self, source, options):
Image.MAX_IMAGE_PIXELS = int(2048 * 2048 * 2048 // 4 // 3)
self.opt = options
self.source = source
self.size = self.opt.profileData[1]
@@ -105,6 +121,9 @@ class ComicPageParser:
self.image = Image.open(os.path.join(source[0], source[1])).convert('RGB')
self.color = self.colorCheck()
self.fill = self.fillCheck()
# backwards compatibility for Pillow >9.1.0
if not hasattr(Image, 'Resampling'):
Image.Resampling = Image
self.splitCheck()
def getImageHistogram(self, image):
@@ -119,9 +138,22 @@ class ComicPageParser:
def splitCheck(self):
width, height = self.image.size
dstwidth, dstheight = self.size
if (width > height) != (dstwidth > dstheight) and width <= dstheight and height <= dstwidth \
if self.opt.maximizestrips:
leftbox = (0, 0, int(width / 2), height)
rightbox = (int(width / 2), 0, width, height)
if self.opt.righttoleft:
pageone = self.image.crop(rightbox)
pagetwo = self.image.crop(leftbox)
else:
pageone = self.image.crop(leftbox)
pagetwo = self.image.crop(rightbox)
new_image = Image.new("RGB", (int(width / 2), int(height*2)))
new_image.paste(pageone, (0, 0))
new_image.paste(pagetwo, (0, height))
self.payload.append(['N', self.source, new_image, self.color, self.fill])
elif (width > height) != (dstwidth > dstheight) and width <= dstheight and height <= dstwidth \
and not self.opt.webtoon and self.opt.splitter == 1:
self.payload.append(['R', self.source, self.image.rotate(90, Image.BICUBIC, True), self.color, self.fill])
self.payload.append(['R', self.source, self.image.rotate(90, Image.Resampling.BICUBIC, True), self.color, self.fill])
elif (width > height) != (dstwidth > dstheight) and not self.opt.webtoon:
if self.opt.splitter != 1:
if width > height:
@@ -139,7 +171,7 @@ class ComicPageParser:
self.payload.append(['S1', self.source, pageone, self.color, self.fill])
self.payload.append(['S2', self.source, pagetwo, self.color, self.fill])
if self.opt.splitter > 0:
self.payload.append(['R', self.source, self.image.rotate(90, Image.BICUBIC, True),
self.payload.append(['R', self.source, self.image.rotate(90, Image.Resampling.BICUBIC, True),
self.color, self.fill])
else:
self.payload.append(['N', self.source, self.image, self.color, self.fill])
@@ -211,6 +243,7 @@ class ComicPage:
_, self.size, self.palette, self.gamma = self.opt.profileData
if self.opt.hq:
self.size = (int(self.size[0] * 1.5), int(self.size[1] * 1.5))
self.kindle_scribe_azw3 = (options.profile == 'KS') and (options.format in ('MOBI', 'EPUB'))
self.image = image
self.color = color
self.fill = fill
@@ -225,6 +258,9 @@ class ComicPage:
self.targetPath = os.path.join(path[0], os.path.splitext(path[1])[0]) + '-KCC-B'
elif 'S2' in mode:
self.targetPath = os.path.join(path[0], os.path.splitext(path[1])[0]) + '-KCC-C'
# backwards compatibility for Pillow >9.1.0
if not hasattr(Image, 'Resampling'):
Image.Resampling = Image
def saveToDir(self):
try:
@@ -236,11 +272,20 @@ class ComicPage:
if self.fill != 'white':
flags.append('BlackBackground')
if self.opt.forcepng:
self.image.info["transparency"] = None
self.targetPath += '.png'
self.image.save(self.targetPath, 'PNG', optimize=1)
else:
self.targetPath += '.jpg'
self.image.save(self.targetPath, 'JPEG', optimize=1, quality=85)
if self.opt.mozjpeg:
with io.BytesIO() as output:
self.image.save(output, format="JPEG", optimize=1, quality=85)
input_jpeg_bytes = output.getvalue()
output_jpeg_bytes = mozjpeg_lossless_optimization.optimize(input_jpeg_bytes)
with open(self.targetPath, "wb") as output_jpeg_file:
output_jpeg_file.write(output_jpeg_bytes)
else:
self.image.save(self.targetPath, 'JPEG', optimize=1, quality=85)
return [md5Checksum(self.targetPath), flags, self.orgPath]
except IOError as err:
raise RuntimeError('Cannot save image. ' + str(err))
@@ -254,7 +299,7 @@ class ComicPage:
if gamma == 1.0:
self.image = ImageOps.autocontrast(self.image)
else:
self.image = ImageOps.autocontrast(Image.eval(self.image, lambda a: 255 * (a / 255.) ** gamma))
self.image = ImageOps.autocontrast(Image.eval(self.image, lambda a: int(255 * (a / 255.) ** gamma)))
def quantizeImage(self):
colors = len(self.palette) // 3
@@ -268,89 +313,93 @@ class ComicPage:
self.image = self.image.quantize(palette=palImg)
def resizeImage(self):
if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]:
method = Image.BICUBIC
else:
method = Image.LANCZOS
# kindle scribe conversion to mobi is limited in resolution by kindlegen, same with send to kindle and epub
if self.kindle_scribe_azw3:
self.size = (1440, 1920)
ratio_device = float(self.size[1]) / float(self.size[0])
ratio_image = float(self.image.size[1]) / float(self.image.size[0])
method = self.resize_method()
if self.opt.stretch:
self.image = self.image.resize(self.size, method)
elif self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1] and not self.opt.upscale:
if self.opt.format == 'CBZ':
elif method == Image.Resampling.BICUBIC and not self.opt.upscale:
if self.opt.format == 'CBZ' or self.opt.kfx:
borderw = int((self.size[0] - self.image.size[0]) / 2)
borderh = int((self.size[1] - self.image.size[1]) / 2)
self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=self.fill)
if self.image.size[0] != self.size[0] or self.image.size[1] != self.size[1]:
self.image = ImageOps.fit(self.image, self.size, method=Image.BICUBIC, centering=(0.5, 0.5))
else:
if self.opt.format == 'CBZ':
ratioDev = float(self.size[0]) / float(self.size[1])
if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev:
diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
self.image = ImageOps.expand(self.image, border=(int(diff / 2), 0), fill=self.fill)
elif (float(self.image.size[0]) / float(self.image.size[1])) > ratioDev:
diff = int(self.image.size[0] / ratioDev) - self.image.size[1]
self.image = ImageOps.expand(self.image, border=(0, int(diff / 2)), fill=self.fill)
self.image = ImageOps.fit(self.image, self.size, method=method, centering=(0.5, 0.5))
self.image = ImageOps.fit(self.image, self.size, method=method)
else: # if image bigger than device resolution or smaller with upscaling
if abs(ratio_image - ratio_device) < AUTO_CROP_THRESHOLD:
self.image = ImageOps.fit(self.image, self.size, method=method)
elif self.opt.format == 'CBZ' or self.opt.kfx:
self.image = ImageOps.pad(self.image, self.size, method=method, color=self.fill)
else:
hpercent = self.size[1] / float(self.image.size[1])
wsize = int((float(self.image.size[0]) * float(hpercent)))
self.image = self.image.resize((wsize, self.size[1]), method)
if self.image.size[0] > self.size[0] or self.image.size[1] > self.size[1]:
self.image.thumbnail(self.size, Image.LANCZOS)
if self.kindle_scribe_azw3:
self.size = (1860, 1920)
self.image = ImageOps.contain(self.image, self.size, method=method)
def getBoundingBox(self, tmpImg):
min_margin = [int(0.005 * i + 0.5) for i in tmpImg.size]
max_margin = [int(0.1 * i + 0.5) for i in tmpImg.size]
bbox = tmpImg.getbbox()
def resize_method(self):
if self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1]:
return Image.Resampling.BICUBIC
else:
return Image.Resampling.LANCZOS
def getBoundingBox(self, tmptmg):
min_margin = [int(0.005 * i + 0.5) for i in tmptmg.size]
max_margin = [int(0.1 * i + 0.5) for i in tmptmg.size]
bbox = tmptmg.getbbox()
bbox = (
max(0, min(max_margin[0], bbox[0] - min_margin[0])),
max(0, min(max_margin[1], bbox[1] - min_margin[1])),
min(tmpImg.size[0],
max(tmpImg.size[0] - max_margin[0], bbox[2] + min_margin[0])),
min(tmpImg.size[1],
max(tmpImg.size[1] - max_margin[1], bbox[3] + min_margin[1])),
min(tmptmg.size[0],
max(tmptmg.size[0] - max_margin[0], bbox[2] + min_margin[0])),
min(tmptmg.size[1],
max(tmptmg.size[1] - max_margin[1], bbox[3] + min_margin[1])),
)
return bbox
def cropPageNumber(self, power):
if self.fill != 'white':
tmpImg = self.image.convert(mode='L')
else:
tmpImg = ImageOps.invert(self.image.convert(mode='L'))
tmpImg = tmpImg.point(lambda x: x and 255)
tmpImg = tmpImg.filter(ImageFilter.MinFilter(size=3))
tmpImg = tmpImg.filter(ImageFilter.GaussianBlur(radius=5))
tmpImg = tmpImg.point(lambda x: (x >= 16 * power) and x)
self.image = self.image.crop(tmpImg.getbbox()) if tmpImg.getbbox() else self.image
def maybeCrop(self, box, minimum):
box_area = (box[2] - box[0]) * (box[3] - box[1])
image_area = self.image.size[0] * self.image.size[1]
if (box_area / image_area) >= minimum:
self.image = self.image.crop(box)
def cropMargin(self, power):
def cropPageNumber(self, power, minimum):
if self.fill != 'white':
tmpImg = self.image.convert(mode='L')
tmptmg = self.image.convert(mode='L')
else:
tmpImg = ImageOps.invert(self.image.convert(mode='L'))
tmpImg = tmpImg.filter(ImageFilter.GaussianBlur(radius=3))
tmpImg = tmpImg.point(lambda x: (x >= 16 * power) and x)
self.image = self.image.crop(self.getBoundingBox(tmpImg)) if tmpImg.getbbox() else self.image
tmptmg = ImageOps.invert(self.image.convert(mode='L'))
tmptmg = tmptmg.point(lambda x: x and 255)
tmptmg = tmptmg.filter(ImageFilter.MinFilter(size=3))
tmptmg = tmptmg.filter(ImageFilter.GaussianBlur(radius=5))
tmptmg = tmptmg.point(lambda x: (x >= 16 * power) and x)
if tmptmg.getbbox():
self.maybeCrop(tmptmg.getbbox(), minimum)
def cropMargin(self, power, minimum):
if self.fill != 'white':
tmptmg = self.image.convert(mode='L')
else:
tmptmg = ImageOps.invert(self.image.convert(mode='L'))
tmptmg = tmptmg.filter(ImageFilter.GaussianBlur(radius=3))
tmptmg = tmptmg.point(lambda x: (x >= 16 * power) and x)
if tmptmg.getbbox():
self.maybeCrop(self.getBoundingBox(tmptmg), minimum)
class Cover:
def __init__(self, source, target, opt, tomeNumber):
def __init__(self, source, target, opt, tomeid):
self.options = opt
self.source = source
self.target = target
if tomeNumber == 0:
self.tomeNumber = 1
if tomeid == 0:
self.tomeid = 1
else:
self.tomeNumber = tomeNumber
if self.tomeNumber in self.options.remoteCovers:
try:
source = urlopen(Request(quote(self.options.remoteCovers[self.tomeNumber]).replace('%3A', ':', 1),
headers={'User-Agent': 'KindleComicConverter/' + __version__})).read()
self.image = Image.open(BytesIO(source))
except Exception:
self.image = Image.open(source)
else:
self.image = Image.open(source)
self.tomeid = tomeid
self.image = Image.open(source)
# backwards compatibility for Pillow >9.1.0
if not hasattr(Image, 'Resampling'):
Image.Resampling = Image
self.process()
def process(self):
@@ -358,17 +407,17 @@ class Cover:
self.image = ImageOps.autocontrast(self.image)
if not self.options.forcecolor:
self.image = self.image.convert('L')
self.image.thumbnail(self.options.profileData[1], Image.LANCZOS)
self.image.thumbnail(self.options.profileData[1], Image.Resampling.LANCZOS)
self.save()
def save(self):
try:
self.image.save(self.target, "JPEG", optimize=1, quality=85)
except IOError:
raise RuntimeError('Failed to process downloaded cover.')
raise RuntimeError('Failed to save cover.')
def saveToKindle(self, kindle, asin):
self.image = self.image.resize((300, 470), Image.ANTIALIAS)
self.image = self.image.resize((300, 470), Image.Resampling.LANCZOS)
try:
self.image.save(os.path.join(kindle.path.split('documents')[0], 'system', 'thumbnails',
'thumbnail_' + asin + '_EBOK_portrait.jpg'), 'JPEG', optimize=1, quality=85)

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
#
# Permission to use, copy, modify, and/or distribute this software for
# any purpose with or without fee is hereby granted, provided that the
@@ -31,8 +31,7 @@ class Kindle:
def findDevice(self):
for drive in reversed(psutil.disk_partitions(False)):
if (drive[2] == 'FAT32' and drive[3] == 'rw,removable') or \
(drive[2] == 'vfat' and 'rw' in drive[3]) or \
(drive[2] == 'msdos' and 'rw' in drive[3]):
(drive[2] in ('vfat', 'msdos', 'FAT', 'apfs') and 'rw' in drive[3]):
if os.path.isdir(os.path.join(drive[1], 'system')) and \
os.path.isdir(os.path.join(drive[1], 'documents')):
return drive[1]

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
#
# Permission to use, copy, modify, and/or distribute this software for
# any purpose with or without fee is hereby granted, provided that the
@@ -18,14 +18,9 @@
import os
from xml.dom.minidom import parse, Document
from re import compile
from zipfile import is_zipfile, ZipFile, ZIP_DEFLATED
from subprocess import STDOUT, PIPE
from psutil import Popen
from tempfile import mkdtemp
from shutil import rmtree
from .shared import removeFromZIP, check7ZFile as is_7zfile
from . import rarfile
from . import comicarchive
class MetadataParser:
@@ -39,50 +34,21 @@ class MetadataParser:
'Inkers': [],
'Colorists': [],
'Summary': '',
'MUid': '',
'Bookmarks': []}
'Bookmarks': [],
'Title': ''}
self.rawdata = None
self.compressor = None
if self.source.endswith('.xml'):
self.format = None
if self.source.endswith('.xml') and os.path.exists(self.source):
self.rawdata = parse(self.source)
elif not self.source.endswith('.xml'):
try:
cbx = comicarchive.ComicArchive(self.source)
self.rawdata = cbx.extractMetadata()
self.format = cbx.type
except OSError as e:
raise UserWarning(e)
if self.rawdata:
self.parseXML()
else:
if is_zipfile(self.source):
self.compressor = 'zip'
with ZipFile(self.source) as zip_file:
for member in zip_file.namelist():
if member != 'ComicInfo.xml':
continue
with zip_file.open(member) as xml_file:
self.rawdata = parse(xml_file)
elif rarfile.is_rarfile(self.source):
self.compressor = 'rar'
with rarfile.RarFile(self.source) as rar_file:
for member in rar_file.namelist():
if member != 'ComicInfo.xml':
continue
with rar_file.open(member) as xml_file:
self.rawdata = parse(xml_file)
elif is_7zfile(self.source):
self.compressor = '7z'
workdir = mkdtemp('', 'KCC-')
tmpXML = os.path.join(workdir, 'ComicInfo.xml')
output = Popen('7za e "' + self.source + '" ComicInfo.xml -o"' + workdir + '"',
stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
extracted = False
for line in output.stdout:
if b"Everything is Ok" in line or b"No files to process" in line:
extracted = True
if not extracted:
rmtree(workdir)
raise OSError('Failed to extract 7ZIP file.')
if os.path.isfile(tmpXML):
self.rawdata = parse(tmpXML)
rmtree(workdir)
else:
raise OSError('Failed to detect archive format.')
if self.rawdata:
self.parseXML()
def parseXML(self):
if len(self.rawdata.getElementsByTagName('Series')) != 0:
@@ -93,17 +59,14 @@ class MetadataParser:
self.data['Number'] = self.rawdata.getElementsByTagName('Number')[0].firstChild.nodeValue
if len(self.rawdata.getElementsByTagName('Summary')) != 0:
self.data['Summary'] = self.rawdata.getElementsByTagName('Summary')[0].firstChild.nodeValue
if len(self.rawdata.getElementsByTagName('Title')) != 0:
self.data['Title'] = self.rawdata.getElementsByTagName('Title')[0].firstChild.nodeValue
for field in ['Writer', 'Penciller', 'Inker', 'Colorist']:
if len(self.rawdata.getElementsByTagName(field)) != 0:
for person in self.rawdata.getElementsByTagName(field)[0].firstChild.nodeValue.split(', '):
self.data[field + 's'].append(person)
self.data[field + 's'] = list(set(self.data[field + 's']))
self.data[field + 's'].sort()
if len(self.rawdata.getElementsByTagName('ScanInformation')) != 0:
coverId = compile('(MCD\\()(\\d+)(\\))')\
.search(self.rawdata.getElementsByTagName('ScanInformation')[0].firstChild.nodeValue)
if coverId:
self.data['MUid'] = coverId.group(2)
if len(self.rawdata.getElementsByTagName('Page')) != 0:
for page in self.rawdata.getElementsByTagName('Page'):
if 'Bookmark' in page.attributes and 'Image' in page.attributes:
@@ -117,7 +80,7 @@ class MetadataParser:
['Number', self.data['Number']], ['Writer', ', '.join(self.data['Writers'])],
['Penciller', ', '.join(self.data['Pencillers'])], ['Inker', ', '.join(self.data['Inkers'])],
['Colorist', ', '.join(self.data['Colorists'])], ['Summary', self.data['Summary']],
['ScanInformation', 'MCD(' + self.data['MUid'] + ')' if self.data['MUid'] else '']):
['Title', self.data['Title']]):
if self.rawdata.getElementsByTagName(row[0]):
node = self.rawdata.getElementsByTagName(row[0])[0]
if row[1]:
@@ -139,7 +102,7 @@ class MetadataParser:
['Number', self.data['Number']], ['Writer', ', '.join(self.data['Writers'])],
['Penciller', ', '.join(self.data['Pencillers'])], ['Inker', ', '.join(self.data['Inkers'])],
['Colorist', ', '.join(self.data['Colorists'])], ['Summary', self.data['Summary']],
['ScanInformation', 'MCD(' + self.data['MUid'] + ')' if self.data['MUid'] else '']):
['Title', self.data['Title']]):
if row[1]:
main = doc.createElement(row[0])
root.appendChild(main)
@@ -154,20 +117,9 @@ class MetadataParser:
tmpXML = os.path.join(workdir, 'ComicInfo.xml')
with open(tmpXML, 'w', encoding='utf-8') as f:
self.rawdata.writexml(f, encoding='utf-8')
if is_zipfile(self.source):
removeFromZIP(self.source, 'ComicInfo.xml')
with ZipFile(self.source, mode='a', compression=ZIP_DEFLATED) as zip_file:
zip_file.write(tmpXML, arcname=tmpXML.split(os.sep)[-1])
elif rarfile.is_rarfile(self.source):
raise NotImplementedError
elif is_7zfile(self.source):
output = Popen('7za a "' + self.source + '" "' + tmpXML + '"',
stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
extracted = False
for line in output.stdout:
if b"Everything is Ok" in line:
extracted = True
if not extracted:
rmtree(workdir)
raise OSError('Failed to modify 7ZIP file.')
try:
cbx = comicarchive.ComicArchive(self.source)
cbx.addFile(tmpXML)
except OSError as e:
raise UserWarning(e)
rmtree(workdir)

View File

@@ -1,5 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
#
# Based upon the code snippet by Ned Batchelder
# (http://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html)
@@ -23,19 +25,23 @@ import os
from random import choice
from string import ascii_uppercase, digits
# skip stray images a few pixels in size in some PDFs
# typical images are many thousands in length
# https://github.com/ciromattia/kcc/pull/546
STRAY_IMAGE_LENGTH_THRESHOLD = 300
class PdfJpgExtract:
def __init__(self, origFileName):
self.origFileName = origFileName
self.filename = os.path.splitext(origFileName)
# noinspection PyUnusedLocal
self.path = self.filename[0] + "-KCC-" + ''.join(choice(ascii_uppercase + digits) for x in range(3))
def __init__(self, fname):
self.fname = fname
self.filename = os.path.splitext(fname)
self.path = self.filename[0] + "-KCC-" + ''.join(choice(ascii_uppercase + digits) for _ in range(3))
def getPath(self):
return self.path
def extract(self):
pdf = open(self.origFileName, "rb").read()
pdf = open(self.fname, "rb").read()
startmark = b"\xff\xd8"
startfix = 0
endmark = b"\xff\xd9"
@@ -59,10 +65,15 @@ class PdfJpgExtract:
raise Exception("Didn't find end of JPG!")
istart += startfix
iend += endfix
i = iend
if iend - istart < STRAY_IMAGE_LENGTH_THRESHOLD:
continue
jpg = pdf[istart:iend]
jpgfile = open(self.path + "/jpg%d.jpg" % njpg, "wb")
jpgfile.write(jpg)
jpgfile.close()
njpg += 1
i = iend
return self.path, njpg

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
#
# Permission to use, copy, modify, and/or distribute this software for
# any purpose with or without fee is hereby granted, provided that the
@@ -19,11 +21,10 @@
import os
from hashlib import md5
from html.parser import HTMLParser
from distutils.version import StrictVersion
from shutil import rmtree, copy
from tempfile import mkdtemp
from zipfile import ZipFile, ZIP_DEFLATED
import subprocess
from packaging.version import Version
from re import split
import sys
from traceback import format_tb
@@ -48,7 +49,7 @@ class HTMLStripper(HTMLParser):
def getImageFileName(imgfile):
name, ext = os.path.splitext(imgfile)
ext = ext.lower()
if name.startswith('.') or (ext != '.png' and ext != '.jpg' and ext != '.jpeg' and ext != '.gif'):
if (name.startswith('.') and len(name) == 1) or ext not in ['.png', '.jpg', '.jpeg', '.gif', '.webp']:
return None
return [name, ext]
@@ -73,8 +74,8 @@ def walkLevel(some_dir, level=1):
del dirs[:]
def md5Checksum(filePath):
with open(filePath, 'rb') as fh:
def md5Checksum(fpath):
with open(fpath, 'rb') as fh:
m = md5()
while True:
data = fh.read(8192)
@@ -84,45 +85,28 @@ def md5Checksum(filePath):
return m.hexdigest()
def check7ZFile(filePath):
with open(filePath, 'rb') as fh:
header = fh.read(6)
return header == b"7z\xbc\xaf'\x1c"
def removeFromZIP(zipfname, *filenames):
tempdir = mkdtemp('', 'KCC-')
try:
tempname = os.path.join(tempdir, 'KCC.zip')
with ZipFile(zipfname, 'r') as zipread:
with ZipFile(tempname, 'w', compression=ZIP_DEFLATED) as zipwrite:
for item in zipread.infolist():
if item.filename not in filenames:
zipwrite.writestr(item, zipread.read(item.filename))
copy(tempname, zipfname)
finally:
rmtree(tempdir, True)
def sanitizeTrace(traceback):
return ''.join(format_tb(traceback))\
.replace('C:/Users/Pawel/Documents/Projekty/KCC/', '')\
.replace('C:/Python35/', '')\
.replace('c:/python35/', '')\
.replace('C:\\Users\\Pawel\\Documents\\Projekty\\KCC\\', '')\
.replace('C:\\Python35\\', '')\
.replace('c:\\python35\\', '')
.replace('C:/projects/kcc/', '')\
.replace('c:/projects/kcc/', '')\
.replace('C:/python37-x64/', '')\
.replace('c:/python37-x64/', '')\
.replace('C:\\projects\\kcc\\', '')\
.replace('c:\\projects\\kcc\\', '')\
.replace('C:\\python37-x64\\', '')\
.replace('c:\\python37-x64\\', '')
# noinspection PyUnresolvedReferences
def dependencyCheck(level):
missing = []
if level > 2:
try:
from PyQt5.QtCore import qVersion as qtVersion
if StrictVersion('5.6.0') > StrictVersion(qtVersion()):
missing.append('PyQt 5.6.0+')
from PySide6.QtCore import qVersion as qtVersion
if Version('6.5.1') > Version(qtVersion()):
missing.append('PySide 6.5.1+')
except ImportError:
missing.append('PyQt 5.6.0+')
missing.append('PySide 6.5.1+')
try:
import raven
except ImportError:
@@ -130,22 +114,30 @@ def dependencyCheck(level):
if level > 1:
try:
from psutil import __version__ as psutilVersion
if StrictVersion('5.0.0') > StrictVersion(psutilVersion):
if Version('5.0.0') > Version(psutilVersion):
missing.append('psutil 5.0.0+')
except ImportError:
missing.append('psutil 5.0.0+')
try:
from types import ModuleType
from slugify import __version__ as slugifyVersion
if StrictVersion('1.2.1') > StrictVersion(slugifyVersion):
if isinstance(slugifyVersion, ModuleType):
slugifyVersion = slugifyVersion.__version__
if Version('1.2.1') > Version(slugifyVersion):
missing.append('python-slugify 1.2.1+')
except ImportError:
missing.append('python-slugify 1.2.1+')
try:
from PIL import PILLOW_VERSION as pillowVersion
if StrictVersion('4.0.0') > StrictVersion(pillowVersion):
missing.append('Pillow 4.0.0+')
from PIL import __version__ as pillowVersion
if Version('5.2.0') > Version(pillowVersion):
missing.append('Pillow 5.2.0+')
except ImportError:
missing.append('Pillow 4.0.0+')
missing.append('Pillow 5.2.0+')
if len(missing) > 0:
print('ERROR: ' + ', '.join(missing) + ' is not installed!')
exit(1)
sys.exit(1)
def subprocess_run(command, **kwargs):
if (os.name == 'nt'):
kwargs.setdefault('creationflags', subprocess.CREATE_NO_WINDOW)
return subprocess.run(command, **kwargs)

View File

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
# Copyright (c) 2013-2019 Pawel Jastrzebski <pawelj@iosphe.re>
#
# Permission to use, copy, modify, and/or distribute this software for
# any purpose with or without fee is hereby granted, provided that the
@@ -30,15 +30,15 @@ def start():
os.environ['QT_AUTO_SCREEN_SCALE_FACTOR'] = "1"
KCCAplication = KCC_gui.QApplicationMessaging(sys.argv)
if KCCAplication.isRunning():
if len(sys.argv) > 1:
KCCAplication.sendMessage(sys.argv[1])
for i in range(1, len(sys.argv)):
KCCAplication.sendMessage(sys.argv[i])
else:
KCCAplication.sendMessage('ARISE')
else:
KCCWindow = KCC_gui.QMainWindowKCC()
KCCUI = KCC_gui.KCCGUI(KCCAplication, KCCWindow)
if len(sys.argv) > 1:
KCCUI.handleMessage(sys.argv[1])
for i in range(1, len(sys.argv)):
KCCUI.handleMessage(sys.argv[i])
sys.exit(KCCAplication.exec_())

View File

@@ -1,4 +0,0 @@
kindlecomicconverter: binary-without-manpage usr/bin/kcc
kindlecomicconverter: wrong-name-for-changelog-of-native-package usr/share/doc/kindlecomicconverter/changelog.Debian.gz
kindlecomicconverter: file-missing-in-md5sums usr/share/doc/kindlecomicconverter/changelog.Debian.gz
kindlecomicconverter: hardening-no-relro usr/bin/kcc

View File

@@ -1,11 +0,0 @@
[Desktop Entry]
Type=Application
Version=1.0
Name=Kindle Comic Converter
GenericName=Kindle Comic Converter
Comment=Comic and Manga converter for e-book readers
Icon=/usr/share/kindlecomicconverter/comic2ebook.png
Exec=/usr/bin/kcc %f
Terminal=false
Categories=Graphics;
MimeType=application/zip;application/x-rar;application/x-7z-compressed;

Binary file not shown.

View File

@@ -1,68 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDisplayName</key>
<string>Kindle Comic Converter</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>cbz</string>
<string>cbr</string>
<string>cb7</string>
<string>zip</string>
<string>rar</string>
<string>7z</string>
<string>pdf</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>comic2ebook.icns</string>
<key>CFBundleTypeName</key>
<string>Comics</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>MacOS/Kindle Comic Converter</string>
<key>CFBundleGetInfoString</key>
<string>KindleComicConverter 5.4.0, written 2012-2017 by Ciro Mattia Gonano and Pawel Jastrzebski</string>
<key>CFBundleIconFile</key>
<string>comic2ebook.icns</string>
<key>CFBundleIdentifier</key>
<string>com.kindlecomicconverter.KindleComicConverter</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Kindle Comic Converter</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>5.4.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5.4.0</string>
<key>LSEnvironment</key>
<dict>
<key>PATH</key>
<string>./../Resources:/usr/local/bin:/usr/bin:/bin</string>
</dict>
<key>LSHasLocalizedDisplayName</key>
<false/>
<key>LSMinimumSystemVersion</key>
<string>10.9.0</string>
<key>NSAppleScriptEnabled</key>
<false/>
<key>NSHumanReadableCopyright</key>
<string>ISC License (ISCL)</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

Binary file not shown.

Binary file not shown.

View File

@@ -1,91 +0,0 @@
****** ***** ****** 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

View File

@@ -1,229 +0,0 @@
{\rtf1\adeflang1025\ansi\ansicpg1250\uc1\adeff0\deff0\stshfdbch0\stshfloch31506\stshfhich31506\stshfbi31506\deflang1045\deflangfe1045\themelang1045\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset238\fprq2{\*\panose 02020603050405020304}Times New Roman;}
{\f0\fbidi \froman\fcharset238\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f37\fbidi \fswiss\fcharset238\fprq2{\*\panose 020f0502020204030204}Calibri;}
{\flomajor\f31500\fbidi \froman\fcharset238\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbmajor\f31501\fbidi \froman\fcharset238\fprq2{\*\panose 02020603050405020304}Times New Roman;}
{\fhimajor\f31502\fbidi \fswiss\fcharset238\fprq2{\*\panose 020f0302020204030204}Calibri Light;}{\fbimajor\f31503\fbidi \froman\fcharset238\fprq2{\*\panose 02020603050405020304}Times New Roman;}
{\flominor\f31504\fbidi \froman\fcharset238\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbminor\f31505\fbidi \froman\fcharset238\fprq2{\*\panose 02020603050405020304}Times New Roman;}
{\fhiminor\f31506\fbidi \fswiss\fcharset238\fprq2{\*\panose 020f0502020204030204}Calibri;}{\fbiminor\f31507\fbidi \froman\fcharset238\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f41\fbidi \froman\fcharset0\fprq2 Times New Roman;}
{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f41\fbidi \froman\fcharset0\fprq2 Times New Roman;}
{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f411\fbidi \fswiss\fcharset0\fprq2 Calibri;}
{\f410\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f412\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f413\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f416\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}
{\f417\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31510\fbidi \froman\fcharset0\fprq2 Times New Roman;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
{\fdbmajor\f31520\fbidi \froman\fcharset0\fprq2 Times New Roman;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31530\fbidi \fswiss\fcharset0\fprq2 Calibri Light;}
{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;}{\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}
{\fhimajor\f31535\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31540\fbidi \froman\fcharset0\fprq2 Times New Roman;}
{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31550\fbidi \froman\fcharset0\fprq2 Times New Roman;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
{\fdbminor\f31560\fbidi \froman\fcharset0\fprq2 Times New Roman;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31570\fbidi \fswiss\fcharset0\fprq2 Calibri;}
{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31580\fbidi \froman\fcharset0\fprq2 Times New Roman;}
{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;
\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;
\chyperlink\ctint255\cshade255\red5\green99\blue193;\cfollowedhyperlink\ctint255\cshade255\red149\green79\blue114;}{\*\defchp \f31506\fs22\lang1045\langfe1033\langfenp1033 }{\*\defpap \ql \li0\ri0\sa160\sl259\slmult1
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0
\f31506\fs22\lang1045\langfe1033\cgrid\langnp1045\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*
\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa160\sl259\slmult1
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31506\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1045\langfe1033\cgrid\langnp1045\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}{\*\cs15 \additive
\rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf17 \sbasedon10 \sunhideused \styrsid3562894 Hyperlink;}{\*\cs16 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf18 \sbasedon10 \ssemihidden \sunhideused \styrsid7678248 FollowedHyperlink;}}{\*\rsidtbl \rsid1081196
\rsid3146412\rsid3562894\rsid5731975\rsid7678248\rsid9265883\rsid11107340\rsid12600926\rsid13187577}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info
{\author Pawe\'b3 Jastrz\'eabski}{\operator Pawe\'b3 Jastrz\'eabski}{\creatim\yr2013\mo10\dy29\hr15\min17}{\revtim\yr2013\mo10\dy29\hr15\min28}{\version8}{\edmins8}{\nofpages1}{\nofwords33}{\nofchars200}{\nofcharsws232}{\vern57435}}{\*\xmlnstbl {\xmlns1 h
ttp://schemas.microsoft.com/office/word/2003/wordml}}\paperw11906\paperh16838\margl1417\margr1417\margt1417\margb1417\gutter0\ltrsect
\deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0
\showxmlerrors1\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1417\dgvorigin1417\dghshow1\dgvshow1
\jexpand\viewkind1\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct
\asianbrkrule\rsidroot11107340\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0
{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2
\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6
\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang
{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0
\f31506\fs22\lang1045\langfe1033\cgrid\langnp1045\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \b\fs52\cf6\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid3562894 Warning!}{\rtlch\fcs1 \af0 \ltrch\fcs0
\b\fs52\cf6\lang2057\langfe1033\langnp2057\insrsid13187577\charrsid3562894
\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \fs28\lang2057\langfe1033\langnp2057\insrsid1081196 Creation of}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
\b\fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 MOBI}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 files }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
\fs28\lang2057\langfe1033\langnp2057\insrsid5731975\charrsid12600926 require additional software.}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926
\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 Please download: }{\field\flddirty{\*\fldinst {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
\b\fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 HYPERLINK "http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211" }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926
{\*\datafield
00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b9600000068007400740070003a002f002f007700770077002e0061006d0061007a006f006e002e0063006f006d002f00670070002f0066006500610074007500720065002e00680074006d006c003f00690065003d00
5500540046003800260064006f006300490064003d0031003000300030003700360035003200310031000000795881f43b1d7f48af2c825dc485276300000000a5ab000000}}}{\fldrslt {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
\cs15\b\fs28\ul\cf17\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 KindleGen}}}\sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
\b\fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926
\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 And place }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \i\fs28\lang2057\langfe1033\langnp2057\insrsid5731975\charrsid12600926 kindlegen.exe}{\rtlch\fcs1
\af0\afs24 \ltrch\fcs0 \fs28\lang2057\langfe1033\langnp2057\insrsid5731975\charrsid12600926 }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 inside }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
\b\fs28\lang2057\langfe1033\langnp2057\insrsid3146412\charrsid3146412 Kindle}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\fs28\lang2057\langfe1033\langnp2057\insrsid3146412 }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
\b\fs28\lang2057\langfe1033\langnp2057\insrsid3146412\charrsid3146412 Comic}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\fs28\lang2057\langfe1033\langnp2057\insrsid3146412 }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
\b\fs28\lang2057\langfe1033\langnp2057\insrsid3146412\charrsid3146412 Converter}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\fs28\lang2057\langfe1033\langnp2057\insrsid3146412 }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0
\fs28\lang2057\langfe1033\langnp2057\insrsid3562894\charrsid12600926 directory.
\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a
9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad
5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6
b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0
0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6
a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f
c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512
0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462
a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865
6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b
4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b
4757e8d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100b7e72e45da060000a81a0000160000007468656d652f7468656d652f
7468656d65312e786d6cec595d8b1b37147d2ff43f0cf3eef86bc61f4bbcc11edbd936bbc9123b2979d4dab24759cdc88ce4dd981028c963a1509a963e34d0b7
3e94b68104fa92fe9a6d53da14f2177aa5198f255bdb4d96149692352c63f9dcaba37bef9cab195dbe722fa2ce114e386171cb2d5f2ab90e8e476c4ce269cbbd
35ec171aaec3058ac788b218b7dc05e6ee95ed0f3fb88cb6448823ec807dccb750cb0d85986d158b7c04c3885f62331cc36f13964448c0d7645a1c27e818fc46
b45829956ac50891d875621481db3d2616c7ce0c1d122ce6ce8dc9848cb0bbbd9ca44761a658703930a2c9404e8133cb7d65a39b8c0fcb12c8173ca089738468
cb8569c7ec7888ef09d7a1880bf8a1e596d49f5bdcbe5c445b991115a7d86a767df597d96506e3c38a9a33991ee4937a9eefd5dab97f05a06213d7abf76abd5a
ee4f01d068040b4eb9e83efd4eb3d3f533ac064a2f2dbebbf56eb56ce035ffd50dce6d5f7e0cbc02a5febd0d7cbf1f40140dbc02a5787f03ef79f54ae0197805
4af1b50d7cbdd4ee7a7503af402125f1e106bae4d7aac172b53964c2e88e15def4bd7ebd92395fa1a01af22293534c582cce28b908dd65491f70124f9120b123
16333c4123a8ed005172901067974c43a8bf198a1987e152a5d42f55e1bffc78ea4a05066d61a4594b7a40886f0c495a0e1f2564265aeec7e0d5d520af5ffcf8
fac533e7e4e1f39387bf9c3c7a74f2f0e7d49161b583e2a96ef5eafb2ffe7ef2a9f3d7b3ef5e3dfeca8ee73afef79f3efbedd72fed4058e92a042fbf7efac7f3
a72fbff9fccf1f1e5be0ed041de8f021893077aee363e7268b60612a0426737c90bc9dc5304444b768c7538e622467b1f8ef89d0405f5f208a2cb80e3623783b
01a5b101afceef1a8407613217c4e2f15a1819c03dc6688725d6285c937369611ecee3a97df264aee36e2274649b3b40b191dfde7c064a4b6c2e83101b34f729
8a059ae2180b47fec60e31b6acee0e21465cf7c828619c4d847387381d44ac21199203a39a56463b2482bc2c6c0421df466cf66e3b1d466dabeee22313097705
a216f2434c8d305e457381229bcb218aa81ef05d24421bc9c12219e9b81e1790e929a6cce98d31e7369b1b09ac574bfa3590177bdaf7e8223291892087369fbb
88311dd965874188a2990d3b2071a8633fe28750a2c8d967c206df63e61d22bf431e507c6aba6fc31e409fe06c35b805caaa5bac0a44fe324f2cb9bc8a9951bf
83059d20aca406f4dfd0f388c4678afb9aacfbffadac8390befcf68965551755d0db09b1de513b6b327e1a6e5dbc03968cc9c5d7ee2e9ac7fb186e97cd06f65e
badf4bb7fbbf97eed3eee7772fd82b8d06f9965bc574c7aef6efd159dbf709a174201614ef72b583e7d0a0c67d1894e6ea8116e74f75b3102ee50d0df318b869
82948d9330f10911e1204433d8e6975de964ca33d753eecc1887ddbf1ab6fa96783a8ff6d8387d782d97e5836aaa211c89d578c9cfc7e18943a4e85a7df54096
bb576ca7eaf9794940dabe0d096d329344d542a2be1c9441524feb10340b09b5b277c2a26961d190ee97a9da6001d4f2acc00eca817d57cbf53d30012378b042
148f659ed2542fb3ab92f92e337d5a308d0a80edc4b20256996e4aaea72e4fae2e2db537c8b441422b3793848a8c6a653c44639c55a71c7d131a6f9bebe62aa5
063d190a351f94d68a46bdf16f2cce9b6bb05bd7061aeb4a4163e7b8e5d6aa3e94cc08cd5aee049efee1329a41ed70b9f345740a2fd64622496ff8f328cb2ce1
a28b7898065c894eaa061111387128895aae5c7e9e061a2b0d51dcca1510840b4bae09b272d1c841d2cd24e3c9048f849e766d44463afd0a0a9f6a85f557657e
7eb0b4647348f7201c1f3b07749edc4450627ebd2c0338261c5e0295d3688e09bcdccc856c557f6b8d29935dfdeda2aaa1741cd15988b28ea28b790a57529ed3
51dff21868dfb2354340b590648df0602a1bac1e54a39be65d23e5706ad73ddb48464e13cd55cf345445764dbb8a19332cdbc05a2ccfd7e43556cb1083a6e91d
3e95ee75c96d2eb56e6d9f90770908781e3f4bd77d8386a0515b4d6650938c3765586a76366af68ee502cfa0f6264d4253fddad2ed5adcf21e619d0e06cfd5f9
c16ebd6a6168b2dc5eaa48ab4311fdbc821ddc05f1e8c2bbe039155ca5128e2112041ba281da93a4b201b7c83d91dd1a70e5cc13d272ef97fcb61754fca0506a
f8bd8257f54a8586dfae16dabe5f2df7fc72a9dba93c80c622c2a8eca707327d78234517d9b18c1adf389a89962fdd2e8d585464eab0a5a888aba39972c5389a
490f639ca13c73711d02a273bf56e937abcd4eadd0acb6fb05afdb69149a41ad53e8d6827ab7df0dfc46b3ffc0758e14d86b5703afd66b146ae5202878b592a4
df6816ea5ea5d2f6eaed46cf6b3fc8b631b0f2543eb258407815afed7f000000ffff0300504b0304140006000800000021000dd1909fb60000001b0100002700
00007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0ad
d40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b
284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f16
5dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c0200001300000000
000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b000000
00000000000000000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c00000000000000000000
000000190200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d0014000600080000002100b7e72e45da060000a81a000016
00000000000000000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b
0100002700000000000000000000000000e40900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000df0a00000000}
{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d
617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169
6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363
656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e}
{\*\latentstyles\lsdstimax371\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4;
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9;
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3;
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6;
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;
\lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1;
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid;
\lsdsemihidden1 \lsdlocked0 Placeholder Text;\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List;\lsdpriority62 \lsdlocked0 Light Grid;
\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdpriority68 \lsdlocked0 Medium Grid 2;
\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid;\lsdpriority60 \lsdlocked0 Light Shading Accent 1;
\lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;
\lsdsemihidden1 \lsdlocked0 Revision;\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;
\lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdpriority62 \lsdlocked0 Light Grid Accent 2;
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;
\lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3;
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;
\lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4;
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4;
\lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdpriority62 \lsdlocked0 Light Grid Accent 5;
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;
\lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6;
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;
\lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis;
\lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography;
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4;
\lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4;
\lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1;
\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1;
\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2;
\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2;
\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3;
\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4;
\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4;
\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5;
\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5;
\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6;
\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6;
\lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark;
\lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1;
\lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1;
\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2;
\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3;
\lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3;
\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4;
\lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4;
\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5;
\lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5;
\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6;
\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;}}{\*\datastore 010500000200000018000000
4d73786d6c322e534158584d4c5265616465722e362e30000000000000000000000e0000
d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff0900060000000000000000000000010000000100000000000000001000000200000001000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
fffffffffffffffffdffffff04000000feffffff05000000fefffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffff010000000c6ad98892f1d411a65f0040963251e50000000000000000000000006069
e214b3d4ce010300000080020000000000004d0073006f004400610074006100530074006f0072006500000000000000000000000000000000000000000000000000000000000000000000000000000000001a000101ffffffffffffffff0200000000000000000000000000000000000000000000006069e214b3d4ce01
6069e214b3d4ce010000000000000000000000003500d900ca00dd00ce004400cc00c8005a0045004700c400cd0057004900c500d400c900cb00ce00570051003d003d000000000000000000000000000000000032000101ffffffffffffffff0300000000000000000000000000000000000000000000006069e214b3d4
ce016069e214b3d4ce010000000000000000000000004900740065006d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000201ffffffff04000000ffffffff000000000000000000000000000000000000000000000000
00000000000000000000000000000000fc00000000000000010000000200000003000000feffffff0500000006000000070000000800000009000000feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3c623a536f75726365732053656c65637465645374796c653d225c415041536978746845646974696f6e4f66666963654f6e6c696e652e78736c22205374796c654e616d653d22415041222056657273696f6e3d22362220786d6c6e733a
623d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f6269626c696f6772617068792220786d6c6e733d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e74
2f323030362f6269626c696f677261706879223e3c2f623a536f75726365733e000000003c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d226e6f223f3e0d0a3c64733a6461746173746f72654974656d2064733a6974656d49443d227b42384244
394137462d323833422d343136342d413442352d3632323544323941454535397d2220786d6c6e733a64733d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f637573746f6d586d6c223e3c64733a736368656d61526566733e3c
64733a736368656d615265662064733a7572693d22687474703a2f2f736368656d61732e6f70656e500072006f007000650072007400690065007300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000200ffffffffffffffffffffffff000000000000
0000000000000000000000000000000000000000000000000000000000000400000055010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f6269626c696f677261706879222f3e3c2f64733a736368656d61526566733e3c2f64733a6461746173746f
72654974656d3e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105000000000000}}

Binary file not shown.

Binary file not shown.

View File

@@ -1,5 +1,10 @@
PyQt5>=5.6.0
Pillow>=4.0.0
psutil>=5.0.0
PySide6>=6.5.1
Pillow>=5.2.0
psutil>=5.9.5
requests>=2.31.0
python-slugify>=1.2.1
raven>=6.0.0
raven>=6.0.0
packaging>=23.2
mozjpeg-lossless-optimization>=1.1.2
natsort[fast]>=8.4.0
distro>=1.8.0

59
setup.py Executable file → Normal file
View File

@@ -1,19 +1,19 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
pip/pyinstaller build script for KCC.
Install as Python package:
python3 setup.py install
Create EXE/APP/DEB:
Create EXE/APP:
python3 setup.py build_binary
"""
import os
import platform
import sys
import shutil
import setuptools
import distutils.cmd
from kindlecomicconverter import __version__
NAME = 'KindleComicConverter'
@@ -21,7 +21,8 @@ MAIN = 'kcc.py'
VERSION = __version__
class BuildBinaryCommand(distutils.cmd.Command):
# noinspection PyUnresolvedReferences
class BuildBinaryCommand(setuptools.Command):
description = 'build binary release'
user_options = []
@@ -31,34 +32,24 @@ class BuildBinaryCommand(distutils.cmd.Command):
def finalize_options(self):
pass
# noinspection PyShadowingNames
def run(self):
VERSION = __version__
if sys.platform == 'darwin':
if os.path.isfile('Kindle Comic Converter.spec'):
os.system('pyinstaller "Kindle Comic Converter.spec"')
else:
os.system('pyinstaller -y -F -i icons/comic2ebook.icns -n "Kindle Comic Converter" -w -s kcc.py')
shutil.copy('other/osx/7za', 'dist/Kindle Comic Converter.app/Contents/Resources')
shutil.copy('other/osx/unrar', 'dist/Kindle Comic Converter.app/Contents/Resources')
shutil.copy('other/osx/Info.plist', 'dist/Kindle Comic Converter.app/Contents')
shutil.copy('LICENSE.txt', 'dist/Kindle Comic Converter.app/Contents/Resources')
shutil.copy('other/windows/Additional-LICENSE.txt', 'dist/Kindle Comic Converter.app/Contents/Resources')
os.chmod('dist/Kindle Comic Converter.app/Contents/Resources/unrar', 0o777)
os.chmod('dist/Kindle Comic Converter.app/Contents/Resources/7za', 0o777)
if os.path.isfile('setup.sh'):
os.system('./setup.sh')
os.system('appdmg kcc.json dist/KindleComicConverter_osx_' + VERSION + '.dmg')
exit(0)
os.system('pyinstaller --hidden-import=_cffi_backend -y -D -i icons/comic2ebook.icns -n "Kindle Comic Converter" -w -s kcc.py')
# TODO /usr/bin/codesign --force -s "$MACOS_CERTIFICATE_NAME" --options runtime dist/Applications/Kindle\ Comic\ Converter.app -v
os.system(f'appdmg kcc.json dist/kcc_macos_{platform.processor()}_{VERSION}.dmg')
sys.exit(0)
elif sys.platform == 'win32':
if os.path.isfile('KCC.spec'):
os.system('pyinstaller KCC.spec')
else:
os.system('pyinstaller -y -F -i icons\comic2ebook.ico -n KCC -w --noupx kcc.py')
if os.path.isfile('setup.bat'):
os.system('setup.bat')
exit(0)
os.system('pyinstaller --hidden-import=_cffi_backend -y -F -i icons\\comic2ebook.ico -n KCC_' + VERSION + ' -w --noupx kcc.py')
sys.exit(0)
elif sys.platform == 'linux':
os.system(
'pyinstaller --hidden-import=_cffi_backend --hidden-import=queue -y -F -i icons/comic2ebook.ico -n kcc_linux_' + VERSION + ' kcc.py')
sys.exit(0)
else:
os.system('docker run --rm -v ' + os.getcwd() + ':/app -e KCCVER=' + VERSION + ' acidweb/kcc')
exit(0)
sys.exit(0)
setuptools.setup(
cmdclass={
@@ -83,11 +74,15 @@ setuptools.setup(
},
packages=['kindlecomicconverter'],
install_requires=[
'PyQt5>=5.6.0',
'Pillow>=4.0.0',
'psutil>=5.0.0',
'python-slugify>=1.2.1',
'pyside6>=6.5.1',
'Pillow>=5.2.0',
'psutil>=5.9.5',
'python-slugify>=1.2.1,<9.0.0',
'raven>=6.0.0',
'requests>=2.31.0',
'mozjpeg-lossless-optimization>=1.1.2',
'natsort[fast]>=8.4.0',
'distro',
],
classifiers=[],
zip_safe=False,