iccdev 0.1.0__cp313-cp313-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- iccdev/__init__.py +110 -0
- iccdev/_iccdev.cp313-win_amd64.pyd +0 -0
- iccdev/_iccdev.pyi +299 -0
- iccdev/_iccdev.pyx +1283 -0
- iccdev/cicc_wrapper.pxd +306 -0
- iccdev/cli.py +357 -0
- iccdev/py.typed +1 -0
- iccdev-0.1.0.dist-info/METADATA +447 -0
- iccdev-0.1.0.dist-info/RECORD +12 -0
- iccdev-0.1.0.dist-info/WHEEL +5 -0
- iccdev-0.1.0.dist-info/licenses/LICENSE.md +26 -0
- iccdev-0.1.0.dist-info/top_level.txt +1 -0
iccdev/__init__.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# iccdev - Python bindings for RefIccMAX / iccDEV
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) International Color Consortium.
|
|
4
|
+
# BSD 3-Clause License. See LICENSE.md for details.
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
Python bindings for the RefIccMAX (iccDEV) ICC color profile library.
|
|
8
|
+
|
|
9
|
+
Provides Pythonic access to ICC profile reading, color management,
|
|
10
|
+
and color space transformations via Cython wrappers around IccProfLib.
|
|
11
|
+
|
|
12
|
+
Quick start::
|
|
13
|
+
|
|
14
|
+
import iccdev
|
|
15
|
+
|
|
16
|
+
# Read a profile
|
|
17
|
+
profile = iccdev.IccProfile("sRGB.icc")
|
|
18
|
+
header = profile.header
|
|
19
|
+
print(header.version_string)
|
|
20
|
+
|
|
21
|
+
# Apply a color transform
|
|
22
|
+
cmm = iccdev.IccCmm()
|
|
23
|
+
cmm.attach("input.icc", intent=iccdev.Intent.Perceptual)
|
|
24
|
+
cmm.attach("output.icc")
|
|
25
|
+
cmm.begin()
|
|
26
|
+
result = cmm.apply([0.5, 0.3, 0.1])
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
__version__ = "0.1.0"
|
|
30
|
+
|
|
31
|
+
from iccdev._iccdev import (
|
|
32
|
+
# Classes
|
|
33
|
+
IccProfile,
|
|
34
|
+
IccCmm,
|
|
35
|
+
IccApply,
|
|
36
|
+
IccProfileHeader,
|
|
37
|
+
ValidationResult,
|
|
38
|
+
# Exceptions
|
|
39
|
+
IccError,
|
|
40
|
+
IccProfileError,
|
|
41
|
+
IccCmmError,
|
|
42
|
+
# Enums
|
|
43
|
+
ColorSpace,
|
|
44
|
+
ProfileClass,
|
|
45
|
+
RenderingIntent,
|
|
46
|
+
Interpolation,
|
|
47
|
+
LutType,
|
|
48
|
+
CmmStatus,
|
|
49
|
+
ValidationStatus,
|
|
50
|
+
# Convenience functions
|
|
51
|
+
sig_to_str,
|
|
52
|
+
open_profile,
|
|
53
|
+
read_profile,
|
|
54
|
+
validate_profile,
|
|
55
|
+
validate_profile_file,
|
|
56
|
+
)
|
|
57
|
+
from iccdev.cli import (
|
|
58
|
+
IccToolError,
|
|
59
|
+
available_tools,
|
|
60
|
+
dump_profile,
|
|
61
|
+
find_tool,
|
|
62
|
+
heif_dump,
|
|
63
|
+
icc_from_json,
|
|
64
|
+
icc_from_xml,
|
|
65
|
+
icc_to_json,
|
|
66
|
+
icc_to_xml,
|
|
67
|
+
round_trip,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# Short alias for RenderingIntent
|
|
71
|
+
Intent = RenderingIntent
|
|
72
|
+
|
|
73
|
+
__all__ = [
|
|
74
|
+
# Classes
|
|
75
|
+
"IccProfile",
|
|
76
|
+
"IccCmm",
|
|
77
|
+
"IccApply",
|
|
78
|
+
"IccProfileHeader",
|
|
79
|
+
"ValidationResult",
|
|
80
|
+
# Exceptions
|
|
81
|
+
"IccError",
|
|
82
|
+
"IccProfileError",
|
|
83
|
+
"IccCmmError",
|
|
84
|
+
# Enums
|
|
85
|
+
"ColorSpace",
|
|
86
|
+
"ProfileClass",
|
|
87
|
+
"RenderingIntent",
|
|
88
|
+
"Intent",
|
|
89
|
+
"Interpolation",
|
|
90
|
+
"LutType",
|
|
91
|
+
"CmmStatus",
|
|
92
|
+
"ValidationStatus",
|
|
93
|
+
# Functions
|
|
94
|
+
"sig_to_str",
|
|
95
|
+
"open_profile",
|
|
96
|
+
"read_profile",
|
|
97
|
+
"validate_profile",
|
|
98
|
+
"validate_profile_file",
|
|
99
|
+
# CLI-backed helpers
|
|
100
|
+
"IccToolError",
|
|
101
|
+
"available_tools",
|
|
102
|
+
"find_tool",
|
|
103
|
+
"heif_dump",
|
|
104
|
+
"icc_to_xml",
|
|
105
|
+
"icc_from_xml",
|
|
106
|
+
"icc_to_json",
|
|
107
|
+
"icc_from_json",
|
|
108
|
+
"dump_profile",
|
|
109
|
+
"round_trip",
|
|
110
|
+
]
|
|
Binary file
|
iccdev/_iccdev.pyi
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
"""Type stubs for iccdev._iccdev (Cython extension)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import enum
|
|
6
|
+
import os
|
|
7
|
+
from collections.abc import Sequence
|
|
8
|
+
from typing import NamedTuple, Optional, Union
|
|
9
|
+
|
|
10
|
+
# NumPy is optional
|
|
11
|
+
try:
|
|
12
|
+
import numpy as np
|
|
13
|
+
import numpy.typing as npt
|
|
14
|
+
except ImportError:
|
|
15
|
+
np = None # type: ignore[assignment]
|
|
16
|
+
npt = None # type: ignore[assignment]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# ---------------------------------------------------------------------------
|
|
20
|
+
# Enums
|
|
21
|
+
# ---------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
class ColorSpace(enum.IntEnum):
|
|
24
|
+
XYZ = ...
|
|
25
|
+
Lab = ...
|
|
26
|
+
Luv = ...
|
|
27
|
+
YCbCr = ...
|
|
28
|
+
Yxy = ...
|
|
29
|
+
RGB = ...
|
|
30
|
+
Gray = ...
|
|
31
|
+
HSV = ...
|
|
32
|
+
HLS = ...
|
|
33
|
+
CMYK = ...
|
|
34
|
+
CMY = ...
|
|
35
|
+
CLR1 = ...
|
|
36
|
+
CLR2 = ...
|
|
37
|
+
CLR3 = ...
|
|
38
|
+
CLR4 = ...
|
|
39
|
+
CLR5 = ...
|
|
40
|
+
CLR6 = ...
|
|
41
|
+
CLR7 = ...
|
|
42
|
+
CLR8 = ...
|
|
43
|
+
CLR9 = ...
|
|
44
|
+
CLR10 = ...
|
|
45
|
+
CLR11 = ...
|
|
46
|
+
CLR12 = ...
|
|
47
|
+
CLR13 = ...
|
|
48
|
+
CLR14 = ...
|
|
49
|
+
CLR15 = ...
|
|
50
|
+
Named = ...
|
|
51
|
+
NChannel = ...
|
|
52
|
+
DevLab = ...
|
|
53
|
+
DevXYZ = ...
|
|
54
|
+
Gamut = ...
|
|
55
|
+
Unknown = ...
|
|
56
|
+
|
|
57
|
+
@classmethod
|
|
58
|
+
def from_sig(cls, sig: int) -> ColorSpace: ...
|
|
59
|
+
|
|
60
|
+
class ProfileClass(enum.IntEnum):
|
|
61
|
+
Input = ...
|
|
62
|
+
Display = ...
|
|
63
|
+
Output = ...
|
|
64
|
+
Link = ...
|
|
65
|
+
Abstract = ...
|
|
66
|
+
ColorSpace = ...
|
|
67
|
+
NamedColor = ...
|
|
68
|
+
ColorEncoding = ...
|
|
69
|
+
MaterialID = ...
|
|
70
|
+
MaterialLink = ...
|
|
71
|
+
MaterialVis = ...
|
|
72
|
+
|
|
73
|
+
class RenderingIntent(enum.IntEnum):
|
|
74
|
+
Perceptual = ...
|
|
75
|
+
RelativeColorimetric = ...
|
|
76
|
+
Saturation = ...
|
|
77
|
+
AbsoluteColorimetric = ...
|
|
78
|
+
|
|
79
|
+
Intent = RenderingIntent
|
|
80
|
+
|
|
81
|
+
class Interpolation(enum.IntEnum):
|
|
82
|
+
Linear = ...
|
|
83
|
+
Tetrahedral = ...
|
|
84
|
+
|
|
85
|
+
class LutType(enum.IntEnum):
|
|
86
|
+
Color = ...
|
|
87
|
+
NamedColor = ...
|
|
88
|
+
Preview = ...
|
|
89
|
+
Gamut = ...
|
|
90
|
+
BPC = ...
|
|
91
|
+
BRDFParam = ...
|
|
92
|
+
BRDFDirect = ...
|
|
93
|
+
BRDFMcsParam = ...
|
|
94
|
+
MCS = ...
|
|
95
|
+
Colorimetric = ...
|
|
96
|
+
Spectral = ...
|
|
97
|
+
|
|
98
|
+
class CmmStatus(enum.IntEnum):
|
|
99
|
+
Bad = ...
|
|
100
|
+
Ok = ...
|
|
101
|
+
CantOpenProfile = ...
|
|
102
|
+
BadSpaceLink = ...
|
|
103
|
+
InvalidProfile = ...
|
|
104
|
+
BadXform = ...
|
|
105
|
+
InvalidLut = ...
|
|
106
|
+
ProfileMissingTag = ...
|
|
107
|
+
ColorNotFound = ...
|
|
108
|
+
IncorrectApply = ...
|
|
109
|
+
BadColorEncoding = ...
|
|
110
|
+
AllocErr = ...
|
|
111
|
+
BadLutType = ...
|
|
112
|
+
IdentityXform = ...
|
|
113
|
+
UnsupportedPcsLink = ...
|
|
114
|
+
BadConnection = ...
|
|
115
|
+
BadTintXform = ...
|
|
116
|
+
TooManySamples = ...
|
|
117
|
+
BadMCSLink = ...
|
|
118
|
+
Unsupported = ...
|
|
119
|
+
UnsupportedProfileClass = ...
|
|
120
|
+
CantAdjustPcs = ...
|
|
121
|
+
|
|
122
|
+
class ValidationStatus(enum.IntEnum):
|
|
123
|
+
OK = ...
|
|
124
|
+
WARNING = ...
|
|
125
|
+
NON_COMPLIANT = ...
|
|
126
|
+
CRITICAL_ERROR = ...
|
|
127
|
+
INVALID_ARGUMENT = ...
|
|
128
|
+
INTERNAL_ERROR = ...
|
|
129
|
+
|
|
130
|
+
class ValidationResult(NamedTuple):
|
|
131
|
+
status: ValidationStatus
|
|
132
|
+
report: str
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
# ---------------------------------------------------------------------------
|
|
136
|
+
# Exceptions
|
|
137
|
+
# ---------------------------------------------------------------------------
|
|
138
|
+
|
|
139
|
+
class IccError(Exception):
|
|
140
|
+
status: int
|
|
141
|
+
status_code: int # backward compat alias
|
|
142
|
+
status_name: str
|
|
143
|
+
def __init__(self, message: str, status: int = -1) -> None: ...
|
|
144
|
+
|
|
145
|
+
class IccProfileError(IccError): ...
|
|
146
|
+
class IccCmmError(IccError): ...
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
# ---------------------------------------------------------------------------
|
|
150
|
+
# IccProfileHeader (named tuple)
|
|
151
|
+
# ---------------------------------------------------------------------------
|
|
152
|
+
|
|
153
|
+
class IccProfileHeader(NamedTuple):
|
|
154
|
+
size: int
|
|
155
|
+
cmm_id: int
|
|
156
|
+
version: int
|
|
157
|
+
device_class: int
|
|
158
|
+
color_space: int
|
|
159
|
+
pcs: int
|
|
160
|
+
date: dict[str, int]
|
|
161
|
+
magic: int
|
|
162
|
+
platform: int
|
|
163
|
+
flags: int
|
|
164
|
+
manufacturer: int
|
|
165
|
+
model: int
|
|
166
|
+
attributes: int
|
|
167
|
+
rendering_intent: int
|
|
168
|
+
illuminant: dict[str, float]
|
|
169
|
+
creator: int
|
|
170
|
+
profile_id: bytes
|
|
171
|
+
spectral_pcs: int
|
|
172
|
+
spectral_range: dict[str, int]
|
|
173
|
+
bi_spectral_range: dict[str, int]
|
|
174
|
+
mcs: int
|
|
175
|
+
device_sub_class: int
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def version_string(self) -> str: ...
|
|
179
|
+
@property
|
|
180
|
+
def color_space_name(self) -> str: ...
|
|
181
|
+
@property
|
|
182
|
+
def pcs_name(self) -> str: ...
|
|
183
|
+
@property
|
|
184
|
+
def device_class_name(self) -> str: ...
|
|
185
|
+
@property
|
|
186
|
+
def rendering_intent_name(self) -> str: ...
|
|
187
|
+
@property
|
|
188
|
+
def platform_name(self) -> str: ...
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
# ---------------------------------------------------------------------------
|
|
192
|
+
# IccProfile
|
|
193
|
+
# ---------------------------------------------------------------------------
|
|
194
|
+
|
|
195
|
+
class IccProfile:
|
|
196
|
+
def __init__(self, path: Optional[Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]] = None, *, lazy: bool = True) -> None: ...
|
|
197
|
+
def close(self) -> None: ...
|
|
198
|
+
def __enter__(self) -> IccProfile: ...
|
|
199
|
+
def __exit__(self, exc_type: object, exc_val: object, exc_tb: object) -> bool: ...
|
|
200
|
+
def __bool__(self) -> bool: ...
|
|
201
|
+
|
|
202
|
+
@property
|
|
203
|
+
def is_valid(self) -> bool: ...
|
|
204
|
+
@property
|
|
205
|
+
def header(self) -> IccProfileHeader: ...
|
|
206
|
+
@property
|
|
207
|
+
def color_space(self) -> ColorSpace: ...
|
|
208
|
+
@property
|
|
209
|
+
def pcs(self) -> ColorSpace: ...
|
|
210
|
+
@property
|
|
211
|
+
def device_class(self) -> Union[ProfileClass, int]: ...
|
|
212
|
+
@property
|
|
213
|
+
def version_string(self) -> str: ...
|
|
214
|
+
@property
|
|
215
|
+
def is_v5(self) -> bool: ...
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
# ---------------------------------------------------------------------------
|
|
219
|
+
# IccApply
|
|
220
|
+
# ---------------------------------------------------------------------------
|
|
221
|
+
|
|
222
|
+
class IccApply:
|
|
223
|
+
def close(self) -> None: ...
|
|
224
|
+
def __enter__(self) -> IccApply: ...
|
|
225
|
+
def __exit__(self, exc_type: object, exc_val: object, exc_tb: object) -> bool: ...
|
|
226
|
+
def __bool__(self) -> bool: ...
|
|
227
|
+
|
|
228
|
+
def apply(self, pixel: Sequence[float]) -> list[float]: ...
|
|
229
|
+
def apply_multi(self, pixels: Sequence[Sequence[float]]) -> list[list[float]]: ...
|
|
230
|
+
def apply_ndarray(self, pixels: np.ndarray) -> np.ndarray: ...
|
|
231
|
+
|
|
232
|
+
@property
|
|
233
|
+
def src_channels(self) -> int: ...
|
|
234
|
+
@property
|
|
235
|
+
def dst_channels(self) -> int: ...
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
# ---------------------------------------------------------------------------
|
|
239
|
+
# IccCmm
|
|
240
|
+
# ---------------------------------------------------------------------------
|
|
241
|
+
|
|
242
|
+
class IccCmm:
|
|
243
|
+
def __init__(
|
|
244
|
+
self,
|
|
245
|
+
src_space: Union[ColorSpace, int] = ...,
|
|
246
|
+
dst_space: Union[ColorSpace, int] = ...,
|
|
247
|
+
first_is_input: bool = True,
|
|
248
|
+
) -> None: ...
|
|
249
|
+
|
|
250
|
+
def close(self) -> None: ...
|
|
251
|
+
def __enter__(self) -> IccCmm: ...
|
|
252
|
+
def __exit__(self, exc_type: object, exc_val: object, exc_tb: object) -> bool: ...
|
|
253
|
+
def __bool__(self) -> bool: ...
|
|
254
|
+
|
|
255
|
+
def attach(
|
|
256
|
+
self,
|
|
257
|
+
path: Union[str, bytes, os.PathLike[str], os.PathLike[bytes]],
|
|
258
|
+
*,
|
|
259
|
+
intent: Union[RenderingIntent, int] = ...,
|
|
260
|
+
interp: Union[Interpolation, int] = ...,
|
|
261
|
+
lut_type: Union[LutType, int] = ...,
|
|
262
|
+
use_d2b: bool = True,
|
|
263
|
+
use_bpc: bool = False,
|
|
264
|
+
) -> None: ...
|
|
265
|
+
|
|
266
|
+
def attach_profile(
|
|
267
|
+
self,
|
|
268
|
+
path: Union[str, bytes, os.PathLike[str], os.PathLike[bytes]],
|
|
269
|
+
**kwargs: object,
|
|
270
|
+
) -> None: ...
|
|
271
|
+
|
|
272
|
+
def begin(self) -> None: ...
|
|
273
|
+
def get_apply(self) -> IccApply: ...
|
|
274
|
+
|
|
275
|
+
def apply(self, pixel: Sequence[float]) -> list[float]: ...
|
|
276
|
+
def apply_multi(self, pixels: Sequence[Sequence[float]]) -> list[list[float]]: ...
|
|
277
|
+
def apply_ndarray(self, pixels: np.ndarray) -> np.ndarray: ...
|
|
278
|
+
|
|
279
|
+
@property
|
|
280
|
+
def src_space(self) -> ColorSpace: ...
|
|
281
|
+
@property
|
|
282
|
+
def dst_space(self) -> ColorSpace: ...
|
|
283
|
+
@property
|
|
284
|
+
def src_channels(self) -> int: ...
|
|
285
|
+
@property
|
|
286
|
+
def dst_channels(self) -> int: ...
|
|
287
|
+
@property
|
|
288
|
+
def is_ready(self) -> bool: ...
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
# ---------------------------------------------------------------------------
|
|
292
|
+
# Module-level functions
|
|
293
|
+
# ---------------------------------------------------------------------------
|
|
294
|
+
|
|
295
|
+
def sig_to_str(sig: int) -> str: ...
|
|
296
|
+
def open_profile(path: Union[str, bytes, os.PathLike[str], os.PathLike[bytes]], *, lazy: bool = True) -> IccProfile: ...
|
|
297
|
+
def read_profile(path: Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]) -> IccProfile: ...
|
|
298
|
+
def validate_profile(profile: Union[bytes, bytearray, memoryview]) -> ValidationResult: ...
|
|
299
|
+
def validate_profile_file(path: Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]) -> ValidationResult: ...
|