1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
if not modules then modules = { } end modules ['colo-icc'] = {
version = 1.000,
comment = "companion to colo-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
local char, byte, gsub, match, format, strip = string.char, string.byte, string.gsub, string.match, string.format, string.strip
local readstring, readnumber = io.readstring, io.readnumber
local band = bit32.band
local next = next
local colors = attributes and attributes.colors or { } -- when used in mtxrun
local report_colors = logs.reporter("colors","icc")
local R, Cs, lpegmatch = lpeg.R, lpeg.Cs, lpeg.match
local invalid = R(char(0)..char(31))
local cleaned = invalid^0 * Cs((1-invalid)^0)
function colors.iccprofile(filename,verbose)
local fullname = resolvers.findfile(filename,"icc") or ""
if fullname == "" then
local locate = resolvers.finders.byscheme -- not in mtxrun
if locate then
fullname = locate("loc",filename)
end
end
if fullname == "" then
report_colors("profile %a cannot be found",filename)
return nil, false
end
local f = io.open(fullname,"rb")
if not f then
report_colors("profile %a cannot be loaded",fullname)
return nil, false
end
local header = {
size = readnumber(f,4),
cmmtype = readnumber(f,4),
version = readnumber(f,4),
deviceclass = strip(readstring(f,4)),
colorspace = strip(readstring(f,4)),
connectionspace = strip(readstring(f,4)),
datetime = {
year = readnumber(f,2),
month = readnumber(f,2),
day = readnumber(f,2),
hour = readnumber(f,2),
minutes = readnumber(f,2),
seconds = readnumber(f,2),
},
filesignature = strip(readstring(f,4)),
platformsignature = strip(readstring(f,4)),
options = readnumber(f,4),
devicemanufacturer = strip(readstring(f,4)),
devicemodel = strip(readstring(f,4)),
deviceattributes = readnumber(f,4),
renderingintent = readnumber(f,4),
illuminantxyz = {
x = readnumber(f,4),
y = readnumber(f,4),
z = readnumber(f,4),
},
profilecreator = readnumber(f,4),
id = strip(readstring(f,16)),
}
local tags = { }
for i=1,readnumber(f,128,4) do
tags[readstring(f,4)] = {
offset = readnumber(f,4),
length = readnumber(f,4),
}
end
local o = header.options
header.options =
o == 0 and "embedded" or
o == 1 and "dependent" or "unknown"
local d = header.deviceattributes
header.deviceattributes = {
[band(d,1) ~= 0 and "transparency" or "reflective"] = true,
[band(d,2) ~= 0 and "mate" or "glossy" ] = true,
[band(d,3) ~= 0 and "negative" or "positive" ] = true,
[band(d,4) ~= 0 and "bw" or "color" ] = true,
}
local r = header.renderingintent
header.renderingintent =
r == 0 and "perceptual" or
r == 1 and "relative" or
r == 2 and "saturation" or
r == 3 and "absolute" or "unknown"
for tag, spec in next, tags do
if tag then
local offset, length = spec.offset, spec.length
local variant = readstring(f,offset,4)
if variant == "text" or variant == "desc" then
local str = readstring(f,length-4)
tags[tag] = {
data = str,
cleaned = lpegmatch(cleaned,str),
}
else
if verbose then
report_colors("ignoring tag %a or type %a in profile %a",tag,variant,fullname)
end
tags[tag] = nil
end
end
end
f:close()
local profile = {
filename = filename,
fullname = fullname,
header = header,
tags = tags,
}
report_colors("profile %a loaded",fullname)
return profile, true
end
|