1*37da2899SCharles.Forsyth #include "lib9.h"
2*37da2899SCharles.Forsyth #include "kernel.h"
3*37da2899SCharles.Forsyth #include "draw.h"
4*37da2899SCharles.Forsyth
5*37da2899SCharles.Forsyth Image*
readimage(Display * d,int fd,int dolock)6*37da2899SCharles.Forsyth readimage(Display *d, int fd, int dolock)
7*37da2899SCharles.Forsyth {
8*37da2899SCharles.Forsyth char hdr[5*12+1];
9*37da2899SCharles.Forsyth int dy;
10*37da2899SCharles.Forsyth int new;
11*37da2899SCharles.Forsyth uint l, n;
12*37da2899SCharles.Forsyth int m, j, chunk;
13*37da2899SCharles.Forsyth int miny, maxy;
14*37da2899SCharles.Forsyth Rectangle r;
15*37da2899SCharles.Forsyth int ldepth;
16*37da2899SCharles.Forsyth ulong chan;
17*37da2899SCharles.Forsyth uchar *tmp;
18*37da2899SCharles.Forsyth Image *i;
19*37da2899SCharles.Forsyth
20*37da2899SCharles.Forsyth if(libreadn(fd, hdr, 11) != 11) {
21*37da2899SCharles.Forsyth kwerrstr("readimage: short header");
22*37da2899SCharles.Forsyth return nil;
23*37da2899SCharles.Forsyth }
24*37da2899SCharles.Forsyth if(memcmp(hdr, "compressed\n", 11) == 0)
25*37da2899SCharles.Forsyth return creadimage(d, fd, dolock);
26*37da2899SCharles.Forsyth dolock &= 1;
27*37da2899SCharles.Forsyth if(libreadn(fd, hdr+11, 5*12-11) != 5*12-11) {
28*37da2899SCharles.Forsyth kwerrstr("readimage: short header");
29*37da2899SCharles.Forsyth return nil;
30*37da2899SCharles.Forsyth }
31*37da2899SCharles.Forsyth chunk = d->bufsize - 32; /* a little room for header */
32*37da2899SCharles.Forsyth
33*37da2899SCharles.Forsyth /*
34*37da2899SCharles.Forsyth * distinguish new channel descriptor from old ldepth.
35*37da2899SCharles.Forsyth * channel descriptors have letters as well as numbers,
36*37da2899SCharles.Forsyth * while ldepths are a single digit formatted as %-11d.
37*37da2899SCharles.Forsyth */
38*37da2899SCharles.Forsyth new = 0;
39*37da2899SCharles.Forsyth for(m=0; m<10; m++){
40*37da2899SCharles.Forsyth if(hdr[m] != ' '){
41*37da2899SCharles.Forsyth new = 1;
42*37da2899SCharles.Forsyth break;
43*37da2899SCharles.Forsyth }
44*37da2899SCharles.Forsyth }
45*37da2899SCharles.Forsyth if(hdr[11] != ' '){
46*37da2899SCharles.Forsyth kwerrstr("readimage: bad format");
47*37da2899SCharles.Forsyth return nil;
48*37da2899SCharles.Forsyth }
49*37da2899SCharles.Forsyth if(new){
50*37da2899SCharles.Forsyth hdr[11] = '\0';
51*37da2899SCharles.Forsyth if((chan = strtochan(hdr)) == 0){
52*37da2899SCharles.Forsyth kwerrstr("readimage: bad channel string %s", hdr);
53*37da2899SCharles.Forsyth return nil;
54*37da2899SCharles.Forsyth }
55*37da2899SCharles.Forsyth }else{
56*37da2899SCharles.Forsyth ldepth = ((int)hdr[10])-'0';
57*37da2899SCharles.Forsyth if(ldepth<0 || ldepth>3){
58*37da2899SCharles.Forsyth kwerrstr("readimage: bad ldepth %d", ldepth);
59*37da2899SCharles.Forsyth return nil;
60*37da2899SCharles.Forsyth }
61*37da2899SCharles.Forsyth chan = drawld2chan[ldepth];
62*37da2899SCharles.Forsyth }
63*37da2899SCharles.Forsyth
64*37da2899SCharles.Forsyth r.min.x = atoi(hdr+1*12);
65*37da2899SCharles.Forsyth r.min.y = atoi(hdr+2*12);
66*37da2899SCharles.Forsyth r.max.x = atoi(hdr+3*12);
67*37da2899SCharles.Forsyth r.max.y = atoi(hdr+4*12);
68*37da2899SCharles.Forsyth if(r.min.x>r.max.x || r.min.y>r.max.y){
69*37da2899SCharles.Forsyth kwerrstr("readimage: bad rectangle");
70*37da2899SCharles.Forsyth return nil;
71*37da2899SCharles.Forsyth }
72*37da2899SCharles.Forsyth
73*37da2899SCharles.Forsyth miny = r.min.y;
74*37da2899SCharles.Forsyth maxy = r.max.y;
75*37da2899SCharles.Forsyth
76*37da2899SCharles.Forsyth l = bytesperline(r, chantodepth(chan));
77*37da2899SCharles.Forsyth if(dolock)
78*37da2899SCharles.Forsyth dolock = lockdisplay(d);
79*37da2899SCharles.Forsyth i = allocimage(d, r, chan, 0, -1);
80*37da2899SCharles.Forsyth if(dolock)
81*37da2899SCharles.Forsyth unlockdisplay(d);
82*37da2899SCharles.Forsyth if(i == nil)
83*37da2899SCharles.Forsyth return nil;
84*37da2899SCharles.Forsyth tmp = malloc(chunk);
85*37da2899SCharles.Forsyth if(tmp == nil)
86*37da2899SCharles.Forsyth goto Err;
87*37da2899SCharles.Forsyth while(maxy > miny){
88*37da2899SCharles.Forsyth dy = maxy - miny;
89*37da2899SCharles.Forsyth if(dy*l > chunk)
90*37da2899SCharles.Forsyth dy = chunk/l;
91*37da2899SCharles.Forsyth if(dy <= 0){
92*37da2899SCharles.Forsyth kwerrstr("readimage: image too wide for buffer");
93*37da2899SCharles.Forsyth goto Err;
94*37da2899SCharles.Forsyth }
95*37da2899SCharles.Forsyth n = dy*l;
96*37da2899SCharles.Forsyth m = libreadn(fd, tmp, n);
97*37da2899SCharles.Forsyth if(m != n){
98*37da2899SCharles.Forsyth kwerrstr("readimage: read count %d not %d: %r", m, n);
99*37da2899SCharles.Forsyth Err:
100*37da2899SCharles.Forsyth if(dolock)
101*37da2899SCharles.Forsyth lockdisplay(d);
102*37da2899SCharles.Forsyth Err1:
103*37da2899SCharles.Forsyth freeimage(i);
104*37da2899SCharles.Forsyth if(dolock)
105*37da2899SCharles.Forsyth unlockdisplay(d);
106*37da2899SCharles.Forsyth free(tmp);
107*37da2899SCharles.Forsyth return nil;
108*37da2899SCharles.Forsyth }
109*37da2899SCharles.Forsyth if(!new) /* an old image: must flip all the bits */
110*37da2899SCharles.Forsyth for(j=0; j<chunk; j++)
111*37da2899SCharles.Forsyth tmp[j] ^= 0xFF;
112*37da2899SCharles.Forsyth
113*37da2899SCharles.Forsyth if(dolock)
114*37da2899SCharles.Forsyth lockdisplay(d);
115*37da2899SCharles.Forsyth if(loadimage(i, Rect(r.min.x, miny, r.max.x, miny+dy), tmp, chunk) <= 0)
116*37da2899SCharles.Forsyth goto Err1;
117*37da2899SCharles.Forsyth if(dolock)
118*37da2899SCharles.Forsyth unlockdisplay(d);
119*37da2899SCharles.Forsyth miny += dy;
120*37da2899SCharles.Forsyth }
121*37da2899SCharles.Forsyth free(tmp);
122*37da2899SCharles.Forsyth return i;
123*37da2899SCharles.Forsyth }
124