Merge pull request #1 from radarhere/qoi_write

Fixed type hints
This commit is contained in:
thisismypassport 2025-06-10 13:05:27 +03:00 committed by GitHub
commit 2a1ed6ee3f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 10 additions and 16 deletions

View File

@ -6,11 +6,7 @@ import pytest
from PIL import Image, QoiImagePlugin from PIL import Image, QoiImagePlugin
from .helper import ( from .helper import assert_image_equal_tofile, hopper
assert_image_equal,
assert_image_equal_tofile,
hopper,
)
def test_sanity() -> None: def test_sanity() -> None:
@ -42,15 +38,13 @@ def test_save(tmp_path: Path) -> None:
im = hopper("RGB") im = hopper("RGB")
im.save(f, qoi_colorspace="sRGB") im.save(f, qoi_colorspace="sRGB")
with Image.open(f) as reloaded: assert_image_equal_tofile(im, f)
assert_image_equal(im, reloaded)
for image in ["Tests/images/default_font.png", "Tests/images/pil123rgba.png"]: for image in ["Tests/images/default_font.png", "Tests/images/pil123rgba.png"]:
with Image.open(image) as im: with Image.open(image) as im:
im.save(f) im.save(f)
with Image.open(f) as reloaded: assert_image_equal_tofile(im, f)
assert_image_equal(im, reloaded)
im = hopper("P") im = hopper("P")
with pytest.raises(ValueError): with pytest.raises(ValueError):

View File

@ -113,7 +113,7 @@ class QoiDecoder(ImageFile.PyDecoder):
return -1, 0 return -1, 0
def _save(im: Image.image, fp: IO[bytes], filename: str | bytes) -> None: def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
if im.mode == "RGB": if im.mode == "RGB":
channels = 3 channels = 3
elif im.mode == "RGBA": elif im.mode == "RGBA":
@ -133,18 +133,18 @@ def _save(im: Image.image, fp: IO[bytes], filename: str | bytes) -> None:
fp.write(o8(channels)) fp.write(o8(channels))
fp.write(o8(colorspace)) fp.write(o8(colorspace))
ImageFile._save(im, fp, [ImageFile._Tile("qoi", (0, 0) + im.size, 0, im.mode)]) ImageFile._save(im, fp, [ImageFile._Tile("qoi", (0, 0) + im.size)])
class QoiEncoder(ImageFile.PyEncoder): class QoiEncoder(ImageFile.PyEncoder):
_pushes_fd = True _pushes_fd = True
_previous_pixel: tuple[int] | None = None _previous_pixel: tuple[int, int, int, int] | None = None
_previously_seen_pixels: dict[int, tuple[int]] = {} _previously_seen_pixels: dict[int, tuple[int, int, int, int]] = {}
def _write_run(self, run): def _write_run(self, run: int) -> bytes:
return o8(0xC0 | (run - 1)) # QOI_OP_RUN return o8(0xC0 | (run - 1)) # QOI_OP_RUN
def _delta(self, left, right): def _delta(self, left: int, right: int) -> int:
result = (left - right) & 0xFF result = (left - right) & 0xFF
if result >= 0x80: if result >= 0x80:
result -= 0x100 result -= 0x100
@ -181,7 +181,7 @@ class QoiEncoder(ImageFile.PyEncoder):
hash_value = (r * 3 + g * 5 + b * 7 + a * 11) % 64 hash_value = (r * 3 + g * 5 + b * 7 + a * 11) % 64
if self._previously_seen_pixels.get(hash_value) == pixel: if self._previously_seen_pixels.get(hash_value) == pixel:
data += o8(hash_value) # QOI_OP_INDEX data += o8(hash_value) # QOI_OP_INDEX
else: elif self._previous_pixel:
self._previously_seen_pixels[hash_value] = pixel self._previously_seen_pixels[hash_value] = pixel
pr, pg, pb, pa = self._previous_pixel pr, pg, pb, pa = self._previous_pixel