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