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