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
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
open Util
module E = struct
open Color
type t = Color.rgba
let bytes_per_pixel = 4
let get str pos =
{ color =
{ r = str @% pos ;
g = str @% pos + 1;
b = str @% pos + 2 };
alpha = str @% pos + 3 }
let set str pos t =
str << pos & char_of_int t.color.r;
str << pos + 1 & char_of_int t.color.g;
str << pos + 2 & char_of_int t.color.b;
str << pos + 3 & char_of_int t.alpha
let make t =
let str = Bytes.create bytes_per_pixel in
set str 0 t;
str
end
module RI = Genimage.MakeRawImage(E)
type rawimage = RI.t
type elt = Color.rgba
type t = {
width : int;
height : int;
rawimage : RI.t;
mutable infos : Info.info list;
}
module C = struct
type rawimage = RI.t
type container = t
let rawimage x = x.rawimage
let create_default width height rawimage =
{ width = width;
height = height;
rawimage = rawimage;
infos = []; }
let create_duplicate src width height rawimage =
{ width = width;
height = height;
rawimage = rawimage;
infos = src.infos; }
end
module IMAGE = Genimage.Make(RI)(C)
let create_with width height infos data =
{ width = width;
height = height;
rawimage = RI.create_with width height data;
infos = infos; }
let create_with_scanlines width height infos data =
{ width = width;
height = height;
rawimage = RI.create_with_scanlines width height data;
infos = infos; }
let rawimage = C.rawimage
let create = IMAGE.create
let make = IMAGE.make
let dump = IMAGE.dump
let unsafe_access = IMAGE.unsafe_access
let get_strip = IMAGE.get_strip
let set_strip = IMAGE.set_strip
let get_scanline = IMAGE.get_scanline
let set_scanline = IMAGE.set_scanline
let unsafe_get = IMAGE.unsafe_get
let unsafe_set = IMAGE.unsafe_set
let get = IMAGE.get
let set = IMAGE.set
let destroy = IMAGE.destroy
let copy = IMAGE.copy
let sub = IMAGE.sub
let blit = IMAGE.blit
let map = IMAGE.map
let blocks = IMAGE.blocks
let dump_block = IMAGE.dump_block
open Color
let resize_reduce prog img nw nh =
let newimage = create nw nh in
let xscale = float nw /. float img.width in
let yscale = float nh /. float img.height in
let xs = Array.init nw (fun x ->
let sx = truncate (float x /. xscale) in
let ex = truncate ((float x +. 0.99) /. xscale) in
let dx = ex - sx + 1 in
(sx, ex, dx)) in
let ys = Array.init nh (fun y ->
let sy = truncate (float y /. yscale) in
let ey = truncate ((float y +. 0.99) /. yscale) in
let dy = ey - sy + 1 in
(sy, ey, dy)) in
for x = 0 to nw - 1 do
let sx, ex, dx = xs.(x) in
for y = 0 to nh - 1 do
let sy, ey, dy = ys.(y) in
let size = dx * dy in
let sr = ref 0
and sg = ref 0
and sb = ref 0
and sa = ref 0 in
for xx = sx to ex do
for yy = sy to ey do
let c = unsafe_get img xx yy in
sr := !sr + c.color.r;
sg := !sg + c.color.g;
sb := !sb + c.color.b;
sa := !sa + c.alpha
done
done;
unsafe_set newimage x y
{ color = { r = !sr / size; g = !sg / size; b = !sb / size };
alpha = !sa / size; }
done;
match prog with
| Some p -> p (float (x + 1) /. float nw)
| None -> ()
done;
newimage
let resize_enlarge prog img nw nh =
let newimage = create nw nh in
let xscale = float nw /. float img.width in
let yscale = float nh /. float img.height in
let ww = truncate (ceil xscale)
and wh = truncate (ceil yscale) in
let weight =
Array.init ww (fun x ->
Array.init wh (fun y ->
let x0 = x - ww / 2
and y0 = y - wh / 2 in
let x1 = x0 + ww - 1
and y1 = y0 + wh - 1 in
Array.init 3 (fun xx ->
Array.init 3 (fun yy ->
let mx0 = (xx - 1) * ww
and my0 = (yy - 1) * wh in
let mx1 = mx0 + ww - 1
and my1 = my0 + wh - 1 in
let cx0 = if x0 < mx0 then mx0 else x0 in
let cy0 = if y0 < my0 then my0 else y0 in
let cx1 = if x1 > mx1 then mx1 else x1 in
let cy1 = if y1 > my1 then my1 else y1 in
let dx = cx1 - cx0 + 1
and dy = cy1 - cy0 + 1 in
let dx = if dx < 0 then 0 else dx
and dy = if dy < 0 then 0 else dy in
dx * dy)))) in
let wsum =
Array.init ww (fun x ->
Array.init wh (fun y ->
let sum = ref 0 in
Array.iter
(Array.iter (fun w -> sum := !sum + w))
weight.(x).(y);
if !sum = 0 then failwith "resize_enlarge wsum";
!sum)) in
let xs = Array.init img.width (fun x ->
let sx = truncate (float x *. xscale) in
let ex = truncate (float (x + 1) *. xscale) - 1 in
let dx = ex - sx + 1 in
if dx > ww then failwith "resize_enlarge";
(sx, ex, dx)) in
let ys = Array.init img.height (fun y ->
let sy = truncate (float y *. yscale) in
let ey = truncate (float (y + 1) *. yscale) - 1 in
let dy = ey - sy + 1 in
if dy > wh then failwith "resize_enlarge";
(sy, ey, dy)) in
let query c x y =
if x < 0 || y < 0 || x >= img.width || y >= img.height
then c
else unsafe_get img x y in
for y = 0 to img.height - 1 do
let sy, _ey, dy = ys.(y) in
for x = 0 to img.width - 1 do
let sx, _ex, dx = xs.(x) in
let colors =
let c = unsafe_get img x y in
Array.init 3 (fun dx ->
Array.init 3 (fun dy ->
query c (x + dx - 1) (y + dy - 1))) in
for xx = 0 to dx - 1 do
for yy = 0 to dy - 1 do
let sr = ref 0
and sg = ref 0
and sb = ref 0
and sa = ref 0 in
let weight = weight.(xx).(yy) in
let wsum = wsum.(xx).(yy) in
for xxx = 0 to 2 do
for yyy = 0 to 2 do
let c = colors.(xxx).(yyy) in
sr := !sr + c.color.r * weight.(xxx).(yyy);
sg := !sg + c.color.g * weight.(xxx).(yyy);
sb := !sb + c.color.b * weight.(xxx).(yyy);
sa := !sa + c.alpha * weight.(xxx).(yyy);
done
done;
unsafe_set newimage (sx + xx) (sy + yy)
{color= {r = !sr / wsum; g = !sg / wsum; b = !sb / wsum};
alpha = !sa / wsum}
done
done
done;
match prog with
| Some p -> p (float (y + 1) /. float img.height)
| None -> ()
done;
newimage
let resize prog img nw nh =
let xscale = float nw /. float img.width in
let yscale = float nh /. float img.height in
if xscale >= 1.0 && yscale >= 1.0 then resize_enlarge prog img nw nh else
if xscale <= 1.0 && yscale <= 1.0 then resize_reduce prog img nw nh
else resize_reduce prog img nw nh