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
|
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <memdraw.h>
double
flerp(double a, double b, double t)
{
return a + (b - a)*t;
}
double
fclamp(double n, double min, double max)
{
return n < min? min: n > max? max: n;
}
Memimage*
lerpimages(Memimage *i0, Memimage *i1, double blendf)
{
Memimage *ri;
Point p;
uchar *s0, *s1, *d;
int bpp;
assert(i0->chan == i1->chan);
assert(Dx(i0->r) == Dx(i1->r) && Dy(i0->r) == Dy(i1->r));
ri = allocmemimage(i0->r, i0->chan);
if(ri == nil)
sysfatal("allocmemimage: %r");
bpp = (i0->depth+7)/8;
for(p.y = 0; p.y < i0->r.max.y; p.y++)
for(p.x = 0; p.x < i0->r.max.x; p.x++){
s0 = byteaddr(i0, addpt(i0->r.min, p));
s1 = byteaddr(i1, addpt(i1->r.min, p));
d = byteaddr(ri, addpt(ri->r.min, p));
switch(bpp){
case 4:
d[3] = flerp(s0[3], s1[3], blendf);
case 3:
d[2] = flerp(s0[2], s1[2], blendf);
case 2:
d[1] = flerp(s0[1], s1[1], blendf);
case 1:
d[0] = flerp(s0[0], s1[0], blendf);
}
}
return ri;
}
void
usage(void)
{
fprint(2, "usage: %s [-f factor] image0 image1\n", argv0);
exits("usage");
}
void
main(int argc, char *argv[])
{
Memimage *m[2], *r;
char *s;
int fd;
double f;
f = 0.5;
ARGBEGIN{
case 'f':
f = strtod(EARGF(usage()), &s);
if(*s != 0)
sysfatal("wrong blending factor");
break;
default: usage();
}ARGEND;
if(argc != 2)
usage();
if(memimageinit() != 0)
sysfatal("memimageinit: %r");
fd = open(argv[0], OREAD);
if(fd < 0)
sysfatal("open: %r");
if((m[0] = readmemimage(fd)) == nil)
sysfatal("readmemimage: %r");
close(fd);
fd = open(argv[1], OREAD);
if(fd < 0)
sysfatal("open: %r");
if((m[1] = readmemimage(fd)) == nil)
sysfatal("readmemimage: %r");
close(fd);
r = lerpimages(m[0], m[1], fclamp(f, 0, 1));
if(writememimage(1, r) < 0)
sysfatal("writememimage: %r");
exits(nil);
}
|