You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

rdbmp.c 13KB

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