blob: 51af23778f885231d08075aa79f962a88dcdf0a2 [file] [log] [blame]
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +00001/*
2 * rdbmp.c
3 *
DRCcf763c02013-01-01 09:51:37 +00004 * This file was part of the Independent JPEG Group's software:
Thomas G. Lane489583f1996-02-07 00:00:00 +00005 * Copyright (C) 1994-1996, Thomas G. Lane.
Leon Scroggins III3993b372018-07-16 10:43:45 -04006 * Modified 2009-2017 by Guido Vollbeding.
DRCa6ef2822013-09-28 03:23:49 +00007 * libjpeg-turbo Modifications:
DRC049aef52011-04-25 22:41:14 +00008 * Modified 2011 by Siarhei Siamashka.
Leon Scroggins III3993b372018-07-16 10:43:45 -04009 * Copyright (C) 2015, 2017-2018, D. R. Commander.
Alex Naidis6eb7d372016-10-16 23:10:08 +020010 * For conditions of distribution and use, see the accompanying README.ijg
11 * file.
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000012 *
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
Leon Scroggins III3993b372018-07-16 10:43:45 -040029#include "cmyk.h"
DRCe5eaf372014-05-09 18:00:32 +000030#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000031
32#ifdef BMP_SUPPORTED
33
34
35/* Macros to deal with unsigned chars as efficiently as compiler allows */
36
37#ifdef HAVE_UNSIGNED_CHAR
38typedef unsigned char U_CHAR;
Leon Scroggins III3993b372018-07-16 10:43:45 -040039#define UCH(x) ((int)(x))
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000040#else /* !HAVE_UNSIGNED_CHAR */
DRC61976bd2014-04-20 19:13:10 +000041#ifdef __CHAR_UNSIGNED__
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000042typedef char U_CHAR;
Leon Scroggins III3993b372018-07-16 10:43:45 -040043#define UCH(x) ((int)(x))
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000044#else
45typedef char U_CHAR;
Leon Scroggins III3993b372018-07-16 10:43:45 -040046#define UCH(x) ((int)(x) & 0xFF)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000047#endif
48#endif /* HAVE_UNSIGNED_CHAR */
49
50
Leon Scroggins III3993b372018-07-16 10:43:45 -040051#define ReadOK(file, buffer, len) \
52 (JFREAD(file, buffer, len) == ((size_t)(len)))
53
54static int alpha_index[JPEG_NUMCS] = {
55 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 3, 0, 0, -1
56};
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000057
58
59/* Private version of data source object */
60
Alex Naidis6eb7d372016-10-16 23:10:08 +020061typedef struct _bmp_source_struct *bmp_source_ptr;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000062
63typedef struct _bmp_source_struct {
64 struct cjpeg_source_struct pub; /* public fields */
65
DRCe5eaf372014-05-09 18:00:32 +000066 j_compress_ptr cinfo; /* back link saves passing separate parm */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000067
DRCe5eaf372014-05-09 18:00:32 +000068 JSAMPARRAY colormap; /* BMP colormap (converted to my format) */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000069
DRCe5eaf372014-05-09 18:00:32 +000070 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 */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000073
DRCe5eaf372014-05-09 18:00:32 +000074 int bits_per_pixel; /* remembers 8- or 24-bit format */
Leon Scroggins III3993b372018-07-16 10:43:45 -040075 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) */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000087} bmp_source_struct;
88
89
Thomas G. Lane489583f1996-02-07 00:00:00 +000090LOCAL(int)
Leon Scroggins III3993b372018-07-16 10:43:45 -040091read_byte(bmp_source_ptr sinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +000092/* 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
Thomas G. Lane489583f1996-02-07 00:00:00 +0000103LOCAL(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400104read_colormap(bmp_source_ptr sinfo, int cmaplen, int mapentrysize)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000105/* Read the colormap from a BMP file */
106{
Leon Scroggins III3993b372018-07-16 10:43:45 -0400107 int i, gray = 1;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000108
109 switch (mapentrysize) {
110 case 3:
111 /* BGR format (occurs in OS/2 files) */
112 for (i = 0; i < cmaplen; i++) {
Leon Scroggins III3993b372018-07-16 10:43:45 -0400113 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;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000119 }
120 break;
121 case 4:
122 /* BGR0 format (occurs in MS Windows files) */
123 for (i = 0; i < cmaplen; i++) {
Leon Scroggins III3993b372018-07-16 10:43:45 -0400124 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;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000131 }
132 break;
133 default:
134 ERREXIT(sinfo->cinfo, JERR_BMP_BADCMAP);
135 break;
136 }
Leon Scroggins III3993b372018-07-16 10:43:45 -0400137
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);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000143}
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
Thomas G. Lane489583f1996-02-07 00:00:00 +0000153METHODDEF(JDIMENSION)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400154get_8bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000155/* This version is for reading 8-bit colormap indexes */
156{
Leon Scroggins III3993b372018-07-16 10:43:45 -0400157 bmp_source_ptr source = (bmp_source_ptr)sinfo;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000158 register JSAMPARRAY colormap = source->colormap;
Leon Scroggins III3993b372018-07-16 10:43:45 -0400159 int cmaplen = source->cmap_length;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000160 JSAMPARRAY image_ptr;
161 register int t;
162 register JSAMPROW inptr, outptr;
163 register JDIMENSION col;
164
Leon Scroggins III3993b372018-07-16 10:43:45 -0400165 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 }
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000177
178 /* Expand the colormap indexes to real data */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000179 outptr = source->pub.buffer[0];
Leon Scroggins III3993b372018-07-16 10:43:45 -0400180 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 }
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000225 }
226
227 return 1;
228}
229
230
Thomas G. Lane489583f1996-02-07 00:00:00 +0000231METHODDEF(JDIMENSION)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400232get_24bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000233/* This version is for reading 24-bit pixels */
234{
Leon Scroggins III3993b372018-07-16 10:43:45 -0400235 bmp_source_ptr source = (bmp_source_ptr)sinfo;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000236 JSAMPARRAY image_ptr;
237 register JSAMPROW inptr, outptr;
238 register JDIMENSION col;
239
Leon Scroggins III3993b372018-07-16 10:43:45 -0400240 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 }
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000252
253 /* Transfer data. Note source values are in BGR order
254 * (even though Microsoft's own documents say the opposite).
255 */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000256 outptr = source->pub.buffer[0];
Leon Scroggins III3993b372018-07-16 10:43:45 -0400257 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 }
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000289 }
290
291 return 1;
292}
293
294
Guido Vollbedingf18f81b2010-02-28 00:00:00 +0000295METHODDEF(JDIMENSION)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400296get_32bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
Guido Vollbedingf18f81b2010-02-28 00:00:00 +0000297/* This version is for reading 32-bit pixels */
298{
Leon Scroggins III3993b372018-07-16 10:43:45 -0400299 bmp_source_ptr source = (bmp_source_ptr)sinfo;
Guido Vollbedingf18f81b2010-02-28 00:00:00 +0000300 JSAMPARRAY image_ptr;
301 register JSAMPROW inptr, outptr;
302 register JDIMENSION col;
303
Leon Scroggins III3993b372018-07-16 10:43:45 -0400304 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
Guido Vollbedingf18f81b2010-02-28 00:00:00 +0000317 /* Transfer data. Note source values are in BGR order
318 * (even though Microsoft's own documents say the opposite).
319 */
Guido Vollbedingf18f81b2010-02-28 00:00:00 +0000320 outptr = source->pub.buffer[0];
Leon Scroggins III3993b372018-07-16 10:43:45 -0400321 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 }
Guido Vollbedingf18f81b2010-02-28 00:00:00 +0000356 }
357
358 return 1;
359}
360
361
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000362/*
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
Guido Vollbedingf18f81b2010-02-28 00:00:00 +0000365 * get_8bit_row, get_24bit_row, or get_32bit_row on subsequent calls.
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000366 */
367
Thomas G. Lane489583f1996-02-07 00:00:00 +0000368METHODDEF(JDIMENSION)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400369preload_image(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000370{
Leon Scroggins III3993b372018-07-16 10:43:45 -0400371 bmp_source_ptr source = (bmp_source_ptr)sinfo;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000372 register FILE *infile = source->pub.input_file;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000373 register JSAMPROW out_ptr;
374 JSAMPARRAY image_ptr;
DRC049aef52011-04-25 22:41:14 +0000375 JDIMENSION row;
Leon Scroggins III3993b372018-07-16 10:43:45 -0400376 cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000377
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) {
Leon Scroggins III3993b372018-07-16 10:43:45 -0400381 progress->pub.pass_counter = (long)row;
382 progress->pub.pass_limit = (long)cinfo->image_height;
383 (*progress->pub.progress_monitor) ((j_common_ptr)cinfo);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000384 }
385 image_ptr = (*cinfo->mem->access_virt_sarray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400386 ((j_common_ptr)cinfo, source->whole_image, row, (JDIMENSION)1, TRUE);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000387 out_ptr = image_ptr[0];
DRC049aef52011-04-25 22:41:14 +0000388 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);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000393 }
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;
Guido Vollbedingf18f81b2010-02-28 00:00:00 +0000406 case 32:
407 source->pub.get_pixel_rows = get_32bit_row;
408 break;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000409 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
Thomas G. Lane489583f1996-02-07 00:00:00 +0000423METHODDEF(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400424start_input_bmp(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000425{
Leon Scroggins III3993b372018-07-16 10:43:45 -0400426 bmp_source_ptr source = (bmp_source_ptr)sinfo;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000427 U_CHAR bmpfileheader[14];
428 U_CHAR bmpinfoheader[64];
Leon Scroggins III3993b372018-07-16 10:43:45 -0400429
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
DRCa3ef34c2015-08-13 11:09:05 -0500439 unsigned int bfOffBits;
440 unsigned int headerSize;
441 int biWidth;
442 int biHeight;
443 unsigned short biPlanes;
444 unsigned int biCompression;
Leon Scroggins III3993b372018-07-16 10:43:45 -0400445 int biXPelsPerMeter, biYPelsPerMeter;
DRCa3ef34c2015-08-13 11:09:05 -0500446 unsigned int biClrUsed = 0;
DRCe5eaf372014-05-09 18:00:32 +0000447 int mapentrysize = 0; /* 0 indicates no colormap */
DRCa3ef34c2015-08-13 11:09:05 -0500448 int bPad;
Leon Scroggins III3993b372018-07-16 10:43:45 -0400449 JDIMENSION row_width = 0;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000450
451 /* Read and verify the bitmap file header */
Leon Scroggins III3993b372018-07-16 10:43:45 -0400452 if (!ReadOK(source->pub.input_file, bmpfileheader, 14))
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000453 ERREXIT(cinfo, JERR_INPUT_EOF);
Leon Scroggins III3993b372018-07-16 10:43:45 -0400454 if (GET_2B(bmpfileheader, 0) != 0x4D42) /* 'BM' */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000455 ERREXIT(cinfo, JERR_BMP_NOT);
Leon Scroggins III3993b372018-07-16 10:43:45 -0400456 bfOffBits = GET_4B(bmpfileheader, 10);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000457 /* 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 */
Leon Scroggins III3993b372018-07-16 10:43:45 -0400462 if (!ReadOK(source->pub.input_file, bmpinfoheader, 4))
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000463 ERREXIT(cinfo, JERR_INPUT_EOF);
Leon Scroggins III3993b372018-07-16 10:43:45 -0400464 headerSize = GET_4B(bmpinfoheader, 0);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000465 if (headerSize < 12 || headerSize > 64)
466 ERREXIT(cinfo, JERR_BMP_BADHEADER);
Leon Scroggins III3993b372018-07-16 10:43:45 -0400467 if (!ReadOK(source->pub.input_file, bmpinfoheader + 4, headerSize - 4))
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000468 ERREXIT(cinfo, JERR_INPUT_EOF);
469
DRCa3ef34c2015-08-13 11:09:05 -0500470 switch (headerSize) {
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000471 case 12:
472 /* Decode OS/2 1.x header (Microsoft calls this a BITMAPCOREHEADER) */
Leon Scroggins III3993b372018-07-16 10:43:45 -0400473 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);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000477
478 switch (source->bits_per_pixel) {
DRCe5eaf372014-05-09 18:00:32 +0000479 case 8: /* colormapped image */
480 mapentrysize = 3; /* OS/2 uses RGBTRIPLE colormap */
DRCa3ef34c2015-08-13 11:09:05 -0500481 TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, biWidth, biHeight);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000482 break;
DRCe5eaf372014-05-09 18:00:32 +0000483 case 24: /* RGB image */
DRCa3ef34c2015-08-13 11:09:05 -0500484 TRACEMS2(cinfo, 1, JTRC_BMP_OS2, biWidth, biHeight);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000485 break;
486 default:
487 ERREXIT(cinfo, JERR_BMP_BADDEPTH);
488 break;
489 }
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000490 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 */
Leon Scroggins III3993b372018-07-16 10:43:45 -0400495 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);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000503 /* biSizeImage, biClrImportant fields are ignored */
504
505 switch (source->bits_per_pixel) {
DRCe5eaf372014-05-09 18:00:32 +0000506 case 8: /* colormapped image */
507 mapentrysize = 4; /* Windows uses RGBQUAD colormap */
DRCa3ef34c2015-08-13 11:09:05 -0500508 TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, biWidth, biHeight);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000509 break;
DRCe5eaf372014-05-09 18:00:32 +0000510 case 24: /* RGB image */
DRCa3ef34c2015-08-13 11:09:05 -0500511 TRACEMS2(cinfo, 1, JTRC_BMP, biWidth, biHeight);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000512 break;
DRCe5eaf372014-05-09 18:00:32 +0000513 case 32: /* RGB image + Alpha channel */
DRCa3ef34c2015-08-13 11:09:05 -0500514 TRACEMS2(cinfo, 1, JTRC_BMP, biWidth, biHeight);
Guido Vollbedingf18f81b2010-02-28 00:00:00 +0000515 break;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000516 default:
517 ERREXIT(cinfo, JERR_BMP_BADDEPTH);
518 break;
519 }
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000520 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 */
Leon Scroggins III3993b372018-07-16 10:43:45 -0400525 cinfo->X_density = (UINT16)(biXPelsPerMeter / 100); /* 100 cm per meter */
526 cinfo->Y_density = (UINT16)(biYPelsPerMeter / 100);
DRCe5eaf372014-05-09 18:00:32 +0000527 cinfo->density_unit = 2; /* dots/cm */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000528 }
529 break;
530 default:
531 ERREXIT(cinfo, JERR_BMP_BADHEADER);
Guido Vollbeding989630f2010-01-10 00:00:00 +0000532 return;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000533 }
534
Guido Vollbeding989630f2010-01-10 00:00:00 +0000535 if (biWidth <= 0 || biHeight <= 0)
536 ERREXIT(cinfo, JERR_BMP_EMPTY);
537 if (biPlanes != 1)
538 ERREXIT(cinfo, JERR_BMP_BADPLANES);
539
Thomas G. Lane9ba2f5e1994-12-07 00:00:00 +0000540 /* Compute distance to bitmap data --- will adjust for colormap below */
541 bPad = bfOffBits - (headerSize + 14);
542
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000543 /* Read the colormap, if any */
544 if (mapentrysize > 0) {
545 if (biClrUsed <= 0)
DRCe5eaf372014-05-09 18:00:32 +0000546 biClrUsed = 256; /* assume it's 256 */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000547 else if (biClrUsed > 256)
548 ERREXIT(cinfo, JERR_BMP_BADCMAP);
549 /* Allocate space to store the colormap */
550 source->colormap = (*cinfo->mem->alloc_sarray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400551 ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)biClrUsed, (JDIMENSION)3);
552 source->cmap_length = (int)biClrUsed;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000553 /* and read it from the file */
Leon Scroggins III3993b372018-07-16 10:43:45 -0400554 read_colormap(source, (int)biClrUsed, mapentrysize);
Thomas G. Lane9ba2f5e1994-12-07 00:00:00 +0000555 /* account for size of colormap */
556 bPad -= biClrUsed * mapentrysize;
557 }
558
559 /* Skip any remaining pad bytes */
DRCe5eaf372014-05-09 18:00:32 +0000560 if (bPad < 0) /* incorrect bfOffBits value? */
Thomas G. Lane9ba2f5e1994-12-07 00:00:00 +0000561 ERREXIT(cinfo, JERR_BMP_BADHEADER);
562 while (--bPad >= 0) {
Leon Scroggins III3993b372018-07-16 10:43:45 -0400563 (void)read_byte(source);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000564 }
565
566 /* Compute row width in file, including padding to 4-byte boundary */
Leon Scroggins III3993b372018-07-16 10:43:45 -0400567 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 }
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000606 while ((row_width & 3) != 0) row_width++;
607 source->row_width = row_width;
608
Leon Scroggins III3993b372018-07-16 10:43:45 -0400609 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 }
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000635 }
636
Leon Scroggins III3993b372018-07-16 10:43:45 -0400637 /* 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);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000643 /* Allocate one-row buffer for returned data */
644 source->pub.buffer = (*cinfo->mem->alloc_sarray)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400645 ((j_common_ptr)cinfo, JPOOL_IMAGE,
646 (JDIMENSION)(biWidth * cinfo->input_components), (JDIMENSION)1);
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000647 source->pub.buffer_height = 1;
648
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000649 cinfo->data_precision = 8;
Leon Scroggins III3993b372018-07-16 10:43:45 -0400650 cinfo->image_width = (JDIMENSION)biWidth;
651 cinfo->image_height = (JDIMENSION)biHeight;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000652}
653
654
655/*
656 * Finish up at the end of the file.
657 */
658
Thomas G. Lane489583f1996-02-07 00:00:00 +0000659METHODDEF(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400660finish_input_bmp(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000661{
662 /* no work */
663}
664
665
666/*
667 * The module selection routine for BMP format input.
668 */
669
Thomas G. Lane489583f1996-02-07 00:00:00 +0000670GLOBAL(cjpeg_source_ptr)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400671jinit_read_bmp(j_compress_ptr cinfo, boolean use_inversion_array)
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000672{
673 bmp_source_ptr source;
674
675 /* Create module interface object */
676 source = (bmp_source_ptr)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400677 (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
678 sizeof(bmp_source_struct));
DRCe5eaf372014-05-09 18:00:32 +0000679 source->cinfo = cinfo; /* make back link for subroutines */
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000680 /* 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
Leon Scroggins III3993b372018-07-16 10:43:45 -0400684 source->use_inversion_array = use_inversion_array;
685
686 return (cjpeg_source_ptr)source;
Thomas G. Lane36a4ccc1994-09-24 00:00:00 +0000687}
688
689#endif /* BMP_SUPPORTED */