jdpostct.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. Unit JdPostCt;
  2. { Original: jdpostct.c ; Copyright (C) 1994-1996, Thomas G. Lane. }
  3. { This file contains the decompression postprocessing controller.
  4. This controller manages the upsampling, color conversion, and color
  5. quantization/reduction steps; specifically, it controls the buffering
  6. between upsample/color conversion and color quantization/reduction.
  7. If no color quantization/reduction is required, then this module has no
  8. work to do, and it just hands off to the upsample/color conversion code.
  9. An integrated upsample/convert/quantize process would replace this module
  10. entirely. }
  11. {$I jconfig.inc}
  12. interface
  13. uses
  14. jmorecfg,
  15. jinclude,
  16. jdeferr,
  17. jerror,
  18. jutils,
  19. jpeglib;
  20. { Initialize postprocessing controller. }
  21. {GLOBAL}
  22. procedure jinit_d_post_controller (cinfo : j_decompress_ptr;
  23. need_full_buffer : boolean);
  24. implementation
  25. { Private buffer controller object }
  26. type
  27. my_post_ptr = ^my_post_controller;
  28. my_post_controller = record
  29. pub : jpeg_d_post_controller; { public fields }
  30. { Color quantization source buffer: this holds output data from
  31. the upsample/color conversion step to be passed to the quantizer.
  32. For two-pass color quantization, we need a full-image buffer;
  33. for one-pass operation, a strip buffer is sufficient. }
  34. whole_image : jvirt_sarray_ptr; { virtual array, or NIL if one-pass }
  35. buffer : JSAMPARRAY; { strip buffer, or current strip of virtual }
  36. strip_height : JDIMENSION; { buffer size in rows }
  37. { for two-pass mode only: }
  38. starting_row : JDIMENSION; { row # of first row in current strip }
  39. next_row : JDIMENSION; { index of next row to fill/empty in strip }
  40. end;
  41. { Forward declarations }
  42. {METHODDEF}
  43. procedure post_process_1pass(cinfo : j_decompress_ptr;
  44. input_buf : JSAMPIMAGE;
  45. var in_row_group_ctr : JDIMENSION;
  46. in_row_groups_avail : JDIMENSION;
  47. output_buf : JSAMPARRAY;
  48. var out_row_ctr : JDIMENSION;
  49. out_rows_avail : JDIMENSION); far; forward;
  50. {$ifdef QUANT_2PASS_SUPPORTED}
  51. {METHODDEF}
  52. procedure post_process_prepass(cinfo : j_decompress_ptr;
  53. input_buf : JSAMPIMAGE;
  54. var in_row_group_ctr : JDIMENSION;
  55. in_row_groups_avail : JDIMENSION;
  56. output_buf : JSAMPARRAY;
  57. var out_row_ctr : JDIMENSION;
  58. out_rows_avail : JDIMENSION); far; forward;
  59. {METHODDEF}
  60. procedure post_process_2pass(cinfo : j_decompress_ptr;
  61. input_buf : JSAMPIMAGE;
  62. var in_row_group_ctr : JDIMENSION;
  63. in_row_groups_avail : JDIMENSION;
  64. output_buf : JSAMPARRAY;
  65. var out_row_ctr : JDIMENSION;
  66. out_rows_avail : JDIMENSION); far; forward;
  67. {$endif}
  68. { Initialize for a processing pass. }
  69. {METHODDEF}
  70. procedure start_pass_dpost (cinfo : j_decompress_ptr;
  71. pass_mode : J_BUF_MODE); far;
  72. var
  73. post : my_post_ptr;
  74. begin
  75. post := my_post_ptr(cinfo^.post);
  76. case (pass_mode) of
  77. JBUF_PASS_THRU:
  78. if (cinfo^.quantize_colors) then
  79. begin
  80. { Single-pass processing with color quantization. }
  81. post^.pub.post_process_data := post_process_1pass;
  82. { We could be doing buffered-image output before starting a 2-pass
  83. color quantization; in that case, jinit_d_post_controller did not
  84. allocate a strip buffer. Use the virtual-array buffer as workspace. }
  85. if (post^.buffer = NIL) then
  86. begin
  87. post^.buffer := cinfo^.mem^.access_virt_sarray
  88. (j_common_ptr(cinfo), post^.whole_image,
  89. JDIMENSION(0), post^.strip_height, TRUE);
  90. end;
  91. end
  92. else
  93. begin
  94. { For single-pass processing without color quantization,
  95. I have no work to do; just call the upsampler directly. }
  96. post^.pub.post_process_data := cinfo^.upsample^.upsample;
  97. end;
  98. {$ifdef QUANT_2PASS_SUPPORTED}
  99. JBUF_SAVE_AND_PASS:
  100. begin
  101. { First pass of 2-pass quantization }
  102. if (post^.whole_image = NIL) then
  103. ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
  104. post^.pub.post_process_data := post_process_prepass;
  105. end;
  106. JBUF_CRANK_DEST:
  107. begin
  108. { Second pass of 2-pass quantization }
  109. if (post^.whole_image = NIL) then
  110. ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
  111. post^.pub.post_process_data := post_process_2pass;
  112. end;
  113. {$endif} { QUANT_2PASS_SUPPORTED }
  114. else
  115. ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
  116. end;
  117. post^.next_row := 0;
  118. post^.starting_row := 0;
  119. end;
  120. { Process some data in the one-pass (strip buffer) case.
  121. This is used for color precision reduction as well as one-pass quantization. }
  122. {METHODDEF}
  123. procedure post_process_1pass (cinfo : j_decompress_ptr;
  124. input_buf : JSAMPIMAGE;
  125. var in_row_group_ctr : JDIMENSION;
  126. in_row_groups_avail : JDIMENSION;
  127. output_buf : JSAMPARRAY;
  128. var out_row_ctr : JDIMENSION;
  129. out_rows_avail : JDIMENSION);
  130. var
  131. post : my_post_ptr;
  132. num_rows, max_rows : JDIMENSION;
  133. begin
  134. post := my_post_ptr (cinfo^.post);
  135. { Fill the buffer, but not more than what we can dump out in one go. }
  136. { Note we rely on the upsampler to detect bottom of image. }
  137. max_rows := out_rows_avail - out_row_ctr;
  138. if (max_rows > post^.strip_height) then
  139. max_rows := post^.strip_height;
  140. num_rows := 0;
  141. cinfo^.upsample^.upsample (cinfo,
  142. input_buf,
  143. in_row_group_ctr,
  144. in_row_groups_avail,
  145. post^.buffer,
  146. num_rows, { var }
  147. max_rows);
  148. { Quantize and emit data. }
  149. cinfo^.cquantize^.color_quantize (cinfo,
  150. post^.buffer,
  151. JSAMPARRAY(@ output_buf^[out_row_ctr]),
  152. int(num_rows));
  153. Inc(out_row_ctr, num_rows);
  154. end;
  155. {$ifdef QUANT_2PASS_SUPPORTED}
  156. { Process some data in the first pass of 2-pass quantization. }
  157. {METHODDEF}
  158. procedure post_process_prepass (cinfo : j_decompress_ptr;
  159. input_buf : JSAMPIMAGE;
  160. var in_row_group_ctr : JDIMENSION;
  161. in_row_groups_avail : JDIMENSION;
  162. output_buf : JSAMPARRAY;
  163. var out_row_ctr : JDIMENSION;
  164. out_rows_avail:JDIMENSION);
  165. var
  166. post : my_post_ptr;
  167. old_next_row, num_rows : JDIMENSION;
  168. begin
  169. post := my_post_ptr(cinfo^.post);
  170. { Reposition virtual buffer if at start of strip. }
  171. if (post^.next_row = 0) then
  172. begin
  173. post^.buffer := cinfo^.mem^.access_virt_sarray
  174. (j_common_ptr(cinfo), post^.whole_image,
  175. post^.starting_row, post^.strip_height, TRUE);
  176. end;
  177. { Upsample some data (up to a strip height's worth). }
  178. old_next_row := post^.next_row;
  179. cinfo^.upsample^.upsample (cinfo,
  180. input_buf, in_row_group_ctr, in_row_groups_avail,
  181. post^.buffer, post^.next_row, post^.strip_height);
  182. { Allow quantizer to scan new data. No data is emitted, }
  183. { but we advance out_row_ctr so outer loop can tell when we're done. }
  184. if (post^.next_row > old_next_row) then
  185. begin
  186. num_rows := post^.next_row - old_next_row;
  187. cinfo^.cquantize^.color_quantize (cinfo,
  188. JSAMPARRAY(@ post^.buffer^[old_next_row]),
  189. JSAMPARRAY(NIL),
  190. int(num_rows));
  191. Inc(out_row_ctr, num_rows);
  192. end;
  193. { Advance if we filled the strip. }
  194. if (post^.next_row >= post^.strip_height) then
  195. begin
  196. Inc(post^.starting_row, post^.strip_height);
  197. post^.next_row := 0;
  198. end;
  199. end;
  200. { Process some data in the second pass of 2-pass quantization. }
  201. {METHODDEF}
  202. procedure post_process_2pass (cinfo : j_decompress_ptr;
  203. input_buf : JSAMPIMAGE;
  204. var in_row_group_ctr : JDIMENSION;
  205. in_row_groups_avail : JDIMENSION;
  206. output_buf : JSAMPARRAY;
  207. var out_row_ctr : JDIMENSION;
  208. out_rows_avail : JDIMENSION);
  209. var
  210. post : my_post_ptr;
  211. num_rows, max_rows : JDIMENSION;
  212. begin
  213. post := my_post_ptr(cinfo^.post);
  214. { Reposition virtual buffer if at start of strip. }
  215. if (post^.next_row = 0) then
  216. begin
  217. post^.buffer := cinfo^.mem^.access_virt_sarray
  218. (j_common_ptr(cinfo), post^.whole_image,
  219. post^.starting_row, post^.strip_height, FALSE);
  220. end;
  221. { Determine number of rows to emit. }
  222. num_rows := post^.strip_height - post^.next_row; { available in strip }
  223. max_rows := out_rows_avail - out_row_ctr; { available in output area }
  224. if (num_rows > max_rows) then
  225. num_rows := max_rows;
  226. { We have to check bottom of image here, can't depend on upsampler. }
  227. max_rows := cinfo^.output_height - post^.starting_row;
  228. if (num_rows > max_rows) then
  229. num_rows := max_rows;
  230. { Quantize and emit data. }
  231. cinfo^.cquantize^.color_quantize (cinfo,
  232. JSAMPARRAY(@ post^.buffer^[post^.next_row]),
  233. JSAMPARRAY(@ output_buf^[out_row_ctr]),
  234. int(num_rows));
  235. Inc(out_row_ctr, num_rows);
  236. { Advance if we filled the strip. }
  237. Inc(post^.next_row, num_rows);
  238. if (post^.next_row >= post^.strip_height) then
  239. begin
  240. Inc(post^.starting_row, post^.strip_height);
  241. post^.next_row := 0;
  242. end;
  243. end;
  244. {$endif} { QUANT_2PASS_SUPPORTED }
  245. { Initialize postprocessing controller. }
  246. {GLOBAL}
  247. procedure jinit_d_post_controller (cinfo : j_decompress_ptr;
  248. need_full_buffer : boolean);
  249. var
  250. post : my_post_ptr;
  251. begin
  252. post := my_post_ptr(
  253. cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
  254. SIZEOF(my_post_controller)) );
  255. cinfo^.post := jpeg_d_post_controller_ptr (post);
  256. post^.pub.start_pass := start_pass_dpost;
  257. post^.whole_image := NIL; { flag for no virtual arrays }
  258. post^.buffer := NIL; { flag for no strip buffer }
  259. { Create the quantization buffer, if needed }
  260. if (cinfo^.quantize_colors) then
  261. begin
  262. { The buffer strip height is max_v_samp_factor, which is typically
  263. an efficient number of rows for upsampling to return.
  264. (In the presence of output rescaling, we might want to be smarter?) }
  265. post^.strip_height := JDIMENSION (cinfo^.max_v_samp_factor);
  266. if (need_full_buffer) then
  267. begin
  268. { Two-pass color quantization: need full-image storage. }
  269. { We round up the number of rows to a multiple of the strip height. }
  270. {$ifdef QUANT_2PASS_SUPPORTED}
  271. post^.whole_image := cinfo^.mem^.request_virt_sarray
  272. (j_common_ptr(cinfo), JPOOL_IMAGE, FALSE,
  273. cinfo^.output_width * cinfo^.out_color_components,
  274. JDIMENSION (jround_up( long(cinfo^.output_height),
  275. long(post^.strip_height)) ),
  276. post^.strip_height);
  277. {$else}
  278. ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
  279. {$endif} { QUANT_2PASS_SUPPORTED }
  280. end
  281. else
  282. begin
  283. { One-pass color quantization: just make a strip buffer. }
  284. post^.buffer := cinfo^.mem^.alloc_sarray
  285. (j_common_ptr (cinfo), JPOOL_IMAGE,
  286. cinfo^.output_width * cinfo^.out_color_components,
  287. post^.strip_height);
  288. end;
  289. end;
  290. end;
  291. end.