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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
module type COLOR = sig
type t
val t : t
val name : t -> string
val channels : t -> int
val has_alpha : t -> bool
val to_rgb : t -> floatarray -> floatarray
val of_rgb : t -> floatarray -> floatarray
end
open Float.Array
module Rgb : COLOR with type t = [ `Rgb ] = struct
type t = [ `Rgb ]
let t = `Rgb
let name _ = "rgb"
let channels _ = 3
let has_alpha _ = false
let to_rgb _ x = x
let of_rgb _ x = x
end
module Rgba : COLOR with type t = [ `Rgba ] = struct
type t = [ `Rgba ]
let t = `Rgba
let name _ = "rgba"
let channels _ = 4
let has_alpha _ = true
let to_rgb _ x =
let alpha = get x 3 in
set x 0 (get x 0 *. alpha);
set x 1 (get x 1 *. alpha);
set x 2 (get x 2 *. alpha);
set x 3 1.0;
x
let of_rgb _ x =
let dest = Float.Array.create 4 in
set dest 0 (get x 0);
set dest 1 (get x 1);
set dest 2 (get x 2);
set dest 3 1.0;
dest
end
module Gray : COLOR with type t = [ `Gray ] = struct
type t = [ `Gray ]
let t = `Gray
let name _ = "gray"
let channels _ = 1
let has_alpha _ = false
let to_rgb _ (px : floatarray) = make 3 (get px 0)
let of_rgb _ (px : floatarray) =
make 1 ((get px 0 *. 0.21) +. (get px 1 *. 0.72) +. (get px 2 *. 0.07))
end
module Xyz : COLOR with type t = [ `Xyz ] = struct
type t = [ `Xyz ]
let t = `Xyz
let name _ = "xyz"
let channels _ = 3
let has_alpha _ = false
let to_rgb _ (px : floatarray) =
let rgb = make 3 0.0 in
let x = get px 0 /. 100. in
let y = get px 1 /. 100. in
let z = get px 2 /. 100. in
let var_r = (x *. 3.2406) +. (y *. -1.5372) +. (z *. -0.4986) in
let var_g = (x *. -0.9689) +. (y *. 1.8758) +. (z *. 0.0415) in
let var_b = (x *. 0.0557) +. (y *. -0.2040) +. (z *. 1.0570) in
set rgb 0
(if var_r > 0.0031308 then
(1.055 *. Float.pow var_r (1.0 /. 2.4)) -. 0.055
else 12.92 *. var_r);
set rgb 1
(if var_g > 0.0031308 then
(1.055 *. Float.pow var_g (1.0 /. 2.4)) -. 0.055
else 12.92 *. var_g);
set rgb 2
(if var_b > 0.0031308 then
(1.055 *. Float.pow var_b (1.0 /. 2.4)) -. 0.055
else 12.92 *. var_b);
rgb
let of_rgb _ px =
let xyz = make 3 0.0 in
let r = get px 0 in
let g = get px 1 in
let b = get px 2 in
let r =
if r > 0.04045 then Float.pow ((r +. 0.055) /. 1.055) 2.4 else r /. 12.92
in
let g =
if g > 0.04045 then Float.pow ((g +. 0.055) /. 1.055) 2.4 else g /. 12.92
in
let b =
if b > 0.04045 then Float.pow ((b +. 0.055) /. 1.055) 2.4 else b /. 12.92
in
let r = r *. 100. in
let g = g *. 100. in
let b = b *. 100. in
set xyz 0 ((r *. 0.4124) +. (g *. 0.3576) +. (b *. 0.1805));
set xyz 1 ((r *. 0.2126) +. (g *. 0.7152) +. (b *. 0.0722));
set xyz 2 ((r *. 0.0193) +. (g *. 0.1192) +. (b *. 0.9505));
xyz
end
module Yuv : COLOR with type t = [ `Yuv ] = struct
type t = [ `Yuv ]
let t = `Yuv
let name _ = "yuv"
let channels _ = 3
let has_alpha _ = false
let to_rgb _ (px : floatarray) =
let rgb = make 3 0.0 in
let y = get px 0 in
let u = get px 1 in
let v = get px 2 in
set rgb 0 (y +. (1.14 *. v));
set rgb 1 (y -. (0.395 *. u) -. (0.581 *. v));
set rgb 2 (y +. (2.032 *. u));
rgb
let of_rgb _ (px : floatarray) =
let yuv = make 3 0.0 in
let r = get px 0 in
let g = get px 1 in
let b = get px 2 in
set yuv 0 ((0.299 *. r) +. (0.587 *. g) +. (0.114 *. b));
set yuv 1 ((-0.147 *. r) +. 0.289 +. g +. (0.436 *. b));
set yuv 2 ((0.615 *. r) +. (0.515 *. g) +. (0.1 *. b));
yuv
end
module Hsv : COLOR with type t = [ `Hsv ] = struct
type t = [ `Hsv ]
let t = `Hsv
let name _ = "hsv"
let channels _ = 3
let has_alpha _ = false
let to_rgb _ (px : floatarray) =
let h = get px 0 in
let s = get px 1 in
let v = get px 2 in
if s = 0. then
let () = set px 0 v in
let () = set px 1 v in
let () = set px 2 v in
px
else
let var_h = h *. 6. in
let var_h = if var_h = 6. then 0.0 else var_h in
let var_i = Float.floor var_h in
let var_1 = v *. (1. -. s) in
let var_2 = v *. (1. -. (s *. (var_h -. var_i))) in
let var_3 = v *. (1. -. (s *. (1. -. (var_h -. var_i)))) in
let () =
if var_i = 0. then
let () = set px 0 v in
let () = set px 1 var_3 in
set px 2 var_1
else if var_i = 1. then
let () = set px 0 var_2 in
let () = set px 1 v in
set px 2 var_1
else if var_i = 2. then
let () = set px 0 var_1 in
let () = set px 1 v in
set px 2 var_3
else if var_i = 3. then
let () = set px 0 var_1 in
let () = set px 1 var_2 in
set px 2 v
else if var_i = 4. then
let () = set px 0 var_3 in
let () = set px 1 var_1 in
set px 2 v
else
let () = set px 0 v in
let () = set px 1 var_1 in
set px 2 var_2
in
px
let of_rgb _ (px : floatarray) =
let r = get px 0 in
let g = get px 1 in
let b = get px 2 in
let cmax = Float.max (Float.max r g) b in
let cmin = Float.min (Float.min r g) b in
let delta = cmax -. cmin in
let del_r = (((cmax -. r) /. 6.) +. (delta /. 2.)) /. delta in
let del_g = (((cmax -. g) /. 6.) +. (delta /. 2.)) /. delta in
let del_b = (((cmax -. b) /. 6.) +. (delta /. 2.)) /. delta in
set px 0
(if cmin = cmax then 0.0
else if cmax = r then del_b -. del_g
else if cmax = g then (1. /. 3.) +. del_r -. del_b
else if cmax = b then (2. /. 3.) +. del_g -. del_r
else -1.0);
set px 1 (if cmax = 0. then 0.0 else delta /. cmax);
set px 2 cmax;
px
end
type 'a t = (module COLOR with type t = 'a)
type rgb = Rgb.t
type rgba = Rgba.t
type gray = Gray.t
type xyz = Xyz.t
type yuv = Yuv.t
type hsv = Hsv.t
let rgb : rgb t = (module Rgb)
let rgba : rgba t = (module Rgba)
let gray : gray t = (module Gray)
let xyz : xyz t = (module Xyz)
let yuv : yuv t = (module Yuv)
let hsv : hsv t = (module Hsv)
let channels (type a) (module C : COLOR with type t = a) = C.channels C.t
let name (type a) (module C : COLOR with type t = a) = C.name C.t
let has_alpha (type a) (module C : COLOR with type t = a) = C.has_alpha C.t
let alpha_channel (type a) (module C : COLOR with type t = a) =
if C.has_alpha C.t then Some (C.channels C.t - 1) else None