]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libmemdraw/read.c
kernel: cleanup makefile for $CONF.$O target
[plan9front.git] / sys / src / libmemdraw / read.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5
6 Memimage*
7 readmemimage(int fd)
8 {
9         char hdr[5*12+1];
10         int dy;
11         ulong chan;
12         uint l, n;
13         int m, j;
14         int new, miny, maxy;
15         Rectangle r;
16         uchar *tmp;
17         int ldepth, chunk;
18         Memimage *i;
19
20         if(readn(fd, hdr, 11) != 11){
21                 werrstr("readimage: short header");
22                 return nil;
23         }
24         if(memcmp(hdr, "compressed\n", 11) == 0)
25                 return creadmemimage(fd);
26         if(readn(fd, hdr+11, 5*12-11) != 5*12-11){
27                 werrstr("readimage: short header (2)");
28                 return nil;
29         }
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         i = allocmemimage(r, chan);
76         if(i == nil)
77                 return nil;
78         chunk = 32*1024;
79         if(chunk < l)
80                 chunk = l;
81         tmp = malloc(chunk);
82         if(tmp == nil)
83                 goto Err;
84         while(maxy > miny){
85                 dy = maxy - miny;
86                 if(dy*l > chunk)
87                         dy = chunk/l;
88                 n = dy*l;
89                 m = readn(fd, tmp, n);
90                 if(m != n){
91                         werrstr("readmemimage: read count %d not %d: %r", m, n);
92    Err:
93                         freememimage(i);
94                         free(tmp);
95                         return nil;
96                 }
97                 if(!new)        /* an old image: must flip all the bits */
98                         for(j=0; j<chunk; j++)
99                                 tmp[j] ^= 0xFF;
100
101                 if(loadmemimage(i, Rect(r.min.x, miny, r.max.x, miny+dy), tmp, chunk) <= 0)
102                         goto Err;
103                 miny += dy;
104         }
105         free(tmp);
106         return i;
107 }