[pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
This commit is contained in:
pre-commit-ci[bot] 2024-03-02 00:38:49 +00:00
parent 8e0c5db1e0
commit a57ebeaaf4
7 changed files with 65 additions and 59 deletions

View File

@ -1,13 +1,13 @@
from __future__ import annotations
import re import re
import pytest import pytest
from PIL import Image, JxlImagePlugin, features from PIL import Image, JxlImagePlugin, features
from .helper import ( from .helper import (
assert_image_equal,
assert_image_similar,
assert_image_similar_tofile, assert_image_similar_tofile,
hopper,
skip_unless_feature, skip_unless_feature,
) )
@ -21,6 +21,7 @@ except ImportError:
# cjxl v0.9.2 41b8cdab # cjxl v0.9.2 41b8cdab
# hopper.jxl: cjxl hopper.png hopper.jxl -q 75 -e 8 # hopper.jxl: cjxl hopper.png hopper.jxl -q 75 -e 8
class TestUnsupportedJxl: class TestUnsupportedJxl:
def test_unsupported(self) -> None: def test_unsupported(self) -> None:
if HAVE_JXL: if HAVE_JXL:
@ -35,6 +36,7 @@ class TestUnsupportedJxl:
if HAVE_JXL: if HAVE_JXL:
JxlImagePlugin.SUPPORTED = True JxlImagePlugin.SUPPORTED = True
@skip_unless_feature("jxl") @skip_unless_feature("jxl")
class TestFileJxl: class TestFileJxl:
def setup_method(self) -> None: def setup_method(self) -> None:
@ -68,5 +70,3 @@ class TestFileJxl:
with pytest.raises(TypeError): with pytest.raises(TypeError):
_jxl.PILJxlDecoder() _jxl.PILJxlDecoder()

View File

@ -4,9 +4,7 @@ import pytest
from PIL import Image from PIL import Image
from .helper import ( from .helper import assert_image_similar_tofile
assert_image_similar_tofile
)
_webp = pytest.importorskip("PIL._jxl", reason="JXL support not installed") _webp = pytest.importorskip("PIL._jxl", reason="JXL support not installed")
@ -29,4 +27,3 @@ def test_read_rgba() -> None:
image.tobytes() image.tobytes()
assert_image_similar_tofile(image, "Tests/images/transparent.png", 1.0) assert_image_similar_tofile(image, "Tests/images/transparent.png", 1.0)

View File

@ -1,9 +1,8 @@
from __future__ import annotations from __future__ import annotations
import pytest import pytest
from packaging.version import parse as parse_version
from PIL import Image, features from PIL import Image
from .helper import ( from .helper import (
assert_image_equal, assert_image_equal,
@ -53,7 +52,7 @@ def test_seeking() -> None:
im2.seek(frame) im2.seek(frame)
im2.load() im2.load()
assert_image_equal(im1.convert('RGB'), im2.convert('RGB')) assert_image_equal(im1.convert("RGB"), im2.convert("RGB"))
total_dur += im1.info["duration"] total_dur += im1.info["duration"]
assert im1.info["duration"] == im2.info["duration"] assert im1.info["duration"] == im2.info["duration"]

View File

@ -1,14 +1,12 @@
from __future__ import annotations from __future__ import annotations
from io import BytesIO
from pathlib import Path
from types import ModuleType from types import ModuleType
import pytest import pytest
from PIL import Image from PIL import Image
from .helper import mark_if_feature_version, skip_unless_feature from .helper import skip_unless_feature
pytestmark = [ pytestmark = [
skip_unless_feature("jxl"), skip_unless_feature("jxl"),
@ -26,6 +24,7 @@ except ImportError:
# python -c "from PIL import Image; im=Image.open('Tests/images/flower2.webp'); f=open('/tmp/xmp.xml', 'wb'); f.write(im.info['xmp']); f.close()" # python -c "from PIL import Image; im=Image.open('Tests/images/flower2.webp'); f=open('/tmp/xmp.xml', 'wb'); f.write(im.info['xmp']); f.close()"
# cjxl flower2.jpg flower2.jxl --lossless_jpeg=0 -q 75 -e 8 -x xmp=/tmp/xmp.xml # cjxl flower2.jpg flower2.jxl --lossless_jpeg=0 -q 75 -e 8 -x xmp=/tmp/xmp.xml
def test_read_exif_metadata() -> None: def test_read_exif_metadata() -> None:
file_path = "Tests/images/flower.jxl" file_path = "Tests/images/flower.jxl"
with Image.open(file_path) as image: with Image.open(file_path) as image:
@ -85,4 +84,3 @@ def test_getxmp() -> None:
im.getxmp()["xmpmeta"]["xmptk"] im.getxmp()["xmpmeta"]["xmptk"]
== "Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27 " == "Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27 "
) )

View File

@ -1,6 +1,9 @@
from io import BytesIO from __future__ import annotations
from . import Image, ImageFile
import struct import struct
from io import BytesIO
from . import Image, ImageFile
try: try:
from . import _jxl from . import _jxl
@ -16,11 +19,14 @@ except ImportError:
## then libjxl decoder is rewinded and we're ready to decode frame by frame ## then libjxl decoder is rewinded and we're ready to decode frame by frame
## if OPEN_COUNTS_FRAMES is False, n_frames will be None until the last frame is decoded ## if OPEN_COUNTS_FRAMES is False, n_frames will be None until the last frame is decoded
## it only applies to animated jpeg xl images ## it only applies to animated jpeg xl images
#OPEN_COUNTS_FRAMES = True # OPEN_COUNTS_FRAMES = True
def _accept(prefix): def _accept(prefix):
is_jxl = prefix[:2] == b'\xff\x0a' \ is_jxl = (
or prefix[:12] == b'\x00\x00\x00\x0c\x4a\x58\x4c\x20\x0d\x0a\x87\x0a' prefix[:2] == b"\xff\x0a"
or prefix[:12] == b"\x00\x00\x00\x0c\x4a\x58\x4c\x20\x0d\x0a\x87\x0a"
)
if is_jxl and not SUPPORTED: if is_jxl and not SUPPORTED:
return "image file could not be identified because JXL support not installed" return "image file could not be identified because JXL support not installed"
return is_jxl return is_jxl
@ -35,7 +41,9 @@ class JxlImageFile(ImageFile.ImageFile):
def _open(self): def _open(self):
self._decoder = _jxl.PILJxlDecoder(self.fp.read()) self._decoder = _jxl.PILJxlDecoder(self.fp.read())
width, height, mode, has_anim, tps_num, tps_denom, n_loops, n_frames = self._decoder.get_info() width, height, mode, has_anim, tps_num, tps_denom, n_loops, n_frames = (
self._decoder.get_info()
)
self._size = width, height self._size = width, height
self.info["loop"] = n_loops self.info["loop"] = n_loops
self.is_animated = has_anim self.is_animated = has_anim
@ -46,7 +54,7 @@ class JxlImageFile(ImageFile.ImageFile):
self.n_frames = 1 self.n_frames = 1
elif n_frames > 0: elif n_frames > 0:
self.n_frames = n_frames self.n_frames = n_frames
self._tps_dur_secs = tps_num/tps_denom self._tps_dur_secs = tps_num / tps_denom
# TODO: handle libjxl timecods # TODO: handle libjxl timecods
self.__timestamp = 0 self.__timestamp = 0
@ -57,13 +65,17 @@ class JxlImageFile(ImageFile.ImageFile):
icc = self._decoder.get_icc() icc = self._decoder.get_icc()
exif = self._decoder.get_exif() exif = self._decoder.get_exif()
xmp = self._decoder.get_xmp() xmp = self._decoder.get_xmp()
if icc: self.info["icc_profile"] = icc if icc:
self.info["icc_profile"] = icc
import traceback import traceback
try: try:
if exif: self.info["exif"] = self._fix_exif(exif) if exif:
self.info["exif"] = self._fix_exif(exif)
except: except:
traceback.print_exc() traceback.print_exc()
if xmp: self.info["xmp"] = xmp if xmp:
self.info["xmp"] = xmp
self._rewind() self._rewind()
@ -73,7 +85,7 @@ class JxlImageFile(ImageFile.ImageFile):
if len(exif) <= 4: if len(exif) <= 4:
return None return None
exif_start_offset = struct.unpack(">I", exif[:4])[0] exif_start_offset = struct.unpack(">I", exif[:4])[0]
return exif[exif_start_offset+4:] return exif[exif_start_offset + 4 :]
def _getexif(self): def _getexif(self):
if "exif" not in self.info: if "exif" not in self.info:
@ -100,7 +112,7 @@ class JxlImageFile(ImageFile.ImageFile):
self.n_frames = self.__physical_frame self.n_frames = self.__physical_frame
# duration in miliseconds # duration in miliseconds
duration = 1000 * tps_duration * (1/self._tps_dur_secs) duration = 1000 * tps_duration * (1 / self._tps_dur_secs)
timestamp = self.__timestamp timestamp = self.__timestamp
self.__timestamp += duration self.__timestamp += duration
@ -115,15 +127,16 @@ class JxlImageFile(ImageFile.ImageFile):
def _seek_check(self, frame): def _seek_check(self, frame):
# if image is not animated then only the 0th frame is available # if image is not animated then only the 0th frame is available
if (not self.is_animated and frame != 0) or \ if (not self.is_animated and frame != 0) or (
(self.n_frames is not None and (frame >= self.n_frames or frame < 0)): self.n_frames is not None and (frame >= self.n_frames or frame < 0)
):
msg = "attempt to seek outside sequence" msg = "attempt to seek outside sequence"
raise EOFError(msg) raise EOFError(msg)
return self.tell() != frame return self.tell() != frame
def _seek(self, frame): def _seek(self, frame):
#print("_seek: phy: {}, fr: {}".format(self.__physical_frame, frame)) # print("_seek: phy: {}, fr: {}".format(self.__physical_frame, frame))
if frame == self.__physical_frame: if frame == self.__physical_frame:
return # Nothing to do return # Nothing to do
if frame < self.__physical_frame: if frame < self.__physical_frame:

View File

@ -270,8 +270,7 @@ def pilinfo(out=None, supported_formats=True):
("transp_webp", "WEBP Transparency"), ("transp_webp", "WEBP Transparency"),
("webp_mux", "WEBPMUX"), ("webp_mux", "WEBPMUX"),
("webp_anim", "WEBP Animation"), ("webp_anim", "WEBP Animation"),
("jxl", "JPEG XL") ("jxl", "JPEG XL")("jpg", "JPEG"),
("jpg", "JPEG"),
("jpg_2000", "OPENJPEG (JPEG2000)"), ("jpg_2000", "OPENJPEG (JPEG2000)"),
("zlib", "ZLIB (PNG/ZIP)"), ("zlib", "ZLIB (PNG/ZIP)"),
("libtiff", "LIBTIFF"), ("libtiff", "LIBTIFF"),

View File

@ -222,7 +222,7 @@ _jxl_decoder_new(PyObject *self, PyObject *args) {
decp->decoder = JxlDecoderCreate(NULL); decp->decoder = JxlDecoderCreate(NULL);
decp->status = JxlDecoderSetParallelRunner(decp->decoder, decp->status = JxlDecoderSetParallelRunner(decp->decoder,
JxlThreadParallelRunner, decp->runner); JxlThreadParallelRunner, decp->runner);
_PIL_JXL_CHECK("JxlDecoderSetParallelRunner") _PIL_JXL_CHECK("JxlDecoderSetParallelRunner")
decp->status = JxlDecoderSubscribeEvents(decp->decoder, decp->status = JxlDecoderSubscribeEvents(decp->decoder,