Team Fortress 2 Source Code as on 22/4/2020
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.

253 lines
7.3 KiB

  1. /*
  2. * wrtarga.c
  3. *
  4. * Copyright (C) 1991-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 write output images in Targa format.
  9. *
  10. * These routines may need modification for non-Unix environments or
  11. * specialized applications. As they stand, they assume output to
  12. * an ordinary stdio stream.
  13. *
  14. * Based on code contributed by Lee Daniel Crocker.
  15. */
  16. #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
  17. #ifdef TARGA_SUPPORTED
  18. /*
  19. * To support 12-bit JPEG data, we'd have to scale output down to 8 bits.
  20. * This is not yet implemented.
  21. */
  22. #if BITS_IN_JSAMPLE != 8
  23. Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
  24. #endif
  25. /*
  26. * The output buffer needs to be writable by fwrite(). On PCs, we must
  27. * allocate the buffer in near data space, because we are assuming small-data
  28. * memory model, wherein fwrite() can't reach far memory. If you need to
  29. * process very wide images on a PC, you might have to compile in large-memory
  30. * model, or else replace fwrite() with a putc() loop --- which will be much
  31. * slower.
  32. */
  33. /* Private version of data destination object */
  34. typedef struct {
  35. struct djpeg_dest_struct pub; /* public fields */
  36. char *iobuffer; /* physical I/O buffer */
  37. JDIMENSION buffer_width; /* width of one row */
  38. } tga_dest_struct;
  39. typedef tga_dest_struct * tga_dest_ptr;
  40. LOCAL(void)
  41. write_header (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, int num_colors)
  42. /* Create and write a Targa header */
  43. {
  44. char targaheader[18];
  45. /* Set unused fields of header to 0 */
  46. MEMZERO(targaheader, SIZEOF(targaheader));
  47. if (num_colors > 0) {
  48. targaheader[1] = 1; /* color map type 1 */
  49. targaheader[5] = (char) (num_colors & 0xFF);
  50. targaheader[6] = (char) (num_colors >> 8);
  51. targaheader[7] = 24; /* 24 bits per cmap entry */
  52. }
  53. targaheader[12] = (char) (cinfo->output_width & 0xFF);
  54. targaheader[13] = (char) (cinfo->output_width >> 8);
  55. targaheader[14] = (char) (cinfo->output_height & 0xFF);
  56. targaheader[15] = (char) (cinfo->output_height >> 8);
  57. targaheader[17] = 0x20; /* Top-down, non-interlaced */
  58. if (cinfo->out_color_space == JCS_GRAYSCALE) {
  59. targaheader[2] = 3; /* image type = uncompressed gray-scale */
  60. targaheader[16] = 8; /* bits per pixel */
  61. } else { /* must be RGB */
  62. if (num_colors > 0) {
  63. targaheader[2] = 1; /* image type = colormapped RGB */
  64. targaheader[16] = 8;
  65. } else {
  66. targaheader[2] = 2; /* image type = uncompressed RGB */
  67. targaheader[16] = 24;
  68. }
  69. }
  70. if (JFWRITE(dinfo->output_file, targaheader, 18) != (size_t) 18)
  71. ERREXIT(cinfo, JERR_FILE_WRITE);
  72. }
  73. /*
  74. * Write some pixel data.
  75. * In this module rows_supplied will always be 1.
  76. */
  77. METHODDEF(void)
  78. put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
  79. JDIMENSION rows_supplied)
  80. /* used for unquantized full-color output */
  81. {
  82. tga_dest_ptr dest = (tga_dest_ptr) dinfo;
  83. register JSAMPROW inptr;
  84. register char * outptr;
  85. register JDIMENSION col;
  86. inptr = dest->pub.buffer[0];
  87. outptr = dest->iobuffer;
  88. for (col = cinfo->output_width; col > 0; col--) {
  89. outptr[0] = (char) GETJSAMPLE(inptr[2]); /* RGB to BGR order */
  90. outptr[1] = (char) GETJSAMPLE(inptr[1]);
  91. outptr[2] = (char) GETJSAMPLE(inptr[0]);
  92. inptr += 3, outptr += 3;
  93. }
  94. (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
  95. }
  96. METHODDEF(void)
  97. put_gray_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
  98. JDIMENSION rows_supplied)
  99. /* used for grayscale OR quantized color output */
  100. {
  101. tga_dest_ptr dest = (tga_dest_ptr) dinfo;
  102. register JSAMPROW inptr;
  103. register char * outptr;
  104. register JDIMENSION col;
  105. inptr = dest->pub.buffer[0];
  106. outptr = dest->iobuffer;
  107. for (col = cinfo->output_width; col > 0; col--) {
  108. *outptr++ = (char) GETJSAMPLE(*inptr++);
  109. }
  110. (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
  111. }
  112. /*
  113. * Write some demapped pixel data when color quantization is in effect.
  114. * For Targa, this is only applied to grayscale data.
  115. */
  116. METHODDEF(void)
  117. put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
  118. JDIMENSION rows_supplied)
  119. {
  120. tga_dest_ptr dest = (tga_dest_ptr) dinfo;
  121. register JSAMPROW inptr;
  122. register char * outptr;
  123. register JSAMPROW color_map0 = cinfo->colormap[0];
  124. register JDIMENSION col;
  125. inptr = dest->pub.buffer[0];
  126. outptr = dest->iobuffer;
  127. for (col = cinfo->output_width; col > 0; col--) {
  128. *outptr++ = (char) GETJSAMPLE(color_map0[GETJSAMPLE(*inptr++)]);
  129. }
  130. (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
  131. }
  132. /*
  133. * Startup: write the file header.
  134. */
  135. METHODDEF(void)
  136. start_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
  137. {
  138. tga_dest_ptr dest = (tga_dest_ptr) dinfo;
  139. int num_colors, i;
  140. FILE *outfile;
  141. if (cinfo->out_color_space == JCS_GRAYSCALE) {
  142. /* Targa doesn't have a mapped grayscale format, so we will */
  143. /* demap quantized gray output. Never emit a colormap. */
  144. write_header(cinfo, dinfo, 0);
  145. if (cinfo->quantize_colors)
  146. dest->pub.put_pixel_rows = put_demapped_gray;
  147. else
  148. dest->pub.put_pixel_rows = put_gray_rows;
  149. } else if (cinfo->out_color_space == JCS_RGB) {
  150. if (cinfo->quantize_colors) {
  151. /* We only support 8-bit colormap indexes, so only 256 colors */
  152. num_colors = cinfo->actual_number_of_colors;
  153. if (num_colors > 256)
  154. ERREXIT1(cinfo, JERR_TOO_MANY_COLORS, num_colors);
  155. write_header(cinfo, dinfo, num_colors);
  156. /* Write the colormap. Note Targa uses BGR byte order */
  157. outfile = dest->pub.output_file;
  158. for (i = 0; i < num_colors; i++) {
  159. putc(GETJSAMPLE(cinfo->colormap[2][i]), outfile);
  160. putc(GETJSAMPLE(cinfo->colormap[1][i]), outfile);
  161. putc(GETJSAMPLE(cinfo->colormap[0][i]), outfile);
  162. }
  163. dest->pub.put_pixel_rows = put_gray_rows;
  164. } else {
  165. write_header(cinfo, dinfo, 0);
  166. dest->pub.put_pixel_rows = put_pixel_rows;
  167. }
  168. } else {
  169. ERREXIT(cinfo, JERR_TGA_COLORSPACE);
  170. }
  171. }
  172. /*
  173. * Finish up at the end of the file.
  174. */
  175. METHODDEF(void)
  176. finish_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
  177. {
  178. /* Make sure we wrote the output file OK */
  179. fflush(dinfo->output_file);
  180. if (ferror(dinfo->output_file))
  181. ERREXIT(cinfo, JERR_FILE_WRITE);
  182. }
  183. /*
  184. * The module selection routine for Targa format output.
  185. */
  186. GLOBAL(djpeg_dest_ptr)
  187. jinit_write_targa (j_decompress_ptr cinfo)
  188. {
  189. tga_dest_ptr dest;
  190. /* Create module interface object, fill in method pointers */
  191. dest = (tga_dest_ptr)
  192. (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  193. SIZEOF(tga_dest_struct));
  194. dest->pub.start_output = start_output_tga;
  195. dest->pub.finish_output = finish_output_tga;
  196. /* Calculate output image dimensions so we can allocate space */
  197. jpeg_calc_output_dimensions(cinfo);
  198. /* Create I/O buffer. Note we make this near on a PC. */
  199. dest->buffer_width = cinfo->output_width * cinfo->output_components;
  200. dest->iobuffer = (char *)
  201. (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  202. (size_t) (dest->buffer_width * SIZEOF(char)));
  203. /* Create decompressor output buffer. */
  204. dest->pub.buffer = (*cinfo->mem->alloc_sarray)
  205. ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width, (JDIMENSION) 1);
  206. dest->pub.buffer_height = 1;
  207. return (djpeg_dest_ptr) dest;
  208. }
  209. #endif /* TARGA_SUPPORTED */