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