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