9 Commits
Author SHA1 Message Date
hyugogirubato 0947e1904b New Contributors 2024-07-15 19:54:41 +02:00
hyugogirubato 7f1060fc30 Release v3.3.1 2024-07-15 19:51:54 +02:00
hyugogirubato df54489eef Add from_pdf method 2024-07-15 19:45:38 +02:00
hyugogirubato 68e843af63 Change quit keyboard shortcut to allow clipboard 2024-07-15 19:19:36 +02:00
hyugogirubato 4b2c47b4b8 Fix minimum player dimensions 2024-07-15 19:18:26 +02:00
hyugogirubato 74a6a0e9b6 Fix player border margin 2024-07-15 19:12:22 +02:00
hyugogirubato 82e1764c2e Fix windows taskbar player icon 2024-07-15 19:05:13 +02:00
hyugogirubato f62a508d9a Merge pull request #9 from flolep2607/fix-linux-player
fix: cbzplayer icon  for linux
2024-07-15 18:55:00 +02:00
flolep2607 90abd137c5 fix: cbzplayer icon for linux 2024-07-14 20:26:05 +02:00
8 changed files with 175 additions and 15 deletions
+2 -1
View File
@@ -171,4 +171,5 @@ poetry.toml
pyrightconfig.json
### CBZ ###
.cbz
*.cbz
*.pdf
+23
View File
@@ -4,6 +4,28 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.3.1] - 2024-07-15
### Added
- Added `from_pdf` method to convert `.pdf` files to `.cbz`.
### Changed
- Set a default standard size.
- Changed a keyboard shortcut that prevented copying information.
### Fixed
- Fixed the icon display for Linux in the player.
- Fixed the taskbar icon for Windows in the player.
- Fixed the player margins.
- Automatically detect the player size based on the smallest image.
### New Contributors
- [flolep2607](https://github.com/flolep2607)
## [3.3.0] - 2024-07-14
### Added
@@ -82,6 +104,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- Initial release.
[3.3.1]: https://github.com/hyugogirubato/cbz/releases/tag/v3.3.1
[3.3.0]: https://github.com/hyugogirubato/cbz/releases/tag/v3.3.0
[3.2.0]: https://github.com/hyugogirubato/cbz/releases/tag/v3.2.0
[3.1.2]: https://github.com/hyugogirubato/cbz/releases/tag/v3.1.2
+1
View File
@@ -150,6 +150,7 @@ comic_from_cbz = ComicInfo.from_cbz('/path/to/your_comic.cbz')
<a href="https://github.com/OleskiiPyskun"><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/75667382?v=4&h=25&w=25&fit=cover&mask=circle&maxage=7d" alt="OleskiiPyskun"/></a>
<a href="https://github.com/domenicoblanco"><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/9018104?v=4&h=25&w=25&fit=cover&mask=circle&maxage=7d" alt="domenicoblanco"/></a>
<a href="https://github.com/RivMt"><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/40086827?v=4&h=25&w=25&fit=cover&mask=circle&maxage=7d" alt="RivMt"/></a>
<a href="https://github.com/flolep2607"><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/24566964?v=4&h=25&w=25&fit=cover&mask=circle&maxage=7d" alt="flolep2607"/></a>
## Licensing
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

+45 -2
View File
@@ -7,6 +7,8 @@ from typing import Union
from functools import cache
from pathlib import Path
import fitz
import xmltodict
from cbz.constants import XML_NAME, COMIC_FIELDS, IMAGE_FORMAT, PAGE_FIELDS
@@ -64,10 +66,51 @@ class ComicInfo(ComicModel):
"""
if not isinstance(path, (Path, str)):
raise ValueError(f'Expecting Path object or path string, got {path!r}')
return cls.__unpack(path)
return cls.__unpack_zip(path)
@classmethod
def from_pdf(cls, path: Union[Path, str]) -> ComicInfo:
"""
Create a ComicInfo instance from a PDF file.
Args:
path (Union[Path, str]): Path to the PDF file.
Returns:
ComicInfo: An instance of ComicInfo.
Raises:
ValueError: If the provided path is not a Path object or a string.
"""
if not isinstance(path, (Path, str)):
raise ValueError(f'Expecting Path object or path string, got {path!r}')
return cls.__unpack_pdf(path)
@staticmethod
def __unpack(path: Path) -> ComicInfo:
def __unpack_pdf(path: Path) -> ComicInfo:
"""
Unpack a PDF file and create a ComicInfo instance.
Args:
path (Path): Path to the PDF file.
Returns:
ComicInfo: An instance of ComicInfo.
"""
pages: list[PageInfo] = []
with fitz.open(path) as pf:
for element in pf:
# Check if the page has images
images = element.get_images(full=True)
for i, image in enumerate(images):
base = pf.extract_image(image[0])
pages.append(PageInfo.loads(data=base['image']))
assert pages, 'No valid images present in file'
return ComicInfo.from_pages(pages=pages)
@staticmethod
def __unpack_zip(path: Path) -> ComicInfo:
"""
Unpack a CBZ file and create a ComicInfo instance.
+26 -10
View File
@@ -3,6 +3,7 @@ import tkinter as tk
from io import BytesIO
from tkinter import ttk
from tkinter.constants import DISABLED, NORMAL
from ctypes import windll
from PIL import Image, ImageTk
from pathlib import Path
@@ -10,6 +11,9 @@ from pathlib import Path
from cbz.comic import ComicInfo
from cbz.page import PageInfo
from cbz.utils import readable_size
import os
PARENT = Path(__file__).parent
class Player:
@@ -52,8 +56,12 @@ class Player:
# Set initial window size
self.root.geometry(self._get_initial_geometry())
# Set window icon
self.root.iconbitmap(Path(__file__).parent / 'cbz.ico')
# Check if windows or linux for window icon
if os.name == 'nt':
windll.shell32.SetCurrentProcessExplicitAppUserModelID('cbz.player')
self.root.iconbitmap(PARENT / 'cbz.ico')
else:
self.root.wm_iconphoto(True, tk.PhotoImage(file=PARENT / 'cbz.png'))
# Create main frame for content
self.main_frame = ttk.Frame(self.root)
@@ -70,6 +78,7 @@ class Player:
self._init_summary_text()
# Display initial page content
# TODO: Support scrollable image and/or zoom when it is too large for the screen (eg: webtoon)
self.show_page()
# Bind keys for navigation and window resize
@@ -87,7 +96,7 @@ class Player:
str: Window title.
"""
if self.comic_info.series and self.comic_info.title:
return f"{self.comic_info.series} - {self.comic_info.title}"
return f'{self.comic_info.series} - {self.comic_info.title}'
return self.comic_info.title or self.__class__.__name__
def _get_initial_geometry(self) -> str:
@@ -107,18 +116,25 @@ class Player:
# Calculate scaling factors for width and height
if self.comic_info.pages:
first_page = self.comic_info.pages[0]
scale_width = available_width / first_page.image_width
scale_height = available_height / first_page.image_height
# Get the minimum dimensions from all pages
image_width = self.comic_info.pages[0].image_width
image_height = self.comic_info.pages[0].image_height
for page in self.comic_info.pages[1:]:
if page.image_width <= image_width and page.image_height <= image_height:
image_width = page.image_width
image_height = page.image_height
scale_width = available_width / image_width
scale_height = available_height / image_height
# Choose the smaller scaling factor to maintain proportions
scale_factor = min(scale_width, scale_height)
# Calculate new dimensions
initial_width = int(first_page.image_width * scale_factor)
initial_height = int(first_page.image_height * scale_factor)
initial_width = int(image_width * scale_factor * 0.94)
initial_height = int(image_height * scale_factor)
else:
initial_width = int(available_width)
initial_width = int(available_height * 0.63)
initial_height = int(available_height)
# Calculate initial position to center the window on the screen
@@ -242,7 +258,7 @@ class Player:
self.root.bind('<Right>', lambda event: self.one_next())
# Bind Ctrl+C to exit application
self.root.bind('<Control-c>', lambda event: self.root.quit())
self.root.bind('<Control-q>', lambda event: self.root.quit())
# Bind the configure event to handle window resize
self.root.bind('<Configure>', lambda event: self.on_window(event))
Generated
+76 -1
View File
@@ -256,6 +256,81 @@ type = "legacy"
url = "https://pypi.org/simple"
reference = "localpypi"
[[package]]
name = "pymupdf"
version = "1.24.7"
description = "A high performance Python library for data extraction, analysis, conversion & manipulation of PDF (and other) documents."
optional = false
python-versions = ">=3.8"
files = [
{file = "PyMuPDF-1.24.7-cp310-none-macosx_10_9_x86_64.whl", hash = "sha256:9b6984d57e127e016231b2e89b247f2b0fef07af84d4cc91e4893c6d3fde52c7"},
{file = "PyMuPDF-1.24.7-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:7b8405aac8011b445ceb1bc2d4f4c44b2c969024b301f1178399e0084541d747"},
{file = "PyMuPDF-1.24.7-cp310-none-manylinux2014_aarch64.whl", hash = "sha256:ada392c739f43608611d430305c92d1b8922f66a07bc36a4ea0c7f3f9c1b5dd2"},
{file = "PyMuPDF-1.24.7-cp310-none-manylinux2014_x86_64.whl", hash = "sha256:7a59e24873e6d135f9c07be9f47d98502171210957819c8ffa9a7cca1cac1fb8"},
{file = "PyMuPDF-1.24.7-cp310-none-musllinux_1_2_x86_64.whl", hash = "sha256:bdd9a1b703e3fedd9836d54a13b89ddf772a6eaea3b1e34dcd682b8f0b5b7123"},
{file = "PyMuPDF-1.24.7-cp310-none-win32.whl", hash = "sha256:3a2e8af6e2ef437c4e599c7e520299ea10ef02680be0a8533f78d6ee489c5a60"},
{file = "PyMuPDF-1.24.7-cp310-none-win_amd64.whl", hash = "sha256:8293773e973cf07f5d6398699d5d98151a025c9db04a333fd55a87c8f8c3c74b"},
{file = "PyMuPDF-1.24.7-cp311-none-macosx_10_9_x86_64.whl", hash = "sha256:11770619a1d5b90f5f81cc22c11967b2f473310fc9a8f2aa96c1aabff5971c63"},
{file = "PyMuPDF-1.24.7-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:5e9b6018b3af45c6ca04adb0441369eefc0d66e5023f8d54befde9bb4f078c5a"},
{file = "PyMuPDF-1.24.7-cp311-none-manylinux2014_aarch64.whl", hash = "sha256:40743cbfa40a35e873d4b8642709f45849b3315292957d836be647cdd74d1107"},
{file = "PyMuPDF-1.24.7-cp311-none-manylinux2014_x86_64.whl", hash = "sha256:44f4c58040c496fcfc0719df17dab60348c7988d874c5e17233fa664dcf0a984"},
{file = "PyMuPDF-1.24.7-cp311-none-musllinux_1_2_x86_64.whl", hash = "sha256:0d7e8d2155bdc6e61242bdbf5dff2f6d0118f1a3f9e5d83db334a5cf71c90c5f"},
{file = "PyMuPDF-1.24.7-cp311-none-win32.whl", hash = "sha256:3ea0bb27512e72225822d98b6747b51b02de84cc1e17a5579d90ad957760de03"},
{file = "PyMuPDF-1.24.7-cp311-none-win_amd64.whl", hash = "sha256:785c8a40fd5d76b47759f4ade6db0b78a799bb1fb2dd61bbe59784538299ee21"},
{file = "PyMuPDF-1.24.7-cp312-none-macosx_10_9_x86_64.whl", hash = "sha256:999f40a6ead5aaad0c9e23b3c2ed009080bf51be9485ae122ff2cedd6487874b"},
{file = "PyMuPDF-1.24.7-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:03facd26907dcbba63429e8b56fdbabd717f22fb6d24b38bdefc591b309ce437"},
{file = "PyMuPDF-1.24.7-cp312-none-manylinux2014_aarch64.whl", hash = "sha256:7ec6da974092de0f842f9ef0e355c58a5529c2d5ec792709d2c6fec5ffcd80b1"},
{file = "PyMuPDF-1.24.7-cp312-none-manylinux2014_x86_64.whl", hash = "sha256:89ccd758b5b7d1e05d615e85fb5d358ff1994ff70aaa5df4f0724bd414847949"},
{file = "PyMuPDF-1.24.7-cp312-none-musllinux_1_2_x86_64.whl", hash = "sha256:8873253ffedb7bcc8dcafa9bfe8f1efa39ac91732ccc579e1c1746eeff4ed83a"},
{file = "PyMuPDF-1.24.7-cp312-none-win32.whl", hash = "sha256:5341440bfc6c89f025990d181896b74097f6b145f5e563e3d5e5fa944c79aae6"},
{file = "PyMuPDF-1.24.7-cp312-none-win_amd64.whl", hash = "sha256:a906b57dae8f3870663f3d3a1d4a66b67cc8f5cf644bcbdd175a391f5f74f2ef"},
{file = "PyMuPDF-1.24.7-cp38-none-macosx_10_9_x86_64.whl", hash = "sha256:b18630fead76175059b973230cc175c4ed30e9f4ea03d25963d2c74440bdb78b"},
{file = "PyMuPDF-1.24.7-cp38-none-macosx_11_0_arm64.whl", hash = "sha256:a94d556b7ea25e6195c46dc2c4114d30e8e51233a49f0ed589f8e0190d2cc3b5"},
{file = "PyMuPDF-1.24.7-cp38-none-manylinux2014_aarch64.whl", hash = "sha256:da82dc784e52b3635110995a75189cdef71b02d9a3a2635cd1d216133d547519"},
{file = "PyMuPDF-1.24.7-cp38-none-manylinux2014_x86_64.whl", hash = "sha256:d95c0cc4768ce09d06c31280cda6fc7619026e615d33beee2dbd1c74ea3a1e08"},
{file = "PyMuPDF-1.24.7-cp38-none-musllinux_1_2_x86_64.whl", hash = "sha256:5c7c964e4b3dfbcd7a0ec11f44090002967c9652cf1dbaf5e09de333c479eae3"},
{file = "PyMuPDF-1.24.7-cp38-none-win32.whl", hash = "sha256:5812645087eaf537efb168df1a78b40b76d6b01c694b890d31e362fd007926fe"},
{file = "PyMuPDF-1.24.7-cp38-none-win_amd64.whl", hash = "sha256:b11065d5192bdc6e80046505ed68447276d3698ec1d0a3eea8dc2533f972f8fb"},
{file = "PyMuPDF-1.24.7-cp39-none-macosx_10_9_x86_64.whl", hash = "sha256:102d3427fcc3a47084eb2faa670de8a58e5d2061b4e61365b323d12a7bac0afd"},
{file = "PyMuPDF-1.24.7-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:5580c975a166a3fb1908fb055c0427bcd23abe7a7d3113777d15c0e5f8a2133b"},
{file = "PyMuPDF-1.24.7-cp39-none-manylinux2014_aarch64.whl", hash = "sha256:1553df16e6e141314fa33534800aee2bc4eab1daa8057bf791584b318aa114f6"},
{file = "PyMuPDF-1.24.7-cp39-none-manylinux2014_x86_64.whl", hash = "sha256:53cedffedc7ec5c019f8b06d0e18b1f410f4af15e0c122330b79d5e617739042"},
{file = "PyMuPDF-1.24.7-cp39-none-musllinux_1_2_x86_64.whl", hash = "sha256:371b983ba2b396a636518e2cfaa76ea8cccd38c9bdbc942256df678e421f7063"},
{file = "PyMuPDF-1.24.7-cp39-none-win32.whl", hash = "sha256:0a93d0f5c5b5cdc2f1718dbdf4b1c34aafc68ee4e44688b58c0a2894277ca941"},
{file = "PyMuPDF-1.24.7-cp39-none-win_amd64.whl", hash = "sha256:f82db6fd757fb3698075e2e68e4f6df7ae89b82a96ae102e178e5b01a250359b"},
{file = "PyMuPDF-1.24.7.tar.gz", hash = "sha256:a34ceae204f215bad51f49dd43987116c6a6269fc03d8770224f7067013b59b8"},
]
[package.dependencies]
PyMuPDFb = "1.24.6"
[package.source]
type = "legacy"
url = "https://pypi.org/simple"
reference = "localpypi"
[[package]]
name = "pymupdfb"
version = "1.24.6"
description = "MuPDF shared libraries for PyMuPDF."
optional = false
python-versions = ">=3.8"
files = [
{file = "PyMuPDFb-1.24.6-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:21e3ed890f736def68b9a031122ae1fb854d5cb9a53aa144b6e2ca3092416a6b"},
{file = "PyMuPDFb-1.24.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8704d2dfadc9448ce184597d8b0f9c30143e379ac948a517f9c4db7c0c71ed51"},
{file = "PyMuPDFb-1.24.6-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:01662584d5cfa7a91f77585f13fc23a12291cfd76a57e0a28dd5a56bf521cb2c"},
{file = "PyMuPDFb-1.24.6-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e1f7657353529ae3f88575c83ee49eac9adea311a034b9c97248a65cee7df0e5"},
{file = "PyMuPDFb-1.24.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:cebc2cedb870d1e1168e2f502eb06f05938f6df69103b0853a2b329611ec19a7"},
{file = "PyMuPDFb-1.24.6-py3-none-win32.whl", hash = "sha256:ac4b865cd1e239db04674f85e02844a0e405f8255ee7a74dfee0d86aad0d3576"},
{file = "PyMuPDFb-1.24.6-py3-none-win_amd64.whl", hash = "sha256:9224e088a0d3c188dea03831807789e245b812fbd071c8d498da8f7cc33142b2"},
{file = "PyMuPDFb-1.24.6.tar.gz", hash = "sha256:f5a40b1732d65a1e519916d698858b9ce7473e23edf9001ddd085c5293d59d30"},
]
[package.source]
type = "legacy"
url = "https://pypi.org/simple"
reference = "localpypi"
[[package]]
name = "setuptools"
version = "70.3.0"
@@ -295,4 +370,4 @@ reference = "localpypi"
[metadata]
lock-version = "2.0"
python-versions = "^3.8"
content-hash = "dfb034cdc323648effbcfff969cae65cbca1b04130c64d68c8c8968f0d692e71"
content-hash = "080fe35089770ecee25895cdd4ee4aa14b9e9c818c199908f066bc94c4470530"
+2 -1
View File
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "cbz"
version = "3.3.0"
version = "3.3.1"
description = "CBZ simplifies creating, managing, and viewing comic book files in CBZ format, offering seamless packaging, metadata handling, and built-in viewing capabilities"
license = "MIT"
authors = ["hyugogirubato <65763543+hyugogirubato@users.noreply.github.com>"]
@@ -34,6 +34,7 @@ python = "^3.8"
xmltodict = "^0.13.0"
langcodes = "^3.4.0"
Pillow = "^10.4.0"
PyMuPDF = "^1.24.7"
[tool.poetry.scripts]
cbzplayer = "cbz.__main__:main"