colo-icc.lua /size: 9691 b    last modification: 2021-10-28 13:50
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
colo-icc
'
]
=
{
2
version
=
1
.
000
,
3
comment
=
"
companion to colo-ini.mkiv
"
,
4
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
5
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
6
license
=
"
see context related readme files
"
7
}
8 9
local
char
,
byte
,
gsub
,
match
,
format
,
strip
=
string
.
char
,
string
.
byte
,
string
.
gsub
,
string
.
match
,
string
.
format
,
string
.
strip
10
local
readstring
,
readnumber
=
io
.
readstring
,
io
.
readnumber
11
local
band
=
bit32
.
band
12
local
next
=
next
13 14
local
colors
=
attributes
and
attributes
.
colors
or
{
}
-- when used in mtxrun
15 16
local
report_colors
=
logs
.
reporter
(
"
colors
"
,
"
icc
"
)
17 18
local
R
,
Cs
,
lpegmatch
=
lpeg
.
R
,
lpeg
.
Cs
,
lpeg
.
match
19 20
local
invalid
=
R
(
char
(
0
)
.
.
char
(
31
)
)
21
local
cleaned
=
invalid
^
0
*
Cs
(
(
1
-
invalid
)
^
0
)
22 23
function
colors
.
iccprofile
(
filename
,
verbose
)
24
local
fullname
=
resolvers
.
findfile
(
filename
,
"
icc
"
)
or
"
"
25
if
fullname
=
=
"
"
then
26
local
locate
=
resolvers
.
finders
.
byscheme
-- not in mtxrun
27
if
locate
then
28
fullname
=
locate
(
"
loc
"
,
filename
)
29
end
30
end
31
if
fullname
=
=
"
"
then
32
report_colors
(
"
profile %a cannot be found
"
,
filename
)
33
return
nil
,
false
34
end
35
local
f
=
io
.
open
(
fullname
,
"
rb
"
)
36
if
not
f
then
37
report_colors
(
"
profile %a cannot be loaded
"
,
fullname
)
38
return
nil
,
false
39
end
40
local
header
=
{
41
size
=
readnumber
(
f
,
4
)
,
42
cmmtype
=
readnumber
(
f
,
4
)
,
43
version
=
readnumber
(
f
,
4
)
,
44
deviceclass
=
strip
(
readstring
(
f
,
4
)
)
,
45
colorspace
=
strip
(
readstring
(
f
,
4
)
)
,
46
connectionspace
=
strip
(
readstring
(
f
,
4
)
)
,
47
datetime
=
{
48
year
=
readnumber
(
f
,
2
)
,
49
month
=
readnumber
(
f
,
2
)
,
50
day
=
readnumber
(
f
,
2
)
,
51
hour
=
readnumber
(
f
,
2
)
,
52
minutes
=
readnumber
(
f
,
2
)
,
53
seconds
=
readnumber
(
f
,
2
)
,
54
}
,
55
filesignature
=
strip
(
readstring
(
f
,
4
)
)
,
56
platformsignature
=
strip
(
readstring
(
f
,
4
)
)
,
57
options
=
readnumber
(
f
,
4
)
,
58
devicemanufacturer
=
strip
(
readstring
(
f
,
4
)
)
,
59
devicemodel
=
strip
(
readstring
(
f
,
4
)
)
,
60
deviceattributes
=
readnumber
(
f
,
4
)
,
61
renderingintent
=
readnumber
(
f
,
4
)
,
62
illuminantxyz
=
{
63
x
=
readnumber
(
f
,
4
)
,
64
y
=
readnumber
(
f
,
4
)
,
65
z
=
readnumber
(
f
,
4
)
,
66
}
,
67
profilecreator
=
readnumber
(
f
,
4
)
,
68
id
=
strip
(
readstring
(
f
,
16
)
)
,
69
}
70
local
tags
=
{
}
71
for
i
=
1
,
readnumber
(
f
,
128
,
4
)
do
72
tags
[
readstring
(
f
,
4
)
]
=
{
73
offset
=
readnumber
(
f
,
4
)
,
74
length
=
readnumber
(
f
,
4
)
,
75
}
76
end
77
local
o
=
header
.
options
78
header
.
options
=
79
o
=
=
0
and
"
embedded
"
or
80
o
=
=
1
and
"
dependent
"
or
"
unknown
"
81
local
d
=
header
.
deviceattributes
82
header
.
deviceattributes
=
{
83
[
band
(
d
,
1
)
~
=
0
and
"
transparency
"
or
"
reflective
"
]
=
true
,
84
[
band
(
d
,
2
)
~
=
0
and
"
mate
"
or
"
glossy
"
]
=
true
,
85
[
band
(
d
,
3
)
~
=
0
and
"
negative
"
or
"
positive
"
]
=
true
,
86
[
band
(
d
,
4
)
~
=
0
and
"
bw
"
or
"
color
"
]
=
true
,
87
}
88
local
r
=
header
.
renderingintent
89
header
.
renderingintent
=
90
r
=
=
0
and
"
perceptual
"
or
91
r
=
=
1
and
"
relative
"
or
92
r
=
=
2
and
"
saturation
"
or
93
r
=
=
3
and
"
absolute
"
or
"
unknown
"
94
for
tag
,
spec
in
next
,
tags
do
95
if
tag
then
96
local
offset
,
length
=
spec
.
offset
,
spec
.
length
97
local
variant
=
readstring
(
f
,
offset
,
4
)
98
if
variant
=
=
"
text
"
or
variant
=
=
"
desc
"
then
99
local
str
=
readstring
(
f
,
length
-4
)
100
tags
[
tag
]
=
{
101
data
=
str
,
102
cleaned
=
lpegmatch
(
cleaned
,
str
)
,
103
}
104
else
105
if
verbose
then
106
report_colors
(
"
ignoring tag %a or type %a in profile %a
"
,
tag
,
variant
,
fullname
)
107
end
108
tags
[
tag
]
=
nil
109
end
110
end
111
end
112
f
:
close
(
)
113
local
profile
=
{
114
filename
=
filename
,
115
fullname
=
fullname
,
116
header
=
header
,
117
tags
=
tags
,
118
}
119
report_colors
(
"
profile %a loaded
"
,
fullname
)
120
return
profile
,
true
121
end
122 123
-- This is just some fun stuff I decided to check out when I was making sure that
124
-- the 2020 metafun manual could be processed with lmtx 2021. Color conversion has
125
-- been part of ConTeXt from the start but it has been extended to the less commonly
126
-- used color spaces. We already do some CIE but didn't have lab converters to play
127
-- with (although I had some MetaPost done for a friend long ago). So, when we moved
128
-- to lmtx it made sense to also move some into the core. When searching for info
129
-- I ran into some formulas for lab/xyz: http://www.easyrgb.com/en/math.php and
130
-- http://www.brucelindbloom.com/ are useful resources. I didn't touch existing
131
-- code (as it works ok).
132
--
133
-- local illuminants = { -- 2=CIE 1931 10=CIE 1964
134
-- A = { [2] = { 109.850, 100, 35.585 }, [10] = { 111.144, 100, 35.200 } }, -- incandescent/tungsten
135
-- B = { [2] = { 99.093, 100, 85.313 }, [10] = { 99.178, 100, 84.349 } }, -- old direct sunlight at noon
136
-- C = { [2] = { 98.074, 100, 118.232 }, [10] = { 97.285, 100, 116.145 } }, -- old daylight
137
-- D50 = { [2] = { 96.422, 100, 82.521 }, [10] = { 96.720, 100, 81.427 } }, -- icc profile pcs
138
-- D55 = { [2] = { 95.682, 100, 92.149 }, [10] = { 95.799, 100, 90.926 } }, -- mid-morning daylight
139
-- D65 = { [2] = { 95.047, 100, 108.883 }, [10] = { 94.811, 100, 107.304 } }, -- daylight, srgb, adobe-rgb
140
-- D75 = { [2] = { 94.972, 100, 122.638 }, [10] = { 94.416, 100, 120.641 } }, -- north sky daylight
141
-- E = { [2] = { 100.000, 100, 100.000 }, [10] = { 100.000, 100, 100.000 } }, -- equal energy
142
-- F1 = { [2] = { 92.834, 100, 103.665 }, [10] = { 94.791, 100, 103.191 } }, -- daylight fluorescent
143
-- F2 = { [2] = { 99.187, 100, 67.395 }, [10] = { 103.280, 100, 69.026 } }, -- cool fluorescent
144
-- F3 = { [2] = { 103.754, 100, 49.861 }, [10] = { 108.968, 100, 51.965 } }, -- white fluorescent
145
-- F4 = { [2] = { 109.147, 100, 38.813 }, [10] = { 114.961, 100, 40.963 } }, -- warm white fluorescent
146
-- F5 = { [2] = { 90.872, 100, 98.723 }, [10] = { 93.369, 100, 98.636 } }, -- daylight fluorescent
147
-- F6 = { [2] = { 97.309, 100, 60.191 }, [10] = { 102.148, 100, 62.074 } }, -- lite white fluorescent
148
-- F7 = { [2] = { 95.044, 100, 108.755 }, [10] = { 95.792, 100, 107.687 } }, -- daylight fluorescent, d65 simulator
149
-- F8 = { [2] = { 96.413, 100, 82.333 }, [10] = { 97.115, 100, 81.135 } }, -- sylvania f40, d50 simulator
150
-- F9 = { [2] = { 100.365, 100, 67.868 }, [10] = { 102.116, 100, 67.826 } }, -- cool white fluorescent
151
-- F10 = { [2] = { 96.174, 100, 81.712 }, [10] = { 99.001, 100, 83.134 } }, -- ultralume 50, philips tl85
152
-- F11 = { [2] = { 100.966, 100, 64.370 }, [10] = { 103.866, 100, 65.627 } }, -- ultralume 40, philips tl84
153
-- F12 = { [2] = { 108.046, 100, 39.228 }, [10] = { 111.428, 100, 40.353 } }, -- ultralume 30, philips tl83
154
-- }
155
--
156
-- local D65 = illuminants.D65
157
-- local D652 = { 95.047, 100, 108.883 }
158
--
159
-- local function labref(illuminate,observer)
160
-- local r = illuminants[illuminant or "D65"] or D65
161
-- return r[observer or 2] or r[2] or D652
162
-- end
163
--
164
-- This is hardly useful but nice for metafun demos:
165 166
local
D652
=
{
95
.
047
,
100
,
108
.
883
}
167 168
local
function
xyztolab
(
x
,
y
,
z
,
mapping
)
169
if
not
mapping
then
170
mapping
=
D652
171
end
172
x
=
x
/
mapping
[
1
]
173
y
=
y
/
mapping
[
2
]
174
z
=
z
/
mapping
[
3
]
175
x
=
(
x
>
0
.
008856
)
and
x
^
(
1
/
3
)
or
(
7
.
787
*
x
)
+
(
16
/
116
)
176
y
=
(
y
>
0
.
008856
)
and
y
^
(
1
/
3
)
or
(
7
.
787
*
y
)
+
(
16
/
116
)
177
z
=
(
z
>
0
.
008856
)
and
z
^
(
1
/
3
)
or
(
7
.
787
*
z
)
+
(
16
/
116
)
178
return
179
116
*
y
-
16
,
180
500
*
(
x
-
y
)
,
181
200
*
(
y
-
z
)
182
end
183 184
local
function
labtoxyz
(
l
,
a
,
b
,
mapping
)
185
if
not
mapping
then
186
mapping
=
D652
187
end
188
local
y
=
(
l
+
16
)
/
116
189
local
x
=
a
/
500
+
y
190
local
z
=
y
-
b
/
200
191
return
192
mapping
[
1
]
*
(
(
x
^
3
>
0
.
008856
)
and
x
^
3
or
(
x
-
16
/
116
)
/
7
.
787
)
,
193
mapping
[
2
]
*
(
(
y
^
3
>
0
.
008856
)
and
y
^
3
or
(
y
-
16
/
116
)
/
7
.
787
)
,
194
mapping
[
3
]
*
(
(
z
^
3
>
0
.
008856
)
and
z
^
3
or
(
z
-
16
/
116
)
/
7
.
787
)
195
end
196 197
local
function
xyztorgb
(
x
,
y
,
z
)
-- D65/2°
198
local
r
=
(
x
*
3
.
2404542
+
y
*
-1
.
5371385
+
z
*
-0
.
4985314
)
/
100
199
local
g
=
(
x
*
-0
.
9692660
+
y
*
1
.
8760108
+
z
*
0
.
0415560
)
/
100
200
local
b
=
(
x
*
0
.
0556434
+
y
*
-0
.
2040259
+
z
*
1
.
0572252
)
/
100
201
r
=
(
r
>
0
.
0031308
)
and
(
1
.
055
*
r
^
(
1
/
2
.
4
)
-
0
.
055
)
or
(
12
.
92
*
r
)
202
g
=
(
g
>
0
.
0031308
)
and
(
1
.
055
*
g
^
(
1
/
2
.
4
)
-
0
.
055
)
or
(
12
.
92
*
g
)
203
b
=
(
b
>
0
.
0031308
)
and
(
1
.
055
*
b
^
(
1
/
2
.
4
)
-
0
.
055
)
or
(
12
.
92
*
b
)
204
if
r
<
0
then
r
=
0
elseif
r
>
1
then
r
=
1
end
205
if
g
<
0
then
g
=
0
elseif
g
>
1
then
g
=
1
end
206
if
b
<
0
then
b
=
0
elseif
b
>
1
then
b
=
1
end
207
return
r
,
g
,
b
208
end
209 210
local
function
rgbtoxyz
(
r
,
g
,
b
)
211
r
=
100
*
(
(
r
>
0
.
04045
)
and
(
(
r
+
0
.
055
)
/
1
.
055
)
^
2
.
4
or
(
r
/
12
.
92
)
)
212
g
=
100
*
(
(
g
>
0
.
04045
)
and
(
(
g
+
0
.
055
)
/
1
.
055
)
^
2
.
4
or
(
g
/
12
.
92
)
)
213
b
=
100
*
(
(
b
>
0
.
04045
)
and
(
(
b
+
0
.
055
)
/
1
.
055
)
^
2
.
4
or
(
b
/
12
.
92
)
)
214
return
215
r
*
0
.
4124
+
g
*
0
.
3576
+
b
*
0
.
1805
,
216
r
*
0
.
2126
+
g
*
0
.
7152
+
b
*
0
.
0722
,
217
r
*
0
.
0193
+
g
*
0
.
1192
+
b
*
0
.
9505
218
end
219 220
local
function
labtorgb
(
l
,
a
,
b
,
mapping
)
221
return
xyztorgb
(
labtoxyz
(
l
,
a
,
b
,
mapping
)
)
222
end
223 224
colors
.
xyztolab
=
xyztolab
225
colors
.
labtoxyz
=
labtoxyz
226
colors
.
xyztorgb
=
xyztorgb
227
colors
.
rgbtoxyz
=
rgbtoxyz
228
colors
.
labtorgb
=
labtorgb
229