diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e648ef..ca452fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [3.3.2] - Not released +### Changed + +- Simplification of the player icon set. + ### Fixed - Fixed lag when stretching player. diff --git a/cbz/cbz.png b/cbz/cbz.png deleted file mode 100644 index 5f9bcae..0000000 Binary files a/cbz/cbz.png and /dev/null differ diff --git a/cbz/player.py b/cbz/player.py index c68b499..27ef290 100644 --- a/cbz/player.py +++ b/cbz/player.py @@ -10,7 +10,7 @@ from pathlib import Path from cbz.comic import ComicInfo from cbz.page import PageInfo -from cbz.utils import readable_size +from cbz.utils import readable_size, ico_to_png import os PARENT = Path(__file__).parent @@ -56,12 +56,8 @@ class Player: # Set initial window size self.root.geometry(self._get_initial_geometry()) - # 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')) + # Set the application icon + self._set_icon() # Create main frame for content self.main_frame = ttk.Frame(self.root) @@ -91,6 +87,20 @@ class Player: # Initialize resize timer self.resize_timer = None + def _set_icon(self) -> None: + """ + Set the application icon for the window. + """ + image_path = PARENT / 'cbz.ico' + if os.name == 'nt': + # Set the application ID and icon on Windows + windll.shell32.SetCurrentProcessExplicitAppUserModelID('cbz.player') + self.root.iconbitmap(image_path) + else: + # Convert ICO to PNG for other operating systems + image = ico_to_png(image_path) + self.root.iconphoto(True, tk.PhotoImage(data=image.getvalue())) + def _get_window_title(self) -> str: """ Get the window title based on the comic series and title. @@ -242,7 +252,7 @@ class Player: # Resize image new_width = int(img.width * scale_factor) new_height = int(img.height * scale_factor) - img = img.resize((new_width, new_height), Image.LANCZOS) + img = img.resize((new_width, new_height), Image.Resampling.LANCZOS) # Set image on canvas self.canvas.image = ImageTk.PhotoImage(img) diff --git a/cbz/utils.py b/cbz/utils.py index 8971c9f..8064afb 100644 --- a/cbz/utils.py +++ b/cbz/utils.py @@ -1,4 +1,54 @@ +import struct from enum import Enum +from io import BytesIO + +from PIL import Image +from path import Path + + +def extract_ico(path: Path) -> list[Image]: + """ + Extracts all the images from an ICO file. + + Args: + path (Path): Path to the ICO file. + + Returns: + list[Image]: List of PIL Image objects representing the icons in the ICO file. + """ + # https://stackoverflow.com/questions/74341558/how-do-i-read-a-different-size-of-an-icon-file + # https://en.wikipedia.org/wiki/ICO_(file_format) + icons = [] + + # Constants for ICO file structure + ICONDIRSIZE = 6 + ICONDIRENTRYSIZE = 16 + + # Read the entire ICO file content + d = path.read_bytes() + + # Extract ICONDIR header + hdrReserved, hdrImageType, hdrNumImages = struct.unpack(' any: @@ -77,3 +127,19 @@ def readable_size(size: int, decimal: int = 2) -> str: if size < 1024: return f'{size:.{decimal}f} {unit}' size /= 1024 + + +def ico_to_png(path: Path) -> BytesIO: + """ + Converts the largest icon in an ICO file to PNG format. + + Args: + path (Path): Path to the ICO file. + + Returns: + BytesIO: In-memory PNG file of the largest icon. + """ + icons = extract_ico(path) + content = BytesIO() + icons[-1].save(content, format='PNG') + return content diff --git a/docs/favicon/favicon.svg b/docs/favicon/favicon.svg new file mode 100644 index 0000000..309013e --- /dev/null +++ b/docs/favicon/favicon.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +