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