51 lines
1.9 KiB
Python
51 lines
1.9 KiB
Python
from __future__ import annotations
|
|
from dataclasses import dataclass
|
|
import numpy as np
|
|
|
|
# Локальные импорты внутри методов уменьшают риск циклов зависимостей
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class YcbcrImage512:
|
|
"""YCbCr-изображение 512x512."""
|
|
|
|
data: np.ndarray # uint8, shape (512, 512, 3)
|
|
|
|
def __post_init__(self):
|
|
arr = np.asarray(self.data, dtype=np.uint8)
|
|
if arr.shape != (512, 512, 3):
|
|
raise ValueError("Изображение должно быть 512x512x3 (YCbCr).")
|
|
object.__setattr__(self, "data", arr)
|
|
|
|
@classmethod
|
|
def from_rgb(cls, rgb_img) -> "YcbcrImage512":
|
|
"""Создать из RgbImage512."""
|
|
from .color_space import ColorSpace
|
|
from .rgb_image512 import RgbImage512
|
|
if not isinstance(rgb_img, RgbImage512):
|
|
raise TypeError("Ожидается RgbImage512.")
|
|
ycbcr = ColorSpace.rgb_to_ycbcr(rgb_img.to_array())
|
|
return cls(ycbcr)
|
|
|
|
def to_rgb(self):
|
|
"""Преобразовать в RgbImage512."""
|
|
from .color_space import ColorSpace
|
|
from .rgb_image512 import RgbImage512
|
|
rgb = ColorSpace.ycbcr_to_rgb(self.data)
|
|
return RgbImage512.from_array(rgb)
|
|
|
|
def get_channel(self, name: str) -> np.ndarray:
|
|
"""Вернуть 2D-компоненту канала."""
|
|
from .channel_view import ChannelView
|
|
return ChannelView.get(self.data, name)
|
|
|
|
def with_channel(self, name: str, component: np.ndarray) -> "YcbcrImage512":
|
|
"""Вернуть копию с заменённым каналом."""
|
|
from .channel_view import ChannelView
|
|
new_ycbcr = ChannelView.set(self.data, name, component)
|
|
return YcbcrImage512(new_ycbcr)
|
|
|
|
def to_array(self) -> np.ndarray:
|
|
"""Вернуть массив uint8 512x512x3."""
|
|
return self.data
|