Blame


1 28994509 2004-04-21 devnull #include <u.h>
2 28994509 2004-04-21 devnull #include <libc.h>
3 28994509 2004-04-21 devnull #include <bio.h>
4 28994509 2004-04-21 devnull #include <draw.h>
5 28994509 2004-04-21 devnull #include "imagefile.h"
6 28994509 2004-04-21 devnull #include "bmp.h"
7 28994509 2004-04-21 devnull
8 28994509 2004-04-21 devnull /*
9 28994509 2004-04-21 devnull MS-BMP file reader
10 28994509 2004-04-21 devnull (c) 2003, I.P.Keller
11 28994509 2004-04-21 devnull
12 28994509 2004-04-21 devnull aims to decode *all* valid bitmap formats, although some of the
13 28994509 2004-04-21 devnull flavours couldn't be verified due to lack of suitable test-files.
14 28994509 2004-04-21 devnull the following flavours are supported:
15 28994509 2004-04-21 devnull
16 28994509 2004-04-21 devnull Bit/Pix Orientation Compression Tested?
17 28994509 2004-04-21 devnull 1 top->bottom n/a yes
18 28994509 2004-04-21 devnull 1 bottom->top n/a yes
19 28994509 2004-04-21 devnull 4 top->bottom no yes
20 28994509 2004-04-21 devnull 4 bottom->top no yes
21 28994509 2004-04-21 devnull 4 top->bottom RLE4 yes, but not with displacement
22 28994509 2004-04-21 devnull 8 top->bottom no yes
23 28994509 2004-04-21 devnull 8 bottom->top no yes
24 28994509 2004-04-21 devnull 8 top->bottom RLE8 yes, but not with displacement
25 28994509 2004-04-21 devnull 16 top->bottom no no
26 28994509 2004-04-21 devnull 16 bottom->top no no
27 28994509 2004-04-21 devnull 16 top->bottom BITMASK no
28 28994509 2004-04-21 devnull 16 bottom->top BITMASK no
29 28994509 2004-04-21 devnull 24 top->bottom n/a yes
30 28994509 2004-04-21 devnull 24 bottom->top n/a yes
31 28994509 2004-04-21 devnull 32 top->bottom no no
32 28994509 2004-04-21 devnull 32 bottom->top no no
33 28994509 2004-04-21 devnull 32 top->bottom BITMASK no
34 28994509 2004-04-21 devnull 32 bottom->top BITMASK no
35 28994509 2004-04-21 devnull
36 28994509 2004-04-21 devnull OS/2 1.x bmp files are recognised as well, but testing was very limited.
37 28994509 2004-04-21 devnull
38 28994509 2004-04-21 devnull verifying was done with a number of test files, generated by
39 28994509 2004-04-21 devnull different tools. nevertheless, the tests were in no way exhaustive
40 28994509 2004-04-21 devnull enough to guarantee bug-free decoding. caveat emptor!
41 28994509 2004-04-21 devnull */
42 28994509 2004-04-21 devnull
43 28994509 2004-04-21 devnull static short
44 28994509 2004-04-21 devnull r16(Biobuf*b)
45 28994509 2004-04-21 devnull {
46 28994509 2004-04-21 devnull short s;
47 28994509 2004-04-21 devnull
48 28994509 2004-04-21 devnull s = Bgetc(b);
49 28994509 2004-04-21 devnull s |= ((short)Bgetc(b)) << 8;
50 28994509 2004-04-21 devnull return s;
51 28994509 2004-04-21 devnull }
52 28994509 2004-04-21 devnull
53 28994509 2004-04-21 devnull
54 28994509 2004-04-21 devnull static long
55 28994509 2004-04-21 devnull r32(Biobuf*b)
56 28994509 2004-04-21 devnull {
57 28994509 2004-04-21 devnull long l;
58 28994509 2004-04-21 devnull
59 28994509 2004-04-21 devnull l = Bgetc(b);
60 28994509 2004-04-21 devnull l |= ((long)Bgetc(b)) << 8;
61 28994509 2004-04-21 devnull l |= ((long)Bgetc(b)) << 16;
62 28994509 2004-04-21 devnull l |= ((long)Bgetc(b)) << 24;
63 28994509 2004-04-21 devnull return l;
64 28994509 2004-04-21 devnull }
65 28994509 2004-04-21 devnull
66 28994509 2004-04-21 devnull
67 28994509 2004-04-21 devnull /* get highest bit set */
68 28994509 2004-04-21 devnull static int
69 28994509 2004-04-21 devnull msb(ulong x)
70 28994509 2004-04-21 devnull {
71 28994509 2004-04-21 devnull int i;
72 28994509 2004-04-21 devnull for(i = 32; i; i--, x <<= 1)
73 28994509 2004-04-21 devnull if(x & 0x80000000L)
74 28994509 2004-04-21 devnull return i;
75 28994509 2004-04-21 devnull return 0;
76 28994509 2004-04-21 devnull }
77 28994509 2004-04-21 devnull
78 28994509 2004-04-21 devnull /* Load a 1-Bit encoded BMP file (uncompressed) */
79 28994509 2004-04-21 devnull static int
80 28994509 2004-04-21 devnull load_1T(Biobuf *b, long width, long height, Rgb* buf, Rgb* clut)
81 28994509 2004-04-21 devnull {
82 28994509 2004-04-21 devnull long ix, iy, i = 0, step_up = 0, padded_width = ((width + 31) / 32) * 32;
83 28994509 2004-04-21 devnull int val = 0, n;
84 28994509 2004-04-21 devnull
85 28994509 2004-04-21 devnull if(height > 0) { /* bottom-up */
86 28994509 2004-04-21 devnull i = (height - 1) * width;
87 28994509 2004-04-21 devnull step_up = -2 * width;
88 28994509 2004-04-21 devnull } else
89 28994509 2004-04-21 devnull height = -height;
90 28994509 2004-04-21 devnull
91 28994509 2004-04-21 devnull for(iy = height; iy; iy--, i += step_up)
92 28994509 2004-04-21 devnull for(ix = 0, n = 0; ix < padded_width; ix++, n--) {
93 28994509 2004-04-21 devnull if(!n) {
94 28994509 2004-04-21 devnull val = Bgetc(b);
95 28994509 2004-04-21 devnull n = 8;
96 28994509 2004-04-21 devnull }
97 28994509 2004-04-21 devnull if(ix < width) {
98 28994509 2004-04-21 devnull buf[i] = clut[val & 0x80 ? 1 : 0];
99 28994509 2004-04-21 devnull i++;
100 28994509 2004-04-21 devnull }
101 28994509 2004-04-21 devnull val <<= 1;
102 28994509 2004-04-21 devnull }
103 28994509 2004-04-21 devnull return 0;
104 28994509 2004-04-21 devnull }
105 28994509 2004-04-21 devnull
106 28994509 2004-04-21 devnull /* Load a 4-Bit encoded BMP file (uncompressed) */
107 28994509 2004-04-21 devnull static int
108 28994509 2004-04-21 devnull load_4T(Biobuf* b, long width, long height, Rgb* buf, Rgb* clut)
109 28994509 2004-04-21 devnull {
110 28994509 2004-04-21 devnull long ix, iy, i = 0, step_up = 0, skip = (4 - (((width % 8) + 1) / 2)) & 3;
111 28994509 2004-04-21 devnull uint valH, valL;
112 28994509 2004-04-21 devnull
113 28994509 2004-04-21 devnull if(height > 0) { /* bottom-up */
114 28994509 2004-04-21 devnull i = (height - 1) * width;
115 28994509 2004-04-21 devnull step_up = -2 * width;
116 28994509 2004-04-21 devnull } else
117 28994509 2004-04-21 devnull height = -height;
118 28994509 2004-04-21 devnull
119 28994509 2004-04-21 devnull for(iy = height; iy; iy--, i += step_up) {
120 28994509 2004-04-21 devnull for(ix = 0; ix < width; ) {
121 28994509 2004-04-21 devnull valH = valL = Bgetc(b) & 0xff;
122 28994509 2004-04-21 devnull valH >>= 4;
123 28994509 2004-04-21 devnull
124 28994509 2004-04-21 devnull buf[i] = clut[valH];
125 28994509 2004-04-21 devnull i++; ix++;
126 28994509 2004-04-21 devnull
127 28994509 2004-04-21 devnull if(ix < width) {
128 28994509 2004-04-21 devnull valL &= 0xf;
129 28994509 2004-04-21 devnull buf[i] = clut[valL];
130 28994509 2004-04-21 devnull i++; ix++;
131 28994509 2004-04-21 devnull }
132 28994509 2004-04-21 devnull }
133 28994509 2004-04-21 devnull Bseek(b, skip, 1);
134 28994509 2004-04-21 devnull }
135 28994509 2004-04-21 devnull return 0;
136 28994509 2004-04-21 devnull }
137 28994509 2004-04-21 devnull
138 28994509 2004-04-21 devnull /* Load a 4-Bit encoded BMP file (RLE4-compressed) */
139 28994509 2004-04-21 devnull static int
140 28994509 2004-04-21 devnull load_4C(Biobuf *b, long width, long height, Rgb* buf, Rgb* clut)
141 28994509 2004-04-21 devnull {
142 28994509 2004-04-21 devnull long ix, iy = height -1;
143 28994509 2004-04-21 devnull uint val, valS, skip;
144 28994509 2004-04-21 devnull Rgb* p;
145 28994509 2004-04-21 devnull
146 28994509 2004-04-21 devnull while(iy >= 0) {
147 28994509 2004-04-21 devnull ix = 0;
148 28994509 2004-04-21 devnull while(ix < width) {
149 28994509 2004-04-21 devnull val = Bgetc(b);
150 28994509 2004-04-21 devnull
151 28994509 2004-04-21 devnull if(0 != val) {
152 28994509 2004-04-21 devnull valS = (uint)Bgetc(b);
153 28994509 2004-04-21 devnull p = &buf[ix + iy * width];
154 28994509 2004-04-21 devnull while(val--) {
155 28994509 2004-04-21 devnull *p = clut[0xf & (valS >> 4)];
156 28994509 2004-04-21 devnull p++;
157 28994509 2004-04-21 devnull ix++;
158 28994509 2004-04-21 devnull if(0 < val) {
159 28994509 2004-04-21 devnull *p = clut[0xf & valS];
160 28994509 2004-04-21 devnull p++;
161 28994509 2004-04-21 devnull ix++;
162 28994509 2004-04-21 devnull val--;
163 28994509 2004-04-21 devnull }
164 28994509 2004-04-21 devnull }
165 28994509 2004-04-21 devnull } else {
166 28994509 2004-04-21 devnull /* Special modes... */
167 28994509 2004-04-21 devnull val = Bgetc(b);
168 28994509 2004-04-21 devnull switch(val) {
169 28994509 2004-04-21 devnull case 0: /* End-Of-Line detected */
170 28994509 2004-04-21 devnull ix = width;
171 28994509 2004-04-21 devnull iy--;
172 28994509 2004-04-21 devnull break;
173 28994509 2004-04-21 devnull case 1: /* End-Of-Picture detected -->> abort */
174 28994509 2004-04-21 devnull ix = width;
175 28994509 2004-04-21 devnull iy = -1;
176 28994509 2004-04-21 devnull break;
177 28994509 2004-04-21 devnull case 2: /* Position change detected */
178 28994509 2004-04-21 devnull val = Bgetc(b);
179 28994509 2004-04-21 devnull ix += val;
180 28994509 2004-04-21 devnull val = Bgetc(b);
181 28994509 2004-04-21 devnull iy -= val;
182 28994509 2004-04-21 devnull break;
183 28994509 2004-04-21 devnull
184 28994509 2004-04-21 devnull default:/* Transparent data sequence detected */
185 28994509 2004-04-21 devnull p = &buf[ix + iy * width];
186 28994509 2004-04-21 devnull if((1 == (val & 3)) || (2 == (val & 3)))
187 28994509 2004-04-21 devnull skip = 1;
188 28994509 2004-04-21 devnull else
189 28994509 2004-04-21 devnull skip = 0;
190 28994509 2004-04-21 devnull
191 28994509 2004-04-21 devnull while(val--) {
192 28994509 2004-04-21 devnull valS = (uint)Bgetc(b);
193 28994509 2004-04-21 devnull *p = clut[0xf & (valS >> 4)];
194 28994509 2004-04-21 devnull p++;
195 28994509 2004-04-21 devnull ix++;
196 28994509 2004-04-21 devnull if(0 < val) {
197 28994509 2004-04-21 devnull *p = clut[0xf & valS];
198 28994509 2004-04-21 devnull p++;
199 28994509 2004-04-21 devnull ix++;
200 28994509 2004-04-21 devnull val--;
201 28994509 2004-04-21 devnull }
202 28994509 2004-04-21 devnull }
203 28994509 2004-04-21 devnull if(skip)
204 28994509 2004-04-21 devnull Bgetc(b);
205 28994509 2004-04-21 devnull break;
206 28994509 2004-04-21 devnull }
207 28994509 2004-04-21 devnull }
208 28994509 2004-04-21 devnull }
209 28994509 2004-04-21 devnull }
210 28994509 2004-04-21 devnull return 0;
211 28994509 2004-04-21 devnull }
212 28994509 2004-04-21 devnull
213 28994509 2004-04-21 devnull /* Load a 8-Bit encoded BMP file (uncompressed) */
214 28994509 2004-04-21 devnull static int
215 28994509 2004-04-21 devnull load_8T(Biobuf *b, long width, long height, Rgb* buf, Rgb* clut)
216 28994509 2004-04-21 devnull {
217 28994509 2004-04-21 devnull long ix, iy, i = 0, step_up = 0, skip = (4 - (width % 4)) & 3;
218 28994509 2004-04-21 devnull
219 28994509 2004-04-21 devnull if(height > 0) { /* bottom-up */
220 28994509 2004-04-21 devnull i = (height - 1) * width;
221 28994509 2004-04-21 devnull step_up = -2 * width;
222 28994509 2004-04-21 devnull } else
223 28994509 2004-04-21 devnull height = -height;
224 28994509 2004-04-21 devnull
225 28994509 2004-04-21 devnull for(iy = height; iy; iy--, i += step_up) {
226 28994509 2004-04-21 devnull for(ix = 0; ix < width; ix++, i++)
227 28994509 2004-04-21 devnull buf[i] = clut[Bgetc(b) & 0xff];
228 28994509 2004-04-21 devnull Bseek(b, skip, 1);
229 28994509 2004-04-21 devnull }
230 28994509 2004-04-21 devnull return 0;
231 28994509 2004-04-21 devnull }
232 28994509 2004-04-21 devnull
233 28994509 2004-04-21 devnull /* Load a 8-Bit encoded BMP file (RLE8-compressed) */
234 28994509 2004-04-21 devnull static int
235 28994509 2004-04-21 devnull load_8C(Biobuf *b, long width, long height, Rgb* buf, Rgb* clut)
236 28994509 2004-04-21 devnull {
237 28994509 2004-04-21 devnull long ix, iy = height -1;
238 28994509 2004-04-21 devnull int val, valS, skip;
239 28994509 2004-04-21 devnull Rgb* p;
240 28994509 2004-04-21 devnull
241 28994509 2004-04-21 devnull while(iy >= 0) {
242 28994509 2004-04-21 devnull ix = 0;
243 28994509 2004-04-21 devnull while(ix < width) {
244 28994509 2004-04-21 devnull val = Bgetc(b);
245 28994509 2004-04-21 devnull
246 28994509 2004-04-21 devnull if(0 != val) {
247 28994509 2004-04-21 devnull valS = Bgetc(b);
248 28994509 2004-04-21 devnull p = &buf[ix + iy * width];
249 28994509 2004-04-21 devnull while(val--) {
250 28994509 2004-04-21 devnull *p = clut[valS];
251 28994509 2004-04-21 devnull p++;
252 28994509 2004-04-21 devnull ix++;
253 28994509 2004-04-21 devnull }
254 28994509 2004-04-21 devnull } else {
255 28994509 2004-04-21 devnull /* Special modes... */
256 28994509 2004-04-21 devnull val = Bgetc(b);
257 28994509 2004-04-21 devnull switch(val) {
258 28994509 2004-04-21 devnull case 0: /* End-Of-Line detected */
259 28994509 2004-04-21 devnull ix = width;
260 28994509 2004-04-21 devnull iy--;
261 28994509 2004-04-21 devnull break;
262 28994509 2004-04-21 devnull case 1: /* End-Of-Picture detected */
263 28994509 2004-04-21 devnull ix = width;
264 28994509 2004-04-21 devnull iy = -1;
265 28994509 2004-04-21 devnull break;
266 28994509 2004-04-21 devnull case 2: /* Position change detected */
267 28994509 2004-04-21 devnull val = Bgetc(b);
268 28994509 2004-04-21 devnull ix += val;
269 28994509 2004-04-21 devnull val = Bgetc(b);
270 28994509 2004-04-21 devnull iy -= val;
271 28994509 2004-04-21 devnull break;
272 28994509 2004-04-21 devnull default: /* Transparent (not compressed) sequence detected */
273 28994509 2004-04-21 devnull p = &buf[ix + iy * width];
274 28994509 2004-04-21 devnull if(val & 1)
275 28994509 2004-04-21 devnull skip = 1;
276 28994509 2004-04-21 devnull else
277 28994509 2004-04-21 devnull skip = 0;
278 28994509 2004-04-21 devnull
279 28994509 2004-04-21 devnull while(val--) {
280 28994509 2004-04-21 devnull valS = Bgetc(b);
281 28994509 2004-04-21 devnull *p = clut[valS];
282 28994509 2004-04-21 devnull p++;
283 28994509 2004-04-21 devnull ix++;
284 28994509 2004-04-21 devnull }
285 28994509 2004-04-21 devnull if(skip)
286 28994509 2004-04-21 devnull /* Align data stream */
287 28994509 2004-04-21 devnull Bgetc(b);
288 28994509 2004-04-21 devnull break;
289 28994509 2004-04-21 devnull }
290 28994509 2004-04-21 devnull }
291 28994509 2004-04-21 devnull }
292 28994509 2004-04-21 devnull }
293 28994509 2004-04-21 devnull return 0;
294 28994509 2004-04-21 devnull }
295 28994509 2004-04-21 devnull
296 28994509 2004-04-21 devnull /* Load a 16-Bit encoded BMP file (uncompressed) */
297 28994509 2004-04-21 devnull static int
298 28994509 2004-04-21 devnull load_16(Biobuf *b, long width, long height, Rgb* buf, Rgb* clut)
299 28994509 2004-04-21 devnull {
300 28994509 2004-04-21 devnull uchar c[2];
301 28994509 2004-04-21 devnull long ix, iy, i = 0, step_up = 0;
302 28994509 2004-04-21 devnull
303 28994509 2004-04-21 devnull if(height > 0) { /* bottom-up */
304 28994509 2004-04-21 devnull i = (height - 1) * width;
305 28994509 2004-04-21 devnull step_up = -2 * width;
306 28994509 2004-04-21 devnull } else
307 28994509 2004-04-21 devnull height = -height;
308 28994509 2004-04-21 devnull
309 28994509 2004-04-21 devnull if(clut) {
310 28994509 2004-04-21 devnull unsigned mask_blue = (unsigned)clut[0].blue +
311 28994509 2004-04-21 devnull ((unsigned)clut[0].green << 8);
312 28994509 2004-04-21 devnull unsigned mask_green = (unsigned)clut[1].blue +
313 28994509 2004-04-21 devnull ((unsigned)clut[1].green << 8);
314 28994509 2004-04-21 devnull unsigned mask_red = (unsigned)clut[2].blue +
315 28994509 2004-04-21 devnull ((unsigned)clut[2].green << 8);
316 28994509 2004-04-21 devnull int shft_blue = msb((ulong)mask_blue) - 8;
317 28994509 2004-04-21 devnull int shft_green = msb((ulong)mask_green) - 8;
318 28994509 2004-04-21 devnull int shft_red = msb((ulong)mask_red) - 8;
319 28994509 2004-04-21 devnull
320 28994509 2004-04-21 devnull for(iy = height; iy; iy--, i += step_up)
321 28994509 2004-04-21 devnull for(ix = 0; ix < width; ix++, i++) {
322 28994509 2004-04-21 devnull unsigned val;
323 28994509 2004-04-21 devnull Bread(b, c, sizeof(c));
324 28994509 2004-04-21 devnull val = (unsigned)c[0] + ((unsigned)c[1] << 8);
325 28994509 2004-04-21 devnull
326 28994509 2004-04-21 devnull buf[i].alpha = 0;
327 28994509 2004-04-21 devnull if(shft_blue >= 0)
328 28994509 2004-04-21 devnull buf[i].blue = (uchar)((val & mask_blue) >> shft_blue);
329 28994509 2004-04-21 devnull else
330 28994509 2004-04-21 devnull buf[i].blue = (uchar)((val & mask_blue) << -shft_blue);
331 28994509 2004-04-21 devnull if(shft_green >= 0)
332 28994509 2004-04-21 devnull buf[i].green = (uchar)((val & mask_green) >> shft_green);
333 28994509 2004-04-21 devnull else
334 28994509 2004-04-21 devnull buf[i].green = (uchar)((val & mask_green) << -shft_green);
335 28994509 2004-04-21 devnull if(shft_red >= 0)
336 28994509 2004-04-21 devnull buf[i].red = (uchar)((val & mask_red) >> shft_red);
337 28994509 2004-04-21 devnull else
338 28994509 2004-04-21 devnull buf[i].red = (uchar)((val & mask_red) << -shft_red);
339 28994509 2004-04-21 devnull }
340 28994509 2004-04-21 devnull } else
341 28994509 2004-04-21 devnull for(iy = height; iy; iy--, i += step_up)
342 28994509 2004-04-21 devnull for(ix = 0; ix < width; ix++, i++) {
343 28994509 2004-04-21 devnull Bread(b, c, sizeof(c));
344 28994509 2004-04-21 devnull buf[i].blue = (uchar)((c[0] << 3) & 0xf8);
345 28994509 2004-04-21 devnull buf[i].green = (uchar)(((((unsigned)c[1] << 6) +
346 28994509 2004-04-21 devnull (((unsigned)c[0]) >> 2))) & 0xf8);
347 28994509 2004-04-21 devnull buf[i].red = (uchar)((c[1] << 1) & 0xf8);
348 28994509 2004-04-21 devnull }
349 28994509 2004-04-21 devnull return 0;
350 28994509 2004-04-21 devnull }
351 28994509 2004-04-21 devnull
352 28994509 2004-04-21 devnull /* Load a 24-Bit encoded BMP file (uncompressed) */
353 28994509 2004-04-21 devnull static int
354 28994509 2004-04-21 devnull load_24T(Biobuf* b, long width, long height, Rgb* buf)
355 28994509 2004-04-21 devnull {
356 28994509 2004-04-21 devnull long ix, iy, i = 0, step_up = 0, skip = (4 - ((width * 3) % 4)) & 3;
357 28994509 2004-04-21 devnull
358 28994509 2004-04-21 devnull if(height > 0) { /* bottom-up */
359 28994509 2004-04-21 devnull i = (height - 1) * width;
360 28994509 2004-04-21 devnull step_up = -2 * width;
361 28994509 2004-04-21 devnull } else
362 28994509 2004-04-21 devnull height = -height;
363 28994509 2004-04-21 devnull
364 28994509 2004-04-21 devnull for(iy = height; iy; iy--, i += step_up) {
365 28994509 2004-04-21 devnull for(ix = 0; ix < width; ix++, i++) {
366 28994509 2004-04-21 devnull buf[i].alpha = 0;
367 28994509 2004-04-21 devnull buf[i].blue = Bgetc(b);
368 28994509 2004-04-21 devnull buf[i].green = Bgetc(b);
369 28994509 2004-04-21 devnull buf[i].red = Bgetc(b);
370 28994509 2004-04-21 devnull }
371 28994509 2004-04-21 devnull Bseek(b, skip, 1);
372 28994509 2004-04-21 devnull }
373 28994509 2004-04-21 devnull return 0;
374 28994509 2004-04-21 devnull }
375 28994509 2004-04-21 devnull
376 28994509 2004-04-21 devnull /* Load a 32-Bit encoded BMP file (uncompressed) */
377 28994509 2004-04-21 devnull static int
378 28994509 2004-04-21 devnull load_32(Biobuf *b, long width, long height, Rgb* buf, Rgb* clut)
379 28994509 2004-04-21 devnull {
380 28994509 2004-04-21 devnull uchar c[4];
381 28994509 2004-04-21 devnull long ix, iy, i = 0, step_up = 0;
382 28994509 2004-04-21 devnull
383 28994509 2004-04-21 devnull if(height > 0) { /* bottom-up */
384 28994509 2004-04-21 devnull i = (height - 1) * width;
385 28994509 2004-04-21 devnull step_up = -2 * width;
386 28994509 2004-04-21 devnull } else
387 28994509 2004-04-21 devnull height = -height;
388 28994509 2004-04-21 devnull
389 28994509 2004-04-21 devnull if(clut) {
390 28994509 2004-04-21 devnull ulong mask_blue = (ulong)clut[0].blue +
391 28994509 2004-04-21 devnull ((ulong)clut[0].green << 8) +
392 28994509 2004-04-21 devnull ((ulong)clut[0].red << 16) +
393 28994509 2004-04-21 devnull ((ulong)clut[0].alpha << 24);
394 28994509 2004-04-21 devnull ulong mask_green = (ulong)clut[1].blue +
395 28994509 2004-04-21 devnull ((ulong)clut[1].green << 8) +
396 28994509 2004-04-21 devnull ((ulong)clut[1].red << 16) +
397 28994509 2004-04-21 devnull ((ulong)clut[1].alpha << 24);
398 28994509 2004-04-21 devnull ulong mask_red = (ulong)clut[2].blue +
399 28994509 2004-04-21 devnull ((ulong)clut[2].green << 8) +
400 28994509 2004-04-21 devnull ((ulong)clut[2].red << 16) +
401 28994509 2004-04-21 devnull ((ulong)clut[2].alpha << 24);
402 28994509 2004-04-21 devnull int shft_blue = msb(mask_blue) - 8;
403 28994509 2004-04-21 devnull int shft_green = msb(mask_green) - 8;
404 28994509 2004-04-21 devnull int shft_red = msb(mask_red) - 8;
405 28994509 2004-04-21 devnull
406 28994509 2004-04-21 devnull for(iy = height; iy; iy--, i += step_up)
407 28994509 2004-04-21 devnull for(ix = 0; ix < width; ix++, i++) {
408 28994509 2004-04-21 devnull ulong val;
409 28994509 2004-04-21 devnull Bread(b, c, sizeof(c));
410 28994509 2004-04-21 devnull val = (ulong)c[0] + ((ulong)c[1] << 8) +
411 28994509 2004-04-21 devnull ((ulong)c[2] << 16) + ((ulong)c[1] << 24);
412 28994509 2004-04-21 devnull
413 28994509 2004-04-21 devnull buf[i].alpha = 0;
414 28994509 2004-04-21 devnull if(shft_blue >= 0)
415 28994509 2004-04-21 devnull buf[i].blue = (uchar)((val & mask_blue) >> shft_blue);
416 28994509 2004-04-21 devnull else
417 28994509 2004-04-21 devnull buf[i].blue = (uchar)((val & mask_blue) << -shft_blue);
418 28994509 2004-04-21 devnull if(shft_green >= 0)
419 28994509 2004-04-21 devnull buf[i].green = (uchar)((val & mask_green) >> shft_green);
420 28994509 2004-04-21 devnull else
421 28994509 2004-04-21 devnull buf[i].green = (uchar)((val & mask_green) << -shft_green);
422 28994509 2004-04-21 devnull if(shft_red >= 0)
423 28994509 2004-04-21 devnull buf[i].red = (uchar)((val & mask_red) >> shft_red);
424 28994509 2004-04-21 devnull else
425 28994509 2004-04-21 devnull buf[i].red = (uchar)((val & mask_red) << -shft_red);
426 28994509 2004-04-21 devnull }
427 28994509 2004-04-21 devnull } else
428 28994509 2004-04-21 devnull for(iy = height; iy; iy--, i += step_up)
429 28994509 2004-04-21 devnull for(ix = 0; ix < width; ix++, i++) {
430 28994509 2004-04-21 devnull Bread(b, c, nelem(c));
431 28994509 2004-04-21 devnull buf[i].blue = c[0];
432 28994509 2004-04-21 devnull buf[i].green = c[1];
433 28994509 2004-04-21 devnull buf[i].red = c[2];
434 28994509 2004-04-21 devnull }
435 28994509 2004-04-21 devnull return 0;
436 28994509 2004-04-21 devnull }
437 28994509 2004-04-21 devnull
438 28994509 2004-04-21 devnull
439 28994509 2004-04-21 devnull static Rgb*
440 28994509 2004-04-21 devnull ReadBMP(Biobuf *b, int *width, int *height)
441 28994509 2004-04-21 devnull {
442 28994509 2004-04-21 devnull int colours, num_coltab = 0;
443 28994509 2004-04-21 devnull Filehdr bmfh;
444 28994509 2004-04-21 devnull Infohdr bmih;
445 28994509 2004-04-21 devnull Rgb clut[256];
446 28994509 2004-04-21 devnull Rgb* buf;
447 28994509 2004-04-21 devnull
448 28994509 2004-04-21 devnull bmfh.type = r16(b);
449 28994509 2004-04-21 devnull if(bmfh.type != 0x4d42) /* signature must be 'BM' */
450 28994509 2004-04-21 devnull sysfatal("bad magic number, not a BMP file");
451 28994509 2004-04-21 devnull
452 28994509 2004-04-21 devnull bmfh.size = r32(b);
453 28994509 2004-04-21 devnull bmfh.reserved1 = r16(b);
454 28994509 2004-04-21 devnull bmfh.reserved2 = r16(b);
455 28994509 2004-04-21 devnull bmfh.offbits = r32(b);
456 28994509 2004-04-21 devnull
457 28994509 2004-04-21 devnull memset(&bmih, 0, sizeof(bmih));
458 28994509 2004-04-21 devnull bmih.size = r32(b);
459 28994509 2004-04-21 devnull
460 28994509 2004-04-21 devnull if(bmih.size == 0x0c) { /* OS/2 1.x version */
461 28994509 2004-04-21 devnull bmih.width = r16(b);
462 28994509 2004-04-21 devnull bmih.height = r16(b);
463 28994509 2004-04-21 devnull bmih.planes = r16(b);
464 28994509 2004-04-21 devnull bmih.bpp = r16(b);
465 28994509 2004-04-21 devnull bmih.compression = BMP_RGB;
466 28994509 2004-04-21 devnull } else { /* Windows */
467 28994509 2004-04-21 devnull bmih.width = r32(b);
468 28994509 2004-04-21 devnull bmih.height = r32(b);
469 28994509 2004-04-21 devnull bmih.planes = r16(b);
470 28994509 2004-04-21 devnull bmih.bpp = r16(b);
471 28994509 2004-04-21 devnull bmih.compression = r32(b);
472 28994509 2004-04-21 devnull bmih.imagesize = r32(b);
473 28994509 2004-04-21 devnull bmih.hres = r32(b);
474 28994509 2004-04-21 devnull bmih.vres = r32(b);
475 28994509 2004-04-21 devnull bmih.colours = r32(b);
476 28994509 2004-04-21 devnull bmih.impcolours = r32(b);
477 28994509 2004-04-21 devnull }
478 28994509 2004-04-21 devnull
479 28994509 2004-04-21 devnull if(bmih.bpp < 16) {
480 28994509 2004-04-21 devnull /* load colour table */
481 28994509 2004-04-21 devnull if(bmih.impcolours)
482 28994509 2004-04-21 devnull num_coltab = (int)bmih.impcolours;
483 28994509 2004-04-21 devnull else
484 28994509 2004-04-21 devnull num_coltab = 1 << bmih.bpp;
485 28994509 2004-04-21 devnull } else if(bmih.compression == BMP_BITFIELDS &&
486 28994509 2004-04-21 devnull (bmih.bpp == 16 || bmih.bpp == 32))
487 28994509 2004-04-21 devnull /* load bitmasks */
488 28994509 2004-04-21 devnull num_coltab = 3;
489 28994509 2004-04-21 devnull
490 28994509 2004-04-21 devnull if(num_coltab) {
491 28994509 2004-04-21 devnull int i;
492 28994509 2004-04-21 devnull Bseek(b, bmih.size + sizeof(Infohdr), 0);
493 28994509 2004-04-21 devnull
494 28994509 2004-04-21 devnull for(i = 0; i < num_coltab; i++) {
495 28994509 2004-04-21 devnull clut[i].blue = (uchar)Bgetc(b);
496 28994509 2004-04-21 devnull clut[i].green = (uchar)Bgetc(b);
497 28994509 2004-04-21 devnull clut[i].red = (uchar)Bgetc(b);
498 28994509 2004-04-21 devnull clut[i].alpha = (uchar)Bgetc(b);
499 28994509 2004-04-21 devnull }
500 28994509 2004-04-21 devnull }
501 28994509 2004-04-21 devnull
502 28994509 2004-04-21 devnull *width = bmih.width;
503 28994509 2004-04-21 devnull *height = bmih.height;
504 28994509 2004-04-21 devnull colours = bmih.bpp;
505 28994509 2004-04-21 devnull
506 28994509 2004-04-21 devnull Bseek(b, bmfh.offbits, 0);
507 28994509 2004-04-21 devnull
508 28994509 2004-04-21 devnull if ((buf = calloc(sizeof(Rgb), *width * abs(*height))) == nil)
509 28994509 2004-04-21 devnull sysfatal("no memory");
510 28994509 2004-04-21 devnull
511 28994509 2004-04-21 devnull switch(colours) {
512 28994509 2004-04-21 devnull case 1:
513 28994509 2004-04-21 devnull load_1T(b, *width, *height, buf, clut);
514 28994509 2004-04-21 devnull break;
515 28994509 2004-04-21 devnull case 4:
516 28994509 2004-04-21 devnull if(bmih.compression == BMP_RLE4)
517 28994509 2004-04-21 devnull load_4C(b, *width, *height, buf, clut);
518 28994509 2004-04-21 devnull else
519 28994509 2004-04-21 devnull load_4T(b, *width, *height, buf, clut);
520 28994509 2004-04-21 devnull break;
521 28994509 2004-04-21 devnull case 8:
522 28994509 2004-04-21 devnull if(bmih.compression == BMP_RLE8)
523 28994509 2004-04-21 devnull load_8C(b, *width, *height, buf, clut);
524 28994509 2004-04-21 devnull else
525 28994509 2004-04-21 devnull load_8T(b, *width, *height, buf, clut);
526 28994509 2004-04-21 devnull break;
527 28994509 2004-04-21 devnull case 16:
528 28994509 2004-04-21 devnull load_16(b, *width, *height, buf,
529 28994509 2004-04-21 devnull bmih.compression == BMP_BITFIELDS ? clut : nil);
530 28994509 2004-04-21 devnull break;
531 28994509 2004-04-21 devnull case 24:
532 28994509 2004-04-21 devnull load_24T(b, *width, *height, buf);
533 28994509 2004-04-21 devnull break;
534 28994509 2004-04-21 devnull case 32:
535 28994509 2004-04-21 devnull load_32(b, *width, *height, buf,
536 28994509 2004-04-21 devnull bmih.compression == BMP_BITFIELDS ? clut : nil);
537 28994509 2004-04-21 devnull break;
538 28994509 2004-04-21 devnull }
539 28994509 2004-04-21 devnull return buf;
540 28994509 2004-04-21 devnull }
541 28994509 2004-04-21 devnull
542 28994509 2004-04-21 devnull Rawimage**
543 28994509 2004-04-21 devnull Breadbmp(Biobuf *bp, int colourspace)
544 28994509 2004-04-21 devnull {
545 28994509 2004-04-21 devnull Rawimage *a, **array;
546 28994509 2004-04-21 devnull int c, width, height;
547 28994509 2004-04-21 devnull uchar *r, *g, *b;
548 28994509 2004-04-21 devnull Rgb *s, *e;
549 28994509 2004-04-21 devnull Rgb *bmp;
550 28994509 2004-04-21 devnull char ebuf[128];
551 28994509 2004-04-21 devnull
552 28994509 2004-04-21 devnull a = nil;
553 28994509 2004-04-21 devnull bmp = nil;
554 28994509 2004-04-21 devnull array = nil;
555 28994509 2004-04-21 devnull USED(a);
556 28994509 2004-04-21 devnull USED(bmp);
557 28994509 2004-04-21 devnull if (colourspace != CRGB) {
558 28994509 2004-04-21 devnull errstr(ebuf, sizeof ebuf); /* throw it away */
559 28994509 2004-04-21 devnull werrstr("ReadRGB: unknown colour space %d", colourspace);
560 28994509 2004-04-21 devnull return nil;
561 28994509 2004-04-21 devnull }
562 28994509 2004-04-21 devnull
563 28994509 2004-04-21 devnull if ((bmp = ReadBMP(bp, &width, &height)) == nil)
564 28994509 2004-04-21 devnull return nil;
565 28994509 2004-04-21 devnull
566 28994509 2004-04-21 devnull if ((a = calloc(sizeof(Rawimage), 1)) == nil)
567 28994509 2004-04-21 devnull goto Error;
568 28994509 2004-04-21 devnull
569 28994509 2004-04-21 devnull for (c = 0; c < 3; c++)
570 28994509 2004-04-21 devnull if ((a->chans[c] = calloc(width, height)) == nil)
571 28994509 2004-04-21 devnull goto Error;
572 28994509 2004-04-21 devnull
573 28994509 2004-04-21 devnull if ((array = calloc(sizeof(Rawimage *), 2)) == nil)
574 28994509 2004-04-21 devnull goto Error;
575 28994509 2004-04-21 devnull array[0] = a;
576 28994509 2004-04-21 devnull array[1] = nil;
577 28994509 2004-04-21 devnull
578 28994509 2004-04-21 devnull a->nchans = 3;
579 28994509 2004-04-21 devnull a->chandesc = CRGB;
580 28994509 2004-04-21 devnull a->chanlen = width * height;
581 28994509 2004-04-21 devnull a->r = Rect(0, 0, width, height);
582 28994509 2004-04-21 devnull
583 28994509 2004-04-21 devnull s = bmp;
584 28994509 2004-04-21 devnull e = s + width * height;
585 28994509 2004-04-21 devnull r = a->chans[0];
586 28994509 2004-04-21 devnull g = a->chans[1];
587 28994509 2004-04-21 devnull b = a->chans[2];
588 28994509 2004-04-21 devnull
589 28994509 2004-04-21 devnull do {
590 28994509 2004-04-21 devnull *r++ = s->red;
591 28994509 2004-04-21 devnull *g++ = s->green;
592 28994509 2004-04-21 devnull *b++ = s->blue;
593 28994509 2004-04-21 devnull }while(++s < e);
594 28994509 2004-04-21 devnull
595 28994509 2004-04-21 devnull free(bmp);
596 28994509 2004-04-21 devnull return array;
597 28994509 2004-04-21 devnull
598 28994509 2004-04-21 devnull Error:
599 28994509 2004-04-21 devnull if (a)
600 28994509 2004-04-21 devnull for (c = 0; c < 3; c++)
601 28994509 2004-04-21 devnull if (a->chans[c])
602 28994509 2004-04-21 devnull free(a->chans[c]);
603 28994509 2004-04-21 devnull if (a)
604 28994509 2004-04-21 devnull free(a);
605 28994509 2004-04-21 devnull if (array)
606 28994509 2004-04-21 devnull free(array);
607 28994509 2004-04-21 devnull if (bmp)
608 28994509 2004-04-21 devnull free(bmp);
609 28994509 2004-04-21 devnull return nil;
610 28994509 2004-04-21 devnull
611 28994509 2004-04-21 devnull }
612 28994509 2004-04-21 devnull
613 28994509 2004-04-21 devnull Rawimage**
614 28994509 2004-04-21 devnull readbmp(int fd, int colorspace)
615 28994509 2004-04-21 devnull {
616 28994509 2004-04-21 devnull Rawimage * *a;
617 28994509 2004-04-21 devnull Biobuf b;
618 28994509 2004-04-21 devnull
619 28994509 2004-04-21 devnull if (Binit(&b, fd, OREAD) < 0)
620 28994509 2004-04-21 devnull return nil;
621 28994509 2004-04-21 devnull a = Breadbmp(&b, colorspace);
622 28994509 2004-04-21 devnull Bterm(&b);
623 28994509 2004-04-21 devnull return a;
624 28994509 2004-04-21 devnull }
625 28994509 2004-04-21 devnull
626 28994509 2004-04-21 devnull