root / Imaging / JpegLib / imjccoefct.pas @ 0:95bd93c28625
History | View | Annotate | Download (18.2 kB)
| 1 | unit imjccoefct;
|
|---|---|
| 2 | |
| 3 | { This file contains the coefficient buffer controller for compression.
|
| 4 | This controller is the top level of the JPEG compressor proper. |
| 5 | The coefficient buffer lies between forward-DCT and entropy encoding steps.} |
| 6 | |
| 7 | { Original: jccoefct.c; Copyright (C) 1994-1997, Thomas G. Lane. }
|
| 8 | |
| 9 | interface
|
| 10 | |
| 11 | {$I imjconfig.inc}
|
| 12 | |
| 13 | uses
|
| 14 | imjmorecfg, |
| 15 | imjinclude, |
| 16 | imjerror, |
| 17 | imjdeferr, |
| 18 | imjutils, |
| 19 | imjpeglib; |
| 20 | |
| 21 | { We use a full-image coefficient buffer when doing Huffman optimization,
|
| 22 | and also for writing multiple-scan JPEG files. In all cases, the DCT |
| 23 | step is run during the first pass, and subsequent passes need only read |
| 24 | the buffered coefficients. } |
| 25 | {$ifdef ENTROPY_OPT_SUPPORTED}
|
| 26 | {$define FULL_COEF_BUFFER_SUPPORTED}
|
| 27 | {$else}
|
| 28 | {$ifdef C_MULTISCAN_FILES_SUPPORTED}
|
| 29 | {$define FULL_COEF_BUFFER_SUPPORTED}
|
| 30 | {$endif}
|
| 31 | {$endif}
|
| 32 | |
| 33 | { Initialize coefficient buffer controller. }
|
| 34 | |
| 35 | {GLOBAL}
|
| 36 | procedure jinit_c_coef_controller (cinfo : j_compress_ptr;
|
| 37 | need_full_buffer : boolean); |
| 38 | |
| 39 | implementation
|
| 40 | |
| 41 | { Private buffer controller object }
|
| 42 | |
| 43 | type
|
| 44 | my_coef_ptr = ^my_coef_controller; |
| 45 | my_coef_controller = record
|
| 46 | pub : jpeg_c_coef_controller; { public fields }
|
| 47 | |
| 48 | iMCU_row_num : JDIMENSION; { iMCU row # within image }
|
| 49 | mcu_ctr : JDIMENSION; { counts MCUs processed in current row }
|
| 50 | MCU_vert_offset : int; { counts MCU rows within iMCU row }
|
| 51 | MCU_rows_per_iMCU_row : int; { number of such rows needed }
|
| 52 | |
| 53 | { For single-pass compression, it's sufficient to buffer just one MCU
|
| 54 | (although this may prove a bit slow in practice). We allocate a |
| 55 | workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each |
| 56 | MCU constructed and sent. (On 80x86, the workspace is FAR even though |
| 57 | it's not really very big; this is to keep the module interfaces unchanged |
| 58 | when a large coefficient buffer is necessary.) |
| 59 | In multi-pass modes, this array points to the current MCU's blocks |
| 60 | within the virtual arrays. } |
| 61 | |
| 62 | MCU_buffer : array[0..C_MAX_BLOCKS_IN_MCU-1] of JBLOCKROW; |
| 63 | |
| 64 | { In multi-pass modes, we need a virtual block array for each component. }
|
| 65 | whole_image : array[0..MAX_COMPONENTS-1] of jvirt_barray_ptr; |
| 66 | end;
|
| 67 | |
| 68 | |
| 69 | { Forward declarations }
|
| 70 | {METHODDEF}
|
| 71 | function compress_data(cinfo : j_compress_ptr;
|
| 72 | input_buf : JSAMPIMAGE) : boolean; forward;
|
| 73 | {$ifdef FULL_COEF_BUFFER_SUPPORTED}
|
| 74 | {METHODDEF}
|
| 75 | function compress_first_pass(cinfo : j_compress_ptr;
|
| 76 | input_buf : JSAMPIMAGE) : boolean; forward;
|
| 77 | {METHODDEF}
|
| 78 | function compress_output(cinfo : j_compress_ptr;
|
| 79 | input_buf : JSAMPIMAGE) : boolean; forward;
|
| 80 | {$endif}
|
| 81 | |
| 82 | |
| 83 | {LOCAL}
|
| 84 | procedure start_iMCU_row (cinfo : j_compress_ptr);
|
| 85 | { Reset within-iMCU-row counters for a new row }
|
| 86 | var
|
| 87 | coef : my_coef_ptr; |
| 88 | begin
|
| 89 | coef := my_coef_ptr (cinfo^.coef); |
| 90 | |
| 91 | { In an interleaved scan, an MCU row is the same as an iMCU row.
|
| 92 | In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. |
| 93 | But at the bottom of the image, process only what's left. } |
| 94 | if (cinfo^.comps_in_scan > 1) then |
| 95 | begin
|
| 96 | coef^.MCU_rows_per_iMCU_row := 1;
|
| 97 | end
|
| 98 | else
|
| 99 | begin
|
| 100 | if (coef^.iMCU_row_num < (cinfo^.total_iMCU_rows-1)) then |
| 101 | coef^.MCU_rows_per_iMCU_row := cinfo^.cur_comp_info[0]^.v_samp_factor
|
| 102 | else
|
| 103 | coef^.MCU_rows_per_iMCU_row := cinfo^.cur_comp_info[0]^.last_row_height;
|
| 104 | end;
|
| 105 | |
| 106 | coef^.mcu_ctr := 0;
|
| 107 | coef^.MCU_vert_offset := 0;
|
| 108 | end;
|
| 109 | |
| 110 | |
| 111 | { Initialize for a processing pass. }
|
| 112 | |
| 113 | {METHODDEF}
|
| 114 | procedure start_pass_coef (cinfo : j_compress_ptr;
|
| 115 | pass_mode : J_BUF_MODE); |
| 116 | var
|
| 117 | coef : my_coef_ptr; |
| 118 | begin
|
| 119 | coef := my_coef_ptr (cinfo^.coef); |
| 120 | |
| 121 | coef^.iMCU_row_num := 0;
|
| 122 | start_iMCU_row(cinfo); |
| 123 | |
| 124 | case (pass_mode) of |
| 125 | JBUF_PASS_THRU: |
| 126 | begin
|
| 127 | if (coef^.whole_image[0] <> NIL) then |
| 128 | ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); |
| 129 | coef^.pub.compress_data := compress_data; |
| 130 | end;
|
| 131 | {$ifdef FULL_COEF_BUFFER_SUPPORTED}
|
| 132 | JBUF_SAVE_AND_PASS: |
| 133 | begin
|
| 134 | if (coef^.whole_image[0] = NIL) then |
| 135 | ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); |
| 136 | coef^.pub.compress_data := compress_first_pass; |
| 137 | end;
|
| 138 | JBUF_CRANK_DEST: |
| 139 | begin
|
| 140 | if (coef^.whole_image[0] = NIL) then |
| 141 | ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); |
| 142 | coef^.pub.compress_data := compress_output; |
| 143 | end;
|
| 144 | {$endif}
|
| 145 | else
|
| 146 | ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); |
| 147 | end;
|
| 148 | end;
|
| 149 | |
| 150 | |
| 151 | { Process some data in the single-pass case.
|
| 152 | We process the equivalent of one fully interleaved MCU row ("iMCU" row)
|
| 153 | per call, ie, v_samp_factor block rows for each component in the image. |
| 154 | Returns TRUE if the iMCU row is completed, FALSE if suspended. |
| 155 | |
| 156 | NB: input_buf contains a plane for each component in image, |
| 157 | which we index according to the component's SOF position. } |
| 158 | |
| 159 | |
| 160 | {METHODDEF}
|
| 161 | function compress_data (cinfo : j_compress_ptr;
|
| 162 | input_buf : JSAMPIMAGE) : boolean; |
| 163 | var
|
| 164 | coef : my_coef_ptr; |
| 165 | MCU_col_num : JDIMENSION; { index of current MCU within row }
|
| 166 | last_MCU_col : JDIMENSION; |
| 167 | last_iMCU_row : JDIMENSION; |
| 168 | blkn, bi, ci, yindex, yoffset, blockcnt : int; |
| 169 | ypos, xpos : JDIMENSION; |
| 170 | compptr : jpeg_component_info_ptr; |
| 171 | begin
|
| 172 | coef := my_coef_ptr (cinfo^.coef); |
| 173 | last_MCU_col := cinfo^.MCUs_per_row - 1;
|
| 174 | last_iMCU_row := cinfo^.total_iMCU_rows - 1;
|
| 175 | |
| 176 | { Loop to write as much as one whole iMCU row }
|
| 177 | for yoffset := coef^.MCU_vert_offset to pred(coef^.MCU_rows_per_iMCU_row) do |
| 178 | begin
|
| 179 | for MCU_col_num := coef^.mcu_ctr to last_MCU_col do |
| 180 | begin
|
| 181 | { Determine where data comes from in input_buf and do the DCT thing.
|
| 182 | Each call on forward_DCT processes a horizontal row of DCT blocks |
| 183 | as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks |
| 184 | sequentially. Dummy blocks at the right or bottom edge are filled in |
| 185 | specially. The data in them does not matter for image reconstruction, |
| 186 | so we fill them with values that will encode to the smallest amount of |
| 187 | data, viz: all zeroes in the AC entries, DC entries equal to previous |
| 188 | block's DC value. (Thanks to Thomas Kinsman for this idea.) } |
| 189 | |
| 190 | blkn := 0;
|
| 191 | for ci := 0 to pred(cinfo^.comps_in_scan) do |
| 192 | begin
|
| 193 | compptr := cinfo^.cur_comp_info[ci]; |
| 194 | if (MCU_col_num < last_MCU_col) then |
| 195 | blockcnt := compptr^.MCU_width |
| 196 | else
|
| 197 | blockcnt := compptr^.last_col_width; |
| 198 | xpos := MCU_col_num * JDIMENSION(compptr^.MCU_sample_width); |
| 199 | ypos := yoffset * DCTSIZE; { ypos = (yoffset+yindex) * DCTSIZE }
|
| 200 | for yindex := 0 to pred(compptr^.MCU_height) do |
| 201 | begin
|
| 202 | if (coef^.iMCU_row_num < last_iMCU_row) or |
| 203 | (yoffset+yindex < compptr^.last_row_height) then
|
| 204 | begin
|
| 205 | cinfo^.fdct^.forward_DCT (cinfo, compptr, |
| 206 | input_buf^[compptr^.component_index], |
| 207 | coef^.MCU_buffer[blkn], |
| 208 | ypos, xpos, JDIMENSION (blockcnt)); |
| 209 | |
| 210 | if (blockcnt < compptr^.MCU_width) then |
| 211 | begin
|
| 212 | { Create some dummy blocks at the right edge of the image. }
|
| 213 | jzero_far({FAR}pointer(coef^.MCU_buffer[blkn + blockcnt]),
|
| 214 | (compptr^.MCU_width - blockcnt) * SIZEOF(JBLOCK)); |
| 215 | for bi := blockcnt to pred(compptr^.MCU_width) do |
| 216 | begin
|
| 217 | coef^.MCU_buffer[blkn+bi]^[0][0] := coef^.MCU_buffer[blkn+bi-1]^[0][0]; |
| 218 | end;
|
| 219 | end;
|
| 220 | end
|
| 221 | else
|
| 222 | begin
|
| 223 | { Create a row of dummy blocks at the bottom of the image. }
|
| 224 | jzero_far({FAR}pointer(coef^.MCU_buffer[blkn]),
|
| 225 | compptr^.MCU_width * SIZEOF(JBLOCK)); |
| 226 | for bi := 0 to pred(compptr^.MCU_width) do |
| 227 | begin
|
| 228 | coef^.MCU_buffer[blkn+bi]^[0][0] := coef^.MCU_buffer[blkn-1]^[0][0]; |
| 229 | end;
|
| 230 | end;
|
| 231 | Inc(blkn, compptr^.MCU_width); |
| 232 | Inc(ypos, DCTSIZE); |
| 233 | end;
|
| 234 | end;
|
| 235 | { Try to write the MCU. In event of a suspension failure, we will
|
| 236 | re-DCT the MCU on restart (a bit inefficient, could be fixed...) } |
| 237 | |
| 238 | if (not cinfo^.entropy^.encode_mcu (cinfo, JBLOCKARRAY(@coef^.MCU_buffer)^)) then |
| 239 | begin
|
| 240 | { Suspension forced; update state counters and exit }
|
| 241 | coef^.MCU_vert_offset := yoffset; |
| 242 | coef^.mcu_ctr := MCU_col_num; |
| 243 | compress_data := FALSE; |
| 244 | exit; |
| 245 | end;
|
| 246 | end;
|
| 247 | { Completed an MCU row, but perhaps not an iMCU row }
|
| 248 | coef^.mcu_ctr := 0;
|
| 249 | end;
|
| 250 | { Completed the iMCU row, advance counters for next one }
|
| 251 | Inc(coef^.iMCU_row_num); |
| 252 | start_iMCU_row(cinfo); |
| 253 | compress_data := TRUE; |
| 254 | end;
|
| 255 | |
| 256 | |
| 257 | {$ifdef FULL_COEF_BUFFER_SUPPORTED}
|
| 258 | |
| 259 | { Process some data in the first pass of a multi-pass case.
|
| 260 | We process the equivalent of one fully interleaved MCU row ("iMCU" row)
|
| 261 | per call, ie, v_samp_factor block rows for each component in the image. |
| 262 | This amount of data is read from the source buffer, DCT'd and quantized, |
| 263 | and saved into the virtual arrays. We also generate suitable dummy blocks |
| 264 | as needed at the right and lower edges. (The dummy blocks are constructed |
| 265 | in the virtual arrays, which have been padded appropriately.) This makes |
| 266 | it possible for subsequent passes not to worry about real vs. dummy blocks. |
| 267 | |
| 268 | We must also emit the data to the entropy encoder. This is conveniently |
| 269 | done by calling compress_output() after we've loaded the current strip |
| 270 | of the virtual arrays. |
| 271 | |
| 272 | NB: input_buf contains a plane for each component in image. All |
| 273 | components are DCT'd and loaded into the virtual arrays in this pass. |
| 274 | However, it may be that only a subset of the components are emitted to |
| 275 | the entropy encoder during this first pass; be careful about looking |
| 276 | at the scan-dependent variables (MCU dimensions, etc). } |
| 277 | |
| 278 | {METHODDEF}
|
| 279 | function compress_first_pass (cinfo : j_compress_ptr;
|
| 280 | input_buf : JSAMPIMAGE) : boolean; |
| 281 | var
|
| 282 | coef : my_coef_ptr; |
| 283 | last_iMCU_row : JDIMENSION; |
| 284 | blocks_across, MCUs_across, MCUindex : JDIMENSION; |
| 285 | bi, ci, h_samp_factor, block_row, block_rows, ndummy : int; |
| 286 | lastDC : JCOEF; |
| 287 | compptr : jpeg_component_info_ptr; |
| 288 | buffer : JBLOCKARRAY; |
| 289 | thisblockrow, lastblockrow : JBLOCKROW; |
| 290 | begin
|
| 291 | coef := my_coef_ptr (cinfo^.coef); |
| 292 | last_iMCU_row := cinfo^.total_iMCU_rows - 1;
|
| 293 | |
| 294 | compptr := jpeg_component_info_ptr(cinfo^.comp_info); |
| 295 | for ci := 0 to pred(cinfo^.num_components) do |
| 296 | begin
|
| 297 | { Align the virtual buffer for this component. }
|
| 298 | buffer := cinfo^.mem^.access_virt_barray |
| 299 | (j_common_ptr(cinfo), coef^.whole_image[ci], |
| 300 | coef^.iMCU_row_num * JDIMENSION(compptr^.v_samp_factor), |
| 301 | JDIMENSION (compptr^.v_samp_factor), TRUE); |
| 302 | { Count non-dummy DCT block rows in this iMCU row. }
|
| 303 | if (coef^.iMCU_row_num < last_iMCU_row) then |
| 304 | block_rows := compptr^.v_samp_factor |
| 305 | else
|
| 306 | begin
|
| 307 | { NB: can't use last_row_height here, since may not be set! }
|
| 308 | block_rows := int (compptr^.height_in_blocks) mod compptr^.v_samp_factor;
|
| 309 | if (block_rows = 0) then |
| 310 | block_rows := compptr^.v_samp_factor; |
| 311 | end;
|
| 312 | blocks_across := compptr^.width_in_blocks; |
| 313 | h_samp_factor := compptr^.h_samp_factor; |
| 314 | { Count number of dummy blocks to be added at the right margin. }
|
| 315 | ndummy := int (blocks_across) mod h_samp_factor;
|
| 316 | if (ndummy > 0) then |
| 317 | ndummy := h_samp_factor - ndummy; |
| 318 | { Perform DCT for all non-dummy blocks in this iMCU row. Each call
|
| 319 | on forward_DCT processes a complete horizontal row of DCT blocks. } |
| 320 | |
| 321 | for block_row := 0 to pred(block_rows) do |
| 322 | begin
|
| 323 | thisblockrow := buffer^[block_row]; |
| 324 | cinfo^.fdct^.forward_DCT (cinfo, compptr, |
| 325 | input_buf^[ci], |
| 326 | thisblockrow, |
| 327 | JDIMENSION (block_row * DCTSIZE), |
| 328 | JDIMENSION (0),
|
| 329 | blocks_across); |
| 330 | if (ndummy > 0) then |
| 331 | begin
|
| 332 | { Create dummy blocks at the right edge of the image. }
|
| 333 | Inc(JBLOCK_PTR(thisblockrow), blocks_across); { => first dummy block }
|
| 334 | jzero_far({FAR}pointer(thisblockrow), ndummy * SIZEOF(JBLOCK));
|
| 335 | {lastDC := thisblockrow^[-1][0];}
|
| 336 | { work around Range Checking }
|
| 337 | Dec(JBLOCK_PTR(thisblockrow)); |
| 338 | lastDC := thisblockrow^[0][0]; |
| 339 | Inc(JBLOCK_PTR(thisblockrow)); |
| 340 | |
| 341 | for bi := 0 to pred(ndummy) do |
| 342 | begin
|
| 343 | thisblockrow^[bi][0] := lastDC;
|
| 344 | end;
|
| 345 | end;
|
| 346 | end;
|
| 347 | { If at end of image, create dummy block rows as needed.
|
| 348 | The tricky part here is that within each MCU, we want the DC values |
| 349 | of the dummy blocks to match the last real block's DC value. |
| 350 | This squeezes a few more bytes out of the resulting file... } |
| 351 | |
| 352 | if (coef^.iMCU_row_num = last_iMCU_row) then |
| 353 | begin
|
| 354 | Inc(blocks_across, ndummy); { include lower right corner }
|
| 355 | MCUs_across := blocks_across div JDIMENSION(h_samp_factor);
|
| 356 | for block_row := block_rows to pred(compptr^.v_samp_factor) do |
| 357 | begin
|
| 358 | thisblockrow := buffer^[block_row]; |
| 359 | lastblockrow := buffer^[block_row-1];
|
| 360 | jzero_far({FAR} pointer(thisblockrow),
|
| 361 | size_t(blocks_across * SIZEOF(JBLOCK))); |
| 362 | for MCUindex := 0 to pred(MCUs_across) do |
| 363 | begin
|
| 364 | lastDC := lastblockrow^[h_samp_factor-1][0]; |
| 365 | for bi := 0 to pred(h_samp_factor) do |
| 366 | begin
|
| 367 | thisblockrow^[bi][0] := lastDC;
|
| 368 | end;
|
| 369 | Inc(JBLOCK_PTR(thisblockrow), h_samp_factor); { advance to next MCU in row }
|
| 370 | Inc(JBLOCK_PTR(lastblockrow), h_samp_factor); |
| 371 | end;
|
| 372 | end;
|
| 373 | end;
|
| 374 | Inc(compptr); |
| 375 | end;
|
| 376 | { NB: compress_output will increment iMCU_row_num if successful.
|
| 377 | A suspension return will result in redoing all the work above next time.} |
| 378 | |
| 379 | |
| 380 | { Emit data to the entropy encoder, sharing code with subsequent passes }
|
| 381 | compress_first_pass := compress_output(cinfo, input_buf); |
| 382 | end;
|
| 383 | |
| 384 | |
| 385 | { Process some data in subsequent passes of a multi-pass case.
|
| 386 | We process the equivalent of one fully interleaved MCU row ("iMCU" row)
|
| 387 | per call, ie, v_samp_factor block rows for each component in the scan. |
| 388 | The data is obtained from the virtual arrays and fed to the entropy coder. |
| 389 | Returns TRUE if the iMCU row is completed, FALSE if suspended. |
| 390 | |
| 391 | NB: input_buf is ignored; it is likely to be a NIL pointer. } |
| 392 | |
| 393 | {METHODDEF}
|
| 394 | function compress_output (cinfo : j_compress_ptr;
|
| 395 | input_buf : JSAMPIMAGE) : boolean; |
| 396 | var
|
| 397 | coef : my_coef_ptr; |
| 398 | MCU_col_num : JDIMENSION; { index of current MCU within row }
|
| 399 | blkn, ci, xindex, yindex, yoffset : int; |
| 400 | start_col : JDIMENSION; |
| 401 | buffer : array[0..MAX_COMPS_IN_SCAN-1] of JBLOCKARRAY; |
| 402 | buffer_ptr : JBLOCKROW; |
| 403 | compptr : jpeg_component_info_ptr; |
| 404 | begin
|
| 405 | coef := my_coef_ptr (cinfo^.coef); |
| 406 | |
| 407 | { Align the virtual buffers for the components used in this scan.
|
| 408 | NB: during first pass, this is safe only because the buffers will |
| 409 | already be aligned properly, so jmemmgr.c won't need to do any I/O. } |
| 410 | |
| 411 | for ci := 0 to pred(cinfo^.comps_in_scan) do |
| 412 | begin
|
| 413 | compptr := cinfo^.cur_comp_info[ci]; |
| 414 | buffer[ci] := cinfo^.mem^.access_virt_barray ( |
| 415 | j_common_ptr(cinfo), coef^.whole_image[compptr^.component_index], |
| 416 | coef^.iMCU_row_num * JDIMENSION(compptr^.v_samp_factor), |
| 417 | JDIMENSION (compptr^.v_samp_factor), FALSE); |
| 418 | end;
|
| 419 | |
| 420 | { Loop to process one whole iMCU row }
|
| 421 | for yoffset := coef^.MCU_vert_offset to pred(coef^.MCU_rows_per_iMCU_row) do |
| 422 | begin
|
| 423 | for MCU_col_num := coef^.mcu_ctr to pred(cinfo^.MCUs_per_row) do |
| 424 | begin
|
| 425 | { Construct list of pointers to DCT blocks belonging to this MCU }
|
| 426 | blkn := 0; { index of current DCT block within MCU } |
| 427 | for ci := 0 to pred(cinfo^.comps_in_scan) do |
| 428 | begin
|
| 429 | compptr := cinfo^.cur_comp_info[ci]; |
| 430 | start_col := MCU_col_num * JDIMENSION(compptr^.MCU_width); |
| 431 | for yindex := 0 to pred(compptr^.MCU_height) do |
| 432 | begin
|
| 433 | buffer_ptr := JBLOCKROW(@ buffer[ci]^[yindex+yoffset]^[start_col]); |
| 434 | for xindex := 0 to pred(compptr^.MCU_width) do |
| 435 | begin
|
| 436 | coef^.MCU_buffer[blkn] := buffer_ptr; |
| 437 | Inc(blkn); |
| 438 | Inc(JBLOCK_PTR(buffer_ptr)); |
| 439 | end;
|
| 440 | end;
|
| 441 | end;
|
| 442 | { Try to write the MCU. }
|
| 443 | if (not cinfo^.entropy^.encode_mcu (cinfo, coef^.MCU_buffer)) then |
| 444 | begin
|
| 445 | { Suspension forced; update state counters and exit }
|
| 446 | coef^.MCU_vert_offset := yoffset; |
| 447 | coef^.mcu_ctr := MCU_col_num; |
| 448 | compress_output := FALSE; |
| 449 | exit; |
| 450 | end;
|
| 451 | end;
|
| 452 | { Completed an MCU row, but perhaps not an iMCU row }
|
| 453 | coef^.mcu_ctr := 0;
|
| 454 | end;
|
| 455 | { Completed the iMCU row, advance counters for next one }
|
| 456 | Inc(coef^.iMCU_row_num); |
| 457 | start_iMCU_row(cinfo); |
| 458 | compress_output := TRUE; |
| 459 | end;
|
| 460 | |
| 461 | {$endif} { FULL_COEF_BUFFER_SUPPORTED } |
| 462 | |
| 463 | |
| 464 | { Initialize coefficient buffer controller. }
|
| 465 | |
| 466 | {GLOBAL}
|
| 467 | procedure jinit_c_coef_controller (cinfo : j_compress_ptr;
|
| 468 | need_full_buffer : boolean); |
| 469 | var
|
| 470 | coef : my_coef_ptr; |
| 471 | var
|
| 472 | buffer : JBLOCKROW; |
| 473 | i : int; |
| 474 | var
|
| 475 | ci : int; |
| 476 | compptr : jpeg_component_info_ptr; |
| 477 | begin
|
| 478 | coef := my_coef_ptr ( |
| 479 | cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, |
| 480 | SIZEOF(my_coef_controller)) ); |
| 481 | cinfo^.coef := jpeg_c_coef_controller_ptr(coef); |
| 482 | coef^.pub.start_pass := start_pass_coef; |
| 483 | |
| 484 | { Create the coefficient buffer. }
|
| 485 | if (need_full_buffer) then |
| 486 | begin
|
| 487 | {$ifdef FULL_COEF_BUFFER_SUPPORTED}
|
| 488 | { Allocate a full-image virtual array for each component, }
|
| 489 | { padded to a multiple of samp_factor DCT blocks in each direction. }
|
| 490 | |
| 491 | compptr := jpeg_component_info_ptr(cinfo^.comp_info); |
| 492 | for ci := 0 to pred(cinfo^.num_components) do |
| 493 | begin
|
| 494 | coef^.whole_image[ci] := cinfo^.mem^.request_virt_barray |
| 495 | (j_common_ptr(cinfo), JPOOL_IMAGE, FALSE, |
| 496 | JDIMENSION (jround_up( long (compptr^.width_in_blocks), |
| 497 | long (compptr^.h_samp_factor) )), |
| 498 | JDIMENSION (jround_up(long (compptr^.height_in_blocks), |
| 499 | long (compptr^.v_samp_factor))), |
| 500 | JDIMENSION (compptr^.v_samp_factor)); |
| 501 | Inc(compptr); |
| 502 | end;
|
| 503 | {$else}
|
| 504 | ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); |
| 505 | {$endif}
|
| 506 | end
|
| 507 | else
|
| 508 | begin
|
| 509 | { We only need a single-MCU buffer. }
|
| 510 | buffer := JBLOCKROW ( |
| 511 | cinfo^.mem^.alloc_large (j_common_ptr(cinfo), JPOOL_IMAGE, |
| 512 | C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)) ); |
| 513 | for i := 0 to pred(C_MAX_BLOCKS_IN_MCU) do |
| 514 | begin
|
| 515 | coef^.MCU_buffer[i] := JBLOCKROW(@ buffer^[i]); |
| 516 | end;
|
| 517 | coef^.whole_image[0] := NIL; { flag for no virtual arrays } |
| 518 | end;
|
| 519 | end;
|
| 520 | |
| 521 | end.
|