Blob


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