rdtarga.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. /*
  2. * rdtarga.c
  3. *
  4. * This file was part of the Independent JPEG Group's software:
  5. * Copyright (C) 1991-1996, Thomas G. Lane.
  6. * Modified 2017 by Guido Vollbeding.
  7. * libjpeg-turbo Modifications:
  8. * Copyright (C) 2018, D. R. Commander.
  9. * For conditions of distribution and use, see the accompanying README.ijg
  10. * file.
  11. *
  12. * This file contains routines to read input images in Targa format.
  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 Targa format).
  20. *
  21. * Based on code contributed by Lee Daniel Crocker.
  22. */
  23. #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
  24. #ifdef TARGA_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_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) \
  39. (JFREAD(file, buffer, len) == ((size_t)(len)))
  40. /* Private version of data source object */
  41. typedef struct _tga_source_struct *tga_source_ptr;
  42. typedef struct _tga_source_struct {
  43. struct cjpeg_source_struct pub; /* public fields */
  44. j_compress_ptr cinfo; /* back link saves passing separate parm */
  45. JSAMPARRAY colormap; /* Targa colormap (converted to my format) */
  46. jvirt_sarray_ptr whole_image; /* Needed if funny input row order */
  47. JDIMENSION current_row; /* Current logical row number to read */
  48. /* Pointer to routine to extract next Targa pixel from input file */
  49. void (*read_pixel) (tga_source_ptr sinfo);
  50. /* Result of read_pixel is delivered here: */
  51. U_CHAR tga_pixel[4];
  52. int pixel_size; /* Bytes per Targa pixel (1 to 4) */
  53. int cmap_length; /* colormap length */
  54. /* State info for reading RLE-coded pixels; both counts must be init to 0 */
  55. int block_count; /* # of pixels remaining in RLE block */
  56. int dup_pixel_count; /* # of times to duplicate previous pixel */
  57. /* This saves the correct pixel-row-expansion method for preload_image */
  58. JDIMENSION (*get_pixel_rows) (j_compress_ptr cinfo, cjpeg_source_ptr sinfo);
  59. } tga_source_struct;
  60. /* For expanding 5-bit pixel values to 8-bit with best rounding */
  61. static const UINT8 c5to8bits[32] = {
  62. 0, 8, 16, 25, 33, 41, 49, 58,
  63. 66, 74, 82, 90, 99, 107, 115, 123,
  64. 132, 140, 148, 156, 165, 173, 181, 189,
  65. 197, 206, 214, 222, 230, 239, 247, 255
  66. };
  67. LOCAL(int)
  68. read_byte(tga_source_ptr sinfo)
  69. /* Read next byte from Targa file */
  70. {
  71. register FILE *infile = sinfo->pub.input_file;
  72. register int c;
  73. if ((c = getc(infile)) == EOF)
  74. ERREXIT(sinfo->cinfo, JERR_INPUT_EOF);
  75. return c;
  76. }
  77. LOCAL(void)
  78. read_colormap(tga_source_ptr sinfo, int cmaplen, int mapentrysize)
  79. /* Read the colormap from a Targa file */
  80. {
  81. int i;
  82. /* Presently only handles 24-bit BGR format */
  83. if (mapentrysize != 24)
  84. ERREXIT(sinfo->cinfo, JERR_TGA_BADCMAP);
  85. for (i = 0; i < cmaplen; i++) {
  86. sinfo->colormap[2][i] = (JSAMPLE)read_byte(sinfo);
  87. sinfo->colormap[1][i] = (JSAMPLE)read_byte(sinfo);
  88. sinfo->colormap[0][i] = (JSAMPLE)read_byte(sinfo);
  89. }
  90. }
  91. /*
  92. * read_pixel methods: get a single pixel from Targa file into tga_pixel[]
  93. */
  94. METHODDEF(void)
  95. read_non_rle_pixel(tga_source_ptr sinfo)
  96. /* Read one Targa pixel from the input file; no RLE expansion */
  97. {
  98. register int i;
  99. for (i = 0; i < sinfo->pixel_size; i++) {
  100. sinfo->tga_pixel[i] = (U_CHAR)read_byte(sinfo);
  101. }
  102. }
  103. METHODDEF(void)
  104. read_rle_pixel(tga_source_ptr sinfo)
  105. /* Read one Targa pixel from the input file, expanding RLE data as needed */
  106. {
  107. register int i;
  108. /* Duplicate previously read pixel? */
  109. if (sinfo->dup_pixel_count > 0) {
  110. sinfo->dup_pixel_count--;
  111. return;
  112. }
  113. /* Time to read RLE block header? */
  114. if (--sinfo->block_count < 0) { /* decrement pixels remaining in block */
  115. i = read_byte(sinfo);
  116. if (i & 0x80) { /* Start of duplicate-pixel block? */
  117. sinfo->dup_pixel_count = i & 0x7F; /* number of dups after this one */
  118. sinfo->block_count = 0; /* then read new block header */
  119. } else {
  120. sinfo->block_count = i & 0x7F; /* number of pixels after this one */
  121. }
  122. }
  123. /* Read next pixel */
  124. for (i = 0; i < sinfo->pixel_size; i++) {
  125. sinfo->tga_pixel[i] = (U_CHAR)read_byte(sinfo);
  126. }
  127. }
  128. /*
  129. * Read one row of pixels.
  130. *
  131. * We provide several different versions depending on input file format.
  132. */
  133. METHODDEF(JDIMENSION)
  134. get_8bit_gray_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  135. /* This version is for reading 8-bit grayscale pixels */
  136. {
  137. tga_source_ptr source = (tga_source_ptr)sinfo;
  138. register JSAMPROW ptr;
  139. register JDIMENSION col;
  140. ptr = source->pub.buffer[0];
  141. for (col = cinfo->image_width; col > 0; col--) {
  142. (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
  143. *ptr++ = (JSAMPLE)UCH(source->tga_pixel[0]);
  144. }
  145. return 1;
  146. }
  147. METHODDEF(JDIMENSION)
  148. get_8bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  149. /* This version is for reading 8-bit colormap indexes */
  150. {
  151. tga_source_ptr source = (tga_source_ptr)sinfo;
  152. register int t;
  153. register JSAMPROW ptr;
  154. register JDIMENSION col;
  155. register JSAMPARRAY colormap = source->colormap;
  156. int cmaplen = source->cmap_length;
  157. ptr = source->pub.buffer[0];
  158. for (col = cinfo->image_width; col > 0; col--) {
  159. (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
  160. t = UCH(source->tga_pixel[0]);
  161. if (t >= cmaplen)
  162. ERREXIT(cinfo, JERR_TGA_BADPARMS);
  163. *ptr++ = colormap[0][t];
  164. *ptr++ = colormap[1][t];
  165. *ptr++ = colormap[2][t];
  166. }
  167. return 1;
  168. }
  169. METHODDEF(JDIMENSION)
  170. get_16bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  171. /* This version is for reading 16-bit pixels */
  172. {
  173. tga_source_ptr source = (tga_source_ptr)sinfo;
  174. register int t;
  175. register JSAMPROW ptr;
  176. register JDIMENSION col;
  177. ptr = source->pub.buffer[0];
  178. for (col = cinfo->image_width; col > 0; col--) {
  179. (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
  180. t = UCH(source->tga_pixel[0]);
  181. t += UCH(source->tga_pixel[1]) << 8;
  182. /* We expand 5 bit data to 8 bit sample width.
  183. * The format of the 16-bit (LSB first) input word is
  184. * xRRRRRGGGGGBBBBB
  185. */
  186. ptr[2] = (JSAMPLE)c5to8bits[t & 0x1F];
  187. t >>= 5;
  188. ptr[1] = (JSAMPLE)c5to8bits[t & 0x1F];
  189. t >>= 5;
  190. ptr[0] = (JSAMPLE)c5to8bits[t & 0x1F];
  191. ptr += 3;
  192. }
  193. return 1;
  194. }
  195. METHODDEF(JDIMENSION)
  196. get_24bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  197. /* This version is for reading 24-bit pixels */
  198. {
  199. tga_source_ptr source = (tga_source_ptr)sinfo;
  200. register JSAMPROW ptr;
  201. register JDIMENSION col;
  202. ptr = source->pub.buffer[0];
  203. for (col = cinfo->image_width; col > 0; col--) {
  204. (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
  205. *ptr++ = (JSAMPLE)UCH(source->tga_pixel[2]); /* change BGR to RGB order */
  206. *ptr++ = (JSAMPLE)UCH(source->tga_pixel[1]);
  207. *ptr++ = (JSAMPLE)UCH(source->tga_pixel[0]);
  208. }
  209. return 1;
  210. }
  211. /*
  212. * Targa also defines a 32-bit pixel format with order B,G,R,A.
  213. * We presently ignore the attribute byte, so the code for reading
  214. * these pixels is identical to the 24-bit routine above.
  215. * This works because the actual pixel length is only known to read_pixel.
  216. */
  217. #define get_32bit_row get_24bit_row
  218. /*
  219. * This method is for re-reading the input data in standard top-down
  220. * row order. The entire image has already been read into whole_image
  221. * with proper conversion of pixel format, but it's in a funny row order.
  222. */
  223. METHODDEF(JDIMENSION)
  224. get_memory_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  225. {
  226. tga_source_ptr source = (tga_source_ptr)sinfo;
  227. JDIMENSION source_row;
  228. /* Compute row of source that maps to current_row of normal order */
  229. /* For now, assume image is bottom-up and not interlaced. */
  230. /* NEEDS WORK to support interlaced images! */
  231. source_row = cinfo->image_height - source->current_row - 1;
  232. /* Fetch that row from virtual array */
  233. source->pub.buffer = (*cinfo->mem->access_virt_sarray)
  234. ((j_common_ptr)cinfo, source->whole_image,
  235. source_row, (JDIMENSION)1, FALSE);
  236. source->current_row++;
  237. return 1;
  238. }
  239. /*
  240. * This method loads the image into whole_image during the first call on
  241. * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call
  242. * get_memory_row on subsequent calls.
  243. */
  244. METHODDEF(JDIMENSION)
  245. preload_image(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  246. {
  247. tga_source_ptr source = (tga_source_ptr)sinfo;
  248. JDIMENSION row;
  249. cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress;
  250. /* Read the data into a virtual array in input-file row order. */
  251. for (row = 0; row < cinfo->image_height; row++) {
  252. if (progress != NULL) {
  253. progress->pub.pass_counter = (long)row;
  254. progress->pub.pass_limit = (long)cinfo->image_height;
  255. (*progress->pub.progress_monitor) ((j_common_ptr)cinfo);
  256. }
  257. source->pub.buffer = (*cinfo->mem->access_virt_sarray)
  258. ((j_common_ptr)cinfo, source->whole_image, row, (JDIMENSION)1, TRUE);
  259. (*source->get_pixel_rows) (cinfo, sinfo);
  260. }
  261. if (progress != NULL)
  262. progress->completed_extra_passes++;
  263. /* Set up to read from the virtual array in unscrambled order */
  264. source->pub.get_pixel_rows = get_memory_row;
  265. source->current_row = 0;
  266. /* And read the first row */
  267. return get_memory_row(cinfo, sinfo);
  268. }
  269. /*
  270. * Read the file header; return image size and component count.
  271. */
  272. METHODDEF(void)
  273. start_input_tga(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  274. {
  275. tga_source_ptr source = (tga_source_ptr)sinfo;
  276. U_CHAR targaheader[18];
  277. int idlen, cmaptype, subtype, flags, interlace_type, components;
  278. unsigned int width, height, maplen;
  279. boolean is_bottom_up;
  280. #define GET_2B(offset) ((unsigned int)UCH(targaheader[offset]) + \
  281. (((unsigned int)UCH(targaheader[offset + 1])) << 8))
  282. if (!ReadOK(source->pub.input_file, targaheader, 18))
  283. ERREXIT(cinfo, JERR_INPUT_EOF);
  284. /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */
  285. if (targaheader[16] == 15)
  286. targaheader[16] = 16;
  287. idlen = UCH(targaheader[0]);
  288. cmaptype = UCH(targaheader[1]);
  289. subtype = UCH(targaheader[2]);
  290. maplen = GET_2B(5);
  291. width = GET_2B(12);
  292. height = GET_2B(14);
  293. source->pixel_size = UCH(targaheader[16]) >> 3;
  294. flags = UCH(targaheader[17]); /* Image Descriptor byte */
  295. is_bottom_up = ((flags & 0x20) == 0); /* bit 5 set => top-down */
  296. interlace_type = flags >> 6; /* bits 6/7 are interlace code */
  297. if (cmaptype > 1 || /* cmaptype must be 0 or 1 */
  298. source->pixel_size < 1 || source->pixel_size > 4 ||
  299. (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */
  300. interlace_type != 0 || /* currently don't allow interlaced image */
  301. width == 0 || height == 0) /* image width/height must be non-zero */
  302. ERREXIT(cinfo, JERR_TGA_BADPARMS);
  303. if (subtype > 8) {
  304. /* It's an RLE-coded file */
  305. source->read_pixel = read_rle_pixel;
  306. source->block_count = source->dup_pixel_count = 0;
  307. subtype -= 8;
  308. } else {
  309. /* Non-RLE file */
  310. source->read_pixel = read_non_rle_pixel;
  311. }
  312. /* Now should have subtype 1, 2, or 3 */
  313. components = 3; /* until proven different */
  314. cinfo->in_color_space = JCS_RGB;
  315. switch (subtype) {
  316. case 1: /* Colormapped image */
  317. if (source->pixel_size == 1 && cmaptype == 1)
  318. source->get_pixel_rows = get_8bit_row;
  319. else
  320. ERREXIT(cinfo, JERR_TGA_BADPARMS);
  321. TRACEMS2(cinfo, 1, JTRC_TGA_MAPPED, width, height);
  322. break;
  323. case 2: /* RGB image */
  324. switch (source->pixel_size) {
  325. case 2:
  326. source->get_pixel_rows = get_16bit_row;
  327. break;
  328. case 3:
  329. source->get_pixel_rows = get_24bit_row;
  330. break;
  331. case 4:
  332. source->get_pixel_rows = get_32bit_row;
  333. break;
  334. default:
  335. ERREXIT(cinfo, JERR_TGA_BADPARMS);
  336. break;
  337. }
  338. TRACEMS2(cinfo, 1, JTRC_TGA, width, height);
  339. break;
  340. case 3: /* Grayscale image */
  341. components = 1;
  342. cinfo->in_color_space = JCS_GRAYSCALE;
  343. if (source->pixel_size == 1)
  344. source->get_pixel_rows = get_8bit_gray_row;
  345. else
  346. ERREXIT(cinfo, JERR_TGA_BADPARMS);
  347. TRACEMS2(cinfo, 1, JTRC_TGA_GRAY, width, height);
  348. break;
  349. default:
  350. ERREXIT(cinfo, JERR_TGA_BADPARMS);
  351. break;
  352. }
  353. if (is_bottom_up) {
  354. /* Create a virtual array to buffer the upside-down image. */
  355. source->whole_image = (*cinfo->mem->request_virt_sarray)
  356. ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE,
  357. (JDIMENSION)width * components, (JDIMENSION)height, (JDIMENSION)1);
  358. if (cinfo->progress != NULL) {
  359. cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress;
  360. progress->total_extra_passes++; /* count file input as separate pass */
  361. }
  362. /* source->pub.buffer will point to the virtual array. */
  363. source->pub.buffer_height = 1; /* in case anyone looks at it */
  364. source->pub.get_pixel_rows = preload_image;
  365. } else {
  366. /* Don't need a virtual array, but do need a one-row input buffer. */
  367. source->whole_image = NULL;
  368. source->pub.buffer = (*cinfo->mem->alloc_sarray)
  369. ((j_common_ptr)cinfo, JPOOL_IMAGE,
  370. (JDIMENSION)width * components, (JDIMENSION)1);
  371. source->pub.buffer_height = 1;
  372. source->pub.get_pixel_rows = source->get_pixel_rows;
  373. }
  374. while (idlen--) /* Throw away ID field */
  375. (void)read_byte(source);
  376. if (maplen > 0) {
  377. if (maplen > 256 || GET_2B(3) != 0)
  378. ERREXIT(cinfo, JERR_TGA_BADCMAP);
  379. /* Allocate space to store the colormap */
  380. source->colormap = (*cinfo->mem->alloc_sarray)
  381. ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)maplen, (JDIMENSION)3);
  382. source->cmap_length = (int)maplen;
  383. /* and read it from the file */
  384. read_colormap(source, (int)maplen, UCH(targaheader[7]));
  385. } else {
  386. if (cmaptype) /* but you promised a cmap! */
  387. ERREXIT(cinfo, JERR_TGA_BADPARMS);
  388. source->colormap = NULL;
  389. source->cmap_length = 0;
  390. }
  391. cinfo->input_components = components;
  392. cinfo->data_precision = 8;
  393. cinfo->image_width = width;
  394. cinfo->image_height = height;
  395. }
  396. /*
  397. * Finish up at the end of the file.
  398. */
  399. METHODDEF(void)
  400. finish_input_tga(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
  401. {
  402. /* no work */
  403. }
  404. /*
  405. * The module selection routine for Targa format input.
  406. */
  407. GLOBAL(cjpeg_source_ptr)
  408. jinit_read_targa(j_compress_ptr cinfo)
  409. {
  410. tga_source_ptr source;
  411. /* Create module interface object */
  412. source = (tga_source_ptr)
  413. (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
  414. sizeof(tga_source_struct));
  415. source->cinfo = cinfo; /* make back link for subroutines */
  416. /* Fill in method ptrs, except get_pixel_rows which start_input sets */
  417. source->pub.start_input = start_input_tga;
  418. source->pub.finish_input = finish_input_tga;
  419. return (cjpeg_source_ptr)source;
  420. }
  421. #endif /* TARGA_SUPPORTED */