rdbmp.c 23 KB

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