mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 17:36:18 +03:00
Merge branch 'main' into include-dir-type-confusion
This commit is contained in:
commit
6fce7d6ed4
|
@ -43,7 +43,7 @@ if [[ $(uname) != CYGWIN* ]]; then
|
||||||
# PyQt6 doesn't support PyPy3
|
# PyQt6 doesn't support PyPy3
|
||||||
if [[ $GHA_PYTHON_VERSION == 3.* ]]; then
|
if [[ $GHA_PYTHON_VERSION == 3.* ]]; then
|
||||||
sudo apt-get -qq install libegl1 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0 libxkbcommon-x11-0
|
sudo apt-get -qq install libegl1 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0 libxkbcommon-x11-0
|
||||||
python3 -m pip install pyqt6
|
python3 -m pip install pyqt6 PyQt6-Qt6!=6.5.0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# webp
|
# webp
|
||||||
|
|
1
.github/workflows/test-cygwin.yml
vendored
1
.github/workflows/test-cygwin.yml
vendored
|
@ -67,7 +67,6 @@ jobs:
|
||||||
python3${{ matrix.python-minor-version }}-numpy
|
python3${{ matrix.python-minor-version }}-numpy
|
||||||
python3${{ matrix.python-minor-version }}-sip
|
python3${{ matrix.python-minor-version }}-sip
|
||||||
python3${{ matrix.python-minor-version }}-tkinter
|
python3${{ matrix.python-minor-version }}-tkinter
|
||||||
qt5-devel-tools
|
|
||||||
wget
|
wget
|
||||||
xorg-server-extra
|
xorg-server-extra
|
||||||
zlib-devel
|
zlib-devel
|
||||||
|
|
|
@ -5,6 +5,9 @@ Changelog (Pillow)
|
||||||
10.0.0 (unreleased)
|
10.0.0 (unreleased)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
- Remove deprecations for Pillow 10.0.0 #7059
|
||||||
|
[hugovk, radarhere]
|
||||||
|
|
||||||
- Drop support for soon-EOL Python 3.7 #7058
|
- Drop support for soon-EOL Python 3.7 #7058
|
||||||
[hugovk, radarhere]
|
[hugovk, radarhere]
|
||||||
|
|
||||||
|
|
1
Makefile
1
Makefile
|
@ -78,6 +78,7 @@ debug:
|
||||||
|
|
||||||
.PHONY: release-test
|
.PHONY: release-test
|
||||||
release-test:
|
release-test:
|
||||||
|
python3 Tests/check_release_notes.py
|
||||||
python3 -m pip install -e .[tests]
|
python3 -m pip install -e .[tests]
|
||||||
python3 selftest.py
|
python3 selftest.py
|
||||||
python3 -m pytest Tests
|
python3 -m pytest Tests
|
||||||
|
|
6
Tests/check_release_notes.py
Normal file
6
Tests/check_release_notes.py
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
for rst in Path("docs/releasenotes").glob("[1-9]*.rst"):
|
||||||
|
if "TODO" in open(rst).read():
|
||||||
|
sys.exit(f"Error: remove TODO from {rst}")
|
|
@ -1,18 +0,0 @@
|
||||||
import warnings
|
|
||||||
|
|
||||||
with warnings.catch_warnings(record=True) as w:
|
|
||||||
# Arrange: cause all warnings to always be triggered
|
|
||||||
warnings.simplefilter("always")
|
|
||||||
|
|
||||||
# Act: trigger a warning with Qt5
|
|
||||||
from PIL import ImageQt
|
|
||||||
|
|
||||||
|
|
||||||
def test_deprecated():
|
|
||||||
# Assert
|
|
||||||
if ImageQt.qt_version in ("5", "side2"):
|
|
||||||
assert len(w) == 1
|
|
||||||
assert issubclass(w[0].category, DeprecationWarning)
|
|
||||||
assert "deprecated" in str(w[0].message)
|
|
||||||
else:
|
|
||||||
assert len(w) == 0
|
|
|
@ -655,13 +655,3 @@ def test_different_modes_in_later_frames(mode, tmp_path):
|
||||||
im.save(test_file, save_all=True, append_images=[Image.new(mode, (1, 1))])
|
im.save(test_file, save_all=True, append_images=[Image.new(mode, (1, 1))])
|
||||||
with Image.open(test_file) as reloaded:
|
with Image.open(test_file) as reloaded:
|
||||||
assert reloaded.mode == mode
|
assert reloaded.mode == mode
|
||||||
|
|
||||||
|
|
||||||
def test_constants_deprecation():
|
|
||||||
for enum, prefix in {
|
|
||||||
PngImagePlugin.Disposal: "APNG_DISPOSE_",
|
|
||||||
PngImagePlugin.Blend: "APNG_BLEND_",
|
|
||||||
}.items():
|
|
||||||
for name in enum.__members__:
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
assert getattr(PngImagePlugin, prefix + name) == enum[name]
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from PIL import BlpImagePlugin, Image
|
from PIL import Image
|
||||||
|
|
||||||
from .helper import (
|
from .helper import (
|
||||||
assert_image_equal,
|
assert_image_equal,
|
||||||
|
@ -72,14 +72,3 @@ def test_crashes(test_file):
|
||||||
with Image.open(f) as im:
|
with Image.open(f) as im:
|
||||||
with pytest.raises(OSError):
|
with pytest.raises(OSError):
|
||||||
im.load()
|
im.load()
|
||||||
|
|
||||||
|
|
||||||
def test_constants_deprecation():
|
|
||||||
for enum, prefix in {
|
|
||||||
BlpImagePlugin.Format: "BLP_FORMAT_",
|
|
||||||
BlpImagePlugin.Encoding: "BLP_ENCODING_",
|
|
||||||
BlpImagePlugin.AlphaEncoding: "BLP_ALPHA_ENCODING_",
|
|
||||||
}.items():
|
|
||||||
for name in enum.__members__:
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
assert getattr(BlpImagePlugin, prefix + name) == enum[name]
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ from io import BytesIO
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from PIL import FitsImagePlugin, FitsStubImagePlugin, Image
|
from PIL import FitsImagePlugin, Image
|
||||||
|
|
||||||
from .helper import assert_image_equal, hopper
|
from .helper import assert_image_equal, hopper
|
||||||
|
|
||||||
|
@ -48,39 +48,3 @@ def test_comment():
|
||||||
image_data = b"SIMPLE = T / comment string"
|
image_data = b"SIMPLE = T / comment string"
|
||||||
with pytest.raises(OSError):
|
with pytest.raises(OSError):
|
||||||
FitsImagePlugin.FitsImageFile(BytesIO(image_data))
|
FitsImagePlugin.FitsImageFile(BytesIO(image_data))
|
||||||
|
|
||||||
|
|
||||||
def test_stub_deprecated():
|
|
||||||
class Handler:
|
|
||||||
opened = False
|
|
||||||
loaded = False
|
|
||||||
|
|
||||||
def open(self, im):
|
|
||||||
self.opened = True
|
|
||||||
|
|
||||||
def load(self, im):
|
|
||||||
self.loaded = True
|
|
||||||
im.fp.close()
|
|
||||||
return Image.new("RGB", (1, 1))
|
|
||||||
|
|
||||||
handler = Handler()
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
FitsStubImagePlugin.register_handler(handler)
|
|
||||||
|
|
||||||
with Image.open(TEST_FILE) as im:
|
|
||||||
assert im.format == "FITS"
|
|
||||||
assert im.size == (128, 128)
|
|
||||||
assert im.mode == "L"
|
|
||||||
|
|
||||||
assert handler.opened
|
|
||||||
assert not handler.loaded
|
|
||||||
|
|
||||||
im.load()
|
|
||||||
assert handler.loaded
|
|
||||||
|
|
||||||
FitsStubImagePlugin._handler = None
|
|
||||||
Image.register_open(
|
|
||||||
FitsImagePlugin.FitsImageFile.format,
|
|
||||||
FitsImagePlugin.FitsImageFile,
|
|
||||||
FitsImagePlugin._accept,
|
|
||||||
)
|
|
||||||
|
|
|
@ -21,12 +21,3 @@ def test_invalid_file():
|
||||||
|
|
||||||
with pytest.raises(SyntaxError):
|
with pytest.raises(SyntaxError):
|
||||||
FtexImagePlugin.FtexImageFile(invalid_file)
|
FtexImagePlugin.FtexImageFile(invalid_file)
|
||||||
|
|
||||||
|
|
||||||
def test_constants_deprecation():
|
|
||||||
for enum, prefix in {
|
|
||||||
FtexImagePlugin.Format: "FORMAT_",
|
|
||||||
}.items():
|
|
||||||
for name in enum.__members__:
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
assert getattr(FtexImagePlugin, prefix + name) == enum[name]
|
|
||||||
|
|
|
@ -636,12 +636,6 @@ class TestFileJpeg:
|
||||||
assert max(im2.quantization[0]) <= 255
|
assert max(im2.quantization[0]) <= 255
|
||||||
assert max(im2.quantization[1]) <= 255
|
assert max(im2.quantization[1]) <= 255
|
||||||
|
|
||||||
def test_convert_dict_qtables_deprecation(self):
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
qtable = {0: [1, 2, 3, 4]}
|
|
||||||
qtable2 = JpegImagePlugin.convert_dict_qtables(qtable)
|
|
||||||
assert qtable == qtable2
|
|
||||||
|
|
||||||
@pytest.mark.skipif(not djpeg_available(), reason="djpeg not available")
|
@pytest.mark.skipif(not djpeg_available(), reason="djpeg not available")
|
||||||
def test_load_djpeg(self):
|
def test_load_djpeg(self):
|
||||||
with Image.open(TEST_FILE) as img:
|
with Image.open(TEST_FILE) as img:
|
||||||
|
|
|
@ -929,25 +929,7 @@ class TestImage:
|
||||||
im.apply_transparency()
|
im.apply_transparency()
|
||||||
assert im.palette.colors[(27, 35, 6, 214)] == 24
|
assert im.palette.colors[(27, 35, 6, 214)] == 24
|
||||||
|
|
||||||
def test_categories_deprecation(self):
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
assert hopper().category == 0
|
|
||||||
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
assert Image.NORMAL == 0
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
assert Image.SEQUENCE == 1
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
assert Image.CONTAINER == 2
|
|
||||||
|
|
||||||
def test_constants(self):
|
def test_constants(self):
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
assert Image.LINEAR == Image.Resampling.BILINEAR
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
assert Image.CUBIC == Image.Resampling.BICUBIC
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
assert Image.ANTIALIAS == Image.Resampling.LANCZOS
|
|
||||||
|
|
||||||
for enum in (
|
for enum in (
|
||||||
Image.Transpose,
|
Image.Transpose,
|
||||||
Image.Transform,
|
Image.Transform,
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from PIL import Image
|
|
||||||
|
|
||||||
from .helper import assert_image_equal, hopper
|
from .helper import assert_image_equal, hopper
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,8 +60,3 @@ def test_f_mode():
|
||||||
im = hopper("F")
|
im = hopper("F")
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
im.point(None)
|
im.point(None)
|
||||||
|
|
||||||
|
|
||||||
def test_coerce_e_deprecation():
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
assert Image.coerce_e(2).data == 2
|
|
||||||
|
|
|
@ -617,16 +617,6 @@ def test_auxiliary_channels_isolated():
|
||||||
assert_image_equal(test_image.convert(dst_format[2]), reference_image)
|
assert_image_equal(test_image.convert(dst_format[2]), reference_image)
|
||||||
|
|
||||||
|
|
||||||
def test_constants_deprecation():
|
|
||||||
for enum, prefix in {
|
|
||||||
ImageCms.Intent: "INTENT_",
|
|
||||||
ImageCms.Direction: "DIRECTION_",
|
|
||||||
}.items():
|
|
||||||
for name in enum.__members__:
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
assert getattr(ImageCms, prefix + name) == enum[name]
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("mode", ("RGB", "RGBA", "RGBX"))
|
@pytest.mark.parametrize("mode", ("RGB", "RGBA", "RGBX"))
|
||||||
def test_rgb_lab(mode):
|
def test_rgb_lab(mode):
|
||||||
im = Image.new(mode, (1, 1))
|
im = Image.new(mode, (1, 1))
|
||||||
|
|
|
@ -1083,14 +1083,6 @@ def test_woff2(layout_engine):
|
||||||
assert_image_similar_tofile(im, "Tests/images/test_woff2.png", 5)
|
assert_image_similar_tofile(im, "Tests/images/test_woff2.png", 5)
|
||||||
|
|
||||||
|
|
||||||
def test_fill_deprecation(font):
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
font.getmask2("Hello world", fill=Image.core.fill)
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
with pytest.raises(TypeError):
|
|
||||||
font.getmask2("Hello world", fill=None)
|
|
||||||
|
|
||||||
|
|
||||||
def test_render_mono_size():
|
def test_render_mono_size():
|
||||||
# issue 4177
|
# issue 4177
|
||||||
|
|
||||||
|
@ -1130,12 +1122,3 @@ def test_raqm_missing_warning(monkeypatch):
|
||||||
"Raqm layout was requested, but Raqm is not available. "
|
"Raqm layout was requested, but Raqm is not available. "
|
||||||
"Falling back to basic layout."
|
"Falling back to basic layout."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_constants_deprecation():
|
|
||||||
for enum, prefix in {
|
|
||||||
ImageFont.Layout: "LAYOUT_",
|
|
||||||
}.items():
|
|
||||||
for name in enum.__members__:
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
assert getattr(ImageFont, prefix + name) == enum[name]
|
|
||||||
|
|
|
@ -9,10 +9,6 @@ def test_sanity():
|
||||||
palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)
|
palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)
|
||||||
assert len(palette.colors) == 256
|
assert len(palette.colors) == 256
|
||||||
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
ImagePalette.ImagePalette("RGB", list(range(256)) * 3, 10)
|
|
||||||
|
|
||||||
|
|
||||||
def test_reload():
|
def test_reload():
|
||||||
with Image.open("Tests/images/hopper.gif") as im:
|
with Image.open("Tests/images/hopper.gif") as im:
|
||||||
|
|
|
@ -2,13 +2,10 @@ import warnings
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from PIL import ImageQt
|
||||||
|
|
||||||
from .helper import assert_image_similar, hopper
|
from .helper import assert_image_similar, hopper
|
||||||
|
|
||||||
with warnings.catch_warnings() as w:
|
|
||||||
warnings.simplefilter("ignore", category=DeprecationWarning)
|
|
||||||
from PIL import ImageQt
|
|
||||||
|
|
||||||
|
|
||||||
pytestmark = pytest.mark.skipif(
|
pytestmark = pytest.mark.skipif(
|
||||||
not ImageQt.qt_is_installed, reason="Qt bindings are not installed"
|
not ImageQt.qt_is_installed, reason="Qt bindings are not installed"
|
||||||
)
|
)
|
||||||
|
@ -26,10 +23,6 @@ def test_rgb():
|
||||||
from PyQt6.QtGui import qRgb
|
from PyQt6.QtGui import qRgb
|
||||||
elif ImageQt.qt_version == "side6":
|
elif ImageQt.qt_version == "side6":
|
||||||
from PySide6.QtGui import qRgb
|
from PySide6.QtGui import qRgb
|
||||||
elif ImageQt.qt_version == "5":
|
|
||||||
from PyQt5.QtGui import qRgb
|
|
||||||
elif ImageQt.qt_version == "side2":
|
|
||||||
from PySide2.QtGui import qRgb
|
|
||||||
|
|
||||||
assert qRgb(0, 0, 0) == qRgba(0, 0, 0, 255)
|
assert qRgb(0, 0, 0) == qRgba(0, 0, 0, 255)
|
||||||
|
|
||||||
|
|
|
@ -89,20 +89,3 @@ def test_ipythonviewer():
|
||||||
|
|
||||||
im = hopper()
|
im = hopper()
|
||||||
assert test_viewer.show(im) == 1
|
assert test_viewer.show(im) == 1
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(
|
|
||||||
not on_ci() or is_win32(),
|
|
||||||
reason="Only run on CIs; hangs on Windows CIs",
|
|
||||||
)
|
|
||||||
@pytest.mark.parametrize("viewer", ImageShow._viewers)
|
|
||||||
def test_file_deprecated(tmp_path, viewer):
|
|
||||||
f = str(tmp_path / "temp.jpg")
|
|
||||||
hopper().save(f)
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
try:
|
|
||||||
viewer.show_file(file=f)
|
|
||||||
except NotImplementedError:
|
|
||||||
pass
|
|
||||||
with pytest.raises(TypeError):
|
|
||||||
viewer.show_file()
|
|
||||||
|
|
|
@ -89,13 +89,6 @@ def test_photoimage_blank(mode):
|
||||||
assert_image_equal(reloaded.convert(mode), im)
|
assert_image_equal(reloaded.convert(mode), im)
|
||||||
|
|
||||||
|
|
||||||
def test_box_deprecation():
|
|
||||||
im = hopper()
|
|
||||||
im_tk = ImageTk.PhotoImage(im)
|
|
||||||
with pytest.warns(DeprecationWarning):
|
|
||||||
im_tk.paste(im, (0, 0, 128, 128))
|
|
||||||
|
|
||||||
|
|
||||||
def test_bitmapimage():
|
def test_bitmapimage():
|
||||||
im = hopper("1")
|
im = hopper("1")
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
import warnings
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
with warnings.catch_warnings():
|
from PIL import ImageQt
|
||||||
warnings.simplefilter("ignore", category=DeprecationWarning)
|
|
||||||
from PIL import ImageQt
|
|
||||||
|
|
||||||
from .helper import assert_image_equal_tofile, assert_image_similar, hopper
|
from .helper import assert_image_equal_tofile, assert_image_similar, hopper
|
||||||
|
|
||||||
|
@ -19,14 +15,6 @@ if ImageQt.qt_is_installed:
|
||||||
from PySide6.QtCore import QPoint
|
from PySide6.QtCore import QPoint
|
||||||
from PySide6.QtGui import QImage, QPainter, QRegion
|
from PySide6.QtGui import QImage, QPainter, QRegion
|
||||||
from PySide6.QtWidgets import QApplication, QHBoxLayout, QLabel, QWidget
|
from PySide6.QtWidgets import QApplication, QHBoxLayout, QLabel, QWidget
|
||||||
elif ImageQt.qt_version == "5":
|
|
||||||
from PyQt5.QtCore import QPoint
|
|
||||||
from PyQt5.QtGui import QImage, QPainter, QRegion
|
|
||||||
from PyQt5.QtWidgets import QApplication, QHBoxLayout, QLabel, QWidget
|
|
||||||
elif ImageQt.qt_version == "side2":
|
|
||||||
from PySide2.QtCore import QPoint
|
|
||||||
from PySide2.QtGui import QImage, QPainter, QRegion
|
|
||||||
from PySide2.QtWidgets import QApplication, QHBoxLayout, QLabel, QWidget
|
|
||||||
|
|
||||||
class Example(QWidget):
|
class Example(QWidget):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
import warnings
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
with warnings.catch_warnings():
|
from PIL import ImageQt
|
||||||
warnings.simplefilter("ignore", category=DeprecationWarning)
|
|
||||||
from PIL import ImageQt
|
|
||||||
|
|
||||||
from .helper import assert_image_equal, assert_image_equal_tofile, hopper
|
from .helper import assert_image_equal, assert_image_equal_tofile, hopper
|
||||||
|
|
||||||
|
@ -32,7 +28,7 @@ def test_sanity(mode, tmp_path):
|
||||||
assert_image_equal(rt, src)
|
assert_image_equal(rt, src)
|
||||||
|
|
||||||
if mode == "1":
|
if mode == "1":
|
||||||
# BW appears to not save correctly on QT5
|
# BW appears to not save correctly on Qt
|
||||||
# kicks out errors on console:
|
# kicks out errors on console:
|
||||||
# libpng warning: Invalid color type/bit depth combination
|
# libpng warning: Invalid color type/bit depth combination
|
||||||
# in IHDR
|
# in IHDR
|
||||||
|
|
|
@ -12,150 +12,6 @@ Deprecated features
|
||||||
Below are features which are considered deprecated. Where appropriate,
|
Below are features which are considered deprecated. Where appropriate,
|
||||||
a ``DeprecationWarning`` is issued.
|
a ``DeprecationWarning`` is issued.
|
||||||
|
|
||||||
Tk/Tcl 8.4
|
|
||||||
~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 8.2.0
|
|
||||||
|
|
||||||
Support for Tk/Tcl 8.4 is deprecated and will be removed in Pillow 10.0.0 (2023-07-01),
|
|
||||||
when Tk/Tcl 8.5 will be the minimum supported.
|
|
||||||
|
|
||||||
Categories
|
|
||||||
~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 8.2.0
|
|
||||||
|
|
||||||
``im.category`` is deprecated and will be removed in Pillow 10.0.0 (2023-07-01),
|
|
||||||
along with the related ``Image.NORMAL``, ``Image.SEQUENCE`` and
|
|
||||||
``Image.CONTAINER`` attributes.
|
|
||||||
|
|
||||||
To determine if an image has multiple frames or not,
|
|
||||||
``getattr(im, "is_animated", False)`` can be used instead.
|
|
||||||
|
|
||||||
JpegImagePlugin.convert_dict_qtables
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 8.3.0
|
|
||||||
|
|
||||||
JPEG ``quantization`` is now automatically converted, but still returned as a
|
|
||||||
dictionary. The :py:attr:`~PIL.JpegImagePlugin.convert_dict_qtables` method no longer
|
|
||||||
performs any operations on the data given to it, has been deprecated and will be
|
|
||||||
removed in Pillow 10.0.0 (2023-07-01).
|
|
||||||
|
|
||||||
ImagePalette size parameter
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 8.4.0
|
|
||||||
|
|
||||||
The ``size`` parameter will be removed in Pillow 10.0.0 (2023-07-01).
|
|
||||||
|
|
||||||
Before Pillow 8.3.0, ``ImagePalette`` required palette data of particular lengths by
|
|
||||||
default, and the size parameter could be used to override that. Pillow 8.3.0 removed
|
|
||||||
the default required length, also removing the need for the size parameter.
|
|
||||||
|
|
||||||
ImageShow.Viewer.show_file file argument
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 9.1.0
|
|
||||||
|
|
||||||
The ``file`` argument in :py:meth:`~PIL.ImageShow.Viewer.show_file()` has been
|
|
||||||
deprecated and will be removed in Pillow 10.0.0 (2023-07-01). It has been replaced by
|
|
||||||
``path``.
|
|
||||||
|
|
||||||
In effect, ``viewer.show_file("test.jpg")`` will continue to work unchanged.
|
|
||||||
``viewer.show_file(file="test.jpg")`` will raise a deprecation warning, and suggest
|
|
||||||
``viewer.show_file(path="test.jpg")`` instead.
|
|
||||||
|
|
||||||
Constants
|
|
||||||
~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 9.1.0
|
|
||||||
|
|
||||||
A number of constants have been deprecated and will be removed in Pillow 10.0.0
|
|
||||||
(2023-07-01). Instead, ``enum.IntEnum`` classes have been added.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
Additional ``Image`` constants were deprecated in Pillow 9.1.0, but that
|
|
||||||
was reversed in Pillow 9.4.0 and those constants will now remain available.
|
|
||||||
See :ref:`restored-image-constants`
|
|
||||||
|
|
||||||
===================================================== ============================================================
|
|
||||||
Deprecated Use instead
|
|
||||||
===================================================== ============================================================
|
|
||||||
``Image.LINEAR`` ``Image.BILINEAR`` or ``Image.Resampling.BILINEAR``
|
|
||||||
``Image.CUBIC`` ``Image.BICUBIC`` or ``Image.Resampling.BICUBIC``
|
|
||||||
``Image.ANTIALIAS`` ``Image.LANCZOS`` or ``Image.Resampling.LANCZOS``
|
|
||||||
``ImageCms.INTENT_PERCEPTUAL`` ``ImageCms.Intent.PERCEPTUAL``
|
|
||||||
``ImageCms.INTENT_RELATIVE_COLORMETRIC`` ``ImageCms.Intent.RELATIVE_COLORMETRIC``
|
|
||||||
``ImageCms.INTENT_SATURATION`` ``ImageCms.Intent.SATURATION``
|
|
||||||
``ImageCms.INTENT_ABSOLUTE_COLORIMETRIC`` ``ImageCms.Intent.ABSOLUTE_COLORIMETRIC``
|
|
||||||
``ImageCms.DIRECTION_INPUT`` ``ImageCms.Direction.INPUT``
|
|
||||||
``ImageCms.DIRECTION_OUTPUT`` ``ImageCms.Direction.OUTPUT``
|
|
||||||
``ImageCms.DIRECTION_PROOF`` ``ImageCms.Direction.PROOF``
|
|
||||||
``ImageFont.LAYOUT_BASIC`` ``ImageFont.Layout.BASIC``
|
|
||||||
``ImageFont.LAYOUT_RAQM`` ``ImageFont.Layout.RAQM``
|
|
||||||
``BlpImagePlugin.BLP_FORMAT_JPEG`` ``BlpImagePlugin.Format.JPEG``
|
|
||||||
``BlpImagePlugin.BLP_ENCODING_UNCOMPRESSED`` ``BlpImagePlugin.Encoding.UNCOMPRESSED``
|
|
||||||
``BlpImagePlugin.BLP_ENCODING_DXT`` ``BlpImagePlugin.Encoding.DXT``
|
|
||||||
``BlpImagePlugin.BLP_ENCODING_UNCOMPRESSED_RAW_RGBA`` ``BlpImagePlugin.Encoding.UNCOMPRESSED_RAW_RGBA``
|
|
||||||
``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT1`` ``BlpImagePlugin.AlphaEncoding.DXT1``
|
|
||||||
``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT3`` ``BlpImagePlugin.AlphaEncoding.DXT3``
|
|
||||||
``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT5`` ``BlpImagePlugin.AlphaEncoding.DXT5``
|
|
||||||
``FtexImagePlugin.FORMAT_DXT1`` ``FtexImagePlugin.Format.DXT1``
|
|
||||||
``FtexImagePlugin.FORMAT_UNCOMPRESSED`` ``FtexImagePlugin.Format.UNCOMPRESSED``
|
|
||||||
``PngImagePlugin.APNG_DISPOSE_OP_NONE`` ``PngImagePlugin.Disposal.OP_NONE``
|
|
||||||
``PngImagePlugin.APNG_DISPOSE_OP_BACKGROUND`` ``PngImagePlugin.Disposal.OP_BACKGROUND``
|
|
||||||
``PngImagePlugin.APNG_DISPOSE_OP_PREVIOUS`` ``PngImagePlugin.Disposal.OP_PREVIOUS``
|
|
||||||
``PngImagePlugin.APNG_BLEND_OP_SOURCE`` ``PngImagePlugin.Blend.OP_SOURCE``
|
|
||||||
``PngImagePlugin.APNG_BLEND_OP_OVER`` ``PngImagePlugin.Blend.OP_OVER``
|
|
||||||
===================================================== ============================================================
|
|
||||||
|
|
||||||
FitsStubImagePlugin
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 9.1.0
|
|
||||||
|
|
||||||
The stub image plugin ``FitsStubImagePlugin`` has been deprecated and will be removed in
|
|
||||||
Pillow 10.0.0 (2023-07-01). FITS images can be read without a handler through
|
|
||||||
:mod:`~PIL.FitsImagePlugin` instead.
|
|
||||||
|
|
||||||
FreeTypeFont.getmask2 fill parameter
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 9.2.0
|
|
||||||
|
|
||||||
The undocumented ``fill`` parameter of :py:meth:`.FreeTypeFont.getmask2` has been
|
|
||||||
deprecated and will be removed in Pillow 10 (2023-07-01).
|
|
||||||
|
|
||||||
PhotoImage.paste box parameter
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 9.2.0
|
|
||||||
|
|
||||||
The ``box`` parameter is unused. It will be removed in Pillow 10.0.0 (2023-07-01).
|
|
||||||
|
|
||||||
PyQt5 and PySide2
|
|
||||||
~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 9.2.0
|
|
||||||
|
|
||||||
`Qt 5 reached end-of-life <https://www.qt.io/blog/qt-5.15-released>`_ on 2020-12-08 for
|
|
||||||
open-source users (and will reach EOL on 2023-12-08 for commercial licence holders).
|
|
||||||
|
|
||||||
Support for PyQt5 and PySide2 has been deprecated from ``ImageQt`` and will be removed
|
|
||||||
in Pillow 10 (2023-07-01). Upgrade to
|
|
||||||
`PyQt6 <https://www.riverbankcomputing.com/static/Docs/PyQt6/>`_ or
|
|
||||||
`PySide6 <https://doc.qt.io/qtforpython/>`_ instead.
|
|
||||||
|
|
||||||
Image.coerce_e
|
|
||||||
~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. deprecated:: 9.2.0
|
|
||||||
|
|
||||||
This undocumented method has been deprecated and will be removed in Pillow 10
|
|
||||||
(2023-07-01).
|
|
||||||
|
|
||||||
.. _Font size and offset methods:
|
.. _Font size and offset methods:
|
||||||
|
|
||||||
Font size and offset methods
|
Font size and offset methods
|
||||||
|
@ -223,6 +79,149 @@ Removed features
|
||||||
Deprecated features are only removed in major releases after an appropriate
|
Deprecated features are only removed in major releases after an appropriate
|
||||||
period of deprecation has passed.
|
period of deprecation has passed.
|
||||||
|
|
||||||
|
Tk/Tcl 8.4
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 8.2.0
|
||||||
|
.. versionremoved:: 10.0.0
|
||||||
|
|
||||||
|
Support for Tk/Tcl 8.4 was removed in Pillow 10.0.0 (2023-07-01).
|
||||||
|
|
||||||
|
Categories
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 8.2.0
|
||||||
|
.. versionremoved:: 10.0.0
|
||||||
|
|
||||||
|
``im.category`` was removed along with the related ``Image.NORMAL``,
|
||||||
|
``Image.SEQUENCE`` and ``Image.CONTAINER`` attributes.
|
||||||
|
|
||||||
|
To determine if an image has multiple frames or not,
|
||||||
|
``getattr(im, "is_animated", False)`` can be used instead.
|
||||||
|
|
||||||
|
JpegImagePlugin.convert_dict_qtables
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 8.3.0
|
||||||
|
.. versionremoved:: 10.0.0
|
||||||
|
|
||||||
|
Since deprecation in Pillow 8.3.0, the ``convert_dict_qtables`` method no longer
|
||||||
|
performed any operations on the data given to it, and has been removed.
|
||||||
|
|
||||||
|
ImagePalette size parameter
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 8.4.0
|
||||||
|
.. versionremoved:: 10.0.0
|
||||||
|
|
||||||
|
Before Pillow 8.3.0, ``ImagePalette`` required palette data of particular lengths by
|
||||||
|
default, and the ``size`` parameter could be used to override that. Pillow 8.3.0
|
||||||
|
removed the default required length, also removing the need for the ``size`` parameter.
|
||||||
|
|
||||||
|
ImageShow.Viewer.show_file file argument
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 9.1.0
|
||||||
|
.. versionremoved:: 10.0.0
|
||||||
|
|
||||||
|
The ``file`` argument in :py:meth:`~PIL.ImageShow.Viewer.show_file()` has been
|
||||||
|
removed and replaced by ``path``.
|
||||||
|
|
||||||
|
In effect, ``viewer.show_file("test.jpg")`` will continue to work unchanged.
|
||||||
|
|
||||||
|
Constants
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 9.1.0
|
||||||
|
.. versionremoved:: 10.0.0
|
||||||
|
|
||||||
|
A number of constants have been removed.
|
||||||
|
Instead, ``enum.IntEnum`` classes have been added.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Additional ``Image`` constants were deprecated in Pillow 9.1.0, but that
|
||||||
|
was reversed in Pillow 9.4.0 and those constants will now remain available.
|
||||||
|
See :ref:`restored-image-constants`
|
||||||
|
|
||||||
|
===================================================== ============================================================
|
||||||
|
Removed Use instead
|
||||||
|
===================================================== ============================================================
|
||||||
|
``Image.LINEAR`` ``Image.BILINEAR`` or ``Image.Resampling.BILINEAR``
|
||||||
|
``Image.CUBIC`` ``Image.BICUBIC`` or ``Image.Resampling.BICUBIC``
|
||||||
|
``Image.ANTIALIAS`` ``Image.LANCZOS`` or ``Image.Resampling.LANCZOS``
|
||||||
|
``ImageCms.INTENT_PERCEPTUAL`` ``ImageCms.Intent.PERCEPTUAL``
|
||||||
|
``ImageCms.INTENT_RELATIVE_COLORMETRIC`` ``ImageCms.Intent.RELATIVE_COLORMETRIC``
|
||||||
|
``ImageCms.INTENT_SATURATION`` ``ImageCms.Intent.SATURATION``
|
||||||
|
``ImageCms.INTENT_ABSOLUTE_COLORIMETRIC`` ``ImageCms.Intent.ABSOLUTE_COLORIMETRIC``
|
||||||
|
``ImageCms.DIRECTION_INPUT`` ``ImageCms.Direction.INPUT``
|
||||||
|
``ImageCms.DIRECTION_OUTPUT`` ``ImageCms.Direction.OUTPUT``
|
||||||
|
``ImageCms.DIRECTION_PROOF`` ``ImageCms.Direction.PROOF``
|
||||||
|
``ImageFont.LAYOUT_BASIC`` ``ImageFont.Layout.BASIC``
|
||||||
|
``ImageFont.LAYOUT_RAQM`` ``ImageFont.Layout.RAQM``
|
||||||
|
``BlpImagePlugin.BLP_FORMAT_JPEG`` ``BlpImagePlugin.Format.JPEG``
|
||||||
|
``BlpImagePlugin.BLP_ENCODING_UNCOMPRESSED`` ``BlpImagePlugin.Encoding.UNCOMPRESSED``
|
||||||
|
``BlpImagePlugin.BLP_ENCODING_DXT`` ``BlpImagePlugin.Encoding.DXT``
|
||||||
|
``BlpImagePlugin.BLP_ENCODING_UNCOMPRESSED_RAW_RGBA`` ``BlpImagePlugin.Encoding.UNCOMPRESSED_RAW_RGBA``
|
||||||
|
``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT1`` ``BlpImagePlugin.AlphaEncoding.DXT1``
|
||||||
|
``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT3`` ``BlpImagePlugin.AlphaEncoding.DXT3``
|
||||||
|
``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT5`` ``BlpImagePlugin.AlphaEncoding.DXT5``
|
||||||
|
``FtexImagePlugin.FORMAT_DXT1`` ``FtexImagePlugin.Format.DXT1``
|
||||||
|
``FtexImagePlugin.FORMAT_UNCOMPRESSED`` ``FtexImagePlugin.Format.UNCOMPRESSED``
|
||||||
|
``PngImagePlugin.APNG_DISPOSE_OP_NONE`` ``PngImagePlugin.Disposal.OP_NONE``
|
||||||
|
``PngImagePlugin.APNG_DISPOSE_OP_BACKGROUND`` ``PngImagePlugin.Disposal.OP_BACKGROUND``
|
||||||
|
``PngImagePlugin.APNG_DISPOSE_OP_PREVIOUS`` ``PngImagePlugin.Disposal.OP_PREVIOUS``
|
||||||
|
``PngImagePlugin.APNG_BLEND_OP_SOURCE`` ``PngImagePlugin.Blend.OP_SOURCE``
|
||||||
|
``PngImagePlugin.APNG_BLEND_OP_OVER`` ``PngImagePlugin.Blend.OP_OVER``
|
||||||
|
===================================================== ============================================================
|
||||||
|
|
||||||
|
FitsStubImagePlugin
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 9.1.0
|
||||||
|
.. versionremoved:: 10.0.0
|
||||||
|
|
||||||
|
The stub image plugin ``FitsStubImagePlugin`` has been removed.
|
||||||
|
FITS images can be read without a handler through :mod:`~PIL.FitsImagePlugin` instead.
|
||||||
|
|
||||||
|
FreeTypeFont.getmask2 fill parameter
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 9.2.0
|
||||||
|
.. versionremoved:: 10.0.0
|
||||||
|
|
||||||
|
The undocumented ``fill`` parameter of :py:meth:`.FreeTypeFont.getmask2` has been
|
||||||
|
removed.
|
||||||
|
|
||||||
|
PhotoImage.paste box parameter
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 9.2.0
|
||||||
|
.. versionremoved:: 10.0.0
|
||||||
|
|
||||||
|
The ``box`` parameter was unused and has been removed.
|
||||||
|
|
||||||
|
PyQt5 and PySide2
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 9.2.0
|
||||||
|
.. versionremoved:: 10.0.0
|
||||||
|
|
||||||
|
`Qt 5 reached end-of-life <https://www.qt.io/blog/qt-5.15-released>`_ on 2020-12-08 for
|
||||||
|
open-source users (and will reach EOL on 2023-12-08 for commercial licence holders).
|
||||||
|
|
||||||
|
Support for PyQt5 and PySide2 has been removed from ``ImageQt``. Upgrade to
|
||||||
|
`PyQt6 <https://www.riverbankcomputing.com/static/Docs/PyQt6/>`_ or
|
||||||
|
`PySide6 <https://doc.qt.io/qtforpython/>`_ instead.
|
||||||
|
|
||||||
|
Image.coerce_e
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 9.2.0
|
||||||
|
.. versionremoved:: 10.0.0
|
||||||
|
|
||||||
|
This undocumented method has been removed.
|
||||||
|
|
||||||
PILLOW_VERSION constant
|
PILLOW_VERSION constant
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -412,18 +412,6 @@ See :ref:`concept-filters` for details.
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
:noindex:
|
:noindex:
|
||||||
|
|
||||||
Some deprecated filters are also available under the following names:
|
|
||||||
|
|
||||||
.. data:: NONE
|
|
||||||
:noindex:
|
|
||||||
:value: Resampling.NEAREST
|
|
||||||
.. data:: LINEAR
|
|
||||||
:value: Resampling.BILINEAR
|
|
||||||
.. data:: CUBIC
|
|
||||||
:value: Resampling.BICUBIC
|
|
||||||
.. data:: ANTIALIAS
|
|
||||||
:value: Resampling.LANCZOS
|
|
||||||
|
|
||||||
Dither modes
|
Dither modes
|
||||||
^^^^^^^^^^^^
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
|
@ -4,16 +4,8 @@
|
||||||
:py:mod:`~PIL.ImageQt` Module
|
:py:mod:`~PIL.ImageQt` Module
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
The :py:mod:`~PIL.ImageQt` module contains support for creating PyQt6, PySide6, PyQt5
|
The :py:mod:`~PIL.ImageQt` module contains support for creating PyQt6 or PySide6
|
||||||
or PySide2 QImage objects from PIL images.
|
QImage objects from PIL images.
|
||||||
|
|
||||||
`Qt 5 reached end-of-life <https://www.qt.io/blog/qt-5.15-released>`_ on 2020-12-08 for
|
|
||||||
open-source users (and will reach EOL on 2023-12-08 for commercial licence holders).
|
|
||||||
|
|
||||||
Support for PyQt5 and PySide2 has been deprecated from ``ImageQt`` and will be removed
|
|
||||||
in Pillow 10 (2023-07-01). Upgrade to
|
|
||||||
`PyQt6 <https://www.riverbankcomputing.com/static/Docs/PyQt6/>`_ or
|
|
||||||
`PySide6 <https://doc.qt.io/qtforpython/>`_ instead.
|
|
||||||
|
|
||||||
.. versionadded:: 1.1.6
|
.. versionadded:: 1.1.6
|
||||||
|
|
||||||
|
@ -22,7 +14,7 @@ in Pillow 10 (2023-07-01). Upgrade to
|
||||||
Creates an :py:class:`~PIL.ImageQt.ImageQt` object from a PIL
|
Creates an :py:class:`~PIL.ImageQt.ImageQt` object from a PIL
|
||||||
:py:class:`~PIL.Image.Image` object. This class is a subclass of
|
:py:class:`~PIL.Image.Image` object. This class is a subclass of
|
||||||
QtGui.QImage, which means that you can pass the resulting objects directly
|
QtGui.QImage, which means that you can pass the resulting objects directly
|
||||||
to PyQt6/PySide6/PyQt5/PySide2 API functions and methods.
|
to PyQt6/PySide6 API functions and methods.
|
||||||
|
|
||||||
This operation is currently supported for mode 1, L, P, RGB, and RGBA
|
This operation is currently supported for mode 1, L, P, RGB, and RGBA
|
||||||
images. To handle other modes, you need to convert the image first.
|
images. To handle other modes, you need to convert the image first.
|
||||||
|
|
149
docs/releasenotes/10.0.0.rst
Normal file
149
docs/releasenotes/10.0.0.rst
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
10.0.0
|
||||||
|
------
|
||||||
|
|
||||||
|
Backwards Incompatible Changes
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Categories
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
``im.category`` has been removed, along with the related ``Image.NORMAL``,
|
||||||
|
``Image.SEQUENCE`` and ``Image.CONTAINER`` attributes.
|
||||||
|
|
||||||
|
To determine if an image has multiple frames or not,
|
||||||
|
``getattr(im, "is_animated", False)`` can be used instead.
|
||||||
|
|
||||||
|
Tk/Tcl 8.4
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
Support for Tk/Tcl 8.4 has been removed.
|
||||||
|
|
||||||
|
JpegImagePlugin.convert_dict_qtables
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Since deprecation in Pillow 8.3.0, the ``convert_dict_qtables`` method no longer
|
||||||
|
performed any operations on the data given to it, and has been removed.
|
||||||
|
|
||||||
|
ImagePalette size parameter
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Before Pillow 8.3.0, ``ImagePalette`` required palette data of particular lengths by
|
||||||
|
default, and the ``size`` parameter could be used to override that. Pillow 8.3.0
|
||||||
|
removed the default required length, also removing the need for the ``size`` parameter.
|
||||||
|
|
||||||
|
ImageShow.Viewer.show_file file argument
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The ``file`` argument in :py:meth:`~PIL.ImageShow.Viewer.show_file()` has been
|
||||||
|
removed and replaced by ``path``.
|
||||||
|
|
||||||
|
In effect, ``viewer.show_file("test.jpg")`` will continue to work unchanged.
|
||||||
|
|
||||||
|
Constants
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
A number of constants have been removed.
|
||||||
|
Instead, ``enum.IntEnum`` classes have been added.
|
||||||
|
|
||||||
|
===================================================== ============================================================
|
||||||
|
Removed Use instead
|
||||||
|
===================================================== ============================================================
|
||||||
|
``Image.LINEAR`` ``Image.BILINEAR`` or ``Image.Resampling.BILINEAR``
|
||||||
|
``Image.CUBIC`` ``Image.BICUBIC`` or ``Image.Resampling.BICUBIC``
|
||||||
|
``Image.ANTIALIAS`` ``Image.LANCZOS`` or ``Image.Resampling.LANCZOS``
|
||||||
|
``ImageCms.INTENT_PERCEPTUAL`` ``ImageCms.Intent.PERCEPTUAL``
|
||||||
|
``ImageCms.INTENT_RELATIVE_COLORMETRIC`` ``ImageCms.Intent.RELATIVE_COLORMETRIC``
|
||||||
|
``ImageCms.INTENT_SATURATION`` ``ImageCms.Intent.SATURATION``
|
||||||
|
``ImageCms.INTENT_ABSOLUTE_COLORIMETRIC`` ``ImageCms.Intent.ABSOLUTE_COLORIMETRIC``
|
||||||
|
``ImageCms.DIRECTION_INPUT`` ``ImageCms.Direction.INPUT``
|
||||||
|
``ImageCms.DIRECTION_OUTPUT`` ``ImageCms.Direction.OUTPUT``
|
||||||
|
``ImageCms.DIRECTION_PROOF`` ``ImageCms.Direction.PROOF``
|
||||||
|
``ImageFont.LAYOUT_BASIC`` ``ImageFont.Layout.BASIC``
|
||||||
|
``ImageFont.LAYOUT_RAQM`` ``ImageFont.Layout.RAQM``
|
||||||
|
``BlpImagePlugin.BLP_FORMAT_JPEG`` ``BlpImagePlugin.Format.JPEG``
|
||||||
|
``BlpImagePlugin.BLP_ENCODING_UNCOMPRESSED`` ``BlpImagePlugin.Encoding.UNCOMPRESSED``
|
||||||
|
``BlpImagePlugin.BLP_ENCODING_DXT`` ``BlpImagePlugin.Encoding.DXT``
|
||||||
|
``BlpImagePlugin.BLP_ENCODING_UNCOMPRESSED_RAW_RGBA`` ``BlpImagePlugin.Encoding.UNCOMPRESSED_RAW_RGBA``
|
||||||
|
``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT1`` ``BlpImagePlugin.AlphaEncoding.DXT1``
|
||||||
|
``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT3`` ``BlpImagePlugin.AlphaEncoding.DXT3``
|
||||||
|
``BlpImagePlugin.BLP_ALPHA_ENCODING_DXT5`` ``BlpImagePlugin.AlphaEncoding.DXT5``
|
||||||
|
``FtexImagePlugin.FORMAT_DXT1`` ``FtexImagePlugin.Format.DXT1``
|
||||||
|
``FtexImagePlugin.FORMAT_UNCOMPRESSED`` ``FtexImagePlugin.Format.UNCOMPRESSED``
|
||||||
|
``PngImagePlugin.APNG_DISPOSE_OP_NONE`` ``PngImagePlugin.Disposal.OP_NONE``
|
||||||
|
``PngImagePlugin.APNG_DISPOSE_OP_BACKGROUND`` ``PngImagePlugin.Disposal.OP_BACKGROUND``
|
||||||
|
``PngImagePlugin.APNG_DISPOSE_OP_PREVIOUS`` ``PngImagePlugin.Disposal.OP_PREVIOUS``
|
||||||
|
``PngImagePlugin.APNG_BLEND_OP_SOURCE`` ``PngImagePlugin.Blend.OP_SOURCE``
|
||||||
|
``PngImagePlugin.APNG_BLEND_OP_OVER`` ``PngImagePlugin.Blend.OP_OVER``
|
||||||
|
===================================================== ============================================================
|
||||||
|
|
||||||
|
FitsStubImagePlugin
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The stub image plugin ``FitsStubImagePlugin`` has been removed.
|
||||||
|
FITS images can be read without a handler through :mod:`~PIL.FitsImagePlugin` instead.
|
||||||
|
|
||||||
|
FreeTypeFont.getmask2 fill parameter
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The undocumented ``fill`` parameter of :py:meth:`.FreeTypeFont.getmask2` has been
|
||||||
|
removed.
|
||||||
|
|
||||||
|
PhotoImage.paste box parameter
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The ``box`` parameter was unused and has been removed.
|
||||||
|
|
||||||
|
PyQt5 and PySide2
|
||||||
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
`Qt 5 reached end-of-life <https://www.qt.io/blog/qt-5.15-released>`_ on 2020-12-08 for
|
||||||
|
open-source users (and will reach EOL on 2023-12-08 for commercial licence holders).
|
||||||
|
|
||||||
|
Support for PyQt5 and PySide2 has been removed from ``ImageQt``. Upgrade to
|
||||||
|
`PyQt6 <https://www.riverbankcomputing.com/static/Docs/PyQt6/>`_ or
|
||||||
|
`PySide6 <https://doc.qt.io/qtforpython/>`_ instead.
|
||||||
|
|
||||||
|
Image.coerce_e
|
||||||
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
This undocumented method has been removed.
|
||||||
|
|
||||||
|
Deprecations
|
||||||
|
============
|
||||||
|
|
||||||
|
TODO
|
||||||
|
^^^^
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
API Changes
|
||||||
|
===========
|
||||||
|
|
||||||
|
TODO
|
||||||
|
^^^^
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
API Additions
|
||||||
|
=============
|
||||||
|
|
||||||
|
TODO
|
||||||
|
^^^^
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
Security
|
||||||
|
========
|
||||||
|
|
||||||
|
TODO
|
||||||
|
^^^^
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
Other Changes
|
||||||
|
=============
|
||||||
|
|
||||||
|
TODO
|
||||||
|
^^^^
|
||||||
|
|
||||||
|
TODO
|
|
@ -8,7 +8,7 @@ JpegImagePlugin.convert_dict_qtables
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
JPEG ``quantization`` is now automatically converted, but still returned as a
|
JPEG ``quantization`` is now automatically converted, but still returned as a
|
||||||
dictionary. The :py:attr:`~PIL.JpegImagePlugin.convert_dict_qtables` method no longer
|
dictionary. The ``convert_dict_qtables`` method no longer
|
||||||
performs any operations on the data given to it, has been deprecated and will be
|
performs any operations on the data given to it, has been deprecated and will be
|
||||||
removed in Pillow 10.0.0 (2023-07-01).
|
removed in Pillow 10.0.0 (2023-07-01).
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ expected to be backported to earlier versions.
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
|
10.0.0
|
||||||
9.5.0
|
9.5.0
|
||||||
9.4.0
|
9.4.0
|
||||||
9.3.0
|
9.3.0
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
x.y.z
|
xx.y.z
|
||||||
-----
|
------
|
||||||
|
|
||||||
Backwards Incompatible Changes
|
Backwards Incompatible Changes
|
||||||
==============================
|
==============================
|
||||||
|
|
4
setup.py
4
setup.py
|
@ -685,10 +685,6 @@ class pil_build_ext(build_ext):
|
||||||
# Add the directory to the include path so we can include
|
# Add the directory to the include path so we can include
|
||||||
# <openjpeg.h> rather than having to cope with the versioned
|
# <openjpeg.h> rather than having to cope with the versioned
|
||||||
# include path
|
# include path
|
||||||
# FIXME (melvyn-sopacua):
|
|
||||||
# At this point it's possible that best_path is already in
|
|
||||||
# self.compiler.include_dirs. Should investigate how that is
|
|
||||||
# possible.
|
|
||||||
_add_directory(self.compiler.include_dirs, best_path, 0)
|
_add_directory(self.compiler.include_dirs, best_path, 0)
|
||||||
feature.jpeg2000 = "openjp2"
|
feature.jpeg2000 = "openjp2"
|
||||||
feature.openjpeg_version = ".".join(str(x) for x in best_version)
|
feature.openjpeg_version = ".".join(str(x) for x in best_version)
|
||||||
|
|
|
@ -35,7 +35,6 @@ from enum import IntEnum
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from . import Image, ImageFile
|
from . import Image, ImageFile
|
||||||
from ._deprecate import deprecate
|
|
||||||
|
|
||||||
|
|
||||||
class Format(IntEnum):
|
class Format(IntEnum):
|
||||||
|
@ -54,21 +53,6 @@ class AlphaEncoding(IntEnum):
|
||||||
DXT5 = 7
|
DXT5 = 7
|
||||||
|
|
||||||
|
|
||||||
def __getattr__(name):
|
|
||||||
for enum, prefix in {
|
|
||||||
Format: "BLP_FORMAT_",
|
|
||||||
Encoding: "BLP_ENCODING_",
|
|
||||||
AlphaEncoding: "BLP_ALPHA_ENCODING_",
|
|
||||||
}.items():
|
|
||||||
if name.startswith(prefix):
|
|
||||||
name = name[len(prefix) :]
|
|
||||||
if name in enum.__members__:
|
|
||||||
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
|
||||||
return enum[name]
|
|
||||||
msg = f"module '{__name__}' has no attribute '{name}'"
|
|
||||||
raise AttributeError(msg)
|
|
||||||
|
|
||||||
|
|
||||||
def unpack_565(i):
|
def unpack_565(i):
|
||||||
return ((i >> 11) & 0x1F) << 3, ((i >> 5) & 0x3F) << 2, (i & 0x1F) << 3
|
return ((i >> 11) & 0x1F) << 3, ((i >> 5) & 0x3F) << 2, (i & 0x1F) << 3
|
||||||
|
|
||||||
|
|
|
@ -1,76 +0,0 @@
|
||||||
#
|
|
||||||
# The Python Imaging Library
|
|
||||||
# $Id$
|
|
||||||
#
|
|
||||||
# FITS stub adapter
|
|
||||||
#
|
|
||||||
# Copyright (c) 1998-2003 by Fredrik Lundh
|
|
||||||
#
|
|
||||||
# See the README file for information on usage and redistribution.
|
|
||||||
#
|
|
||||||
|
|
||||||
from . import FitsImagePlugin, Image, ImageFile
|
|
||||||
from ._deprecate import deprecate
|
|
||||||
|
|
||||||
_handler = None
|
|
||||||
|
|
||||||
|
|
||||||
def register_handler(handler):
|
|
||||||
"""
|
|
||||||
Install application-specific FITS image handler.
|
|
||||||
|
|
||||||
:param handler: Handler object.
|
|
||||||
"""
|
|
||||||
global _handler
|
|
||||||
_handler = handler
|
|
||||||
|
|
||||||
deprecate(
|
|
||||||
"FitsStubImagePlugin",
|
|
||||||
10,
|
|
||||||
action="FITS images can now be read without "
|
|
||||||
"a handler through FitsImagePlugin instead",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Override FitsImagePlugin with this handler
|
|
||||||
# for backwards compatibility
|
|
||||||
try:
|
|
||||||
Image.ID.remove(FITSStubImageFile.format)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
Image.register_open(
|
|
||||||
FITSStubImageFile.format, FITSStubImageFile, FitsImagePlugin._accept
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class FITSStubImageFile(ImageFile.StubImageFile):
|
|
||||||
format = FitsImagePlugin.FitsImageFile.format
|
|
||||||
format_description = FitsImagePlugin.FitsImageFile.format_description
|
|
||||||
|
|
||||||
def _open(self):
|
|
||||||
offset = self.fp.tell()
|
|
||||||
|
|
||||||
im = FitsImagePlugin.FitsImageFile(self.fp)
|
|
||||||
self._size = im.size
|
|
||||||
self.mode = im.mode
|
|
||||||
self.tile = []
|
|
||||||
|
|
||||||
self.fp.seek(offset)
|
|
||||||
|
|
||||||
loader = self._load()
|
|
||||||
if loader:
|
|
||||||
loader.open(self)
|
|
||||||
|
|
||||||
def _load(self):
|
|
||||||
return _handler
|
|
||||||
|
|
||||||
|
|
||||||
def _save(im, fp, filename):
|
|
||||||
msg = "FITS save handler not installed"
|
|
||||||
raise OSError(msg)
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
# Registry
|
|
||||||
|
|
||||||
Image.register_save(FITSStubImageFile.format, _save)
|
|
|
@ -56,7 +56,6 @@ from enum import IntEnum
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from . import Image, ImageFile
|
from . import Image, ImageFile
|
||||||
from ._deprecate import deprecate
|
|
||||||
|
|
||||||
MAGIC = b"FTEX"
|
MAGIC = b"FTEX"
|
||||||
|
|
||||||
|
@ -66,17 +65,6 @@ class Format(IntEnum):
|
||||||
UNCOMPRESSED = 1
|
UNCOMPRESSED = 1
|
||||||
|
|
||||||
|
|
||||||
def __getattr__(name):
|
|
||||||
for enum, prefix in {Format: "FORMAT_"}.items():
|
|
||||||
if name.startswith(prefix):
|
|
||||||
name = name[len(prefix) :]
|
|
||||||
if name in enum.__members__:
|
|
||||||
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
|
||||||
return enum[name]
|
|
||||||
msg = f"module '{__name__}' has no attribute '{name}'"
|
|
||||||
raise AttributeError(msg)
|
|
||||||
|
|
||||||
|
|
||||||
class FtexImageFile(ImageFile.ImageFile):
|
class FtexImageFile(ImageFile.ImageFile):
|
||||||
format = "FTEX"
|
format = "FTEX"
|
||||||
format_description = "Texture File Format (IW2:EOC)"
|
format_description = "Texture File Format (IW2:EOC)"
|
||||||
|
|
|
@ -56,29 +56,8 @@ from . import (
|
||||||
_plugins,
|
_plugins,
|
||||||
)
|
)
|
||||||
from ._binary import i32le, o32be, o32le
|
from ._binary import i32le, o32be, o32le
|
||||||
from ._deprecate import deprecate
|
|
||||||
from ._util import DeferredError, is_path
|
from ._util import DeferredError, is_path
|
||||||
|
|
||||||
|
|
||||||
def __getattr__(name):
|
|
||||||
categories = {"NORMAL": 0, "SEQUENCE": 1, "CONTAINER": 2}
|
|
||||||
if name in categories:
|
|
||||||
deprecate("Image categories", 10, "is_animated", plural=True)
|
|
||||||
return categories[name]
|
|
||||||
old_resampling = {
|
|
||||||
"LINEAR": "BILINEAR",
|
|
||||||
"CUBIC": "BICUBIC",
|
|
||||||
"ANTIALIAS": "LANCZOS",
|
|
||||||
}
|
|
||||||
if name in old_resampling:
|
|
||||||
deprecate(
|
|
||||||
name, 10, f"{old_resampling[name]} or Resampling.{old_resampling[name]}"
|
|
||||||
)
|
|
||||||
return Resampling[old_resampling[name]]
|
|
||||||
msg = f"module '{__name__}' has no attribute '{name}'"
|
|
||||||
raise AttributeError(msg)
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -441,26 +420,18 @@ def _getencoder(mode, encoder_name, args, extra=()):
|
||||||
# Simple expression analyzer
|
# Simple expression analyzer
|
||||||
|
|
||||||
|
|
||||||
def coerce_e(value):
|
|
||||||
deprecate("coerce_e", 10)
|
|
||||||
return value if isinstance(value, _E) else _E(1, value)
|
|
||||||
|
|
||||||
|
|
||||||
# _E(scale, offset) represents the affine transformation scale * x + offset.
|
|
||||||
# The "data" field is named for compatibility with the old implementation,
|
|
||||||
# and should be renamed once coerce_e is removed.
|
|
||||||
class _E:
|
class _E:
|
||||||
def __init__(self, scale, data):
|
def __init__(self, scale, offset):
|
||||||
self.scale = scale
|
self.scale = scale
|
||||||
self.data = data
|
self.offset = offset
|
||||||
|
|
||||||
def __neg__(self):
|
def __neg__(self):
|
||||||
return _E(-self.scale, -self.data)
|
return _E(-self.scale, -self.offset)
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
if isinstance(other, _E):
|
if isinstance(other, _E):
|
||||||
return _E(self.scale + other.scale, self.data + other.data)
|
return _E(self.scale + other.scale, self.offset + other.offset)
|
||||||
return _E(self.scale, self.data + other)
|
return _E(self.scale, self.offset + other)
|
||||||
|
|
||||||
__radd__ = __add__
|
__radd__ = __add__
|
||||||
|
|
||||||
|
@ -473,19 +444,19 @@ class _E:
|
||||||
def __mul__(self, other):
|
def __mul__(self, other):
|
||||||
if isinstance(other, _E):
|
if isinstance(other, _E):
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
return _E(self.scale * other, self.data * other)
|
return _E(self.scale * other, self.offset * other)
|
||||||
|
|
||||||
__rmul__ = __mul__
|
__rmul__ = __mul__
|
||||||
|
|
||||||
def __truediv__(self, other):
|
def __truediv__(self, other):
|
||||||
if isinstance(other, _E):
|
if isinstance(other, _E):
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
return _E(self.scale / other, self.data / other)
|
return _E(self.scale / other, self.offset / other)
|
||||||
|
|
||||||
|
|
||||||
def _getscaleoffset(expr):
|
def _getscaleoffset(expr):
|
||||||
a = expr(_E(1, 0))
|
a = expr(_E(1, 0))
|
||||||
return (a.scale, a.data) if isinstance(a, _E) else (0, a)
|
return (a.scale, a.offset) if isinstance(a, _E) else (0, a)
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
@ -516,17 +487,10 @@ class Image:
|
||||||
self._size = (0, 0)
|
self._size = (0, 0)
|
||||||
self.palette = None
|
self.palette = None
|
||||||
self.info = {}
|
self.info = {}
|
||||||
self._category = 0
|
|
||||||
self.readonly = 0
|
self.readonly = 0
|
||||||
self.pyaccess = None
|
self.pyaccess = None
|
||||||
self._exif = None
|
self._exif = None
|
||||||
|
|
||||||
def __getattr__(self, name):
|
|
||||||
if name == "category":
|
|
||||||
deprecate("Image categories", 10, "is_animated", plural=True)
|
|
||||||
return self._category
|
|
||||||
raise AttributeError(name)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def width(self):
|
def width(self):
|
||||||
return self.size[0]
|
return self.size[0]
|
||||||
|
@ -639,7 +603,6 @@ class Image:
|
||||||
and self.mode == other.mode
|
and self.mode == other.mode
|
||||||
and self.size == other.size
|
and self.size == other.size
|
||||||
and self.info == other.info
|
and self.info == other.info
|
||||||
and self._category == other._category
|
|
||||||
and self.getpalette() == other.getpalette()
|
and self.getpalette() == other.getpalette()
|
||||||
and self.tobytes() == other.tobytes()
|
and self.tobytes() == other.tobytes()
|
||||||
)
|
)
|
||||||
|
|
|
@ -20,8 +20,6 @@ from enum import IntEnum
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
from ._deprecate import deprecate
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from PIL import _imagingcms
|
from PIL import _imagingcms
|
||||||
except ImportError as ex:
|
except ImportError as ex:
|
||||||
|
@ -117,17 +115,6 @@ class Direction(IntEnum):
|
||||||
PROOF = 2
|
PROOF = 2
|
||||||
|
|
||||||
|
|
||||||
def __getattr__(name):
|
|
||||||
for enum, prefix in {Intent: "INTENT_", Direction: "DIRECTION_"}.items():
|
|
||||||
if name.startswith(prefix):
|
|
||||||
name = name[len(prefix) :]
|
|
||||||
if name in enum.__members__:
|
|
||||||
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
|
||||||
return enum[name]
|
|
||||||
msg = f"module '{__name__}' has no attribute '{name}'"
|
|
||||||
raise AttributeError(msg)
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# flags
|
# flags
|
||||||
|
|
||||||
|
|
|
@ -43,17 +43,6 @@ class Layout(IntEnum):
|
||||||
RAQM = 1
|
RAQM = 1
|
||||||
|
|
||||||
|
|
||||||
def __getattr__(name):
|
|
||||||
for enum, prefix in {Layout: "LAYOUT_"}.items():
|
|
||||||
if name.startswith(prefix):
|
|
||||||
name = name[len(prefix) :]
|
|
||||||
if name in enum.__members__:
|
|
||||||
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
|
||||||
return enum[name]
|
|
||||||
msg = f"module '{__name__}' has no attribute '{name}'"
|
|
||||||
raise AttributeError(msg)
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from . import _imagingft as core
|
from . import _imagingft as core
|
||||||
except ImportError as ex:
|
except ImportError as ex:
|
||||||
|
@ -62,9 +51,6 @@ except ImportError as ex:
|
||||||
core = DeferredError(ex)
|
core = DeferredError(ex)
|
||||||
|
|
||||||
|
|
||||||
_UNSPECIFIED = object()
|
|
||||||
|
|
||||||
|
|
||||||
# FIXME: add support for pilfont2 format (see FontFile.py)
|
# FIXME: add support for pilfont2 format (see FontFile.py)
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
@ -665,7 +651,6 @@ class FreeTypeFont:
|
||||||
self,
|
self,
|
||||||
text,
|
text,
|
||||||
mode="",
|
mode="",
|
||||||
fill=_UNSPECIFIED,
|
|
||||||
direction=None,
|
direction=None,
|
||||||
features=None,
|
features=None,
|
||||||
language=None,
|
language=None,
|
||||||
|
@ -691,12 +676,6 @@ class FreeTypeFont:
|
||||||
|
|
||||||
.. versionadded:: 1.1.5
|
.. versionadded:: 1.1.5
|
||||||
|
|
||||||
:param fill: Optional fill function. By default, an internal Pillow function
|
|
||||||
will be used.
|
|
||||||
|
|
||||||
Deprecated. This parameter will be removed in Pillow 10
|
|
||||||
(2023-07-01).
|
|
||||||
|
|
||||||
:param direction: Direction of the text. It can be 'rtl' (right to
|
:param direction: Direction of the text. It can be 'rtl' (right to
|
||||||
left), 'ltr' (left to right) or 'ttb' (top to bottom).
|
left), 'ltr' (left to right) or 'ttb' (top to bottom).
|
||||||
Requires libraqm.
|
Requires libraqm.
|
||||||
|
@ -749,10 +728,6 @@ class FreeTypeFont:
|
||||||
:py:mod:`PIL.Image.core` interface module, and the text offset, the
|
:py:mod:`PIL.Image.core` interface module, and the text offset, the
|
||||||
gap between the starting coordinate and the first marking
|
gap between the starting coordinate and the first marking
|
||||||
"""
|
"""
|
||||||
if fill is _UNSPECIFIED:
|
|
||||||
fill = Image.core.fill
|
|
||||||
else:
|
|
||||||
deprecate("fill", 10)
|
|
||||||
size, offset = self.font.getsize(
|
size, offset = self.font.getsize(
|
||||||
text, mode, direction, features, language, anchor
|
text, mode, direction, features, language, anchor
|
||||||
)
|
)
|
||||||
|
@ -761,7 +736,7 @@ class FreeTypeFont:
|
||||||
size = tuple(math.ceil(size[i] + stroke_width * 2 + start[i]) for i in range(2))
|
size = tuple(math.ceil(size[i] + stroke_width * 2 + start[i]) for i in range(2))
|
||||||
offset = offset[0] - stroke_width, offset[1] - stroke_width
|
offset = offset[0] - stroke_width, offset[1] - stroke_width
|
||||||
Image._decompression_bomb_check(size)
|
Image._decompression_bomb_check(size)
|
||||||
im = fill("RGBA" if mode == "RGBA" else "L", size, 0)
|
im = Image.core.fill("RGBA" if mode == "RGBA" else "L", size, 0)
|
||||||
if min(size):
|
if min(size):
|
||||||
self.font.render(
|
self.font.render(
|
||||||
text,
|
text,
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
import array
|
import array
|
||||||
|
|
||||||
from . import GimpGradientFile, GimpPaletteFile, ImageColor, PaletteFile
|
from . import GimpGradientFile, GimpPaletteFile, ImageColor, PaletteFile
|
||||||
from ._deprecate import deprecate
|
|
||||||
|
|
||||||
|
|
||||||
class ImagePalette:
|
class ImagePalette:
|
||||||
|
@ -34,16 +33,11 @@ class ImagePalette:
|
||||||
Defaults to an empty palette.
|
Defaults to an empty palette.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, mode="RGB", palette=None, size=0):
|
def __init__(self, mode="RGB", palette=None):
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.rawmode = None # if set, palette contains raw data
|
self.rawmode = None # if set, palette contains raw data
|
||||||
self.palette = palette or bytearray()
|
self.palette = palette or bytearray()
|
||||||
self.dirty = None
|
self.dirty = None
|
||||||
if size != 0:
|
|
||||||
deprecate("The size parameter", 10, None)
|
|
||||||
if size != len(self.palette):
|
|
||||||
msg = "wrong palette size"
|
|
||||||
raise ValueError(msg)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def palette(self):
|
def palette(self):
|
||||||
|
|
|
@ -20,14 +20,11 @@ import sys
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from . import Image
|
from . import Image
|
||||||
from ._deprecate import deprecate
|
|
||||||
from ._util import is_path
|
from ._util import is_path
|
||||||
|
|
||||||
qt_versions = [
|
qt_versions = [
|
||||||
["6", "PyQt6"],
|
["6", "PyQt6"],
|
||||||
["side6", "PySide6"],
|
["side6", "PySide6"],
|
||||||
["5", "PyQt5"],
|
|
||||||
["side2", "PySide2"],
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# If a version has already been imported, attempt it first
|
# If a version has already been imported, attempt it first
|
||||||
|
@ -40,16 +37,6 @@ for qt_version, qt_module in qt_versions:
|
||||||
elif qt_module == "PySide6":
|
elif qt_module == "PySide6":
|
||||||
from PySide6.QtCore import QBuffer, QIODevice
|
from PySide6.QtCore import QBuffer, QIODevice
|
||||||
from PySide6.QtGui import QImage, QPixmap, qRgba
|
from PySide6.QtGui import QImage, QPixmap, qRgba
|
||||||
elif qt_module == "PyQt5":
|
|
||||||
from PyQt5.QtCore import QBuffer, QIODevice
|
|
||||||
from PyQt5.QtGui import QImage, QPixmap, qRgba
|
|
||||||
|
|
||||||
deprecate("Support for PyQt5", 10, "PyQt6 or PySide6")
|
|
||||||
elif qt_module == "PySide2":
|
|
||||||
from PySide2.QtCore import QBuffer, QIODevice
|
|
||||||
from PySide2.QtGui import QImage, QPixmap, qRgba
|
|
||||||
|
|
||||||
deprecate("Support for PySide2", 10, "PyQt6 or PySide6")
|
|
||||||
except (ImportError, RuntimeError):
|
except (ImportError, RuntimeError):
|
||||||
continue
|
continue
|
||||||
qt_is_installed = True
|
qt_is_installed = True
|
||||||
|
|
|
@ -19,8 +19,6 @@ from shlex import quote
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
from ._deprecate import deprecate
|
|
||||||
|
|
||||||
_viewers = []
|
_viewers = []
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,21 +109,10 @@ class Viewer:
|
||||||
"""Display the given image."""
|
"""Display the given image."""
|
||||||
return self.show_file(self.save_image(image), **options)
|
return self.show_file(self.save_image(image), **options)
|
||||||
|
|
||||||
def show_file(self, path=None, **options):
|
def show_file(self, path, **options):
|
||||||
"""
|
"""
|
||||||
Display given file.
|
Display given file.
|
||||||
|
|
||||||
Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated,
|
|
||||||
and will be removed in Pillow 10.0.0 (2023-07-01). ``path`` should be used
|
|
||||||
instead.
|
|
||||||
"""
|
"""
|
||||||
if path is None:
|
|
||||||
if "file" in options:
|
|
||||||
deprecate("The 'file' argument", 10, "'path'")
|
|
||||||
path = options.pop("file")
|
|
||||||
else:
|
|
||||||
msg = "Missing required argument: 'path'"
|
|
||||||
raise TypeError(msg)
|
|
||||||
os.system(self.get_command(path, **options)) # nosec
|
os.system(self.get_command(path, **options)) # nosec
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@ -164,21 +151,10 @@ class MacViewer(Viewer):
|
||||||
command = f"({command} {quote(file)}; sleep 20; rm -f {quote(file)})&"
|
command = f"({command} {quote(file)}; sleep 20; rm -f {quote(file)})&"
|
||||||
return command
|
return command
|
||||||
|
|
||||||
def show_file(self, path=None, **options):
|
def show_file(self, path, **options):
|
||||||
"""
|
"""
|
||||||
Display given file.
|
Display given file.
|
||||||
|
|
||||||
Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated,
|
|
||||||
and will be removed in Pillow 10.0.0 (2023-07-01). ``path`` should be used
|
|
||||||
instead.
|
|
||||||
"""
|
"""
|
||||||
if path is None:
|
|
||||||
if "file" in options:
|
|
||||||
deprecate("The 'file' argument", 10, "'path'")
|
|
||||||
path = options.pop("file")
|
|
||||||
else:
|
|
||||||
msg = "Missing required argument: 'path'"
|
|
||||||
raise TypeError(msg)
|
|
||||||
subprocess.call(["open", "-a", "Preview.app", path])
|
subprocess.call(["open", "-a", "Preview.app", path])
|
||||||
executable = sys.executable or shutil.which("python3")
|
executable = sys.executable or shutil.which("python3")
|
||||||
if executable:
|
if executable:
|
||||||
|
@ -215,21 +191,10 @@ class XDGViewer(UnixViewer):
|
||||||
command = executable = "xdg-open"
|
command = executable = "xdg-open"
|
||||||
return command, executable
|
return command, executable
|
||||||
|
|
||||||
def show_file(self, path=None, **options):
|
def show_file(self, path, **options):
|
||||||
"""
|
"""
|
||||||
Display given file.
|
Display given file.
|
||||||
|
|
||||||
Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated,
|
|
||||||
and will be removed in Pillow 10.0.0 (2023-07-01). ``path`` should be used
|
|
||||||
instead.
|
|
||||||
"""
|
"""
|
||||||
if path is None:
|
|
||||||
if "file" in options:
|
|
||||||
deprecate("The 'file' argument", 10, "'path'")
|
|
||||||
path = options.pop("file")
|
|
||||||
else:
|
|
||||||
msg = "Missing required argument: 'path'"
|
|
||||||
raise TypeError(msg)
|
|
||||||
subprocess.Popen(["xdg-open", path])
|
subprocess.Popen(["xdg-open", path])
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@ -246,20 +211,10 @@ class DisplayViewer(UnixViewer):
|
||||||
command += f" -title {quote(title)}"
|
command += f" -title {quote(title)}"
|
||||||
return command, executable
|
return command, executable
|
||||||
|
|
||||||
def show_file(self, path=None, **options):
|
def show_file(self, path, **options):
|
||||||
"""
|
"""
|
||||||
Display given file.
|
Display given file.
|
||||||
|
|
||||||
Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated,
|
|
||||||
and ``path`` should be used instead.
|
|
||||||
"""
|
"""
|
||||||
if path is None:
|
|
||||||
if "file" in options:
|
|
||||||
deprecate("The 'file' argument", 10, "'path'")
|
|
||||||
path = options.pop("file")
|
|
||||||
else:
|
|
||||||
msg = "Missing required argument: 'path'"
|
|
||||||
raise TypeError(msg)
|
|
||||||
args = ["display"]
|
args = ["display"]
|
||||||
title = options.get("title")
|
title = options.get("title")
|
||||||
if title:
|
if title:
|
||||||
|
@ -278,20 +233,10 @@ class GmDisplayViewer(UnixViewer):
|
||||||
command = "gm display"
|
command = "gm display"
|
||||||
return command, executable
|
return command, executable
|
||||||
|
|
||||||
def show_file(self, path=None, **options):
|
def show_file(self, path, **options):
|
||||||
"""
|
"""
|
||||||
Display given file.
|
Display given file.
|
||||||
|
|
||||||
Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated,
|
|
||||||
and ``path`` should be used instead.
|
|
||||||
"""
|
"""
|
||||||
if path is None:
|
|
||||||
if "file" in options:
|
|
||||||
deprecate("The 'file' argument", 10, "'path'")
|
|
||||||
path = options.pop("file")
|
|
||||||
else:
|
|
||||||
msg = "Missing required argument: 'path'"
|
|
||||||
raise TypeError(msg)
|
|
||||||
subprocess.Popen(["gm", "display", path])
|
subprocess.Popen(["gm", "display", path])
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@ -304,20 +249,10 @@ class EogViewer(UnixViewer):
|
||||||
command = "eog -n"
|
command = "eog -n"
|
||||||
return command, executable
|
return command, executable
|
||||||
|
|
||||||
def show_file(self, path=None, **options):
|
def show_file(self, path, **options):
|
||||||
"""
|
"""
|
||||||
Display given file.
|
Display given file.
|
||||||
|
|
||||||
Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated,
|
|
||||||
and ``path`` should be used instead.
|
|
||||||
"""
|
"""
|
||||||
if path is None:
|
|
||||||
if "file" in options:
|
|
||||||
deprecate("The 'file' argument", 10, "'path'")
|
|
||||||
path = options.pop("file")
|
|
||||||
else:
|
|
||||||
msg = "Missing required argument: 'path'"
|
|
||||||
raise TypeError(msg)
|
|
||||||
subprocess.Popen(["eog", "-n", path])
|
subprocess.Popen(["eog", "-n", path])
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@ -336,20 +271,10 @@ class XVViewer(UnixViewer):
|
||||||
command += f" -name {quote(title)}"
|
command += f" -name {quote(title)}"
|
||||||
return command, executable
|
return command, executable
|
||||||
|
|
||||||
def show_file(self, path=None, **options):
|
def show_file(self, path, **options):
|
||||||
"""
|
"""
|
||||||
Display given file.
|
Display given file.
|
||||||
|
|
||||||
Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated,
|
|
||||||
and ``path`` should be used instead.
|
|
||||||
"""
|
"""
|
||||||
if path is None:
|
|
||||||
if "file" in options:
|
|
||||||
deprecate("The 'file' argument", 10, "'path'")
|
|
||||||
path = options.pop("file")
|
|
||||||
else:
|
|
||||||
msg = "Missing required argument: 'path'"
|
|
||||||
raise TypeError(msg)
|
|
||||||
args = ["xv"]
|
args = ["xv"]
|
||||||
title = options.get("title")
|
title = options.get("title")
|
||||||
if title:
|
if title:
|
||||||
|
|
|
@ -29,7 +29,6 @@ import tkinter
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from . import Image
|
from . import Image
|
||||||
from ._deprecate import deprecate
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
# Check for Tkinter interface hooks
|
# Check for Tkinter interface hooks
|
||||||
|
@ -162,7 +161,7 @@ class PhotoImage:
|
||||||
"""
|
"""
|
||||||
return self.__size[1]
|
return self.__size[1]
|
||||||
|
|
||||||
def paste(self, im, box=None):
|
def paste(self, im):
|
||||||
"""
|
"""
|
||||||
Paste a PIL image into the photo image. Note that this can
|
Paste a PIL image into the photo image. Note that this can
|
||||||
be very slow if the photo image is displayed.
|
be very slow if the photo image is displayed.
|
||||||
|
@ -170,13 +169,7 @@ class PhotoImage:
|
||||||
:param im: A PIL image. The size must match the target region. If the
|
:param im: A PIL image. The size must match the target region. If the
|
||||||
mode does not match, the image is converted to the mode of
|
mode does not match, the image is converted to the mode of
|
||||||
the bitmap image.
|
the bitmap image.
|
||||||
:param box: Deprecated. This parameter will be removed in Pillow 10
|
|
||||||
(2023-07-01).
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if box is not None:
|
|
||||||
deprecate("The box parameter", 10, None)
|
|
||||||
|
|
||||||
# convert to blittable
|
# convert to blittable
|
||||||
im.load()
|
im.load()
|
||||||
image = im.im
|
image = im.im
|
||||||
|
|
|
@ -46,7 +46,6 @@ from ._binary import i16be as i16
|
||||||
from ._binary import i32be as i32
|
from ._binary import i32be as i32
|
||||||
from ._binary import o8
|
from ._binary import o8
|
||||||
from ._binary import o16be as o16
|
from ._binary import o16be as o16
|
||||||
from ._deprecate import deprecate
|
|
||||||
from .JpegPresets import presets
|
from .JpegPresets import presets
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -612,11 +611,6 @@ samplings = {
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
|
|
||||||
def convert_dict_qtables(qtables):
|
|
||||||
deprecate("convert_dict_qtables", 10, action="Conversion is no longer needed")
|
|
||||||
return qtables
|
|
||||||
|
|
||||||
|
|
||||||
def get_sampling(im):
|
def get_sampling(im):
|
||||||
# There's no subsampling when images have only 1 layer
|
# There's no subsampling when images have only 1 layer
|
||||||
# (grayscale images) or when they are CMYK (4 layers),
|
# (grayscale images) or when they are CMYK (4 layers),
|
||||||
|
|
|
@ -66,9 +66,6 @@ class MicImageFile(TiffImagePlugin.TiffImageFile):
|
||||||
self._n_frames = len(self.images)
|
self._n_frames = len(self.images)
|
||||||
self.is_animated = self._n_frames > 1
|
self.is_animated = self._n_frames > 1
|
||||||
|
|
||||||
if len(self.images) > 1:
|
|
||||||
self._category = Image.CONTAINER
|
|
||||||
|
|
||||||
self.seek(0)
|
self.seek(0)
|
||||||
|
|
||||||
def seek(self, frame):
|
def seek(self, frame):
|
||||||
|
|
|
@ -45,7 +45,6 @@ from ._binary import i32be as i32
|
||||||
from ._binary import o8
|
from ._binary import o8
|
||||||
from ._binary import o16be as o16
|
from ._binary import o16be as o16
|
||||||
from ._binary import o32be as o32
|
from ._binary import o32be as o32
|
||||||
from ._deprecate import deprecate
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -131,17 +130,6 @@ class Blend(IntEnum):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def __getattr__(name):
|
|
||||||
for enum, prefix in {Disposal: "APNG_DISPOSE_", Blend: "APNG_BLEND_"}.items():
|
|
||||||
if name.startswith(prefix):
|
|
||||||
name = name[len(prefix) :]
|
|
||||||
if name in enum.__members__:
|
|
||||||
deprecate(f"{prefix}{name}", 10, f"{enum.__name__}.{name}")
|
|
||||||
return enum[name]
|
|
||||||
msg = f"module '{__name__}' has no attribute '{name}'"
|
|
||||||
raise AttributeError(msg)
|
|
||||||
|
|
||||||
|
|
||||||
def _safe_zlib_decompress(s):
|
def _safe_zlib_decompress(s):
|
||||||
dobj = zlib.decompressobj()
|
dobj = zlib.decompressobj()
|
||||||
plaintext = dobj.decompress(s, MAX_TEXT_CHUNK)
|
plaintext = dobj.decompress(s, MAX_TEXT_CHUNK)
|
||||||
|
|
|
@ -31,7 +31,6 @@ _plugins = [
|
||||||
"DdsImagePlugin",
|
"DdsImagePlugin",
|
||||||
"EpsImagePlugin",
|
"EpsImagePlugin",
|
||||||
"FitsImagePlugin",
|
"FitsImagePlugin",
|
||||||
"FitsStubImagePlugin",
|
|
||||||
"FliImagePlugin",
|
"FliImagePlugin",
|
||||||
"FpxImagePlugin",
|
"FpxImagePlugin",
|
||||||
"FtexImagePlugin",
|
"FtexImagePlugin",
|
||||||
|
|
|
@ -4,8 +4,6 @@ import sys
|
||||||
import tkinter
|
import tkinter
|
||||||
from tkinter import _tkinter as tk
|
from tkinter import _tkinter as tk
|
||||||
|
|
||||||
from ._deprecate import deprecate
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if hasattr(sys, "pypy_find_executable"):
|
if hasattr(sys, "pypy_find_executable"):
|
||||||
TKINTER_LIB = tk.tklib_cffi.__file__
|
TKINTER_LIB = tk.tklib_cffi.__file__
|
||||||
|
@ -17,7 +15,3 @@ except AttributeError:
|
||||||
TKINTER_LIB = None
|
TKINTER_LIB = None
|
||||||
|
|
||||||
tk_version = str(tkinter.TkVersion)
|
tk_version = str(tkinter.TkVersion)
|
||||||
if tk_version == "8.4":
|
|
||||||
deprecate(
|
|
||||||
"Support for Tk/Tcl 8.4", 10, action="Please upgrade to Tk/Tcl 8.5 or newer"
|
|
||||||
)
|
|
||||||
|
|
|
@ -119,17 +119,7 @@ typedef struct Tk_PhotoImageBlock {
|
||||||
} Tk_PhotoImageBlock;
|
} Tk_PhotoImageBlock;
|
||||||
|
|
||||||
/* Typedefs derived from function signatures in Tk header */
|
/* Typedefs derived from function signatures in Tk header */
|
||||||
/* Tk_PhotoPutBlock for Tk <= 8.4 */
|
typedef int (*Tk_PhotoPutBlock_t)(
|
||||||
typedef void (*Tk_PhotoPutBlock_84_t)(
|
|
||||||
Tk_PhotoHandle handle,
|
|
||||||
Tk_PhotoImageBlock *blockPtr,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
int compRule);
|
|
||||||
/* Tk_PhotoPutBlock for Tk >= 8.5 */
|
|
||||||
typedef int (*Tk_PhotoPutBlock_85_t)(
|
|
||||||
Tcl_Interp *interp,
|
Tcl_Interp *interp,
|
||||||
Tk_PhotoHandle handle,
|
Tk_PhotoHandle handle,
|
||||||
Tk_PhotoImageBlock *blockPtr,
|
Tk_PhotoImageBlock *blockPtr,
|
||||||
|
@ -138,8 +128,6 @@ typedef int (*Tk_PhotoPutBlock_85_t)(
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
int compRule);
|
int compRule);
|
||||||
/* Tk_PhotoSetSize for Tk <= 8.4 */
|
|
||||||
typedef void (*Tk_PhotoSetSize_84_t)(Tk_PhotoHandle handle, int width, int height);
|
|
||||||
/* Tk_FindPhoto */
|
/* Tk_FindPhoto */
|
||||||
typedef Tk_PhotoHandle (*Tk_FindPhoto_t)(Tcl_Interp *interp, const char *imageName);
|
typedef Tk_PhotoHandle (*Tk_FindPhoto_t)(Tcl_Interp *interp, const char *imageName);
|
||||||
/* Tk_PhotoGetImage */
|
/* Tk_PhotoGetImage */
|
||||||
|
|
|
@ -48,14 +48,11 @@
|
||||||
* Global vars for Tcl / Tk functions. We load these symbols from the tkinter
|
* Global vars for Tcl / Tk functions. We load these symbols from the tkinter
|
||||||
* extension module or loaded Tcl / Tk libraries at run-time.
|
* extension module or loaded Tcl / Tk libraries at run-time.
|
||||||
*/
|
*/
|
||||||
static int TK_LT_85 = 0;
|
|
||||||
static Tcl_CreateCommand_t TCL_CREATE_COMMAND;
|
static Tcl_CreateCommand_t TCL_CREATE_COMMAND;
|
||||||
static Tcl_AppendResult_t TCL_APPEND_RESULT;
|
static Tcl_AppendResult_t TCL_APPEND_RESULT;
|
||||||
static Tk_FindPhoto_t TK_FIND_PHOTO;
|
static Tk_FindPhoto_t TK_FIND_PHOTO;
|
||||||
static Tk_PhotoGetImage_t TK_PHOTO_GET_IMAGE;
|
static Tk_PhotoGetImage_t TK_PHOTO_GET_IMAGE;
|
||||||
static Tk_PhotoPutBlock_84_t TK_PHOTO_PUT_BLOCK_84;
|
static Tk_PhotoPutBlock_t TK_PHOTO_PUT_BLOCK;
|
||||||
static Tk_PhotoSetSize_84_t TK_PHOTO_SET_SIZE_84;
|
|
||||||
static Tk_PhotoPutBlock_85_t TK_PHOTO_PUT_BLOCK_85;
|
|
||||||
|
|
||||||
static Imaging
|
static Imaging
|
||||||
ImagingFind(const char *name) {
|
ImagingFind(const char *name) {
|
||||||
|
@ -130,17 +127,7 @@ PyImagingPhotoPut(
|
||||||
block.pitch = im->linesize;
|
block.pitch = im->linesize;
|
||||||
block.pixelPtr = (unsigned char *)im->block;
|
block.pixelPtr = (unsigned char *)im->block;
|
||||||
|
|
||||||
if (TK_LT_85) { /* Tk 8.4 */
|
TK_PHOTO_PUT_BLOCK(
|
||||||
TK_PHOTO_PUT_BLOCK_84(
|
|
||||||
photo, &block, 0, 0, block.width, block.height, TK_PHOTO_COMPOSITE_SET);
|
|
||||||
if (strcmp(im->mode, "RGBA") == 0) {
|
|
||||||
/* Tk workaround: we need apply ToggleComplexAlphaIfNeeded */
|
|
||||||
/* (fixed in Tk 8.5a3) */
|
|
||||||
TK_PHOTO_SET_SIZE_84(photo, block.width, block.height);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Tk >=8.5 */
|
|
||||||
TK_PHOTO_PUT_BLOCK_85(
|
|
||||||
interp,
|
interp,
|
||||||
photo,
|
photo,
|
||||||
&block,
|
&block,
|
||||||
|
@ -149,7 +136,6 @@ PyImagingPhotoPut(
|
||||||
block.width,
|
block.width,
|
||||||
block.height,
|
block.height,
|
||||||
TK_PHOTO_COMPOSITE_SET);
|
TK_PHOTO_COMPOSITE_SET);
|
||||||
}
|
|
||||||
|
|
||||||
return TCL_OK;
|
return TCL_OK;
|
||||||
}
|
}
|
||||||
|
@ -290,16 +276,7 @@ get_tk(HMODULE hMod) {
|
||||||
if ((TK_FIND_PHOTO = (Tk_FindPhoto_t)_dfunc(hMod, "Tk_FindPhoto")) == NULL) {
|
if ((TK_FIND_PHOTO = (Tk_FindPhoto_t)_dfunc(hMod, "Tk_FindPhoto")) == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
TK_LT_85 = GetProcAddress(hMod, "Tk_PhotoPutBlock_Panic") == NULL;
|
TK_PHOTO_PUT_BLOCK = (Tk_PhotoPutBlock_t)func;
|
||||||
/* Tk_PhotoPutBlock_Panic defined as of 8.5.0 */
|
|
||||||
if (TK_LT_85) {
|
|
||||||
TK_PHOTO_PUT_BLOCK_84 = (Tk_PhotoPutBlock_84_t)func;
|
|
||||||
return ((TK_PHOTO_SET_SIZE_84 =
|
|
||||||
(Tk_PhotoSetSize_84_t)_dfunc(hMod, "Tk_PhotoSetSize")) == NULL)
|
|
||||||
? -1
|
|
||||||
: 1;
|
|
||||||
}
|
|
||||||
TK_PHOTO_PUT_BLOCK_85 = (Tk_PhotoPutBlock_85_t)func;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,18 +399,9 @@ _func_loader(void *lib) {
|
||||||
if ((TK_FIND_PHOTO = (Tk_FindPhoto_t)_dfunc(lib, "Tk_FindPhoto")) == NULL) {
|
if ((TK_FIND_PHOTO = (Tk_FindPhoto_t)_dfunc(lib, "Tk_FindPhoto")) == NULL) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* Tk_PhotoPutBlock_Panic defined as of 8.5.0 */
|
|
||||||
TK_LT_85 = (dlsym(lib, "Tk_PhotoPutBlock_Panic") == NULL);
|
|
||||||
if (TK_LT_85) {
|
|
||||||
return (
|
return (
|
||||||
((TK_PHOTO_PUT_BLOCK_84 =
|
(TK_PHOTO_PUT_BLOCK =
|
||||||
(Tk_PhotoPutBlock_84_t)_dfunc(lib, "Tk_PhotoPutBlock")) == NULL) ||
|
(Tk_PhotoPutBlock_t)_dfunc(lib, "Tk_PhotoPutBlock")) == NULL);
|
||||||
((TK_PHOTO_SET_SIZE_84 =
|
|
||||||
(Tk_PhotoSetSize_84_t)_dfunc(lib, "Tk_PhotoSetSize")) == NULL));
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
(TK_PHOTO_PUT_BLOCK_85 =
|
|
||||||
(Tk_PhotoPutBlock_85_t)_dfunc(lib, "Tk_PhotoPutBlock")) == NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
Loading…
Reference in New Issue
Block a user