Cat Feeder  1.0.0
The Cat feeder project
Loading...
Searching...
No Matches
image_to_image.py
Go to the documentation of this file.
1r"""
2# +==== BEGIN CatFeeder =================+
3# LOGO:
4# ..............(..../\
5# ...............)..(.')
6# ..............(../..)
7# ...............\‍(__)|
8# Inspired by Joan Stark
9# source https://www.asciiart.eu/
10# animals/cats
11# /STOP
12# PROJECT: CatFeeder
13# FILE: image_to_image.py
14# CREATION DATE: 15-01-2026
15# LAST Modified: 6:13:53 15-01-2026
16# DESCRIPTION:
17# This is the backend server in charge of making the actual website work.
18# /STOP
19# COPYRIGHT: (c) Cat Feeder
20# PURPOSE: The file containing the code for converting unusual image formats to more common ones.
21# // AR
22# +==== END CatFeeder =================+
23"""
24
25from io import BytesIO
26from typing import Optional
27
28from PIL import Image
29from pillow_heif import register_heif_opener
30
31from display_tty import Disp, initialise_logger
32
33from .aliases import PILLOW_FORMAT_ALIASES
34from . import converters_constants as CONV_CONST
35
36from ..http_constants import DataTypes, MEDIA_TYPES
37
38from ...core import FinalClass
39from ...utils import CONST
40
41
42class ImageToImage(metaclass=FinalClass):
43 """Class used to convert images from one format to another using Pillow."""
44
45 disp: Disp = initialise_logger(__qualname__, CONST.DEBUG)
46
47 _instance: Optional["ImageToImage"] = None
48
49 def __new__(cls) -> "ImageToImage":
50 if cls._instance is None:
51 cls._instance = super(ImageToImage, cls).__new__(cls)
52 return cls._instance
53
54 def __init__(self) -> None:
55 self.disp.log_debug("Initialising...")
56 self.disp.log_debug("Acquireing Pillow pointer...")
57 self.pillow = Image
58 self.disp.log_debug("Registering HEIF pillow support...")
59 register_heif_opener()
60 self.disp.log_debug("Initialised.")
61
62 def __call__(self, data: bytes, source_format: DataTypes) -> CONV_CONST.ConversionResult:
63 return self.image_to_image(data, source_format)
64
65 def image_to_image(self, data: bytes, source_format: DataTypes) -> CONV_CONST.ConversionResult:
66 """_summary_
67 Convert image data from one format to another using Pillow.
68 Args:
69 data (bytes): The image data to convert.
70 source_format (DataTypes): The original image format.
71 Returns:
72 ConversionResult: The converted image data in a contained dataclass.
73 """
74 converted_data: Optional[bytes] = None
75 destination_format = MEDIA_TYPES.get_conversion_target(source_format)
76 if destination_format is None:
77 return CONV_CONST.ConversionResult(
78 data=data,
79 converted=False,
80 from_type=source_format,
81 to_type=source_format,
82 result=None
83 )
84 if source_format == destination_format:
85 return CONV_CONST.ConversionResult(
86 data=data,
87 converted=False,
88 from_type=source_format,
89 to_type=source_format,
90 result=data
91 )
92 pillow_format: Optional[str] = PILLOW_FORMAT_ALIASES.get(
93 destination_format
94 )
95 if pillow_format is None:
96 self.disp.log_warning(
97 f"No Pillow alias for {destination_format}, skipping conversion"
98 )
99 return CONV_CONST.ConversionResult(
100 data=data,
101 converted=False,
102 from_type=source_format,
103 to_type=destination_format,
104 result=data
105 )
106 try:
107 with Image.open(BytesIO(data)) as img:
108 output_buffer = BytesIO()
109 img.save(
110 output_buffer,
111 format=pillow_format or destination_format.name
112 )
113 converted_data = output_buffer.getvalue()
114 return CONV_CONST.ConversionResult(
115 data=data,
116 converted=True,
117 from_type=source_format,
118 to_type=destination_format,
119 result=converted_data
120 )
121 except Exception as e:
122 self.disp.log_error(f"Image conversion error: {e}")
123 return CONV_CONST.ConversionResult(
124 data=data,
125 converted=False,
126 from_type=source_format,
127 to_type=destination_format,
128 result=None
129 )
CONV_CONST.ConversionResult __call__(self, bytes data, DataTypes source_format)
CONV_CONST.ConversionResult image_to_image(self, bytes data, DataTypes source_format)