mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 01:16:16 +03:00
Merge pull request #7913 from nulano/types-cms2
This commit is contained in:
commit
6c55ab22d7
|
@ -4,13 +4,14 @@ import datetime
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
|
import sys
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from PIL import Image, ImageMode, features
|
from PIL import Image, ImageMode, ImageWin, features
|
||||||
|
|
||||||
from .helper import (
|
from .helper import (
|
||||||
assert_image,
|
assert_image,
|
||||||
|
@ -18,6 +19,7 @@ from .helper import (
|
||||||
assert_image_similar,
|
assert_image_similar,
|
||||||
assert_image_similar_tofile,
|
assert_image_similar_tofile,
|
||||||
hopper,
|
hopper,
|
||||||
|
is_pypy,
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -213,6 +215,10 @@ def test_display_profile() -> None:
|
||||||
# try fetching the profile for the current display device
|
# try fetching the profile for the current display device
|
||||||
ImageCms.get_display_profile()
|
ImageCms.get_display_profile()
|
||||||
|
|
||||||
|
if sys.platform == "win32":
|
||||||
|
ImageCms.get_display_profile(ImageWin.HDC(0))
|
||||||
|
ImageCms.get_display_profile(ImageWin.HWND(0))
|
||||||
|
|
||||||
|
|
||||||
def test_lab_color_profile() -> None:
|
def test_lab_color_profile() -> None:
|
||||||
ImageCms.createProfile("LAB", 5000)
|
ImageCms.createProfile("LAB", 5000)
|
||||||
|
@ -496,16 +502,34 @@ def test_non_ascii_path(tmp_path: Path) -> None:
|
||||||
|
|
||||||
|
|
||||||
def test_profile_typesafety() -> None:
|
def test_profile_typesafety() -> None:
|
||||||
"""Profile init type safety
|
# does not segfault
|
||||||
|
|
||||||
prepatch, these would segfault, postpatch they should emit a typeerror
|
|
||||||
"""
|
|
||||||
|
|
||||||
with pytest.raises(TypeError, match="Invalid type for Profile"):
|
with pytest.raises(TypeError, match="Invalid type for Profile"):
|
||||||
ImageCms.ImageCmsProfile(0).tobytes()
|
ImageCms.ImageCmsProfile(0).tobytes()
|
||||||
with pytest.raises(TypeError, match="Invalid type for Profile"):
|
with pytest.raises(TypeError, match="Invalid type for Profile"):
|
||||||
ImageCms.ImageCmsProfile(1).tobytes()
|
ImageCms.ImageCmsProfile(1).tobytes()
|
||||||
|
|
||||||
|
# also check core function
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
ImageCms.core.profile_tobytes(0)
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
ImageCms.core.profile_tobytes(1)
|
||||||
|
|
||||||
|
if not is_pypy():
|
||||||
|
# core profile should not be directly instantiable
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
ImageCms.core.CmsProfile()
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
ImageCms.core.CmsProfile(0)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(is_pypy(), reason="fails on PyPy")
|
||||||
|
def test_transform_typesafety() -> None:
|
||||||
|
# core transform should not be directly instantiable
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
ImageCms.core.CmsProfile()
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
ImageCms.core.CmsProfile(0)
|
||||||
|
|
||||||
|
|
||||||
def assert_aux_channel_preserved(
|
def assert_aux_channel_preserved(
|
||||||
mode: str, transform_in_place: bool, preserved_channel: str
|
mode: str, transform_in_place: bool, preserved_channel: str
|
||||||
|
|
|
@ -121,7 +121,12 @@ nitpicky = True
|
||||||
# generating warnings in “nitpicky mode”. Note that type should include the domain name
|
# generating warnings in “nitpicky mode”. Note that type should include the domain name
|
||||||
# if present. Example entries would be ('py:func', 'int') or
|
# if present. Example entries would be ('py:func', 'int') or
|
||||||
# ('envvar', 'LD_LIBRARY_PATH').
|
# ('envvar', 'LD_LIBRARY_PATH').
|
||||||
# nitpick_ignore = []
|
nitpick_ignore = [
|
||||||
|
# Sphinx does not understand typing.Literal[-1]
|
||||||
|
# Will be fixed in a future version.
|
||||||
|
# https://github.com/sphinx-doc/sphinx/pull/11904
|
||||||
|
("py:obj", "typing.Literal[-1, 1]"),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output ----------------------------------------------
|
# -- Options for HTML output ----------------------------------------------
|
||||||
|
|
|
@ -73,7 +73,7 @@ can be easily displayed in a chromaticity diagram, for example).
|
||||||
:canonical: PIL._imagingcms.CmsProfile
|
:canonical: PIL._imagingcms.CmsProfile
|
||||||
|
|
||||||
.. py:attribute:: creation_date
|
.. py:attribute:: creation_date
|
||||||
:type: Optional[datetime.datetime]
|
:type: datetime.datetime | None
|
||||||
|
|
||||||
Date and time this profile was first created (see 7.2.1 of ICC.1:2010).
|
Date and time this profile was first created (see 7.2.1 of ICC.1:2010).
|
||||||
|
|
||||||
|
@ -156,58 +156,58 @@ can be easily displayed in a chromaticity diagram, for example).
|
||||||
not been calculated (see 7.2.18 of ICC.1:2010).
|
not been calculated (see 7.2.18 of ICC.1:2010).
|
||||||
|
|
||||||
.. py:attribute:: copyright
|
.. py:attribute:: copyright
|
||||||
:type: Optional[str]
|
:type: str | None
|
||||||
|
|
||||||
The text copyright information for the profile (see 9.2.21 of ICC.1:2010).
|
The text copyright information for the profile (see 9.2.21 of ICC.1:2010).
|
||||||
|
|
||||||
.. py:attribute:: manufacturer
|
.. py:attribute:: manufacturer
|
||||||
:type: Optional[str]
|
:type: str | None
|
||||||
|
|
||||||
The (English) display string for the device manufacturer (see
|
The (English) display string for the device manufacturer (see
|
||||||
9.2.22 of ICC.1:2010).
|
9.2.22 of ICC.1:2010).
|
||||||
|
|
||||||
.. py:attribute:: model
|
.. py:attribute:: model
|
||||||
:type: Optional[str]
|
:type: str | None
|
||||||
|
|
||||||
The (English) display string for the device model of the device
|
The (English) display string for the device model of the device
|
||||||
for which this profile is created (see 9.2.23 of ICC.1:2010).
|
for which this profile is created (see 9.2.23 of ICC.1:2010).
|
||||||
|
|
||||||
.. py:attribute:: profile_description
|
.. py:attribute:: profile_description
|
||||||
:type: Optional[str]
|
:type: str | None
|
||||||
|
|
||||||
The (English) display string for the profile description (see
|
The (English) display string for the profile description (see
|
||||||
9.2.41 of ICC.1:2010).
|
9.2.41 of ICC.1:2010).
|
||||||
|
|
||||||
.. py:attribute:: target
|
.. py:attribute:: target
|
||||||
:type: Optional[str]
|
:type: str | None
|
||||||
|
|
||||||
The name of the registered characterization data set, or the
|
The name of the registered characterization data set, or the
|
||||||
measurement data for a characterization target (see 9.2.14 of
|
measurement data for a characterization target (see 9.2.14 of
|
||||||
ICC.1:2010).
|
ICC.1:2010).
|
||||||
|
|
||||||
.. py:attribute:: red_colorant
|
.. py:attribute:: red_colorant
|
||||||
:type: Optional[tuple[tuple[float]]]
|
:type: tuple[tuple[float, float, float], tuple[float, float, float]] | None
|
||||||
|
|
||||||
The first column in the matrix used in matrix/TRC transforms (see 9.2.44 of ICC.1:2010).
|
The first column in the matrix used in matrix/TRC transforms (see 9.2.44 of ICC.1:2010).
|
||||||
|
|
||||||
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
|
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
|
||||||
|
|
||||||
.. py:attribute:: green_colorant
|
.. py:attribute:: green_colorant
|
||||||
:type: Optional[tuple[tuple[float]]]
|
:type: tuple[tuple[float, float, float], tuple[float, float, float]] | None
|
||||||
|
|
||||||
The second column in the matrix used in matrix/TRC transforms (see 9.2.30 of ICC.1:2010).
|
The second column in the matrix used in matrix/TRC transforms (see 9.2.30 of ICC.1:2010).
|
||||||
|
|
||||||
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
|
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
|
||||||
|
|
||||||
.. py:attribute:: blue_colorant
|
.. py:attribute:: blue_colorant
|
||||||
:type: Optional[tuple[tuple[float]]]
|
:type: tuple[tuple[float, float, float], tuple[float, float, float]] | None
|
||||||
|
|
||||||
The third column in the matrix used in matrix/TRC transforms (see 9.2.4 of ICC.1:2010).
|
The third column in the matrix used in matrix/TRC transforms (see 9.2.4 of ICC.1:2010).
|
||||||
|
|
||||||
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
|
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
|
||||||
|
|
||||||
.. py:attribute:: luminance
|
.. py:attribute:: luminance
|
||||||
:type: Optional[tuple[tuple[float]]]
|
:type: tuple[tuple[float, float, float], tuple[float, float, float]] | None
|
||||||
|
|
||||||
The absolute luminance of emissive devices in candelas per square
|
The absolute luminance of emissive devices in candelas per square
|
||||||
metre as described by the Y channel (see 9.2.32 of ICC.1:2010).
|
metre as described by the Y channel (see 9.2.32 of ICC.1:2010).
|
||||||
|
@ -215,7 +215,7 @@ can be easily displayed in a chromaticity diagram, for example).
|
||||||
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
|
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
|
||||||
|
|
||||||
.. py:attribute:: chromaticity
|
.. py:attribute:: chromaticity
|
||||||
:type: Optional[tuple[tuple[float]]]
|
:type: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]] | None
|
||||||
|
|
||||||
The data of the phosphor/colorant chromaticity set used (red,
|
The data of the phosphor/colorant chromaticity set used (red,
|
||||||
green and blue channels, see 9.2.16 of ICC.1:2010).
|
green and blue channels, see 9.2.16 of ICC.1:2010).
|
||||||
|
@ -223,7 +223,7 @@ can be easily displayed in a chromaticity diagram, for example).
|
||||||
The value is in the format ``((x, y, Y), (x, y, Y), (x, y, Y))``, if available.
|
The value is in the format ``((x, y, Y), (x, y, Y), (x, y, Y))``, if available.
|
||||||
|
|
||||||
.. py:attribute:: chromatic_adaption
|
.. py:attribute:: chromatic_adaption
|
||||||
:type: tuple[tuple[float]]
|
:type: tuple[tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]] | None
|
||||||
|
|
||||||
The chromatic adaption matrix converts a color measured using the
|
The chromatic adaption matrix converts a color measured using the
|
||||||
actual illumination conditions and relative to the actual adopted
|
actual illumination conditions and relative to the actual adopted
|
||||||
|
@ -249,34 +249,34 @@ can be easily displayed in a chromaticity diagram, for example).
|
||||||
9.2.19 of ICC.1:2010).
|
9.2.19 of ICC.1:2010).
|
||||||
|
|
||||||
.. py:attribute:: colorimetric_intent
|
.. py:attribute:: colorimetric_intent
|
||||||
:type: Optional[str]
|
:type: str | None
|
||||||
|
|
||||||
4-character string (padded with whitespace) identifying the image
|
4-character string (padded with whitespace) identifying the image
|
||||||
state of PCS colorimetry produced using the colorimetric intent
|
state of PCS colorimetry produced using the colorimetric intent
|
||||||
transforms (see 9.2.20 of ICC.1:2010 for details).
|
transforms (see 9.2.20 of ICC.1:2010 for details).
|
||||||
|
|
||||||
.. py:attribute:: perceptual_rendering_intent_gamut
|
.. py:attribute:: perceptual_rendering_intent_gamut
|
||||||
:type: Optional[str]
|
:type: str | None
|
||||||
|
|
||||||
4-character string (padded with whitespace) identifying the (one)
|
4-character string (padded with whitespace) identifying the (one)
|
||||||
standard reference medium gamut (see 9.2.37 of ICC.1:2010 for
|
standard reference medium gamut (see 9.2.37 of ICC.1:2010 for
|
||||||
details).
|
details).
|
||||||
|
|
||||||
.. py:attribute:: saturation_rendering_intent_gamut
|
.. py:attribute:: saturation_rendering_intent_gamut
|
||||||
:type: Optional[str]
|
:type: str | None
|
||||||
|
|
||||||
4-character string (padded with whitespace) identifying the (one)
|
4-character string (padded with whitespace) identifying the (one)
|
||||||
standard reference medium gamut (see 9.2.37 of ICC.1:2010 for
|
standard reference medium gamut (see 9.2.37 of ICC.1:2010 for
|
||||||
details).
|
details).
|
||||||
|
|
||||||
.. py:attribute:: technology
|
.. py:attribute:: technology
|
||||||
:type: Optional[str]
|
:type: str | None
|
||||||
|
|
||||||
4-character string (padded with whitespace) identifying the device
|
4-character string (padded with whitespace) identifying the device
|
||||||
technology (see 9.2.47 of ICC.1:2010 for details).
|
technology (see 9.2.47 of ICC.1:2010 for details).
|
||||||
|
|
||||||
.. py:attribute:: media_black_point
|
.. py:attribute:: media_black_point
|
||||||
:type: Optional[tuple[tuple[float]]]
|
:type: tuple[tuple[float, float, float], tuple[float, float, float]] | None
|
||||||
|
|
||||||
This tag specifies the media black point and is used for
|
This tag specifies the media black point and is used for
|
||||||
generating absolute colorimetry.
|
generating absolute colorimetry.
|
||||||
|
@ -287,19 +287,19 @@ can be easily displayed in a chromaticity diagram, for example).
|
||||||
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
|
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
|
||||||
|
|
||||||
.. py:attribute:: media_white_point_temperature
|
.. py:attribute:: media_white_point_temperature
|
||||||
:type: Optional[float]
|
:type: float | None
|
||||||
|
|
||||||
Calculates the white point temperature (see the LCMS documentation
|
Calculates the white point temperature (see the LCMS documentation
|
||||||
for more information).
|
for more information).
|
||||||
|
|
||||||
.. py:attribute:: viewing_condition
|
.. py:attribute:: viewing_condition
|
||||||
:type: Optional[str]
|
:type: str | None
|
||||||
|
|
||||||
The (English) display string for the viewing conditions (see
|
The (English) display string for the viewing conditions (see
|
||||||
9.2.48 of ICC.1:2010).
|
9.2.48 of ICC.1:2010).
|
||||||
|
|
||||||
.. py:attribute:: screening_description
|
.. py:attribute:: screening_description
|
||||||
:type: Optional[str]
|
:type: str | None
|
||||||
|
|
||||||
The (English) display string for the screening conditions.
|
The (English) display string for the screening conditions.
|
||||||
|
|
||||||
|
@ -307,21 +307,21 @@ can be easily displayed in a chromaticity diagram, for example).
|
||||||
version 4.
|
version 4.
|
||||||
|
|
||||||
.. py:attribute:: red_primary
|
.. py:attribute:: red_primary
|
||||||
:type: Optional[tuple[tuple[float]]]
|
:type: tuple[tuple[float, float, float], tuple[float, float, float]] | None
|
||||||
|
|
||||||
The XYZ-transformed of the RGB primary color red (1, 0, 0).
|
The XYZ-transformed of the RGB primary color red (1, 0, 0).
|
||||||
|
|
||||||
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
|
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
|
||||||
|
|
||||||
.. py:attribute:: green_primary
|
.. py:attribute:: green_primary
|
||||||
:type: Optional[tuple[tuple[float]]]
|
:type: tuple[tuple[float, float, float], tuple[float, float, float]] | None
|
||||||
|
|
||||||
The XYZ-transformed of the RGB primary color green (0, 1, 0).
|
The XYZ-transformed of the RGB primary color green (0, 1, 0).
|
||||||
|
|
||||||
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
|
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
|
||||||
|
|
||||||
.. py:attribute:: blue_primary
|
.. py:attribute:: blue_primary
|
||||||
:type: Optional[tuple[tuple[float]]]
|
:type: tuple[tuple[float, float, float], tuple[float, float, float]] | None
|
||||||
|
|
||||||
The XYZ-transformed of the RGB primary color blue (0, 0, 1).
|
The XYZ-transformed of the RGB primary color blue (0, 0, 1).
|
||||||
|
|
||||||
|
@ -334,7 +334,7 @@ can be easily displayed in a chromaticity diagram, for example).
|
||||||
documentation on LCMS).
|
documentation on LCMS).
|
||||||
|
|
||||||
.. py:attribute:: clut
|
.. py:attribute:: clut
|
||||||
:type: dict[tuple[bool]]
|
:type: dict[int, tuple[bool, bool, bool]] | None
|
||||||
|
|
||||||
Returns a dictionary of all supported intents and directions for
|
Returns a dictionary of all supported intents and directions for
|
||||||
the CLUT model.
|
the CLUT model.
|
||||||
|
@ -353,7 +353,7 @@ can be easily displayed in a chromaticity diagram, for example).
|
||||||
that intent is supported for that direction.
|
that intent is supported for that direction.
|
||||||
|
|
||||||
.. py:attribute:: intent_supported
|
.. py:attribute:: intent_supported
|
||||||
:type: dict[tuple[bool]]
|
:type: dict[int, tuple[bool, bool, bool]] | None
|
||||||
|
|
||||||
Returns a dictionary of all supported intents and directions.
|
Returns a dictionary of all supported intents and directions.
|
||||||
|
|
||||||
|
@ -372,7 +372,7 @@ can be easily displayed in a chromaticity diagram, for example).
|
||||||
|
|
||||||
There is one function defined on the class:
|
There is one function defined on the class:
|
||||||
|
|
||||||
.. py:method:: is_intent_supported(intent, direction)
|
.. py:method:: is_intent_supported(intent: int, direction: int, /)
|
||||||
|
|
||||||
Returns if the intent is supported for the given direction.
|
Returns if the intent is supported for the given direction.
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,7 @@ ignore = [
|
||||||
"E221", # Multiple spaces before operator
|
"E221", # Multiple spaces before operator
|
||||||
"E226", # Missing whitespace around arithmetic operator
|
"E226", # Missing whitespace around arithmetic operator
|
||||||
"E241", # Multiple spaces after ','
|
"E241", # Multiple spaces after ','
|
||||||
|
"PYI026", # flake8-pyi: typing.TypeAlias added in Python 3.10
|
||||||
"PYI034", # flake8-pyi: typing.Self added in Python 3.11
|
"PYI034", # flake8-pyi: typing.Self added in Python 3.11
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -23,19 +23,20 @@ import operator
|
||||||
import sys
|
import sys
|
||||||
from enum import IntEnum, IntFlag
|
from enum import IntEnum, IntFlag
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
from typing import Any
|
from typing import Any, Literal, SupportsFloat, SupportsInt, Union
|
||||||
|
|
||||||
from . import Image, __version__
|
from . import Image, __version__
|
||||||
from ._deprecate import deprecate
|
from ._deprecate import deprecate
|
||||||
|
from ._typing import SupportsRead
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from . import _imagingcms
|
from . import _imagingcms as core
|
||||||
except ImportError as ex:
|
except ImportError as ex:
|
||||||
# Allow error import for doc purposes, but error out when accessing
|
# Allow error import for doc purposes, but error out when accessing
|
||||||
# anything in core.
|
# anything in core.
|
||||||
from ._util import DeferredError
|
from ._util import DeferredError
|
||||||
|
|
||||||
_imagingcms = DeferredError.new(ex)
|
core = DeferredError.new(ex)
|
||||||
|
|
||||||
_DESCRIPTION = """
|
_DESCRIPTION = """
|
||||||
pyCMS
|
pyCMS
|
||||||
|
@ -119,7 +120,6 @@ def __getattr__(name: str) -> Any:
|
||||||
|
|
||||||
# --------------------------------------------------------------------.
|
# --------------------------------------------------------------------.
|
||||||
|
|
||||||
core = _imagingcms
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# intent/direction values
|
# intent/direction values
|
||||||
|
@ -237,7 +237,7 @@ _FLAGS = {
|
||||||
|
|
||||||
|
|
||||||
class ImageCmsProfile:
|
class ImageCmsProfile:
|
||||||
def __init__(self, profile):
|
def __init__(self, profile: str | SupportsRead[bytes] | core.CmsProfile) -> None:
|
||||||
"""
|
"""
|
||||||
:param profile: Either a string representing a filename,
|
:param profile: Either a string representing a filename,
|
||||||
a file like object containing a profile or a
|
a file like object containing a profile or a
|
||||||
|
@ -257,19 +257,19 @@ class ImageCmsProfile:
|
||||||
self._set(core.profile_open(profile), profile)
|
self._set(core.profile_open(profile), profile)
|
||||||
elif hasattr(profile, "read"):
|
elif hasattr(profile, "read"):
|
||||||
self._set(core.profile_frombytes(profile.read()))
|
self._set(core.profile_frombytes(profile.read()))
|
||||||
elif isinstance(profile, _imagingcms.CmsProfile):
|
elif isinstance(profile, core.CmsProfile):
|
||||||
self._set(profile)
|
self._set(profile)
|
||||||
else:
|
else:
|
||||||
msg = "Invalid type for Profile"
|
msg = "Invalid type for Profile" # type: ignore[unreachable]
|
||||||
raise TypeError(msg)
|
raise TypeError(msg)
|
||||||
|
|
||||||
def _set(self, profile, filename=None):
|
def _set(self, profile: core.CmsProfile, filename: str | None = None) -> None:
|
||||||
self.profile = profile
|
self.profile = profile
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.product_name = None # profile.product_name
|
self.product_name = None # profile.product_name
|
||||||
self.product_info = None # profile.product_info
|
self.product_info = None # profile.product_info
|
||||||
|
|
||||||
def tobytes(self):
|
def tobytes(self) -> bytes:
|
||||||
"""
|
"""
|
||||||
Returns the profile in a format suitable for embedding in
|
Returns the profile in a format suitable for embedding in
|
||||||
saved images.
|
saved images.
|
||||||
|
@ -290,14 +290,14 @@ class ImageCmsTransform(Image.ImagePointHandler):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
input,
|
input: ImageCmsProfile,
|
||||||
output,
|
output: ImageCmsProfile,
|
||||||
input_mode,
|
input_mode: str,
|
||||||
output_mode,
|
output_mode: str,
|
||||||
intent=Intent.PERCEPTUAL,
|
intent: Intent = Intent.PERCEPTUAL,
|
||||||
proof=None,
|
proof: ImageCmsProfile | None = None,
|
||||||
proof_intent=Intent.ABSOLUTE_COLORIMETRIC,
|
proof_intent: Intent = Intent.ABSOLUTE_COLORIMETRIC,
|
||||||
flags=Flags.NONE,
|
flags: Flags = Flags.NONE,
|
||||||
):
|
):
|
||||||
if proof is None:
|
if proof is None:
|
||||||
self.transform = core.buildTransform(
|
self.transform = core.buildTransform(
|
||||||
|
@ -320,10 +320,10 @@ class ImageCmsTransform(Image.ImagePointHandler):
|
||||||
|
|
||||||
self.output_profile = output
|
self.output_profile = output
|
||||||
|
|
||||||
def point(self, im):
|
def point(self, im: Image.Image) -> Image.Image:
|
||||||
return self.apply(im)
|
return self.apply(im)
|
||||||
|
|
||||||
def apply(self, im, imOut=None):
|
def apply(self, im: Image.Image, imOut: Image.Image | None = None) -> Image.Image:
|
||||||
im.load()
|
im.load()
|
||||||
if imOut is None:
|
if imOut is None:
|
||||||
imOut = Image.new(self.output_mode, im.size, None)
|
imOut = Image.new(self.output_mode, im.size, None)
|
||||||
|
@ -331,7 +331,7 @@ class ImageCmsTransform(Image.ImagePointHandler):
|
||||||
imOut.info["icc_profile"] = self.output_profile.tobytes()
|
imOut.info["icc_profile"] = self.output_profile.tobytes()
|
||||||
return imOut
|
return imOut
|
||||||
|
|
||||||
def apply_in_place(self, im):
|
def apply_in_place(self, im: Image.Image) -> Image.Image:
|
||||||
im.load()
|
im.load()
|
||||||
if im.mode != self.output_mode:
|
if im.mode != self.output_mode:
|
||||||
msg = "mode mismatch"
|
msg = "mode mismatch"
|
||||||
|
@ -341,7 +341,7 @@ class ImageCmsTransform(Image.ImagePointHandler):
|
||||||
return im
|
return im
|
||||||
|
|
||||||
|
|
||||||
def get_display_profile(handle=None):
|
def get_display_profile(handle: SupportsInt | None = None) -> ImageCmsProfile | None:
|
||||||
"""
|
"""
|
||||||
(experimental) Fetches the profile for the current display device.
|
(experimental) Fetches the profile for the current display device.
|
||||||
|
|
||||||
|
@ -351,12 +351,12 @@ def get_display_profile(handle=None):
|
||||||
if sys.platform != "win32":
|
if sys.platform != "win32":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
from . import ImageWin
|
from . import ImageWin # type: ignore[unused-ignore, unreachable]
|
||||||
|
|
||||||
if isinstance(handle, ImageWin.HDC):
|
if isinstance(handle, ImageWin.HDC):
|
||||||
profile = core.get_display_profile_win32(handle, 1)
|
profile = core.get_display_profile_win32(int(handle), 1)
|
||||||
else:
|
else:
|
||||||
profile = core.get_display_profile_win32(handle or 0)
|
profile = core.get_display_profile_win32(int(handle or 0))
|
||||||
if profile is None:
|
if profile is None:
|
||||||
return None
|
return None
|
||||||
return ImageCmsProfile(profile)
|
return ImageCmsProfile(profile)
|
||||||
|
@ -366,6 +366,10 @@ def get_display_profile(handle=None):
|
||||||
# pyCMS compatible layer
|
# pyCMS compatible layer
|
||||||
# --------------------------------------------------------------------.
|
# --------------------------------------------------------------------.
|
||||||
|
|
||||||
|
_CmsProfileCompatible = Union[
|
||||||
|
str, SupportsRead[bytes], core.CmsProfile, ImageCmsProfile
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class PyCMSError(Exception):
|
class PyCMSError(Exception):
|
||||||
"""(pyCMS) Exception class.
|
"""(pyCMS) Exception class.
|
||||||
|
@ -375,14 +379,14 @@ class PyCMSError(Exception):
|
||||||
|
|
||||||
|
|
||||||
def profileToProfile(
|
def profileToProfile(
|
||||||
im,
|
im: Image.Image,
|
||||||
inputProfile,
|
inputProfile: _CmsProfileCompatible,
|
||||||
outputProfile,
|
outputProfile: _CmsProfileCompatible,
|
||||||
renderingIntent=Intent.PERCEPTUAL,
|
renderingIntent: Intent = Intent.PERCEPTUAL,
|
||||||
outputMode=None,
|
outputMode: str | None = None,
|
||||||
inPlace=False,
|
inPlace: bool = False,
|
||||||
flags=Flags.NONE,
|
flags: Flags = Flags.NONE,
|
||||||
):
|
) -> Image.Image | None:
|
||||||
"""
|
"""
|
||||||
(pyCMS) Applies an ICC transformation to a given image, mapping from
|
(pyCMS) Applies an ICC transformation to a given image, mapping from
|
||||||
``inputProfile`` to ``outputProfile``.
|
``inputProfile`` to ``outputProfile``.
|
||||||
|
@ -470,7 +474,9 @@ def profileToProfile(
|
||||||
return imOut
|
return imOut
|
||||||
|
|
||||||
|
|
||||||
def getOpenProfile(profileFilename):
|
def getOpenProfile(
|
||||||
|
profileFilename: str | SupportsRead[bytes] | core.CmsProfile,
|
||||||
|
) -> ImageCmsProfile:
|
||||||
"""
|
"""
|
||||||
(pyCMS) Opens an ICC profile file.
|
(pyCMS) Opens an ICC profile file.
|
||||||
|
|
||||||
|
@ -493,13 +499,13 @@ def getOpenProfile(profileFilename):
|
||||||
|
|
||||||
|
|
||||||
def buildTransform(
|
def buildTransform(
|
||||||
inputProfile,
|
inputProfile: _CmsProfileCompatible,
|
||||||
outputProfile,
|
outputProfile: _CmsProfileCompatible,
|
||||||
inMode,
|
inMode: str,
|
||||||
outMode,
|
outMode: str,
|
||||||
renderingIntent=Intent.PERCEPTUAL,
|
renderingIntent: Intent = Intent.PERCEPTUAL,
|
||||||
flags=Flags.NONE,
|
flags: Flags = Flags.NONE,
|
||||||
):
|
) -> ImageCmsTransform:
|
||||||
"""
|
"""
|
||||||
(pyCMS) Builds an ICC transform mapping from the ``inputProfile`` to the
|
(pyCMS) Builds an ICC transform mapping from the ``inputProfile`` to the
|
||||||
``outputProfile``. Use applyTransform to apply the transform to a given
|
``outputProfile``. Use applyTransform to apply the transform to a given
|
||||||
|
@ -576,15 +582,15 @@ def buildTransform(
|
||||||
|
|
||||||
|
|
||||||
def buildProofTransform(
|
def buildProofTransform(
|
||||||
inputProfile,
|
inputProfile: _CmsProfileCompatible,
|
||||||
outputProfile,
|
outputProfile: _CmsProfileCompatible,
|
||||||
proofProfile,
|
proofProfile: _CmsProfileCompatible,
|
||||||
inMode,
|
inMode: str,
|
||||||
outMode,
|
outMode: str,
|
||||||
renderingIntent=Intent.PERCEPTUAL,
|
renderingIntent: Intent = Intent.PERCEPTUAL,
|
||||||
proofRenderingIntent=Intent.ABSOLUTE_COLORIMETRIC,
|
proofRenderingIntent: Intent = Intent.ABSOLUTE_COLORIMETRIC,
|
||||||
flags=Flags.SOFTPROOFING,
|
flags: Flags = Flags.SOFTPROOFING,
|
||||||
):
|
) -> ImageCmsTransform:
|
||||||
"""
|
"""
|
||||||
(pyCMS) Builds an ICC transform mapping from the ``inputProfile`` to the
|
(pyCMS) Builds an ICC transform mapping from the ``inputProfile`` to the
|
||||||
``outputProfile``, but tries to simulate the result that would be
|
``outputProfile``, but tries to simulate the result that would be
|
||||||
|
@ -692,7 +698,9 @@ buildTransformFromOpenProfiles = buildTransform
|
||||||
buildProofTransformFromOpenProfiles = buildProofTransform
|
buildProofTransformFromOpenProfiles = buildProofTransform
|
||||||
|
|
||||||
|
|
||||||
def applyTransform(im, transform, inPlace=False):
|
def applyTransform(
|
||||||
|
im: Image.Image, transform: ImageCmsTransform, inPlace: bool = False
|
||||||
|
) -> Image.Image | None:
|
||||||
"""
|
"""
|
||||||
(pyCMS) Applies a transform to a given image.
|
(pyCMS) Applies a transform to a given image.
|
||||||
|
|
||||||
|
@ -745,7 +753,9 @@ def applyTransform(im, transform, inPlace=False):
|
||||||
return imOut
|
return imOut
|
||||||
|
|
||||||
|
|
||||||
def createProfile(colorSpace, colorTemp=-1):
|
def createProfile(
|
||||||
|
colorSpace: Literal["LAB", "XYZ", "sRGB"], colorTemp: SupportsFloat = -1
|
||||||
|
) -> core.CmsProfile:
|
||||||
"""
|
"""
|
||||||
(pyCMS) Creates a profile.
|
(pyCMS) Creates a profile.
|
||||||
|
|
||||||
|
@ -794,7 +804,7 @@ def createProfile(colorSpace, colorTemp=-1):
|
||||||
raise PyCMSError(v) from v
|
raise PyCMSError(v) from v
|
||||||
|
|
||||||
|
|
||||||
def getProfileName(profile):
|
def getProfileName(profile: _CmsProfileCompatible) -> str:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
(pyCMS) Gets the internal product name for the given profile.
|
(pyCMS) Gets the internal product name for the given profile.
|
||||||
|
@ -828,15 +838,15 @@ def getProfileName(profile):
|
||||||
|
|
||||||
if not (model or manufacturer):
|
if not (model or manufacturer):
|
||||||
return (profile.profile.profile_description or "") + "\n"
|
return (profile.profile.profile_description or "") + "\n"
|
||||||
if not manufacturer or len(model) > 30:
|
if not manufacturer or len(model) > 30: # type: ignore[arg-type]
|
||||||
return model + "\n"
|
return model + "\n" # type: ignore[operator]
|
||||||
return f"{model} - {manufacturer}\n"
|
return f"{model} - {manufacturer}\n"
|
||||||
|
|
||||||
except (AttributeError, OSError, TypeError, ValueError) as v:
|
except (AttributeError, OSError, TypeError, ValueError) as v:
|
||||||
raise PyCMSError(v) from v
|
raise PyCMSError(v) from v
|
||||||
|
|
||||||
|
|
||||||
def getProfileInfo(profile):
|
def getProfileInfo(profile: _CmsProfileCompatible) -> str:
|
||||||
"""
|
"""
|
||||||
(pyCMS) Gets the internal product information for the given profile.
|
(pyCMS) Gets the internal product information for the given profile.
|
||||||
|
|
||||||
|
@ -873,7 +883,7 @@ def getProfileInfo(profile):
|
||||||
raise PyCMSError(v) from v
|
raise PyCMSError(v) from v
|
||||||
|
|
||||||
|
|
||||||
def getProfileCopyright(profile):
|
def getProfileCopyright(profile: _CmsProfileCompatible) -> str:
|
||||||
"""
|
"""
|
||||||
(pyCMS) Gets the copyright for the given profile.
|
(pyCMS) Gets the copyright for the given profile.
|
||||||
|
|
||||||
|
@ -901,7 +911,7 @@ def getProfileCopyright(profile):
|
||||||
raise PyCMSError(v) from v
|
raise PyCMSError(v) from v
|
||||||
|
|
||||||
|
|
||||||
def getProfileManufacturer(profile):
|
def getProfileManufacturer(profile: _CmsProfileCompatible) -> str:
|
||||||
"""
|
"""
|
||||||
(pyCMS) Gets the manufacturer for the given profile.
|
(pyCMS) Gets the manufacturer for the given profile.
|
||||||
|
|
||||||
|
@ -929,7 +939,7 @@ def getProfileManufacturer(profile):
|
||||||
raise PyCMSError(v) from v
|
raise PyCMSError(v) from v
|
||||||
|
|
||||||
|
|
||||||
def getProfileModel(profile):
|
def getProfileModel(profile: _CmsProfileCompatible) -> str:
|
||||||
"""
|
"""
|
||||||
(pyCMS) Gets the model for the given profile.
|
(pyCMS) Gets the model for the given profile.
|
||||||
|
|
||||||
|
@ -958,7 +968,7 @@ def getProfileModel(profile):
|
||||||
raise PyCMSError(v) from v
|
raise PyCMSError(v) from v
|
||||||
|
|
||||||
|
|
||||||
def getProfileDescription(profile):
|
def getProfileDescription(profile: _CmsProfileCompatible) -> str:
|
||||||
"""
|
"""
|
||||||
(pyCMS) Gets the description for the given profile.
|
(pyCMS) Gets the description for the given profile.
|
||||||
|
|
||||||
|
@ -987,7 +997,7 @@ def getProfileDescription(profile):
|
||||||
raise PyCMSError(v) from v
|
raise PyCMSError(v) from v
|
||||||
|
|
||||||
|
|
||||||
def getDefaultIntent(profile):
|
def getDefaultIntent(profile: _CmsProfileCompatible) -> int:
|
||||||
"""
|
"""
|
||||||
(pyCMS) Gets the default intent name for the given profile.
|
(pyCMS) Gets the default intent name for the given profile.
|
||||||
|
|
||||||
|
@ -1026,7 +1036,9 @@ def getDefaultIntent(profile):
|
||||||
raise PyCMSError(v) from v
|
raise PyCMSError(v) from v
|
||||||
|
|
||||||
|
|
||||||
def isIntentSupported(profile, intent, direction):
|
def isIntentSupported(
|
||||||
|
profile: _CmsProfileCompatible, intent: Intent, direction: Direction
|
||||||
|
) -> Literal[-1, 1]:
|
||||||
"""
|
"""
|
||||||
(pyCMS) Checks if a given intent is supported.
|
(pyCMS) Checks if a given intent is supported.
|
||||||
|
|
||||||
|
@ -1077,7 +1089,7 @@ def isIntentSupported(profile, intent, direction):
|
||||||
raise PyCMSError(v) from v
|
raise PyCMSError(v) from v
|
||||||
|
|
||||||
|
|
||||||
def versions():
|
def versions() -> tuple[str, str, str, str]:
|
||||||
"""
|
"""
|
||||||
(pyCMS) Fetches versions.
|
(pyCMS) Fetches versions.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,3 +1,145 @@
|
||||||
from typing import Any
|
import datetime
|
||||||
|
import sys
|
||||||
|
from typing import Literal, SupportsFloat, TypedDict
|
||||||
|
|
||||||
def __getattr__(name: str) -> Any: ...
|
littlecms_version: str
|
||||||
|
|
||||||
|
_Tuple3f = tuple[float, float, float]
|
||||||
|
_Tuple2x3f = tuple[_Tuple3f, _Tuple3f]
|
||||||
|
_Tuple3x3f = tuple[_Tuple3f, _Tuple3f, _Tuple3f]
|
||||||
|
|
||||||
|
class _IccMeasurementCondition(TypedDict):
|
||||||
|
observer: int
|
||||||
|
backing: _Tuple3f
|
||||||
|
geo: str
|
||||||
|
flare: float
|
||||||
|
illuminant_type: str
|
||||||
|
|
||||||
|
class _IccViewingCondition(TypedDict):
|
||||||
|
illuminant: _Tuple3f
|
||||||
|
surround: _Tuple3f
|
||||||
|
illuminant_type: str
|
||||||
|
|
||||||
|
class CmsProfile:
|
||||||
|
@property
|
||||||
|
def rendering_intent(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def creation_date(self) -> datetime.datetime | None: ...
|
||||||
|
@property
|
||||||
|
def copyright(self) -> str | None: ...
|
||||||
|
@property
|
||||||
|
def target(self) -> str | None: ...
|
||||||
|
@property
|
||||||
|
def manufacturer(self) -> str | None: ...
|
||||||
|
@property
|
||||||
|
def model(self) -> str | None: ...
|
||||||
|
@property
|
||||||
|
def profile_description(self) -> str | None: ...
|
||||||
|
@property
|
||||||
|
def screening_description(self) -> str | None: ...
|
||||||
|
@property
|
||||||
|
def viewing_condition(self) -> str | None: ...
|
||||||
|
@property
|
||||||
|
def version(self) -> float: ...
|
||||||
|
@property
|
||||||
|
def icc_version(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def attributes(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def header_flags(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def header_manufacturer(self) -> str: ...
|
||||||
|
@property
|
||||||
|
def header_model(self) -> str: ...
|
||||||
|
@property
|
||||||
|
def device_class(self) -> str: ...
|
||||||
|
@property
|
||||||
|
def connection_space(self) -> str: ...
|
||||||
|
@property
|
||||||
|
def xcolor_space(self) -> str: ...
|
||||||
|
@property
|
||||||
|
def profile_id(self) -> bytes: ...
|
||||||
|
@property
|
||||||
|
def is_matrix_shaper(self) -> bool: ...
|
||||||
|
@property
|
||||||
|
def technology(self) -> str | None: ...
|
||||||
|
@property
|
||||||
|
def colorimetric_intent(self) -> str | None: ...
|
||||||
|
@property
|
||||||
|
def perceptual_rendering_intent_gamut(self) -> str | None: ...
|
||||||
|
@property
|
||||||
|
def saturation_rendering_intent_gamut(self) -> str | None: ...
|
||||||
|
@property
|
||||||
|
def red_colorant(self) -> _Tuple2x3f | None: ...
|
||||||
|
@property
|
||||||
|
def green_colorant(self) -> _Tuple2x3f | None: ...
|
||||||
|
@property
|
||||||
|
def blue_colorant(self) -> _Tuple2x3f | None: ...
|
||||||
|
@property
|
||||||
|
def red_primary(self) -> _Tuple2x3f | None: ...
|
||||||
|
@property
|
||||||
|
def green_primary(self) -> _Tuple2x3f | None: ...
|
||||||
|
@property
|
||||||
|
def blue_primary(self) -> _Tuple2x3f | None: ...
|
||||||
|
@property
|
||||||
|
def media_white_point_temperature(self) -> float | None: ...
|
||||||
|
@property
|
||||||
|
def media_white_point(self) -> _Tuple2x3f | None: ...
|
||||||
|
@property
|
||||||
|
def media_black_point(self) -> _Tuple2x3f | None: ...
|
||||||
|
@property
|
||||||
|
def luminance(self) -> _Tuple2x3f | None: ...
|
||||||
|
@property
|
||||||
|
def chromatic_adaptation(self) -> tuple[_Tuple3x3f, _Tuple3x3f] | None: ...
|
||||||
|
@property
|
||||||
|
def chromaticity(self) -> _Tuple3x3f | None: ...
|
||||||
|
@property
|
||||||
|
def colorant_table(self) -> list[str] | None: ...
|
||||||
|
@property
|
||||||
|
def colorant_table_out(self) -> list[str] | None: ...
|
||||||
|
@property
|
||||||
|
def intent_supported(self) -> dict[int, tuple[bool, bool, bool]] | None: ...
|
||||||
|
@property
|
||||||
|
def clut(self) -> dict[int, tuple[bool, bool, bool]] | None: ...
|
||||||
|
@property
|
||||||
|
def icc_measurement_condition(self) -> _IccMeasurementCondition | None: ...
|
||||||
|
@property
|
||||||
|
def icc_viewing_condition(self) -> _IccViewingCondition | None: ...
|
||||||
|
def is_intent_supported(self, intent: int, direction: int, /) -> int: ...
|
||||||
|
|
||||||
|
class CmsTransform:
|
||||||
|
@property
|
||||||
|
def inputMode(self) -> str: ...
|
||||||
|
@property
|
||||||
|
def outputMode(self) -> str: ...
|
||||||
|
def apply(self, id_in: int, id_out: int) -> int: ...
|
||||||
|
|
||||||
|
def profile_open(profile: str, /) -> CmsProfile: ...
|
||||||
|
def profile_frombytes(profile: bytes, /) -> CmsProfile: ...
|
||||||
|
def profile_tobytes(profile: CmsProfile, /) -> bytes: ...
|
||||||
|
def buildTransform(
|
||||||
|
input_profile: CmsProfile,
|
||||||
|
output_profile: CmsProfile,
|
||||||
|
in_mode: str,
|
||||||
|
out_mode: str,
|
||||||
|
rendering_intent: int = 0,
|
||||||
|
cms_flags: int = 0,
|
||||||
|
/,
|
||||||
|
) -> CmsTransform: ...
|
||||||
|
def buildProofTransform(
|
||||||
|
input_profile: CmsProfile,
|
||||||
|
output_profile: CmsProfile,
|
||||||
|
proof_profile: CmsProfile,
|
||||||
|
in_mode: str,
|
||||||
|
out_mode: str,
|
||||||
|
rendering_intent: int = 0,
|
||||||
|
proof_intent: int = 0,
|
||||||
|
cms_flags: int = 0,
|
||||||
|
/,
|
||||||
|
) -> CmsTransform: ...
|
||||||
|
def createProfile(
|
||||||
|
color_space: Literal["LAB", "XYZ", "sRGB"], color_temp: SupportsFloat = 0.0, /
|
||||||
|
) -> CmsProfile: ...
|
||||||
|
|
||||||
|
if sys.platform == "win32":
|
||||||
|
def get_display_profile_win32(handle: int = 0, is_dc: int = 0, /) -> str | None: ...
|
||||||
|
|
|
@ -143,7 +143,7 @@ cms_profile_tobytes(PyObject *self, PyObject *args) {
|
||||||
cmsHPROFILE *profile;
|
cmsHPROFILE *profile;
|
||||||
|
|
||||||
PyObject *ret;
|
PyObject *ret;
|
||||||
if (!PyArg_ParseTuple(args, "O", &CmsProfile)) {
|
if (!PyArg_ParseTuple(args, "O!", &CmsProfile_Type, &CmsProfile)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1421,7 +1421,7 @@ static struct PyGetSetDef cms_profile_getsetters[] = {
|
||||||
{NULL}};
|
{NULL}};
|
||||||
|
|
||||||
static PyTypeObject CmsProfile_Type = {
|
static PyTypeObject CmsProfile_Type = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0) "PIL._imagingcms.CmsProfile", /*tp_name*/
|
PyVarObject_HEAD_INIT(NULL, 0) "PIL.ImageCms.core.CmsProfile", /*tp_name*/
|
||||||
sizeof(CmsProfileObject), /*tp_basicsize*/
|
sizeof(CmsProfileObject), /*tp_basicsize*/
|
||||||
0, /*tp_itemsize*/
|
0, /*tp_itemsize*/
|
||||||
/* methods */
|
/* methods */
|
||||||
|
@ -1473,7 +1473,7 @@ static struct PyGetSetDef cms_transform_getsetters[] = {
|
||||||
{NULL}};
|
{NULL}};
|
||||||
|
|
||||||
static PyTypeObject CmsTransform_Type = {
|
static PyTypeObject CmsTransform_Type = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0) "CmsTransform", /*tp_name*/
|
PyVarObject_HEAD_INIT(NULL, 0) "PIL.ImageCms.core.CmsTransform", /*tp_name*/
|
||||||
sizeof(CmsTransformObject), /*tp_basicsize*/
|
sizeof(CmsTransformObject), /*tp_basicsize*/
|
||||||
0, /*tp_itemsize*/
|
0, /*tp_itemsize*/
|
||||||
/* methods */
|
/* methods */
|
||||||
|
@ -1511,8 +1511,6 @@ setup_module(PyObject *m) {
|
||||||
PyObject *v;
|
PyObject *v;
|
||||||
int vn;
|
int vn;
|
||||||
|
|
||||||
CmsProfile_Type.tp_new = PyType_GenericNew;
|
|
||||||
|
|
||||||
/* Ready object types */
|
/* Ready object types */
|
||||||
PyType_Ready(&CmsProfile_Type);
|
PyType_Ready(&CmsProfile_Type);
|
||||||
PyType_Ready(&CmsTransform_Type);
|
PyType_Ready(&CmsTransform_Type);
|
||||||
|
@ -1520,6 +1518,9 @@ setup_module(PyObject *m) {
|
||||||
Py_INCREF(&CmsProfile_Type);
|
Py_INCREF(&CmsProfile_Type);
|
||||||
PyModule_AddObject(m, "CmsProfile", (PyObject *)&CmsProfile_Type);
|
PyModule_AddObject(m, "CmsProfile", (PyObject *)&CmsProfile_Type);
|
||||||
|
|
||||||
|
Py_INCREF(&CmsTransform_Type);
|
||||||
|
PyModule_AddObject(m, "CmsTransform", (PyObject *)&CmsTransform_Type);
|
||||||
|
|
||||||
d = PyModule_GetDict(m);
|
d = PyModule_GetDict(m);
|
||||||
|
|
||||||
/* this check is also in PIL.features.pilinfo() */
|
/* this check is also in PIL.features.pilinfo() */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user