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