• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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