mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-02-10 16:40:51 +03:00
Merge branch 'main' into fp
This commit is contained in:
commit
b8f8799912
Binary file not shown.
Before Width: | Height: | Size: 486 B After Width: | Height: | Size: 533 B |
|
@ -84,4 +84,4 @@ def test_handler(tmp_path: Path) -> None:
|
||||||
im.save(temp_file)
|
im.save(temp_file)
|
||||||
assert handler.saved
|
assert handler.saved
|
||||||
|
|
||||||
BufrStubImagePlugin._handler = None
|
BufrStubImagePlugin.register_handler(None)
|
||||||
|
|
|
@ -4,8 +4,6 @@ import pytest
|
||||||
|
|
||||||
from PIL import ContainerIO, Image
|
from PIL import ContainerIO, Image
|
||||||
|
|
||||||
from .helper import hopper
|
|
||||||
|
|
||||||
TEST_FILE = "Tests/images/dummy.container"
|
TEST_FILE = "Tests/images/dummy.container"
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,15 +13,15 @@ def test_sanity() -> None:
|
||||||
|
|
||||||
|
|
||||||
def test_isatty() -> None:
|
def test_isatty() -> None:
|
||||||
with hopper() as im:
|
with open(TEST_FILE, "rb") as fh:
|
||||||
container = ContainerIO.ContainerIO(im, 0, 0)
|
container = ContainerIO.ContainerIO(fh, 0, 0)
|
||||||
|
|
||||||
assert container.isatty() is False
|
assert container.isatty() is False
|
||||||
|
|
||||||
|
|
||||||
def test_seekable() -> None:
|
def test_seekable() -> None:
|
||||||
with hopper() as im:
|
with open(TEST_FILE, "rb") as fh:
|
||||||
container = ContainerIO.ContainerIO(im, 0, 0)
|
container = ContainerIO.ContainerIO(fh, 0, 0)
|
||||||
|
|
||||||
assert container.seekable() is True
|
assert container.seekable() is True
|
||||||
|
|
||||||
|
|
|
@ -84,4 +84,4 @@ def test_handler(tmp_path: Path) -> None:
|
||||||
im.save(temp_file)
|
im.save(temp_file)
|
||||||
assert handler.saved
|
assert handler.saved
|
||||||
|
|
||||||
GribStubImagePlugin._handler = None
|
GribStubImagePlugin.register_handler(None)
|
||||||
|
|
|
@ -86,4 +86,4 @@ def test_handler(tmp_path: Path) -> None:
|
||||||
im.save(temp_file)
|
im.save(temp_file)
|
||||||
assert handler.saved
|
assert handler.saved
|
||||||
|
|
||||||
Hdf5StubImagePlugin._handler = None
|
Hdf5StubImagePlugin.register_handler(None)
|
||||||
|
|
|
@ -1000,8 +1000,13 @@ class TestFileJpeg:
|
||||||
with Image.open(f) as reloaded:
|
with Image.open(f) as reloaded:
|
||||||
assert reloaded.info["xmp"] == b"XMP test"
|
assert reloaded.info["xmp"] == b"XMP test"
|
||||||
|
|
||||||
im.info["xmp"] = b"1" * 65504
|
# Check that XMP is not saved from image info
|
||||||
im.save(f)
|
reloaded.save(f)
|
||||||
|
|
||||||
|
with Image.open(f) as reloaded:
|
||||||
|
assert "xmp" not in reloaded.info
|
||||||
|
|
||||||
|
im.save(f, xmp=b"1" * 65504)
|
||||||
with Image.open(f) as reloaded:
|
with Image.open(f) as reloaded:
|
||||||
assert reloaded.info["xmp"] == b"1" * 65504
|
assert reloaded.info["xmp"] == b"1" * 65504
|
||||||
|
|
||||||
|
|
|
@ -424,7 +424,8 @@ def test_pclr() -> None:
|
||||||
|
|
||||||
|
|
||||||
def test_comment() -> None:
|
def test_comment() -> None:
|
||||||
with Image.open("Tests/images/comment.jp2") as im:
|
for path in ("Tests/images/9bit.j2k", "Tests/images/comment.jp2"):
|
||||||
|
with Image.open(path) as im:
|
||||||
assert im.info["comment"] == b"Created by OpenJPEG version 2.5.0"
|
assert im.info["comment"] == b"Created by OpenJPEG version 2.5.0"
|
||||||
|
|
||||||
# Test an image that is truncated partway through a codestream
|
# Test an image that is truncated partway through a codestream
|
||||||
|
|
|
@ -297,3 +297,15 @@ def test_save_all() -> None:
|
||||||
# Test that a single frame image will not be saved as an MPO
|
# Test that a single frame image will not be saved as an MPO
|
||||||
jpg = roundtrip(im, save_all=True)
|
jpg = roundtrip(im, save_all=True)
|
||||||
assert "mp" not in jpg.info
|
assert "mp" not in jpg.info
|
||||||
|
|
||||||
|
|
||||||
|
def test_save_xmp() -> None:
|
||||||
|
im = Image.new("RGB", (1, 1))
|
||||||
|
im2 = Image.new("RGB", (1, 1), "#f00")
|
||||||
|
im2.encoderinfo = {"xmp": b"Second frame"}
|
||||||
|
im_reloaded = roundtrip(im, xmp=b"First frame", save_all=True, append_images=[im2])
|
||||||
|
|
||||||
|
assert im_reloaded.info["xmp"] == b"First frame"
|
||||||
|
|
||||||
|
im_reloaded.seek(1)
|
||||||
|
assert im_reloaded.info["xmp"] == b"Second frame"
|
||||||
|
|
|
@ -772,22 +772,18 @@ class TestFilePng:
|
||||||
im.seek(1)
|
im.seek(1)
|
||||||
|
|
||||||
@pytest.mark.parametrize("buffer", (True, False))
|
@pytest.mark.parametrize("buffer", (True, False))
|
||||||
def test_save_stdout(self, buffer: bool) -> None:
|
def test_save_stdout(self, buffer: bool, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||||
old_stdout = sys.stdout
|
|
||||||
|
|
||||||
class MyStdOut:
|
class MyStdOut:
|
||||||
buffer = BytesIO()
|
buffer = BytesIO()
|
||||||
|
|
||||||
mystdout: MyStdOut | BytesIO = MyStdOut() if buffer else BytesIO()
|
mystdout: MyStdOut | BytesIO = MyStdOut() if buffer else BytesIO()
|
||||||
|
|
||||||
sys.stdout = mystdout
|
monkeypatch.setattr(sys, "stdout", mystdout)
|
||||||
|
|
||||||
with Image.open(TEST_PNG_FILE) as im:
|
with Image.open(TEST_PNG_FILE) as im:
|
||||||
im.save(sys.stdout, "PNG")
|
im.save(sys.stdout, "PNG")
|
||||||
|
|
||||||
# Reset stdout
|
|
||||||
sys.stdout = old_stdout
|
|
||||||
|
|
||||||
if isinstance(mystdout, MyStdOut):
|
if isinstance(mystdout, MyStdOut):
|
||||||
mystdout = mystdout.buffer
|
mystdout = mystdout.buffer
|
||||||
with Image.open(mystdout) as reloaded:
|
with Image.open(mystdout) as reloaded:
|
||||||
|
|
|
@ -367,22 +367,18 @@ def test_mimetypes(tmp_path: Path) -> None:
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("buffer", (True, False))
|
@pytest.mark.parametrize("buffer", (True, False))
|
||||||
def test_save_stdout(buffer: bool) -> None:
|
def test_save_stdout(buffer: bool, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||||
old_stdout = sys.stdout
|
|
||||||
|
|
||||||
class MyStdOut:
|
class MyStdOut:
|
||||||
buffer = BytesIO()
|
buffer = BytesIO()
|
||||||
|
|
||||||
mystdout: MyStdOut | BytesIO = MyStdOut() if buffer else BytesIO()
|
mystdout: MyStdOut | BytesIO = MyStdOut() if buffer else BytesIO()
|
||||||
|
|
||||||
sys.stdout = mystdout
|
monkeypatch.setattr(sys, "stdout", mystdout)
|
||||||
|
|
||||||
with Image.open(TEST_FILE) as im:
|
with Image.open(TEST_FILE) as im:
|
||||||
im.save(sys.stdout, "PPM")
|
im.save(sys.stdout, "PPM")
|
||||||
|
|
||||||
# Reset stdout
|
|
||||||
sys.stdout = old_stdout
|
|
||||||
|
|
||||||
if isinstance(mystdout, MyStdOut):
|
if isinstance(mystdout, MyStdOut):
|
||||||
mystdout = mystdout.buffer
|
mystdout = mystdout.buffer
|
||||||
with Image.open(mystdout) as reloaded:
|
with Image.open(mystdout) as reloaded:
|
||||||
|
|
|
@ -104,20 +104,20 @@ def test_transposed() -> None:
|
||||||
assert im.size == (590, 88)
|
assert im.size == (590, 88)
|
||||||
|
|
||||||
|
|
||||||
def test_load_first_unless_jpeg() -> None:
|
def test_load_first_unless_jpeg(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||||
# Test that thumbnail() still uses draft() for JPEG
|
# Test that thumbnail() still uses draft() for JPEG
|
||||||
with Image.open("Tests/images/hopper.jpg") as im:
|
with Image.open("Tests/images/hopper.jpg") as im:
|
||||||
draft = im.draft
|
original_draft = im.draft
|
||||||
|
|
||||||
def im_draft(
|
def im_draft(
|
||||||
mode: str, size: tuple[int, int]
|
mode: str | None, size: tuple[int, int] | None
|
||||||
) -> tuple[str, tuple[int, int, float, float]] | None:
|
) -> tuple[str, tuple[int, int, float, float]] | None:
|
||||||
result = draft(mode, size)
|
result = original_draft(mode, size)
|
||||||
assert result is not None
|
assert result is not None
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
im.draft = im_draft
|
monkeypatch.setattr(im, "draft", im_draft)
|
||||||
|
|
||||||
im.thumbnail((64, 64))
|
im.thumbnail((64, 64))
|
||||||
|
|
||||||
|
|
|
@ -1674,6 +1674,9 @@ def test_continuous_horizontal_edges_polygon() -> None:
|
||||||
def test_discontiguous_corners_polygon() -> None:
|
def test_discontiguous_corners_polygon() -> None:
|
||||||
img, draw = create_base_image_draw((84, 68))
|
img, draw = create_base_image_draw((84, 68))
|
||||||
draw.polygon(((1, 21), (34, 4), (71, 1), (38, 18)), BLACK)
|
draw.polygon(((1, 21), (34, 4), (71, 1), (38, 18)), BLACK)
|
||||||
|
draw.polygon(
|
||||||
|
((82, 29), (82, 26), (82, 24), (67, 22), (52, 29), (52, 15), (67, 22)), BLACK
|
||||||
|
)
|
||||||
draw.polygon(((71, 44), (38, 27), (1, 24)), BLACK)
|
draw.polygon(((71, 44), (38, 27), (1, 24)), BLACK)
|
||||||
draw.polygon(
|
draw.polygon(
|
||||||
((38, 66), (5, 49), (77, 49), (47, 66), (82, 63), (82, 47), (1, 47), (1, 63)),
|
((38, 66), (5, 49), (77, 49), (47, 66), (82, 63), (82, 47), (1, 47), (1, 63)),
|
||||||
|
|
|
@ -93,6 +93,19 @@ class TestImageFile:
|
||||||
assert p.image is not None
|
assert p.image is not None
|
||||||
assert (48, 48) == p.image.size
|
assert (48, 48) == p.image.size
|
||||||
|
|
||||||
|
@pytest.mark.filterwarnings("ignore:Corrupt EXIF data")
|
||||||
|
def test_incremental_tiff(self) -> None:
|
||||||
|
with ImageFile.Parser() as p:
|
||||||
|
with open("Tests/images/hopper.tif", "rb") as f:
|
||||||
|
p.feed(f.read(1024))
|
||||||
|
|
||||||
|
# Check that insufficient data was given in the first feed
|
||||||
|
assert not p.image
|
||||||
|
|
||||||
|
p.feed(f.read())
|
||||||
|
assert p.image is not None
|
||||||
|
assert (128, 128) == p.image.size
|
||||||
|
|
||||||
@skip_unless_feature("webp")
|
@skip_unless_feature("webp")
|
||||||
def test_incremental_webp(self) -> None:
|
def test_incremental_webp(self) -> None:
|
||||||
with ImageFile.Parser() as p:
|
with ImageFile.Parser() as p:
|
||||||
|
|
|
@ -74,6 +74,17 @@ def test_pickle_image(
|
||||||
helper_pickle_file(tmp_path, protocol, test_file, test_mode)
|
helper_pickle_file(tmp_path, protocol, test_file, test_mode)
|
||||||
|
|
||||||
|
|
||||||
|
def test_pickle_jpeg() -> None:
|
||||||
|
# Arrange
|
||||||
|
with Image.open("Tests/images/hopper.jpg") as image:
|
||||||
|
# Act: roundtrip
|
||||||
|
unpickled_image = pickle.loads(pickle.dumps(image))
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
assert len(unpickled_image.layer) == 3
|
||||||
|
assert unpickled_image.layers == 3
|
||||||
|
|
||||||
|
|
||||||
def test_pickle_la_mode_with_palette(tmp_path: Path) -> None:
|
def test_pickle_la_mode_with_palette(tmp_path: Path) -> None:
|
||||||
# Arrange
|
# Arrange
|
||||||
filename = str(tmp_path / "temp.pkl")
|
filename = str(tmp_path / "temp.pkl")
|
||||||
|
|
|
@ -52,6 +52,12 @@ zlib library, and what version of zlib-ng is being used::
|
||||||
Other Changes
|
Other Changes
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
Reading JPEG 2000 comments
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
When opening a JPEG 2000 image, the comment may now be read into
|
||||||
|
:py:attr:`~PIL.Image.Image.info` for J2K images, not just JP2 images.
|
||||||
|
|
||||||
zlib-ng in wheels
|
zlib-ng in wheels
|
||||||
^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -344,7 +344,7 @@ class pil_build_ext(build_ext):
|
||||||
for x in ("raqm", "fribidi")
|
for x in ("raqm", "fribidi")
|
||||||
]
|
]
|
||||||
+ [
|
+ [
|
||||||
("disable-platform-guessing", None, "Disable platform guessing on Linux"),
|
("disable-platform-guessing", None, "Disable platform guessing"),
|
||||||
("debug", None, "Debug logging"),
|
("debug", None, "Debug logging"),
|
||||||
]
|
]
|
||||||
+ [("add-imaging-libs=", None, "Add libs to _imaging build")]
|
+ [("add-imaging-libs=", None, "Add libs to _imaging build")]
|
||||||
|
|
|
@ -274,7 +274,7 @@ class BlpImageFile(ImageFile.ImageFile):
|
||||||
raise BLPFormatError(msg)
|
raise BLPFormatError(msg)
|
||||||
|
|
||||||
self._mode = "RGBA" if self._blp_alpha_depth else "RGB"
|
self._mode = "RGBA" if self._blp_alpha_depth else "RGB"
|
||||||
self.tile = [ImageFile._Tile(decoder, (0, 0) + self.size, 0, (self.mode, 0, 1))]
|
self.tile = [ImageFile._Tile(decoder, (0, 0) + self.size, 0, self.mode)]
|
||||||
|
|
||||||
|
|
||||||
class _BLPBaseDecoder(ImageFile.PyDecoder):
|
class _BLPBaseDecoder(ImageFile.PyDecoder):
|
||||||
|
|
|
@ -561,9 +561,7 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
||||||
+ struct.pack("<4I", *rgba_mask) # dwRGBABitMask
|
+ struct.pack("<4I", *rgba_mask) # dwRGBABitMask
|
||||||
+ struct.pack("<5I", DDSCAPS.TEXTURE, 0, 0, 0, 0)
|
+ struct.pack("<5I", DDSCAPS.TEXTURE, 0, 0, 0, 0)
|
||||||
)
|
)
|
||||||
ImageFile._save(
|
ImageFile._save(im, fp, [ImageFile._Tile("raw", (0, 0) + im.size, 0, rawmode)])
|
||||||
im, fp, [ImageFile._Tile("raw", (0, 0) + im.size, 0, (rawmode, 0, 1))]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _accept(prefix: bytes) -> bool:
|
def _accept(prefix: bytes) -> bool:
|
||||||
|
|
|
@ -456,7 +456,7 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes, eps: int = 1) -
|
||||||
if hasattr(fp, "flush"):
|
if hasattr(fp, "flush"):
|
||||||
fp.flush()
|
fp.flush()
|
||||||
|
|
||||||
ImageFile._save(im, fp, [ImageFile._Tile("eps", (0, 0) + im.size, 0, None)])
|
ImageFile._save(im, fp, [ImageFile._Tile("eps", (0, 0) + im.size)])
|
||||||
|
|
||||||
fp.write(b"\n%%%%EndBinary\n")
|
fp.write(b"\n%%%%EndBinary\n")
|
||||||
fp.write(b"grestore end\n")
|
fp.write(b"grestore end\n")
|
||||||
|
|
|
@ -161,7 +161,7 @@ class FliImageFile(ImageFile.ImageFile):
|
||||||
framesize = i32(s)
|
framesize = i32(s)
|
||||||
|
|
||||||
self.decodermaxblock = framesize
|
self.decodermaxblock = framesize
|
||||||
self.tile = [ImageFile._Tile("fli", (0, 0) + self.size, self.__offset, None)]
|
self.tile = [ImageFile._Tile("fli", (0, 0) + self.size, self.__offset)]
|
||||||
|
|
||||||
self.__offset += framesize
|
self.__offset += framesize
|
||||||
|
|
||||||
|
|
|
@ -171,7 +171,7 @@ class FpxImageFile(ImageFile.ImageFile):
|
||||||
"raw",
|
"raw",
|
||||||
(x, y, x1, y1),
|
(x, y, x1, y1),
|
||||||
i32(s, i) + 28,
|
i32(s, i) + 28,
|
||||||
(self.rawmode,),
|
self.rawmode,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ class FtexImageFile(ImageFile.ImageFile):
|
||||||
self._mode = "RGBA"
|
self._mode = "RGBA"
|
||||||
self.tile = [ImageFile._Tile("bcn", (0, 0) + self.size, 0, (1,))]
|
self.tile = [ImageFile._Tile("bcn", (0, 0) + self.size, 0, (1,))]
|
||||||
elif format == Format.UNCOMPRESSED:
|
elif format == Format.UNCOMPRESSED:
|
||||||
self.tile = [ImageFile._Tile("raw", (0, 0) + self.size, 0, ("RGB", 0, 1))]
|
self.tile = [ImageFile._Tile("raw", (0, 0) + self.size, 0, "RGB")]
|
||||||
else:
|
else:
|
||||||
msg = f"Invalid texture compression format: {repr(format)}"
|
msg = f"Invalid texture compression format: {repr(format)}"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
|
@ -76,7 +76,7 @@ class GdImageFile(ImageFile.ImageFile):
|
||||||
"raw",
|
"raw",
|
||||||
(0, 0) + self.size,
|
(0, 0) + self.size,
|
||||||
7 + true_color_offset + 4 + 256 * 4,
|
7 + true_color_offset + 4 + 256 * 4,
|
||||||
("L", 0, 1),
|
"L",
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -754,7 +754,7 @@ class Image:
|
||||||
|
|
||||||
def __setstate__(self, state: list[Any]) -> None:
|
def __setstate__(self, state: list[Any]) -> None:
|
||||||
Image.__init__(self)
|
Image.__init__(self)
|
||||||
info, mode, size, palette, data = state
|
info, mode, size, palette, data = state[:5]
|
||||||
self.info = info
|
self.info = info
|
||||||
self._mode = mode
|
self._mode = mode
|
||||||
self._size = size
|
self._size = size
|
||||||
|
@ -2556,7 +2556,7 @@ class Image:
|
||||||
self._ensure_mutable()
|
self._ensure_mutable()
|
||||||
|
|
||||||
save_all = params.pop("save_all", False)
|
save_all = params.pop("save_all", False)
|
||||||
self.encoderinfo = params
|
self.encoderinfo = {**getattr(self, "encoderinfo", {}), **params}
|
||||||
self.encoderconfig: tuple[Any, ...] = ()
|
self.encoderconfig: tuple[Any, ...] = ()
|
||||||
|
|
||||||
preinit()
|
preinit()
|
||||||
|
@ -2603,6 +2603,11 @@ class Image:
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
pass
|
pass
|
||||||
raise
|
raise
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
del self.encoderinfo
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
if open_fp:
|
if open_fp:
|
||||||
fp.close()
|
fp.close()
|
||||||
|
|
||||||
|
|
|
@ -98,8 +98,8 @@ def _tilesort(t: _Tile) -> int:
|
||||||
class _Tile(NamedTuple):
|
class _Tile(NamedTuple):
|
||||||
codec_name: str
|
codec_name: str
|
||||||
extents: tuple[int, int, int, int] | None
|
extents: tuple[int, int, int, int] | None
|
||||||
offset: int
|
offset: int = 0
|
||||||
args: tuple[Any, ...] | str | None
|
args: tuple[Any, ...] | str | None = None
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -104,28 +104,17 @@ def grab(
|
||||||
|
|
||||||
def grabclipboard() -> Image.Image | list[str] | None:
|
def grabclipboard() -> Image.Image | list[str] | None:
|
||||||
if sys.platform == "darwin":
|
if sys.platform == "darwin":
|
||||||
fh, filepath = tempfile.mkstemp(".png")
|
p = subprocess.run(
|
||||||
os.close(fh)
|
["osascript", "-e", "get the clipboard as «class PNGf»"],
|
||||||
commands = [
|
capture_output=True,
|
||||||
'set theFile to (open for access POSIX file "'
|
)
|
||||||
+ filepath
|
if p.returncode != 0:
|
||||||
+ '" with write permission)',
|
return None
|
||||||
"try",
|
|
||||||
" write (the clipboard as «class PNGf») to theFile",
|
|
||||||
"end try",
|
|
||||||
"close access theFile",
|
|
||||||
]
|
|
||||||
script = ["osascript"]
|
|
||||||
for command in commands:
|
|
||||||
script += ["-e", command]
|
|
||||||
subprocess.call(script)
|
|
||||||
|
|
||||||
im = None
|
import binascii
|
||||||
if os.stat(filepath).st_size != 0:
|
|
||||||
im = Image.open(filepath)
|
data = io.BytesIO(binascii.unhexlify(p.stdout[11:-3]))
|
||||||
im.load()
|
return Image.open(data)
|
||||||
os.unlink(filepath)
|
|
||||||
return im
|
|
||||||
elif sys.platform == "win32":
|
elif sys.platform == "win32":
|
||||||
fmt, data = Image.core.grabclipboard_win32()
|
fmt, data = Image.core.grabclipboard_win32()
|
||||||
if fmt == "file": # CF_HDROP
|
if fmt == "file": # CF_HDROP
|
||||||
|
|
|
@ -698,10 +698,11 @@ def exif_transpose(image: Image.Image, *, in_place: bool = False) -> Image.Image
|
||||||
8: Image.Transpose.ROTATE_90,
|
8: Image.Transpose.ROTATE_90,
|
||||||
}.get(orientation)
|
}.get(orientation)
|
||||||
if method is not None:
|
if method is not None:
|
||||||
transposed_image = image.transpose(method)
|
|
||||||
if in_place:
|
if in_place:
|
||||||
image.im = transposed_image.im
|
image.im = image.im.transpose(method)
|
||||||
image._size = transposed_image._size
|
image._size = image.im.size
|
||||||
|
else:
|
||||||
|
transposed_image = image.transpose(method)
|
||||||
exif_image = image if in_place else transposed_image
|
exif_image = image if in_place else transposed_image
|
||||||
|
|
||||||
exif = exif_image.getexif()
|
exif = exif_image.getexif()
|
||||||
|
|
|
@ -62,7 +62,7 @@ class ImtImageFile(ImageFile.ImageFile):
|
||||||
"raw",
|
"raw",
|
||||||
(0, 0) + self.size,
|
(0, 0) + self.size,
|
||||||
self.fp.tell() - len(buffer),
|
self.fp.tell() - len(buffer),
|
||||||
(self.mode, 0, 1),
|
self.mode,
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -253,6 +253,7 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
|
||||||
if sig == b"\xff\x4f\xff\x51":
|
if sig == b"\xff\x4f\xff\x51":
|
||||||
self.codec = "j2k"
|
self.codec = "j2k"
|
||||||
self._size, self._mode = _parse_codestream(self.fp)
|
self._size, self._mode = _parse_codestream(self.fp)
|
||||||
|
self._parse_comment()
|
||||||
else:
|
else:
|
||||||
sig = sig + self.fp.read(8)
|
sig = sig + self.fp.read(8)
|
||||||
|
|
||||||
|
@ -263,6 +264,9 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
|
||||||
if dpi is not None:
|
if dpi is not None:
|
||||||
self.info["dpi"] = dpi
|
self.info["dpi"] = dpi
|
||||||
if self.fp.read(12).endswith(b"jp2c\xff\x4f\xff\x51"):
|
if self.fp.read(12).endswith(b"jp2c\xff\x4f\xff\x51"):
|
||||||
|
hdr = self.fp.read(2)
|
||||||
|
length = _binary.i16be(hdr)
|
||||||
|
self.fp.seek(length - 2, os.SEEK_CUR)
|
||||||
self._parse_comment()
|
self._parse_comment()
|
||||||
else:
|
else:
|
||||||
msg = "not a JPEG 2000 file"
|
msg = "not a JPEG 2000 file"
|
||||||
|
@ -298,10 +302,6 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
def _parse_comment(self) -> None:
|
def _parse_comment(self) -> None:
|
||||||
assert self.fp is not None
|
assert self.fp is not None
|
||||||
hdr = self.fp.read(2)
|
|
||||||
length = _binary.i16be(hdr)
|
|
||||||
self.fp.seek(length - 2, os.SEEK_CUR)
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
marker = self.fp.read(2)
|
marker = self.fp.read(2)
|
||||||
if not marker:
|
if not marker:
|
||||||
|
|
|
@ -401,6 +401,13 @@ class JpegImageFile(ImageFile.ImageFile):
|
||||||
return getattr(self, "_" + name)
|
return getattr(self, "_" + name)
|
||||||
raise AttributeError(name)
|
raise AttributeError(name)
|
||||||
|
|
||||||
|
def __getstate__(self) -> list[Any]:
|
||||||
|
return super().__getstate__() + [self.layers, self.layer]
|
||||||
|
|
||||||
|
def __setstate__(self, state: list[Any]) -> None:
|
||||||
|
super().__setstate__(state)
|
||||||
|
self.layers, self.layer = state[5:]
|
||||||
|
|
||||||
def load_read(self, read_bytes: int) -> bytes:
|
def load_read(self, read_bytes: int) -> bytes:
|
||||||
"""
|
"""
|
||||||
internal: read more image data
|
internal: read more image data
|
||||||
|
@ -758,7 +765,7 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
||||||
extra = info.get("extra", b"")
|
extra = info.get("extra", b"")
|
||||||
|
|
||||||
MAX_BYTES_IN_MARKER = 65533
|
MAX_BYTES_IN_MARKER = 65533
|
||||||
xmp = info.get("xmp", im.info.get("xmp"))
|
xmp = info.get("xmp")
|
||||||
if xmp:
|
if xmp:
|
||||||
overhead_len = 29 # b"http://ns.adobe.com/xap/1.0/\x00"
|
overhead_len = 29 # b"http://ns.adobe.com/xap/1.0/\x00"
|
||||||
max_data_bytes_in_marker = MAX_BYTES_IN_MARKER - overhead_len
|
max_data_bytes_in_marker = MAX_BYTES_IN_MARKER - overhead_len
|
||||||
|
|
|
@ -70,9 +70,9 @@ class MspImageFile(ImageFile.ImageFile):
|
||||||
self._size = i16(s, 4), i16(s, 6)
|
self._size = i16(s, 4), i16(s, 6)
|
||||||
|
|
||||||
if s[:4] == b"DanM":
|
if s[:4] == b"DanM":
|
||||||
self.tile = [ImageFile._Tile("raw", (0, 0) + self.size, 32, ("1", 0, 1))]
|
self.tile = [ImageFile._Tile("raw", (0, 0) + self.size, 32, "1")]
|
||||||
else:
|
else:
|
||||||
self.tile = [ImageFile._Tile("MSP", (0, 0) + self.size, 32, None)]
|
self.tile = [ImageFile._Tile("MSP", (0, 0) + self.size, 32)]
|
||||||
|
|
||||||
|
|
||||||
class MspDecoder(ImageFile.PyDecoder):
|
class MspDecoder(ImageFile.PyDecoder):
|
||||||
|
@ -188,7 +188,7 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
||||||
fp.write(o16(h))
|
fp.write(o16(h))
|
||||||
|
|
||||||
# image body
|
# image body
|
||||||
ImageFile._save(im, fp, [ImageFile._Tile("raw", (0, 0) + im.size, 32, ("1", 0, 1))])
|
ImageFile._save(im, fp, [ImageFile._Tile("raw", (0, 0) + im.size, 32, "1")])
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -47,7 +47,7 @@ class PcdImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
self._mode = "RGB"
|
self._mode = "RGB"
|
||||||
self._size = 768, 512 # FIXME: not correct for rotated images!
|
self._size = 768, 512 # FIXME: not correct for rotated images!
|
||||||
self.tile = [ImageFile._Tile("pcd", (0, 0) + self.size, 96 * 2048, None)]
|
self.tile = [ImageFile._Tile("pcd", (0, 0) + self.size, 96 * 2048)]
|
||||||
|
|
||||||
def load_end(self) -> None:
|
def load_end(self) -> None:
|
||||||
if self.tile_post_rotate:
|
if self.tile_post_rotate:
|
||||||
|
|
|
@ -61,9 +61,7 @@ class PixarImageFile(ImageFile.ImageFile):
|
||||||
# FIXME: to be continued...
|
# FIXME: to be continued...
|
||||||
|
|
||||||
# create tile descriptor (assuming "dumped")
|
# create tile descriptor (assuming "dumped")
|
||||||
self.tile = [
|
self.tile = [ImageFile._Tile("raw", (0, 0) + self.size, 1024, self.mode)]
|
||||||
ImageFile._Tile("raw", (0, 0) + self.size, 1024, (self.mode, 0, 1))
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -33,7 +33,7 @@ class QoiImageFile(ImageFile.ImageFile):
|
||||||
self._mode = "RGB" if channels == 3 else "RGBA"
|
self._mode = "RGB" if channels == 3 else "RGBA"
|
||||||
|
|
||||||
self.fp.seek(1, os.SEEK_CUR) # colorspace
|
self.fp.seek(1, os.SEEK_CUR) # colorspace
|
||||||
self.tile = [ImageFile._Tile("qoi", (0, 0) + self._size, self.fp.tell(), None)]
|
self.tile = [ImageFile._Tile("qoi", (0, 0) + self._size, self.fp.tell())]
|
||||||
|
|
||||||
|
|
||||||
class QoiDecoder(ImageFile.PyDecoder):
|
class QoiDecoder(ImageFile.PyDecoder):
|
||||||
|
|
|
@ -155,9 +155,7 @@ class SpiderImageFile(ImageFile.ImageFile):
|
||||||
self.rawmode = "F;32F"
|
self.rawmode = "F;32F"
|
||||||
self._mode = "F"
|
self._mode = "F"
|
||||||
|
|
||||||
self.tile = [
|
self.tile = [ImageFile._Tile("raw", (0, 0) + self.size, offset, self.rawmode)]
|
||||||
ImageFile._Tile("raw", (0, 0) + self.size, offset, (self.rawmode, 0, 1))
|
|
||||||
]
|
|
||||||
self._fp = self.fp # FIXME: hack
|
self._fp = self.fp # FIXME: hack
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -212,26 +210,27 @@ class SpiderImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
|
|
||||||
# given a list of filenames, return a list of images
|
# given a list of filenames, return a list of images
|
||||||
def loadImageSeries(filelist: list[str] | None = None) -> list[SpiderImageFile] | None:
|
def loadImageSeries(filelist: list[str] | None = None) -> list[Image.Image] | None:
|
||||||
"""create a list of :py:class:`~PIL.Image.Image` objects for use in a montage"""
|
"""create a list of :py:class:`~PIL.Image.Image` objects for use in a montage"""
|
||||||
if filelist is None or len(filelist) < 1:
|
if filelist is None or len(filelist) < 1:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
imglist = []
|
byte_imgs = []
|
||||||
for img in filelist:
|
for img in filelist:
|
||||||
if not os.path.exists(img):
|
if not os.path.exists(img):
|
||||||
print(f"unable to find {img}")
|
print(f"unable to find {img}")
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
with Image.open(img) as im:
|
with Image.open(img) as im:
|
||||||
im = im.convert2byte()
|
assert isinstance(im, SpiderImageFile)
|
||||||
|
byte_im = im.convert2byte()
|
||||||
except Exception:
|
except Exception:
|
||||||
if not isSpiderImage(img):
|
if not isSpiderImage(img):
|
||||||
print(f"{img} is not a Spider image file")
|
print(f"{img} is not a Spider image file")
|
||||||
continue
|
continue
|
||||||
im.info["filename"] = img
|
byte_im.info["filename"] = img
|
||||||
imglist.append(im)
|
byte_imgs.append(byte_im)
|
||||||
return imglist
|
return byte_imgs
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
@ -281,9 +280,7 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
||||||
fp.writelines(hdr)
|
fp.writelines(hdr)
|
||||||
|
|
||||||
rawmode = "F;32NF" # 32-bit native floating point
|
rawmode = "F;32NF" # 32-bit native floating point
|
||||||
ImageFile._save(
|
ImageFile._save(im, fp, [ImageFile._Tile("raw", (0, 0) + im.size, 0, rawmode)])
|
||||||
im, fp, [ImageFile._Tile("raw", (0, 0) + im.size, 0, (rawmode, 0, 1))]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _save_spider(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
def _save_spider(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
||||||
|
|
|
@ -1434,8 +1434,12 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
logger.debug("- YCbCr subsampling: %s", self.tag_v2.get(YCBCRSUBSAMPLING))
|
logger.debug("- YCbCr subsampling: %s", self.tag_v2.get(YCBCRSUBSAMPLING))
|
||||||
|
|
||||||
# size
|
# size
|
||||||
xsize = self.tag_v2.get(IMAGEWIDTH)
|
try:
|
||||||
ysize = self.tag_v2.get(IMAGELENGTH)
|
xsize = self.tag_v2[IMAGEWIDTH]
|
||||||
|
ysize = self.tag_v2[IMAGELENGTH]
|
||||||
|
except KeyError as e:
|
||||||
|
msg = "Missing dimensions"
|
||||||
|
raise TypeError(msg) from e
|
||||||
if not isinstance(xsize, int) or not isinstance(ysize, int):
|
if not isinstance(xsize, int) or not isinstance(ysize, int):
|
||||||
msg = "Invalid dimensions"
|
msg = "Invalid dimensions"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
@ -1916,7 +1920,9 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
||||||
if not getattr(Image.core, "libtiff_support_custom_tags", False):
|
if not getattr(Image.core, "libtiff_support_custom_tags", False):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if tag in ifd.tagtype:
|
if tag in TiffTags.TAGS_V2_GROUPS:
|
||||||
|
types[tag] = TiffTags.LONG8
|
||||||
|
elif tag in ifd.tagtype:
|
||||||
types[tag] = ifd.tagtype[tag]
|
types[tag] = ifd.tagtype[tag]
|
||||||
elif not (isinstance(value, (int, float, str, bytes))):
|
elif not (isinstance(value, (int, float, str, bytes))):
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -74,9 +74,7 @@ class XVThumbImageFile(ImageFile.ImageFile):
|
||||||
self.palette = ImagePalette.raw("RGB", PALETTE)
|
self.palette = ImagePalette.raw("RGB", PALETTE)
|
||||||
|
|
||||||
self.tile = [
|
self.tile = [
|
||||||
ImageFile._Tile(
|
ImageFile._Tile("raw", (0, 0) + self.size, self.fp.tell(), self.mode)
|
||||||
"raw", (0, 0) + self.size, self.fp.tell(), (self.mode, 0, 1)
|
|
||||||
)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ class XbmImageFile(ImageFile.ImageFile):
|
||||||
self._mode = "1"
|
self._mode = "1"
|
||||||
self._size = xsize, ysize
|
self._size = xsize, ysize
|
||||||
|
|
||||||
self.tile = [ImageFile._Tile("xbm", (0, 0) + self.size, m.end(), None)]
|
self.tile = [ImageFile._Tile("xbm", (0, 0) + self.size, m.end())]
|
||||||
|
|
||||||
|
|
||||||
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
||||||
|
@ -85,7 +85,7 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
||||||
|
|
||||||
fp.write(b"static char im_bits[] = {\n")
|
fp.write(b"static char im_bits[] = {\n")
|
||||||
|
|
||||||
ImageFile._save(im, fp, [ImageFile._Tile("xbm", (0, 0) + im.size, 0, None)])
|
ImageFile._save(im, fp, [ImageFile._Tile("xbm", (0, 0) + im.size)])
|
||||||
|
|
||||||
fp.write(b"};\n")
|
fp.write(b"};\n")
|
||||||
|
|
||||||
|
|
|
@ -102,9 +102,7 @@ class XpmImageFile(ImageFile.ImageFile):
|
||||||
self._mode = "P"
|
self._mode = "P"
|
||||||
self.palette = ImagePalette.raw("RGB", b"".join(palette))
|
self.palette = ImagePalette.raw("RGB", b"".join(palette))
|
||||||
|
|
||||||
self.tile = [
|
self.tile = [ImageFile._Tile("raw", (0, 0) + self.size, self.fp.tell(), "P")]
|
||||||
ImageFile._Tile("raw", (0, 0) + self.size, self.fp.tell(), ("P", 0, 1))
|
|
||||||
]
|
|
||||||
|
|
||||||
def load_read(self, read_bytes: int) -> bytes:
|
def load_read(self, read_bytes: int) -> bytes:
|
||||||
#
|
#
|
||||||
|
|
|
@ -346,7 +346,7 @@ pyCMSdoTransform(Imaging im, Imaging imOut, cmsHTRANSFORM hTransform) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
|
|
||||||
// transform color channels only
|
// transform color channels only
|
||||||
for (i = 0; i < im->ysize; i++) {
|
for (i = 0; i < im->ysize; i++) {
|
||||||
|
@ -362,7 +362,7 @@ pyCMSdoTransform(Imaging im, Imaging imOut, cmsHTRANSFORM hTransform) {
|
||||||
// enough available on all platforms, so we polyfill it here for now.
|
// enough available on all platforms, so we polyfill it here for now.
|
||||||
pyCMScopyAux(hTransform, imOut, im);
|
pyCMScopyAux(hTransform, imOut, im);
|
||||||
|
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -378,7 +378,7 @@ _buildTransform(
|
||||||
) {
|
) {
|
||||||
cmsHTRANSFORM hTransform;
|
cmsHTRANSFORM hTransform;
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
|
|
||||||
/* create the transform */
|
/* create the transform */
|
||||||
hTransform = cmsCreateTransform(
|
hTransform = cmsCreateTransform(
|
||||||
|
@ -412,7 +412,7 @@ _buildProofTransform(
|
||||||
) {
|
) {
|
||||||
cmsHTRANSFORM hTransform;
|
cmsHTRANSFORM hTransform;
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
|
|
||||||
/* create the transform */
|
/* create the transform */
|
||||||
hTransform = cmsCreateProofingTransform(
|
hTransform = cmsCreateProofingTransform(
|
||||||
|
|
|
@ -690,9 +690,10 @@ PyImaging_CreateWindowWin32(PyObject *self, PyObject *args) {
|
||||||
SetWindowLongPtr(wnd, 0, (LONG_PTR)callback);
|
SetWindowLongPtr(wnd, 0, (LONG_PTR)callback);
|
||||||
SetWindowLongPtr(wnd, sizeof(callback), (LONG_PTR)PyThreadState_Get());
|
SetWindowLongPtr(wnd, sizeof(callback), (LONG_PTR)PyThreadState_Get());
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS ShowWindow(wnd, SW_SHOWNORMAL);
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
|
ShowWindow(wnd, SW_SHOWNORMAL);
|
||||||
SetForegroundWindow(wnd); /* to make sure it's visible */
|
SetForegroundWindow(wnd); /* to make sure it's visible */
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS;
|
||||||
|
|
||||||
return Py_BuildValue(F_HANDLE, wnd);
|
return Py_BuildValue(F_HANDLE, wnd);
|
||||||
}
|
}
|
||||||
|
@ -701,11 +702,12 @@ PyObject *
|
||||||
PyImaging_EventLoopWin32(PyObject *self, PyObject *args) {
|
PyImaging_EventLoopWin32(PyObject *self, PyObject *args) {
|
||||||
MSG msg;
|
MSG msg;
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS while (mainloop && GetMessage(&msg, NULL, 0, 0)) {
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
|
while (mainloop && GetMessage(&msg, NULL, 0, 0)) {
|
||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
DispatchMessage(&msg);
|
DispatchMessage(&msg);
|
||||||
}
|
}
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS;
|
||||||
|
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
|
|
|
@ -736,7 +736,7 @@ PyImaging_LibTiffEncoderNew(PyObject *self, PyObject *args) {
|
||||||
}
|
}
|
||||||
if (tag_type) {
|
if (tag_type) {
|
||||||
int type_int = PyLong_AsLong(tag_type);
|
int type_int = PyLong_AsLong(tag_type);
|
||||||
if (type_int >= TIFF_BYTE && type_int <= TIFF_DOUBLE) {
|
if (type_int >= TIFF_BYTE && type_int <= TIFF_LONG8) {
|
||||||
type = (TIFFDataType)type_int;
|
type = (TIFFDataType)type_int;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -929,7 +929,7 @@ PyImaging_LibTiffEncoderNew(PyObject *self, PyObject *args) {
|
||||||
);
|
);
|
||||||
} else if (type == TIFF_LONG) {
|
} else if (type == TIFF_LONG) {
|
||||||
status = ImagingLibTiffSetField(
|
status = ImagingLibTiffSetField(
|
||||||
&encoder->state, (ttag_t)key_int, PyLong_AsLongLong(value)
|
&encoder->state, (ttag_t)key_int, (UINT32)PyLong_AsLong(value)
|
||||||
);
|
);
|
||||||
} else if (type == TIFF_SSHORT) {
|
} else if (type == TIFF_SSHORT) {
|
||||||
status = ImagingLibTiffSetField(
|
status = ImagingLibTiffSetField(
|
||||||
|
@ -959,6 +959,10 @@ PyImaging_LibTiffEncoderNew(PyObject *self, PyObject *args) {
|
||||||
status = ImagingLibTiffSetField(
|
status = ImagingLibTiffSetField(
|
||||||
&encoder->state, (ttag_t)key_int, (FLOAT64)PyFloat_AsDouble(value)
|
&encoder->state, (ttag_t)key_int, (FLOAT64)PyFloat_AsDouble(value)
|
||||||
);
|
);
|
||||||
|
} else if (type == TIFF_LONG8) {
|
||||||
|
status = ImagingLibTiffSetField(
|
||||||
|
&encoder->state, (ttag_t)key_int, (uint64_t)PyLong_AsLongLong(value)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
TRACE(
|
TRACE(
|
||||||
("Unhandled type for key %d : %s \n",
|
("Unhandled type for key %d : %s \n",
|
||||||
|
|
|
@ -501,7 +501,8 @@ polygon_generic(
|
||||||
// Needed to draw consistent polygons
|
// Needed to draw consistent polygons
|
||||||
xx[j] = xx[j - 1];
|
xx[j] = xx[j - 1];
|
||||||
j++;
|
j++;
|
||||||
} else if (current->dx != 0 && roundf(xx[j - 1]) == xx[j - 1]) {
|
} else if (current->dx != 0 && j % 2 == 1 &&
|
||||||
|
roundf(xx[j - 1]) == xx[j - 1]) {
|
||||||
// Connect discontiguous corners
|
// Connect discontiguous corners
|
||||||
for (k = 0; k < i; k++) {
|
for (k = 0; k < i; k++) {
|
||||||
Edge *other_edge = edge_table[k];
|
Edge *other_edge = edge_table[k];
|
||||||
|
@ -510,10 +511,8 @@ polygon_generic(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Check if the two edges join to make a corner
|
// Check if the two edges join to make a corner
|
||||||
if (((ymin == current->ymin && ymin == other_edge->ymin) ||
|
if (xx[j - 1] ==
|
||||||
(ymin == current->ymax && ymin == other_edge->ymax)) &&
|
(ymin - other_edge->y0) * other_edge->dx + other_edge->x0) {
|
||||||
xx[j - 1] == (ymin - other_edge->y0) * other_edge->dx +
|
|
||||||
other_edge->x0) {
|
|
||||||
// Determine points from the edges on the next row
|
// Determine points from the edges on the next row
|
||||||
// Or if this is the last row, check the previous row
|
// Or if this is the last row, check the previous row
|
||||||
int offset = ymin == ymax ? -1 : 1;
|
int offset = ymin == ymax ? -1 : 1;
|
||||||
|
|
|
@ -640,7 +640,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) {
|
||||||
opj_dparameters_t params;
|
opj_dparameters_t params;
|
||||||
OPJ_COLOR_SPACE color_space;
|
OPJ_COLOR_SPACE color_space;
|
||||||
j2k_unpacker_t unpack = NULL;
|
j2k_unpacker_t unpack = NULL;
|
||||||
size_t buffer_size = 0, tile_bytes = 0;
|
size_t tile_bytes = 0;
|
||||||
unsigned n, tile_height, tile_width;
|
unsigned n, tile_height, tile_width;
|
||||||
int subsampling;
|
int subsampling;
|
||||||
int total_component_width = 0;
|
int total_component_width = 0;
|
||||||
|
@ -870,7 +870,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) {
|
||||||
tile_info.data_size = tile_bytes;
|
tile_info.data_size = tile_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer_size < tile_info.data_size) {
|
if (tile_info.data_size > 0) {
|
||||||
/* malloc check ok, overflow and tile size sanity check above */
|
/* malloc check ok, overflow and tile size sanity check above */
|
||||||
UINT8 *new = realloc(state->buffer, tile_info.data_size);
|
UINT8 *new = realloc(state->buffer, tile_info.data_size);
|
||||||
if (!new) {
|
if (!new) {
|
||||||
|
@ -883,7 +883,6 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) {
|
||||||
to valgrind errors. */
|
to valgrind errors. */
|
||||||
memset(new, 0, tile_info.data_size);
|
memset(new, 0, tile_info.data_size);
|
||||||
state->buffer = new;
|
state->buffer = new;
|
||||||
buffer_size = tile_info.data_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opj_decode_tile_data(
|
if (!opj_decode_tile_data(
|
||||||
|
|
Loading…
Reference in New Issue
Block a user