1 /*
2 * rdbmp.c
3 *
4 * This file was part of the Independent JPEG Group's software:
5 * Copyright (C) 1994-1996, Thomas G. Lane.
6 * Modified 2009-2017 by Guido Vollbeding.
7 * libjpeg-turbo Modifications:
8 * Modified 2011 by Siarhei Siamashka.
9 * Copyright (C) 2015, 2017-2018, D. R. Commander.
10 * For conditions of distribution and use, see the accompanying README.ijg
11 * file.
12 *
13 * This file contains routines to read input images in Microsoft "BMP"
14 * format (MS Windows 3.x, OS/2 1.x, and OS/2 2.x flavors).
15 * Currently, only 8-bit and 24-bit images are supported, not 1-bit or
16 * 4-bit (feeding such low-depth images into JPEG would be silly anyway).
17 * Also, we don't support RLE-compressed files.
18 *
19 * These routines may need modification for non-Unix environments or
20 * specialized applications. As they stand, they assume input from
21 * an ordinary stdio stream. They further assume that reading begins
22 * at the start of the file; start_input may need work if the
23 * user interface has already read some data (e.g., to determine that
24 * the file is indeed BMP format).
25 *
26 * This code contributed by James Arthur Boucher.
27 */
28
29 #include "cmyk.h"
30 #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
31
32 #ifdef BMP_SUPPORTED
33
34
35 /* Macros to deal with unsigned chars as efficiently as compiler allows */
36
37 #ifdef HAVE_UNSIGNED_CHAR
38 typedef unsigned char U_CHAR;
39 #define UCH(x) ((int)(x))
40 #else /* !HAVE_UNSIGNED_CHAR */
41 #ifdef __CHAR_UNSIGNED__
42 typedef char U_CHAR;
43 #define UCH(x) ((int)(x))
44 #else
45 typedef char U_CHAR;
46 #define UCH(x) ((int)(x) & 0xFF)
47 #endif
48 #endif /* HAVE_UNSIGNED_CHAR */
49
50
51 #define ReadOK(file, buffer, len) \
52 (JFREAD(file, buffer, len) == ((size_t)(len)))
53
54 static int alpha_index[JPEG_NUMCS] = {
55 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 3, 0, 0, -1
56 };
57
58
59 /* Private version of data source object */
60
61 typedef struct _bmp_source_struct *bmp_source_ptr;
62
63 typedef struct _bmp_source_struct {
64 struct cjpeg_source_struct pub; /* public fields */
65
66 j_compress_ptr cinfo; /* back link saves passing separate parm */
67
68 JSAMPARRAY colormap; /* BMP colormap (converted to my format) */
69
70 jvirt_sarray_ptr whole_image; /* Needed to reverse row order */
71 JDIMENSION source_row; /* Current source row number */
72 JDIMENSION row_width; /* Physical width of scanlines in file */
73
74 int bits_per_pixel; /* remembers 8- or 24-bit format */
75 int cmap_length; /* colormap length */
76
77 boolean use_inversion_array; /* TRUE = preload the whole image, which is
78 stored in bottom-up order, and feed it to
79 the calling program in top-down order
80
81 FALSE = the calling program will maintain
82 its own image buffer and read the rows in
83 bottom-up order */
84
85 U_CHAR *iobuffer; /* I/O buffer (used to buffer a single row from
86 disk if use_inversion_array == FALSE) */
87 } bmp_source_struct;
88
89
90 LOCAL(int)
read_byte(bmp_source_ptr sinfo)91 read_byte(bmp_source_ptr sinfo)
92 /* Read next byte from BMP file */
93 {
94 register FILE *infile = sinfo->pub.input_file;
95 register int c;
96
97 if ((c = getc(infile)) == EOF)
98 ERREXIT(sinfo->cinfo, JERR_INPUT_EOF);
99 return c;
100 }
101
102
103 LOCAL(void)
read_colormap(bmp_source_ptr sinfo,int cmaplen,int mapentrysize)104 read_colormap(bmp_source_ptr sinfo, int cmaplen, int mapentrysize)
105 /* Read the colormap from a BMP file */
106 {
107 int i, gray = 1;
108
109 switch (mapentrysize) {
110 case 3:
111 /* BGR format (occurs in OS/2 files) */
112 for (i = 0; i < cmaplen; i++) {
113 sinfo->colormap[2][i] = (JSAMPLE)read_byte(sinfo);
114 sinfo->colormap[1][i] = (JSAMPLE)read_byte(sinfo);
115 sinfo->colormap[0][i] = (JSAMPLE)read_byte(sinfo);
116 if (sinfo->colormap[2][i] != sinfo->colormap[1][i] ||
117 sinfo->colormap[1][i] != sinfo->colormap[0][i])
118 gray = 0;
119 }
120 break;
121 case 4:
122 /* BGR0 format (occurs in MS Windows files) */
123 for (i = 0; i < cmaplen; i++) {
124 sinfo->colormap[2][i] = (JSAMPLE)read_byte(sinfo);
125 sinfo->colormap[1][i] = (JSAMPLE)read_byte(sinfo);
126 sinfo->colormap[0][i] = (JSAMPLE)read_byte(sinfo);
127 (void)read_byte(sinfo);
128 if (sinfo->colormap[2][i] != sinfo->colormap[1][i] ||
129 sinfo->colormap[1][i] != sinfo->colormap[0][i])
130 gray = 0;
131 }
132 break;
133 default:
134 ERREXIT(sinfo->cinfo, JERR_BMP_BADCMAP);
135 break;
136 }
137
138 if (sinfo->cinfo->in_color_space == JCS_UNKNOWN && gray)
139 sinfo->cinfo->in_color_space = JCS_GRAYSCALE;
140
141 if (sinfo->cinfo->in_color_space == JCS_GRAYSCALE && !gray)
142 ERREXIT(sinfo->cinfo, JERR_BAD_IN_COLORSPACE);
143 }
144
145
146 /*
147 * Read one row of pixels.
148 * The image has been read into the whole_image array, but is otherwise
149 * unprocessed. We must read it out in top-to-bottom row order, and if
150 * it is an 8-bit image, we must expand colormapped pixels to 24bit format.
151 */
152
153 METHODDEF(JDIMENSION)
get_8bit_row(j_compress_ptr cinfo,cjpeg_source_ptr sinfo)154 get_8bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
155 /* This version is for reading 8-bit colormap indexes */
156 {
157 bmp_source_ptr source = (bmp_source_ptr)sinfo;
158 register JSAMPARRAY colormap = source->colormap;
159 int cmaplen = source->cmap_length;
160 JSAMPARRAY image_ptr;
161 register int t;
162 register JSAMPROW inptr, outptr;
163 register JDIMENSION col;
164
165 if (source->use_inversion_array) {
166 /* Fetch next row from virtual array */
167 source->source_row--;
168 image_ptr = (*cinfo->mem->access_virt_sarray)
169 ((j_common_ptr)cinfo, source->whole_image,
170 source->source_row, (JDIMENSION)1, FALSE);
171 inptr = image_ptr[0];
172 } else {
173 if (!ReadOK(source->pub.input_file, source->iobuffer, source->row_width))
174 ERREXIT(cinfo, JERR_INPUT_EOF);
175 inptr = source->iobuffer;
176 }
177
178 /* Expand the colormap indexes to real data */
179 outptr = source->pub.buffer[0];
180 if (cinfo->in_color_space == JCS_GRAYSCALE) {
181 for (col = cinfo->image_width; col > 0; col--) {
182 t = GETJSAMPLE(*inptr++);
183 if (t >= cmaplen)
184 ERREXIT(cinfo, JERR_BMP_OUTOFRANGE);
185 *outptr++ = colormap[0][t];
186 }
187 } else if (cinfo->in_color_space == JCS_CMYK) {
188 for (col = cinfo->image_width; col > 0; col--) {
189 t = GETJSAMPLE(*inptr++);
190 if (t >= cmaplen)
191 ERREXIT(cinfo, JERR_BMP_OUTOFRANGE);
192 rgb_to_cmyk(colormap[0][t], colormap[1][t], colormap[2][t], outptr,
193 outptr + 1, outptr + 2, outptr + 3);
194 outptr += 4;
195 }
196 } else {
197 register int rindex = rgb_red[cinfo->in_color_space];
198 register int gindex = rgb_green[cinfo->in_color_space];
199 register int bindex = rgb_blue[cinfo->in_color_space];
200 register int aindex = alpha_index[cinfo->in_color_space];
201 register int ps = rgb_pixelsize[cinfo->in_color_space];
202
203 if (aindex >= 0) {
204 for (col = cinfo->image_width; col > 0; col--) {
205 t = GETJSAMPLE(*inptr++);
206 if (t >= cmaplen)
207 ERREXIT(cinfo, JERR_BMP_OUTOFRANGE);
208 outptr[rindex] = colormap[0][t];
209 outptr[gindex] = colormap[1][t];
210 outptr[bindex] = colormap[2][t];
211 outptr[aindex] = 0xFF;
212 outptr += ps;
213 }
214 } else {
215 for (col = cinfo->image_width; col > 0; col--) {
216 t = GETJSAMPLE(*inptr++);
217 if (t >= cmaplen)
218 ERREXIT(cinfo, JERR_BMP_OUTOFRANGE);
219 outptr[rindex] = colormap[0][t];
220 outptr[gindex] = colormap[1][t];
221 outptr[bindex] = colormap[2][t];
222 outptr += ps;
223 }
224 }
225 }
226
227 return 1;
228 }
229
230
231 METHODDEF(JDIMENSION)
get_24bit_row(j_compress_ptr cinfo,cjpeg_source_ptr sinfo)232 get_24bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
233 /* This version is for reading 24-bit pixels */
234 {
235 bmp_source_ptr source = (bmp_source_ptr)sinfo;
236 JSAMPARRAY image_ptr;
237 register JSAMPROW inptr, outptr;
238 register JDIMENSION col;
239
240 if (source->use_inversion_array) {
241 /* Fetch next row from virtual array */
242 source->source_row--;
243 image_ptr = (*cinfo->mem->access_virt_sarray)
244 ((j_common_ptr)cinfo, source->whole_image,
245 source->source_row, (JDIMENSION)1, FALSE);
246 inptr = image_ptr[0];
247 } else {
248 if (!ReadOK(source->pub.input_file, source->iobuffer, source->row_width))
249 ERREXIT(cinfo, JERR_INPUT_EOF);
250 inptr = source->iobuffer;
251 }
252
253 /* Transfer data. Note source values are in BGR order
254 * (even though Microsoft's own documents say the opposite).
255 */
256 outptr = source->pub.buffer[0];
257 if (cinfo->in_color_space == JCS_EXT_BGR) {
258 MEMCOPY(outptr, inptr, source->row_width);
259 } else if (cinfo->in_color_space == JCS_CMYK) {
260 for (col = cinfo->image_width; col > 0; col--) {
261 /* can omit GETJSAMPLE() safely */
262 JSAMPLE b = *inptr++, g = *inptr++, r = *inptr++;
263 rgb_to_cmyk(r, g, b, outptr, outptr + 1, outptr + 2, outptr + 3);
264 outptr += 4;
265 }
266 } else {
267 register int rindex = rgb_red[cinfo->in_color_space];
268 register int gindex = rgb_green[cinfo->in_color_space];
269 register int bindex = rgb_blue[cinfo->in_color_space];
270 register int aindex = alpha_index[cinfo->in_color_space];
271 register int ps = rgb_pixelsize[cinfo->in_color_space];
272
273 if (aindex >= 0) {
274 for (col = cinfo->image_width; col > 0; col--) {
275 outptr[bindex] = *inptr++; /* can omit GETJSAMPLE() safely */
276 outptr[gindex] = *inptr++;
277 outptr[rindex] = *inptr++;
278 outptr[aindex] = 0xFF;
279 outptr += ps;
280 }
281 } else {
282 for (col = cinfo->image_width; col > 0; col--) {
283 outptr[bindex] = *inptr++; /* can omit GETJSAMPLE() safely */
284 outptr[gindex] = *inptr++;
285 outptr[rindex] = *inptr++;
286 outptr += ps;
287 }
288 }
289 }
290
291 return 1;
292 }
293
294
295 METHODDEF(JDIMENSION)
get_32bit_row(j_compress_ptr cinfo,cjpeg_source_ptr sinfo)296 get_32bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
297 /* This version is for reading 32-bit pixels */
298 {
299 bmp_source_ptr source = (bmp_source_ptr)sinfo;
300 JSAMPARRAY image_ptr;
301 register JSAMPROW inptr, outptr;
302 register JDIMENSION col;
303
304 if (source->use_inversion_array) {
305 /* Fetch next row from virtual array */
306 source->source_row--;
307 image_ptr = (*cinfo->mem->access_virt_sarray)
308 ((j_common_ptr)cinfo, source->whole_image,
309 source->source_row, (JDIMENSION)1, FALSE);
310 inptr = image_ptr[0];
311 } else {
312 if (!ReadOK(source->pub.input_file, source->iobuffer, source->row_width))
313 ERREXIT(cinfo, JERR_INPUT_EOF);
314 inptr = source->iobuffer;
315 }
316
317 /* Transfer data. Note source values are in BGR order
318 * (even though Microsoft's own documents say the opposite).
319 */
320 outptr = source->pub.buffer[0];
321 if (cinfo->in_color_space == JCS_EXT_BGRX ||
322 cinfo->in_color_space == JCS_EXT_BGRA) {
323 MEMCOPY(outptr, inptr, source->row_width);
324 } else if (cinfo->in_color_space == JCS_CMYK) {
325 for (col = cinfo->image_width; col > 0; col--) {
326 /* can omit GETJSAMPLE() safely */
327 JSAMPLE b = *inptr++, g = *inptr++, r = *inptr++;
328 rgb_to_cmyk(r, g, b, outptr, outptr + 1, outptr + 2, outptr + 3);
329 inptr++; /* skip the 4th byte (Alpha channel) */
330 outptr += 4;
331 }
332 } else {
333 register int rindex = rgb_red[cinfo->in_color_space];
334 register int gindex = rgb_green[cinfo->in_color_space];
335 register int bindex = rgb_blue[cinfo->in_color_space];
336 register int aindex = alpha_index[cinfo->in_color_space];
337 register int ps = rgb_pixelsize[cinfo->in_color_space];
338
339 if (aindex >= 0) {
340 for (col = cinfo->image_width; col > 0; col--) {
341 outptr[bindex] = *inptr++; /* can omit GETJSAMPLE() safely */
342 outptr[gindex] = *inptr++;
343 outptr[rindex] = *inptr++;
344 outptr[aindex] = *inptr++;
345 outptr += ps;
346 }
347 } else {
348 for (col = cinfo->image_width; col > 0; col--) {
349 outptr[bindex] = *inptr++; /* can omit GETJSAMPLE() safely */
350 outptr[gindex] = *inptr++;
351 outptr[rindex] = *inptr++;
352 inptr++; /* skip the 4th byte (Alpha channel) */
353 outptr += ps;
354 }
355 }
356 }
357
358 return 1;
359 }
360
361
362 /*
363 * This method loads the image into whole_image during the first call on
364 * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call
365 * get_8bit_row, get_24bit_row, or get_32bit_row on subsequent calls.
366 */
367
368 METHODDEF(JDIMENSION)
preload_image(j_compress_ptr cinfo,cjpeg_source_ptr sinfo)369 preload_image(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
370 {
371 bmp_source_ptr source = (bmp_source_ptr)sinfo;
372 register FILE *infile = source->pub.input_file;
373 register JSAMPROW out_ptr;
374 JSAMPARRAY image_ptr;
375 JDIMENSION row;
376 cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress;
377
378 /* Read the data into a virtual array in input-file row order. */
379 for (row = 0; row < cinfo->image_height; row++) {
380 if (progress != NULL) {
381 progress->pub.pass_counter = (long)row;
382 progress->pub.pass_limit = (long)cinfo->image_height;
383 (*progress->pub.progress_monitor) ((j_common_ptr)cinfo);
384 }
385 image_ptr = (*cinfo->mem->access_virt_sarray)
386 ((j_common_ptr)cinfo, source->whole_image, row, (JDIMENSION)1, TRUE);
387 out_ptr = image_ptr[0];
388 if (fread(out_ptr, 1, source->row_width, infile) != source->row_width) {
389 if (feof(infile))
390 ERREXIT(cinfo, JERR_INPUT_EOF);
391 else
392 ERREXIT(cinfo, JERR_FILE_READ);
393 }
394 }
395 if (progress != NULL)
396 progress->completed_extra_passes++;
397
398 /* Set up to read from the virtual array in top-to-bottom order */
399 switch (source->bits_per_pixel) {
400 case 8:
401 source->pub.get_pixel_rows = get_8bit_row;
402 break;
403 case 24:
404 source->pub.get_pixel_rows = get_24bit_row;
405 break;
406 case 32:
407 source->pub.get_pixel_rows = get_32bit_row;
408 break;
409 default:
410 ERREXIT(cinfo, JERR_BMP_BADDEPTH);
411 }
412 source->source_row = cinfo->image_height;
413
414 /* And read the first row */
415 return (*source->pub.get_pixel_rows) (cinfo, sinfo);
416 }
417
418
419 /*
420 * Read the file header; return image size and component count.
421 */
422
423 METHODDEF(void)
start_input_bmp(j_compress_ptr cinfo,cjpeg_source_ptr sinfo)424 start_input_bmp(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
425 {
426 bmp_source_ptr source = (bmp_source_ptr)sinfo;
427 U_CHAR bmpfileheader[14];
428 U_CHAR bmpinfoheader[64];
429
430 #define GET_2B(array, offset) \
431 ((unsigned short)UCH(array[offset]) + \
432 (((unsigned short)UCH(array[offset + 1])) << 8))
433 #define GET_4B(array, offset) \
434 ((unsigned int)UCH(array[offset]) + \
435 (((unsigned int)UCH(array[offset + 1])) << 8) + \
436 (((unsigned int)UCH(array[offset + 2])) << 16) + \
437 (((unsigned int)UCH(array[offset + 3])) << 24))
438
439 unsigned int bfOffBits;
440 unsigned int headerSize;
441 int biWidth;
442 int biHeight;
443 unsigned short biPlanes;
444 unsigned int biCompression;
445 int biXPelsPerMeter, biYPelsPerMeter;
446 unsigned int biClrUsed = 0;
447 int mapentrysize = 0; /* 0 indicates no colormap */
448 int bPad;
449 JDIMENSION row_width = 0;
450
451 /* Read and verify the bitmap file header */
452 if (!ReadOK(source->pub.input_file, bmpfileheader, 14))
453 ERREXIT(cinfo, JERR_INPUT_EOF);
454 if (GET_2B(bmpfileheader, 0) != 0x4D42) /* 'BM' */
455 ERREXIT(cinfo, JERR_BMP_NOT);
456 bfOffBits = GET_4B(bmpfileheader, 10);
457 /* We ignore the remaining fileheader fields */
458
459 /* The infoheader might be 12 bytes (OS/2 1.x), 40 bytes (Windows),
460 * or 64 bytes (OS/2 2.x). Check the first 4 bytes to find out which.
461 */
462 if (!ReadOK(source->pub.input_file, bmpinfoheader, 4))
463 ERREXIT(cinfo, JERR_INPUT_EOF);
464 headerSize = GET_4B(bmpinfoheader, 0);
465 if (headerSize < 12 || headerSize > 64)
466 ERREXIT(cinfo, JERR_BMP_BADHEADER);
467 if (!ReadOK(source->pub.input_file, bmpinfoheader + 4, headerSize - 4))
468 ERREXIT(cinfo, JERR_INPUT_EOF);
469
470 switch (headerSize) {
471 case 12:
472 /* Decode OS/2 1.x header (Microsoft calls this a BITMAPCOREHEADER) */
473 biWidth = (int)GET_2B(bmpinfoheader, 4);
474 biHeight = (int)GET_2B(bmpinfoheader, 6);
475 biPlanes = GET_2B(bmpinfoheader, 8);
476 source->bits_per_pixel = (int)GET_2B(bmpinfoheader, 10);
477
478 switch (source->bits_per_pixel) {
479 case 8: /* colormapped image */
480 mapentrysize = 3; /* OS/2 uses RGBTRIPLE colormap */
481 TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, biWidth, biHeight);
482 break;
483 case 24: /* RGB image */
484 TRACEMS2(cinfo, 1, JTRC_BMP_OS2, biWidth, biHeight);
485 break;
486 default:
487 ERREXIT(cinfo, JERR_BMP_BADDEPTH);
488 break;
489 }
490 break;
491 case 40:
492 case 64:
493 /* Decode Windows 3.x header (Microsoft calls this a BITMAPINFOHEADER) */
494 /* or OS/2 2.x header, which has additional fields that we ignore */
495 biWidth = (int)GET_4B(bmpinfoheader, 4);
496 biHeight = (int)GET_4B(bmpinfoheader, 8);
497 biPlanes = GET_2B(bmpinfoheader, 12);
498 source->bits_per_pixel = (int)GET_2B(bmpinfoheader, 14);
499 biCompression = GET_4B(bmpinfoheader, 16);
500 biXPelsPerMeter = (int)GET_4B(bmpinfoheader, 24);
501 biYPelsPerMeter = (int)GET_4B(bmpinfoheader, 28);
502 biClrUsed = GET_4B(bmpinfoheader, 32);
503 /* biSizeImage, biClrImportant fields are ignored */
504
505 switch (source->bits_per_pixel) {
506 case 8: /* colormapped image */
507 mapentrysize = 4; /* Windows uses RGBQUAD colormap */
508 TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, biWidth, biHeight);
509 break;
510 case 24: /* RGB image */
511 TRACEMS2(cinfo, 1, JTRC_BMP, biWidth, biHeight);
512 break;
513 case 32: /* RGB image + Alpha channel */
514 TRACEMS2(cinfo, 1, JTRC_BMP, biWidth, biHeight);
515 break;
516 default:
517 ERREXIT(cinfo, JERR_BMP_BADDEPTH);
518 break;
519 }
520 if (biCompression != 0)
521 ERREXIT(cinfo, JERR_BMP_COMPRESSED);
522
523 if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) {
524 /* Set JFIF density parameters from the BMP data */
525 cinfo->X_density = (UINT16)(biXPelsPerMeter / 100); /* 100 cm per meter */
526 cinfo->Y_density = (UINT16)(biYPelsPerMeter / 100);
527 cinfo->density_unit = 2; /* dots/cm */
528 }
529 break;
530 default:
531 ERREXIT(cinfo, JERR_BMP_BADHEADER);
532 return;
533 }
534
535 if (biWidth <= 0 || biHeight <= 0)
536 ERREXIT(cinfo, JERR_BMP_EMPTY);
537 if (biPlanes != 1)
538 ERREXIT(cinfo, JERR_BMP_BADPLANES);
539
540 /* Compute distance to bitmap data --- will adjust for colormap below */
541 bPad = bfOffBits - (headerSize + 14);
542
543 /* Read the colormap, if any */
544 if (mapentrysize > 0) {
545 if (biClrUsed <= 0)
546 biClrUsed = 256; /* assume it's 256 */
547 else if (biClrUsed > 256)
548 ERREXIT(cinfo, JERR_BMP_BADCMAP);
549 /* Allocate space to store the colormap */
550 source->colormap = (*cinfo->mem->alloc_sarray)
551 ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)biClrUsed, (JDIMENSION)3);
552 source->cmap_length = (int)biClrUsed;
553 /* and read it from the file */
554 read_colormap(source, (int)biClrUsed, mapentrysize);
555 /* account for size of colormap */
556 bPad -= biClrUsed * mapentrysize;
557 }
558
559 /* Skip any remaining pad bytes */
560 if (bPad < 0) /* incorrect bfOffBits value? */
561 ERREXIT(cinfo, JERR_BMP_BADHEADER);
562 while (--bPad >= 0) {
563 (void)read_byte(source);
564 }
565
566 /* Compute row width in file, including padding to 4-byte boundary */
567 switch (source->bits_per_pixel) {
568 case 8:
569 if (cinfo->in_color_space == JCS_UNKNOWN)
570 cinfo->in_color_space = JCS_EXT_RGB;
571 if (IsExtRGB(cinfo->in_color_space))
572 cinfo->input_components = rgb_pixelsize[cinfo->in_color_space];
573 else if (cinfo->in_color_space == JCS_GRAYSCALE)
574 cinfo->input_components = 1;
575 else if (cinfo->in_color_space == JCS_CMYK)
576 cinfo->input_components = 4;
577 else
578 ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
579 row_width = (JDIMENSION)biWidth;
580 break;
581 case 24:
582 if (cinfo->in_color_space == JCS_UNKNOWN)
583 cinfo->in_color_space = JCS_EXT_BGR;
584 if (IsExtRGB(cinfo->in_color_space))
585 cinfo->input_components = rgb_pixelsize[cinfo->in_color_space];
586 else if (cinfo->in_color_space == JCS_CMYK)
587 cinfo->input_components = 4;
588 else
589 ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
590 row_width = (JDIMENSION)(biWidth * 3);
591 break;
592 case 32:
593 if (cinfo->in_color_space == JCS_UNKNOWN)
594 cinfo->in_color_space = JCS_EXT_BGRA;
595 if (IsExtRGB(cinfo->in_color_space))
596 cinfo->input_components = rgb_pixelsize[cinfo->in_color_space];
597 else if (cinfo->in_color_space == JCS_CMYK)
598 cinfo->input_components = 4;
599 else
600 ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
601 row_width = (JDIMENSION)(biWidth * 4);
602 break;
603 default:
604 ERREXIT(cinfo, JERR_BMP_BADDEPTH);
605 }
606 while ((row_width & 3) != 0) row_width++;
607 source->row_width = row_width;
608
609 if (source->use_inversion_array) {
610 /* Allocate space for inversion array, prepare for preload pass */
611 source->whole_image = (*cinfo->mem->request_virt_sarray)
612 ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE,
613 row_width, (JDIMENSION)biHeight, (JDIMENSION)1);
614 source->pub.get_pixel_rows = preload_image;
615 if (cinfo->progress != NULL) {
616 cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress;
617 progress->total_extra_passes++; /* count file input as separate pass */
618 }
619 } else {
620 source->iobuffer = (U_CHAR *)
621 (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, row_width);
622 switch (source->bits_per_pixel) {
623 case 8:
624 source->pub.get_pixel_rows = get_8bit_row;
625 break;
626 case 24:
627 source->pub.get_pixel_rows = get_24bit_row;
628 break;
629 case 32:
630 source->pub.get_pixel_rows = get_32bit_row;
631 break;
632 default:
633 ERREXIT(cinfo, JERR_BMP_BADDEPTH);
634 }
635 }
636
637 /* Ensure that biWidth * cinfo->input_components doesn't exceed the maximum
638 value of the JDIMENSION type. This is only a danger with BMP files, since
639 their width and height fields are 32-bit integers. */
640 if ((unsigned long long)biWidth *
641 (unsigned long long)cinfo->input_components > 0xFFFFFFFFULL)
642 ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
643 /* Allocate one-row buffer for returned data */
644 source->pub.buffer = (*cinfo->mem->alloc_sarray)
645 ((j_common_ptr)cinfo, JPOOL_IMAGE,
646 (JDIMENSION)(biWidth * cinfo->input_components), (JDIMENSION)1);
647 source->pub.buffer_height = 1;
648
649 cinfo->data_precision = 8;
650 cinfo->image_width = (JDIMENSION)biWidth;
651 cinfo->image_height = (JDIMENSION)biHeight;
652 }
653
654
655 /*
656 * Finish up at the end of the file.
657 */
658
659 METHODDEF(void)
finish_input_bmp(j_compress_ptr cinfo,cjpeg_source_ptr sinfo)660 finish_input_bmp(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
661 {
662 /* no work */
663 }
664
665
666 /*
667 * The module selection routine for BMP format input.
668 */
669
670 GLOBAL(cjpeg_source_ptr)
jinit_read_bmp(j_compress_ptr cinfo,boolean use_inversion_array)671 jinit_read_bmp(j_compress_ptr cinfo, boolean use_inversion_array)
672 {
673 bmp_source_ptr source;
674
675 /* Create module interface object */
676 source = (bmp_source_ptr)
677 (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
678 sizeof(bmp_source_struct));
679 source->cinfo = cinfo; /* make back link for subroutines */
680 /* Fill in method ptrs, except get_pixel_rows which start_input sets */
681 source->pub.start_input = start_input_bmp;
682 source->pub.finish_input = finish_input_bmp;
683
684 source->use_inversion_array = use_inversion_array;
685
686 return (cjpeg_source_ptr)source;
687 }
688
689 #endif /* BMP_SUPPORTED */
690