treadimage.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
treadimage.c (2432B) | |
--- | |
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 u32int 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 hea… | |
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(d){ | |
76 if(dolock) | |
77 lockdisplay(d); | |
78 i = allocimage(d, r, chan, 0, -1); | |
79 if(dolock) | |
80 unlockdisplay(d); | |
81 if(i == nil) | |
82 return nil; | |
83 }else{ | |
84 i = mallocz(sizeof(Image), 1); | |
85 if(i == nil) | |
86 return nil; | |
87 } | |
88 | |
89 tmp = malloc(chunk); | |
90 if(tmp == nil) | |
91 goto Err; | |
92 while(maxy > miny){ | |
93 dy = maxy - miny; | |
94 if(dy*l > chunk) | |
95 dy = chunk/l; | |
96 if(dy <= 0){ | |
97 werrstr("readimage: image too wide for buffer"); | |
98 goto Err; | |
99 } | |
100 n = dy*l; | |
101 m = readn(fd, tmp, n); | |
102 if(m != n){ | |
103 werrstr("readimage: read count %d not %d: %r", m… | |
104 Err: | |
105 if(dolock) | |
106 lockdisplay(d); | |
107 Err1: | |
108 freeimage(i); | |
109 if(dolock) | |
110 unlockdisplay(d); | |
111 free(tmp); | |
112 return nil; | |
113 } | |
114 if(!new) /* an old image: must flip all the bits … | |
115 for(j=0; j<chunk; j++) | |
116 tmp[j] ^= 0xFF; | |
117 | |
118 if(d){ | |
119 if(dolock) | |
120 lockdisplay(d); | |
121 if(loadimage(i, Rect(r.min.x, miny, r.max.x, min… | |
122 goto Err1; | |
123 if(dolock) | |
124 unlockdisplay(d); | |
125 } | |
126 miny += dy; | |
127 } | |
128 free(tmp); | |
129 return i; | |
130 } |