]> git.ipfire.org Git - thirdparty/cups.git/blob - filter/image-bmp.c
Import cups.org releases
[thirdparty/cups.git] / filter / image-bmp.c
1 /*
2 * "$Id$"
3 *
4 * BMP image routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1993-2001 by Easy Software Products.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
19 *
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
26 * ImageReadBMP() - Read a BMP image file.
27 * read_word() - Read a 16-bit unsigned integer.
28 * read_dword() - Read a 32-bit unsigned integer.
29 * read_long() - Read a 32-bit signed integer.
30 */
31
32 /*
33 * Include necessary headers...
34 */
35
36 #include "image.h"
37
38
39 /*
40 * Constants for the bitmap compression...
41 */
42
43 # define BI_RGB 0 /* No compression - straight BGR data */
44 # define BI_RLE8 1 /* 8-bit run-length compression */
45 # define BI_RLE4 2 /* 4-bit run-length compression */
46 # define BI_BITFIELDS 3 /* RGB bitmap with RGB masks */
47
48
49 /*
50 * Local functions...
51 */
52
53 static unsigned short read_word(FILE *fp);
54 static unsigned int read_dword(FILE *fp);
55 static int read_long(FILE *fp);
56
57
58 /*
59 * 'ImageReadBMP()' - Read a BMP image file.
60 */
61
62 int /* O - Read status */
63 ImageReadBMP(image_t *img, /* IO - Image */
64 FILE *fp, /* I - Image file */
65 int primary, /* I - Primary choice for colorspace */
66 int secondary, /* I - Secondary choice for colorspace */
67 int saturation, /* I - Color saturation (%) */
68 int hue, /* I - Color hue (degrees) */
69 const ib_t *lut) /* I - Lookup table for gamma/brightness */
70 {
71 int offset, /* Offset to bitmap data */
72 info_size, /* Size of info header */
73 planes, /* Number of planes (always 1) */
74 depth, /* Depth of image (bits) */
75 compression, /* Type of compression */
76 image_size, /* Size of image in bytes */
77 colors_used, /* Number of colors used */
78 colors_important, /* Number of important colors */
79 bpp, /* Bytes per pixel */
80 x, y, /* Looping vars */
81 color, /* Color of RLE pixel */
82 count, /* Number of times to repeat */
83 temp, /* Temporary color */
84 align; /* Alignment bytes */
85 ib_t bit, /* Bit in image */
86 byte; /* Byte in image */
87 ib_t *in, /* Input pixels */
88 *out, /* Output pixels */
89 *ptr; /* Pointer into pixels */
90 ib_t colormap[256][4]; /* Colormap */
91
92
93 (void)secondary;
94
95 /*
96 * Get the header...
97 */
98
99 getc(fp); /* Skip "BM" sync chars */
100 getc(fp);
101 read_dword(fp); /* Skip size */
102 read_word(fp); /* Skip reserved stuff */
103 read_word(fp);
104 offset = read_dword(fp);
105
106 fprintf(stderr, "offset = %d\n", offset);
107
108 /*
109 * Then the bitmap information...
110 */
111
112 info_size = read_dword(fp);
113 img->xsize = read_long(fp);
114 img->ysize = read_long(fp);
115 planes = read_word(fp);
116 depth = read_word(fp);
117 compression = read_dword(fp);
118 image_size = read_dword(fp);
119 img->xppi = read_long(fp) * 0.0254 + 0.5;
120 img->yppi = read_long(fp) * 0.0254 + 0.5;
121 colors_used = read_dword(fp);
122 colors_important = read_dword(fp);
123
124 /*
125 * Make sure the resolution info is valid...
126 */
127
128 if (img->xppi == 0)
129 img->xppi = 128;
130 if (img->yppi == 0)
131 img->yppi = 128;
132
133 fprintf(stderr, "info_size = %d, xsize = %d, ysize = %d, planes = %d, depth = %d\n",
134 info_size, img->xsize, img->ysize, planes, depth);
135 fprintf(stderr, "compression = %d, image_size = %d, xppi = %d, yppi = %d\n",
136 compression, image_size, img->xppi, img->yppi);
137 fprintf(stderr, "colors_used = %d, colors_important = %d\n", colors_used,
138 colors_important);
139
140 if (info_size > 40)
141 for (info_size -= 40; info_size > 0; info_size --)
142 getc(fp);
143
144 /*
145 * Get colormap...
146 */
147
148 if (colors_used == 0 && depth <= 8)
149 colors_used = 1 << depth;
150
151 fread(colormap, colors_used, 4, fp);
152
153 /*
154 * Setup image and buffers...
155 */
156
157 img->colorspace = primary;
158
159 ImageSetMaxTiles(img, 0);
160
161 in = malloc(img->xsize * 3);
162 bpp = ImageGetDepth(img);
163 out = malloc(img->xsize * bpp);
164
165 /*
166 * Read the image data...
167 */
168
169 color = 0;
170 count = 0;
171 align = 0;
172
173 for (y = img->ysize - 1; y >= 0; y --)
174 {
175 if (img->colorspace == IMAGE_RGB)
176 ptr = out;
177 else
178 ptr = in;
179
180 switch (depth)
181 {
182 case 1 : /* Bitmap */
183 for (x = img->xsize, bit = 128, byte = 0; x > 0; x --)
184 {
185 if (bit == 128)
186 byte = getc(fp);
187
188 if (byte & bit)
189 {
190 *ptr++ = colormap[1][2];
191 *ptr++ = colormap[1][1];
192 *ptr++ = colormap[1][0];
193 }
194 else
195 {
196 *ptr++ = colormap[0][2];
197 *ptr++ = colormap[0][1];
198 *ptr++ = colormap[0][0];
199 }
200
201 if (bit > 1)
202 bit >>= 1;
203 else
204 bit = 128;
205 }
206
207 /*
208 * Read remaining bytes to align to 32 bits...
209 */
210
211 for (temp = (img->xsize + 7) / 8; temp & 3; temp ++)
212 getc(fp);
213 break;
214
215 case 4 : /* 16-color */
216 for (x = img->xsize, bit = 0xf0, temp = 0; x > 0; x --)
217 {
218 /*
219 * Get a new count as needed...
220 */
221
222 if (compression != BI_RLE4 && count == 0)
223 {
224 count = 2;
225 color = -1;
226 }
227
228 if (count == 0)
229 {
230 while (align > 0)
231 {
232 align --;
233 getc(fp);
234 }
235
236 if ((count = getc(fp)) == 0)
237 {
238 if ((count = getc(fp)) == 0)
239 {
240 /*
241 * End of line...
242 */
243
244 x ++;
245 continue;
246 }
247 else if (count == 1)
248 {
249 /*
250 * End of image...
251 */
252
253 break;
254 }
255 else if (count == 2)
256 {
257 /*
258 * Delta...
259 */
260
261 count = getc(fp) * getc(fp) * img->xsize;
262 color = 0;
263 }
264 else
265 {
266 /*
267 * Absolute...
268 */
269
270 color = -1;
271 align = ((4 - (count & 3)) / 2) & 1;
272 }
273 }
274 else
275 color = getc(fp);
276 }
277
278 /*
279 * Get a new color as needed...
280 */
281
282 count --;
283
284 if (bit == 0xf0)
285 {
286 if (color < 0)
287 temp = getc(fp);
288 else
289 temp = color;
290
291 /*
292 * Copy the color value...
293 */
294
295 *ptr++ = colormap[temp >> 4][2];
296 *ptr++ = colormap[temp >> 4][1];
297 *ptr++ = colormap[temp >> 4][0];
298 bit = 0x0f;
299 }
300 else
301 {
302 /*
303 * Copy the color value...
304 */
305
306 *ptr++ = colormap[temp & 15][2];
307 *ptr++ = colormap[temp & 15][1];
308 *ptr++ = colormap[temp & 15][0];
309 bit = 0xf0;
310 }
311 }
312 break;
313
314 case 8 : /* 256-color */
315 for (x = img->xsize; x > 0; x --)
316 {
317 /*
318 * Get a new count as needed...
319 */
320
321 if (compression != BI_RLE8)
322 {
323 count = 1;
324 color = -1;
325 }
326
327 if (count == 0)
328 {
329 while (align > 0)
330 {
331 align --;
332 getc(fp);
333 }
334
335 if ((count = getc(fp)) == 0)
336 {
337 if ((count = getc(fp)) == 0)
338 {
339 /*
340 * End of line...
341 */
342
343 x ++;
344 continue;
345 }
346 else if (count == 1)
347 {
348 /*
349 * End of image...
350 */
351
352 break;
353 }
354 else if (count == 2)
355 {
356 /*
357 * Delta...
358 */
359
360 count = getc(fp) * getc(fp) * img->xsize;
361 color = 0;
362 }
363 else
364 {
365 /*
366 * Absolute...
367 */
368
369 color = -1;
370 align = (2 - (count & 1)) & 1;
371 }
372 }
373 else
374 color = getc(fp);
375 }
376
377 /*
378 * Get a new color as needed...
379 */
380
381 if (color < 0)
382 temp = getc(fp);
383 else
384 temp = color;
385
386 count --;
387
388 /*
389 * Copy the color value...
390 */
391
392 *ptr++ = colormap[temp][2];
393 *ptr++ = colormap[temp][1];
394 *ptr++ = colormap[temp][0];
395 }
396 break;
397
398 case 24 : /* 24-bit RGB */
399 for (x = img->xsize; x > 0; x --, ptr += 3)
400 {
401 ptr[2] = getc(fp);
402 ptr[1] = getc(fp);
403 ptr[0] = getc(fp);
404 }
405
406 /*
407 * Read remaining bytes to align to 32 bits...
408 */
409
410 for (temp = img->xsize * 3; temp & 3; temp ++)
411 getc(fp);
412 break;
413 }
414
415 if (img->colorspace == IMAGE_RGB)
416 {
417 if (saturation != 100 || hue != 0)
418 ImageRGBAdjust(out, img->xsize, saturation, hue);
419 }
420 else
421 {
422 if (saturation != 100 || hue != 0)
423 ImageRGBAdjust(in, img->xsize, saturation, hue);
424
425 switch (img->colorspace)
426 {
427 case IMAGE_WHITE :
428 ImageRGBToWhite(in, out, img->xsize);
429 break;
430 case IMAGE_BLACK :
431 ImageRGBToBlack(in, out, img->xsize);
432 break;
433 case IMAGE_CMY :
434 ImageRGBToCMY(in, out, img->xsize);
435 break;
436 case IMAGE_CMYK :
437 ImageRGBToCMYK(in, out, img->xsize);
438 break;
439 }
440 }
441
442 if (lut)
443 ImageLut(out, img->xsize * bpp, lut);
444
445 ImagePutRow(img, 0, y, img->xsize, out);
446 }
447
448 fclose(fp);
449 free(in);
450 free(out);
451
452 return (0);
453 }
454
455
456 /*
457 * 'read_word()' - Read a 16-bit unsigned integer.
458 */
459
460 static unsigned short /* O - 16-bit unsigned integer */
461 read_word(FILE *fp) /* I - File to read from */
462 {
463 unsigned char b0, b1; /* Bytes from file */
464
465 b0 = getc(fp);
466 b1 = getc(fp);
467
468 return ((b1 << 8) | b0);
469 }
470
471
472 /*
473 * 'read_dword()' - Read a 32-bit unsigned integer.
474 */
475
476 static unsigned int /* O - 32-bit unsigned integer */
477 read_dword(FILE *fp) /* I - File to read from */
478 {
479 unsigned char b0, b1, b2, b3; /* Bytes from file */
480
481 b0 = getc(fp);
482 b1 = getc(fp);
483 b2 = getc(fp);
484 b3 = getc(fp);
485
486 return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
487 }
488
489
490 /*
491 * 'read_long()' - Read a 32-bit signed integer.
492 */
493
494 static int /* O - 32-bit signed integer */
495 read_long(FILE *fp) /* I - File to read from */
496 {
497 unsigned char b0, b1, b2, b3; /* Bytes from file */
498
499 b0 = getc(fp);
500 b1 = getc(fp);
501 b2 = getc(fp);
502 b3 = getc(fp);
503
504 return ((int)(((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
505 }
506
507
508 /*
509 * End of "$Id$".
510 */