rdbmp.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. /*
  2. * rdbmp.c
  3. *
  4. * Copyright (C) 1994-1996, Thomas G. Lane.
  5. * Modified 2009-2010 by Guido Vollbeding.
  6. * This file is part of the Independent JPEG Group's software.
  7. * For conditions of distribution and use, see the accompanying README file.
  8. *
  9. * This file contains routines to read input images in Microsoft "BMP"
  10. * format (MS Windows 3.x, OS/2 1.x, and OS/2 2.x flavors).
  11. * Currently, only 8-bit and 24-bit images are supported, not 1-bit or
  12. * 4-bit (feeding such low-depth images into JPEG would be silly anyway).
  13. * Also, we don't support RLE-compressed files.
  14. *
  15. * These routines may need modification for non-Unix environments or
  16. * specialized applications. As they stand, they assume input from
  17. * an ordinary stdio stream. They further assume that reading begins
  18. * at the start of the file; start_input may need work if the
  19. * user interface has already read some data (e.g., to determine that
  20. * the file is indeed BMP format).
  21. *
  22. * This code contributed by James Arthur Boucher.
  23. */
  24. #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
  25. #ifdef BMP_SUPPORTED
  26. /* Macros to deal with unsigned chars as efficiently as compiler allows */
  27. #ifdef HAVE_UNSIGNED_CHAR
  28. typedef unsigned char U_CHAR;
  29. #define UCH(x) ((int) (x))
  30. #else /* !HAVE_UNSIGNED_CHAR */
  31. #ifdef CHAR_IS_UNSIGNED
  32. typedef char U_CHAR;
  33. #define UCH(x) ((int) (x))
  34. #else
  35. typedef char U_CHAR;
  36. #define UCH(x) ((int) (x) & 0xFF)
  37. #endif
  38. #endif /* HAVE_UNSIGNED_CHAR */
  39. #define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
  40. /* Private version of data source object */
  41. typedef struct _bmp_source_struct * bmp_source_ptr;
  42. typedef struct _bmp_source_struct {
  43. struct cjpeg_source_struct pub; /* public fields */
  44. j_compress_ptr cinfo; /* back link saves passing separate parm */
  45. JSAMPARRAY colormap; /* BMP colormap (converted to my format) */
  46. jvirt_sarray_ptr whole_image; /* Needed to reverse row order */
  47. JDIMENSION source_row; /* Current source row number */
  48. JDIMENSION row_width; /* Physical width of scanlines in file */
  49. int bits_per_pixel; /* remembers 8- or 24-bit format */
  50. } bmp_source_struct;
  51. LOCAL(int)
  52. read_byte (bmp_source_ptr sinfo)
  53. /* Read next byte from BMP file */
  54. {
  55. register FILE *infile = sinfo->pub.input_file;
  56. register int c;
  57. if ((c = getc(infile)) == EOF)
  58. ERREXIT(sinfo->cinfo, JERR_INPUT_EOF);
  59. return c;
  60. }
  61. LOCAL(void)
  62. read_colormap (bmp_source_ptr sinfo, int cmaplen, int mapentrysize)
  63. /* Read the colormap from a BMP file */
  64. {
  65. int i;
  66. switch (mapentrysize) {
  67. case 3:
  68. /* BGR format (occurs in OS/2 files) */
  69. for (i = 0; i < cmaplen; i++) {
  70. sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
  71. sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
  72. sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
  73. }
  74. break;
  75. case 4:
  76. /* BGR0 format (occurs in MS Windows 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. (void) read_byte(sinfo);
  82. }
  83. break;
  84. default:
  85. ERREXIT(sinfo->cinfo, JERR_BMP_BADCMAP);
  86. break;
  87. }
  88. }
  89. /*
  90. * Read one row of pixels.
  91. * The image has been read into the whole_image array, but is otherwise
  92. * unprocessed. We must read it out in top-to-bottom row order, and if
  93. * it is an 8-bit image, we must expand colormapped pixels to 24bit format.
  94. */
  95. METHODDEF(JDIMENSION)
  96. get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  97. /* This version is for reading 8-bit colormap indexes */
  98. {
  99. bmp_source_ptr source = (bmp_source_ptr) sinfo;
  100. register JSAMPARRAY colormap = source->colormap;
  101. JSAMPARRAY image_ptr;
  102. register int t;
  103. register JSAMPROW inptr, outptr;
  104. register JDIMENSION col;
  105. /* Fetch next row from virtual array */
  106. source->source_row--;
  107. image_ptr = (*cinfo->mem->access_virt_sarray)
  108. ((j_common_ptr) cinfo, source->whole_image,
  109. source->source_row, (JDIMENSION) 1, FALSE);
  110. /* Expand the colormap indexes to real data */
  111. inptr = image_ptr[0];
  112. outptr = source->pub.buffer[0];
  113. for (col = cinfo->image_width; col > 0; col--) {
  114. t = GETJSAMPLE(*inptr++);
  115. *outptr++ = colormap[0][t]; /* can omit GETJSAMPLE() safely */
  116. *outptr++ = colormap[1][t];
  117. *outptr++ = colormap[2][t];
  118. }
  119. return 1;
  120. }
  121. METHODDEF(JDIMENSION)
  122. get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  123. /* This version is for reading 24-bit pixels */
  124. {
  125. bmp_source_ptr source = (bmp_source_ptr) sinfo;
  126. JSAMPARRAY image_ptr;
  127. register JSAMPROW inptr, outptr;
  128. register JDIMENSION col;
  129. /* Fetch next row from virtual array */
  130. source->source_row--;
  131. image_ptr = (*cinfo->mem->access_virt_sarray)
  132. ((j_common_ptr) cinfo, source->whole_image,
  133. source->source_row, (JDIMENSION) 1, FALSE);
  134. /* Transfer data. Note source values are in BGR order
  135. * (even though Microsoft's own documents say the opposite).
  136. */
  137. inptr = image_ptr[0];
  138. outptr = source->pub.buffer[0];
  139. for (col = cinfo->image_width; col > 0; col--) {
  140. outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */
  141. outptr[1] = *inptr++;
  142. outptr[0] = *inptr++;
  143. outptr += 3;
  144. }
  145. return 1;
  146. }
  147. METHODDEF(JDIMENSION)
  148. get_32bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  149. /* This version is for reading 32-bit pixels */
  150. {
  151. bmp_source_ptr source = (bmp_source_ptr) sinfo;
  152. JSAMPARRAY image_ptr;
  153. register JSAMPROW inptr, outptr;
  154. register JDIMENSION col;
  155. /* Fetch next row from virtual array */
  156. source->source_row--;
  157. image_ptr = (*cinfo->mem->access_virt_sarray)
  158. ((j_common_ptr) cinfo, source->whole_image,
  159. source->source_row, (JDIMENSION) 1, FALSE);
  160. /* Transfer data. Note source values are in BGR order
  161. * (even though Microsoft's own documents say the opposite).
  162. */
  163. inptr = image_ptr[0];
  164. outptr = source->pub.buffer[0];
  165. for (col = cinfo->image_width; col > 0; col--) {
  166. outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */
  167. outptr[1] = *inptr++;
  168. outptr[0] = *inptr++;
  169. inptr++; /* skip the 4th byte (Alpha channel) */
  170. outptr += 3;
  171. }
  172. return 1;
  173. }
  174. /*
  175. * This method loads the image into whole_image during the first call on
  176. * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call
  177. * get_8bit_row, get_24bit_row, or get_32bit_row on subsequent calls.
  178. */
  179. METHODDEF(JDIMENSION)
  180. preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  181. {
  182. bmp_source_ptr source = (bmp_source_ptr) sinfo;
  183. register FILE *infile = source->pub.input_file;
  184. register int c;
  185. register JSAMPROW out_ptr;
  186. JSAMPARRAY image_ptr;
  187. JDIMENSION row, col;
  188. cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
  189. /* Read the data into a virtual array in input-file row order. */
  190. for (row = 0; row < cinfo->image_height; row++) {
  191. if (progress != NULL) {
  192. progress->pub.pass_counter = (long) row;
  193. progress->pub.pass_limit = (long) cinfo->image_height;
  194. (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
  195. }
  196. image_ptr = (*cinfo->mem->access_virt_sarray)
  197. ((j_common_ptr) cinfo, source->whole_image,
  198. row, (JDIMENSION) 1, TRUE);
  199. out_ptr = image_ptr[0];
  200. for (col = source->row_width; col > 0; col--) {
  201. /* inline copy of read_byte() for speed */
  202. if ((c = getc(infile)) == EOF)
  203. ERREXIT(cinfo, JERR_INPUT_EOF);
  204. *out_ptr++ = (JSAMPLE) c;
  205. }
  206. }
  207. if (progress != NULL)
  208. progress->completed_extra_passes++;
  209. /* Set up to read from the virtual array in top-to-bottom order */
  210. switch (source->bits_per_pixel) {
  211. case 8:
  212. source->pub.get_pixel_rows = get_8bit_row;
  213. break;
  214. case 24:
  215. source->pub.get_pixel_rows = get_24bit_row;
  216. break;
  217. case 32:
  218. source->pub.get_pixel_rows = get_32bit_row;
  219. break;
  220. default:
  221. ERREXIT(cinfo, JERR_BMP_BADDEPTH);
  222. }
  223. source->source_row = cinfo->image_height;
  224. /* And read the first row */
  225. return (*source->pub.get_pixel_rows) (cinfo, sinfo);
  226. }
  227. /*
  228. * Read the file header; return image size and component count.
  229. */
  230. METHODDEF(void)
  231. start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  232. {
  233. bmp_source_ptr source = (bmp_source_ptr) sinfo;
  234. U_CHAR bmpfileheader[14];
  235. U_CHAR bmpinfoheader[64];
  236. #define GET_2B(array,offset) ((unsigned int) UCH(array[offset]) + \
  237. (((unsigned int) UCH(array[offset+1])) << 8))
  238. #define GET_4B(array,offset) ((INT32) UCH(array[offset]) + \
  239. (((INT32) UCH(array[offset+1])) << 8) + \
  240. (((INT32) UCH(array[offset+2])) << 16) + \
  241. (((INT32) UCH(array[offset+3])) << 24))
  242. INT32 bfOffBits;
  243. INT32 headerSize;
  244. INT32 biWidth;
  245. INT32 biHeight;
  246. unsigned int biPlanes;
  247. INT32 biCompression;
  248. INT32 biXPelsPerMeter,biYPelsPerMeter;
  249. INT32 biClrUsed = 0;
  250. int mapentrysize = 0; /* 0 indicates no colormap */
  251. INT32 bPad;
  252. JDIMENSION row_width;
  253. /* Read and verify the bitmap file header */
  254. if (! ReadOK(source->pub.input_file, bmpfileheader, 14))
  255. ERREXIT(cinfo, JERR_INPUT_EOF);
  256. if (GET_2B(bmpfileheader,0) != 0x4D42) /* 'BM' */
  257. ERREXIT(cinfo, JERR_BMP_NOT);
  258. bfOffBits = (INT32) GET_4B(bmpfileheader,10);
  259. /* We ignore the remaining fileheader fields */
  260. /* The infoheader might be 12 bytes (OS/2 1.x), 40 bytes (Windows),
  261. * or 64 bytes (OS/2 2.x). Check the first 4 bytes to find out which.
  262. */
  263. if (! ReadOK(source->pub.input_file, bmpinfoheader, 4))
  264. ERREXIT(cinfo, JERR_INPUT_EOF);
  265. headerSize = (INT32) GET_4B(bmpinfoheader,0);
  266. if (headerSize < 12 || headerSize > 64)
  267. ERREXIT(cinfo, JERR_BMP_BADHEADER);
  268. if (! ReadOK(source->pub.input_file, bmpinfoheader+4, headerSize-4))
  269. ERREXIT(cinfo, JERR_INPUT_EOF);
  270. switch ((int) headerSize) {
  271. case 12:
  272. /* Decode OS/2 1.x header (Microsoft calls this a BITMAPCOREHEADER) */
  273. biWidth = (INT32) GET_2B(bmpinfoheader,4);
  274. biHeight = (INT32) GET_2B(bmpinfoheader,6);
  275. biPlanes = GET_2B(bmpinfoheader,8);
  276. source->bits_per_pixel = (int) GET_2B(bmpinfoheader,10);
  277. switch (source->bits_per_pixel) {
  278. case 8: /* colormapped image */
  279. mapentrysize = 3; /* OS/2 uses RGBTRIPLE colormap */
  280. TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, (int) biWidth, (int) biHeight);
  281. break;
  282. case 24: /* RGB image */
  283. TRACEMS2(cinfo, 1, JTRC_BMP_OS2, (int) biWidth, (int) biHeight);
  284. break;
  285. default:
  286. ERREXIT(cinfo, JERR_BMP_BADDEPTH);
  287. break;
  288. }
  289. break;
  290. case 40:
  291. case 64:
  292. /* Decode Windows 3.x header (Microsoft calls this a BITMAPINFOHEADER) */
  293. /* or OS/2 2.x header, which has additional fields that we ignore */
  294. biWidth = GET_4B(bmpinfoheader,4);
  295. biHeight = GET_4B(bmpinfoheader,8);
  296. biPlanes = GET_2B(bmpinfoheader,12);
  297. source->bits_per_pixel = (int) GET_2B(bmpinfoheader,14);
  298. biCompression = GET_4B(bmpinfoheader,16);
  299. biXPelsPerMeter = GET_4B(bmpinfoheader,24);
  300. biYPelsPerMeter = GET_4B(bmpinfoheader,28);
  301. biClrUsed = GET_4B(bmpinfoheader,32);
  302. /* biSizeImage, biClrImportant fields are ignored */
  303. switch (source->bits_per_pixel) {
  304. case 8: /* colormapped image */
  305. mapentrysize = 4; /* Windows uses RGBQUAD colormap */
  306. TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, (int) biWidth, (int) biHeight);
  307. break;
  308. case 24: /* RGB image */
  309. TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
  310. break;
  311. case 32: /* RGB image + Alpha channel */
  312. TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
  313. break;
  314. default:
  315. ERREXIT(cinfo, JERR_BMP_BADDEPTH);
  316. break;
  317. }
  318. if (biCompression != 0)
  319. ERREXIT(cinfo, JERR_BMP_COMPRESSED);
  320. if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) {
  321. /* Set JFIF density parameters from the BMP data */
  322. cinfo->X_density = (UINT16) (biXPelsPerMeter/100); /* 100 cm per meter */
  323. cinfo->Y_density = (UINT16) (biYPelsPerMeter/100);
  324. cinfo->density_unit = 2; /* dots/cm */
  325. }
  326. break;
  327. default:
  328. ERREXIT(cinfo, JERR_BMP_BADHEADER);
  329. return;
  330. }
  331. if (biWidth <= 0 || biHeight <= 0)
  332. ERREXIT(cinfo, JERR_BMP_EMPTY);
  333. if (biPlanes != 1)
  334. ERREXIT(cinfo, JERR_BMP_BADPLANES);
  335. /* Compute distance to bitmap data --- will adjust for colormap below */
  336. bPad = bfOffBits - (headerSize + 14);
  337. /* Read the colormap, if any */
  338. if (mapentrysize > 0) {
  339. if (biClrUsed <= 0)
  340. biClrUsed = 256; /* assume it's 256 */
  341. else if (biClrUsed > 256)
  342. ERREXIT(cinfo, JERR_BMP_BADCMAP);
  343. /* Allocate space to store the colormap */
  344. source->colormap = (*cinfo->mem->alloc_sarray)
  345. ((j_common_ptr) cinfo, JPOOL_IMAGE,
  346. (JDIMENSION) biClrUsed, (JDIMENSION) 3);
  347. /* and read it from the file */
  348. read_colormap(source, (int) biClrUsed, mapentrysize);
  349. /* account for size of colormap */
  350. bPad -= biClrUsed * mapentrysize;
  351. }
  352. /* Skip any remaining pad bytes */
  353. if (bPad < 0) /* incorrect bfOffBits value? */
  354. ERREXIT(cinfo, JERR_BMP_BADHEADER);
  355. while (--bPad >= 0) {
  356. (void) read_byte(source);
  357. }
  358. /* Compute row width in file, including padding to 4-byte boundary */
  359. if (source->bits_per_pixel == 24)
  360. row_width = (JDIMENSION) (biWidth * 3);
  361. else if (source->bits_per_pixel == 32)
  362. row_width = (JDIMENSION) (biWidth * 4);
  363. else
  364. row_width = (JDIMENSION) biWidth;
  365. while ((row_width & 3) != 0) row_width++;
  366. source->row_width = row_width;
  367. /* Allocate space for inversion array, prepare for preload pass */
  368. source->whole_image = (*cinfo->mem->request_virt_sarray)
  369. ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
  370. row_width, (JDIMENSION) biHeight, (JDIMENSION) 1);
  371. source->pub.get_pixel_rows = preload_image;
  372. if (cinfo->progress != NULL) {
  373. cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
  374. progress->total_extra_passes++; /* count file input as separate pass */
  375. }
  376. /* Allocate one-row buffer for returned data */
  377. source->pub.buffer = (*cinfo->mem->alloc_sarray)
  378. ((j_common_ptr) cinfo, JPOOL_IMAGE,
  379. (JDIMENSION) (biWidth * 3), (JDIMENSION) 1);
  380. source->pub.buffer_height = 1;
  381. cinfo->in_color_space = JCS_RGB;
  382. cinfo->input_components = 3;
  383. cinfo->data_precision = 8;
  384. cinfo->image_width = (JDIMENSION) biWidth;
  385. cinfo->image_height = (JDIMENSION) biHeight;
  386. }
  387. /*
  388. * Finish up at the end of the file.
  389. */
  390. METHODDEF(void)
  391. finish_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  392. {
  393. /* no work */
  394. }
  395. /*
  396. * The module selection routine for BMP format input.
  397. */
  398. GLOBAL(cjpeg_source_ptr)
  399. jinit_read_bmp (j_compress_ptr cinfo)
  400. {
  401. bmp_source_ptr source;
  402. /* Create module interface object */
  403. source = (bmp_source_ptr)
  404. (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  405. SIZEOF(bmp_source_struct));
  406. source->cinfo = cinfo; /* make back link for subroutines */
  407. /* Fill in method ptrs, except get_pixel_rows which start_input sets */
  408. source->pub.start_input = start_input_bmp;
  409. source->pub.finish_input = finish_input_bmp;
  410. return (cjpeg_source_ptr) source;
  411. }
  412. #endif /* BMP_SUPPORTED */