wrtarga.pas 8.4 KB

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