/packages/pasjpeg/src/jctrans.pas
Pascal | 459 lines | 274 code | 63 blank | 122 comment | 29 complexity | 642dfaa1e8843b23787ec2949788a25f MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, LGPL-3.0
1Unit JcTrans; 2 3{ This file contains library routines for transcoding compression, 4 that is, writing raw DCT coefficient arrays to an output JPEG file. 5 The routines in jcapimin.c will also be needed by a transcoder. } 6 7{ Original : jctrans.c - Copyright (C) 1995-1998, Thomas G. Lane. } 8 9interface 10 11{$I jconfig.inc} 12 13uses 14 jmorecfg, 15 jinclude, 16 jdeferr, 17 jerror, 18 jutils, 19 jpeglib, 20 jcapimin, jcparam, jcomapi, jcmaster, jchuff, jcphuff, jcmarker; 21 22{ Compression initialization for writing raw-coefficient data. 23 Before calling this, all parameters and a data destination must be set up. 24 Call jpeg_finish_compress() to actually write the data. 25 26 The number of passed virtual arrays must match cinfo^.num_components. 27 Note that the virtual arrays need not be filled or even realized at 28 the time write_coefficients is called; indeed, if the virtual arrays 29 were requested from this compression object's memory manager, they 30 typically will be realized during this routine and filled afterwards. } 31 32{GLOBAL} 33procedure jpeg_write_coefficients (cinfo : j_compress_ptr; 34 coef_arrays : jvirt_barray_tbl_ptr); 35 36{ Initialize the compression object with default parameters, 37 then copy from the source object all parameters needed for lossless 38 transcoding. Parameters that can be varied without loss (such as 39 scan script and Huffman optimization) are left in their default states. } 40 41{GLOBAL} 42procedure jpeg_copy_critical_parameters (srcinfo : j_decompress_ptr; 43 dstinfo : j_compress_ptr); 44 45 46implementation 47 48{ Forward declarations } 49{LOCAL} 50procedure transencode_master_selection(cinfo : j_compress_ptr; 51 coef_arrays : jvirt_barray_tbl_ptr); 52 forward; 53{LOCAL} 54procedure transencode_coef_controller(cinfo : j_compress_ptr; 55 coef_arrays : jvirt_barray_tbl_ptr); 56 forward; 57 58 59{ Compression initialization for writing raw-coefficient data. 60 Before calling this, all parameters and a data destination must be set up. 61 Call jpeg_finish_compress() to actually write the data. 62 63 The number of passed virtual arrays must match cinfo^.num_components. 64 Note that the virtual arrays need not be filled or even realized at 65 the time write_coefficients is called; indeed, if the virtual arrays 66 were requested from this compression object's memory manager, they 67 typically will be realized during this routine and filled afterwards. } 68 69{GLOBAL} 70procedure jpeg_write_coefficients (cinfo : j_compress_ptr; 71 coef_arrays : jvirt_barray_tbl_ptr); 72begin 73 if (cinfo^.global_state <> CSTATE_START) then 74 ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); 75 { Mark all tables to be written } 76 jpeg_suppress_tables(cinfo, FALSE); 77 { (Re)initialize error mgr and destination modules } 78 cinfo^.err^.reset_error_mgr (j_common_ptr(cinfo)); 79 cinfo^.dest^.init_destination (cinfo); 80 { Perform master selection of active modules } 81 transencode_master_selection(cinfo, coef_arrays); 82 { Wait for jpeg_finish_compress() call } 83 cinfo^.next_scanline := 0; { so jpeg_write_marker works } 84 cinfo^.global_state := CSTATE_WRCOEFS; 85end; 86 87 88{ Initialize the compression object with default parameters, 89 then copy from the source object all parameters needed for lossless 90 transcoding. Parameters that can be varied without loss (such as 91 scan script and Huffman optimization) are left in their default states. } 92 93{GLOBAL} 94procedure jpeg_copy_critical_parameters (srcinfo : j_decompress_ptr; 95 dstinfo : j_compress_ptr); 96var 97 qtblptr : ^JQUANT_TBL_PTR; 98 incomp, outcomp : jpeg_component_info_ptr; 99 c_quant, slot_quant : JQUANT_TBL_PTR; 100 tblno, ci, coefi : int; 101begin 102 103 { Safety check to ensure start_compress not called yet. } 104 if (dstinfo^.global_state <> CSTATE_START) then 105 ERREXIT1(j_common_ptr(dstinfo), JERR_BAD_STATE, dstinfo^.global_state); 106 { Copy fundamental image dimensions } 107 dstinfo^.image_width := srcinfo^.image_width; 108 dstinfo^.image_height := srcinfo^.image_height; 109 dstinfo^.input_components := srcinfo^.num_components; 110 dstinfo^.in_color_space := srcinfo^.jpeg_color_space; 111 { Initialize all parameters to default values } 112 jpeg_set_defaults(dstinfo); 113 { jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB. 114 Fix it to get the right header markers for the image colorspace. } 115 116 jpeg_set_colorspace(dstinfo, srcinfo^.jpeg_color_space); 117 dstinfo^.data_precision := srcinfo^.data_precision; 118 dstinfo^.CCIR601_sampling := srcinfo^.CCIR601_sampling; 119 { Copy the source's quantization tables. } 120 for tblno := 0 to pred(NUM_QUANT_TBLS) do 121 begin 122 if (srcinfo^.quant_tbl_ptrs[tblno] <> NIL) then 123 begin 124 qtblptr := @dstinfo^.quant_tbl_ptrs[tblno]; 125 if (qtblptr^ = NIL) then 126 qtblptr^ := jpeg_alloc_quant_table(j_common_ptr(dstinfo)); 127 MEMCOPY(@(qtblptr^)^.quantval, 128 @srcinfo^.quant_tbl_ptrs[tblno]^.quantval, 129 SIZEOF((qtblptr^)^.quantval)); 130 (qtblptr^)^.sent_table := FALSE; 131 end; 132 end; 133 { Copy the source's per-component info. 134 Note we assume jpeg_set_defaults has allocated the dest comp_info array. } 135 136 dstinfo^.num_components := srcinfo^.num_components; 137 if (dstinfo^.num_components < 1) or 138 (dstinfo^.num_components > MAX_COMPONENTS) then 139 ERREXIT2(j_common_ptr(dstinfo), JERR_COMPONENT_COUNT, 140 dstinfo^.num_components, MAX_COMPONENTS); 141 incomp := jpeg_component_info_ptr(srcinfo^.comp_info); 142 outcomp := jpeg_component_info_ptr(dstinfo^.comp_info); 143 for ci := 0 to pred(dstinfo^.num_components) do 144 begin 145 146 outcomp^.component_id := incomp^.component_id; 147 outcomp^.h_samp_factor := incomp^.h_samp_factor; 148 outcomp^.v_samp_factor := incomp^.v_samp_factor; 149 outcomp^.quant_tbl_no := incomp^.quant_tbl_no; 150 { Make sure saved quantization table for component matches the qtable 151 slot. If not, the input file re-used this qtable slot. 152 IJG encoder currently cannot duplicate this. } 153 154 tblno := outcomp^.quant_tbl_no; 155 if (tblno < 0) or (tblno >= NUM_QUANT_TBLS) or 156 (srcinfo^.quant_tbl_ptrs[tblno] = NIL) then 157 ERREXIT1(j_common_ptr(dstinfo), JERR_NO_QUANT_TABLE, tblno); 158 slot_quant := srcinfo^.quant_tbl_ptrs[tblno]; 159 c_quant := incomp^.quant_table; 160 if (c_quant <> NIL) then 161 begin 162 for coefi := 0 to pred(DCTSIZE2) do 163 begin 164 if (c_quant^.quantval[coefi] <> slot_quant^.quantval[coefi]) then 165 ERREXIT1(j_common_ptr(dstinfo), JERR_MISMATCHED_QUANT_TABLE, tblno); 166 end; 167 end; 168 { Note: we do not copy the source's Huffman table assignments; 169 instead we rely on jpeg_set_colorspace to have made a suitable choice. } 170 Inc(incomp); 171 Inc(outcomp); 172 end; 173 { Also copy JFIF version and resolution information, if available. 174 Strictly speaking this isn't "critical" info, but it's nearly 175 always appropriate to copy it if available. In particular, 176 if the application chooses to copy JFIF 1.02 extension markers from 177 the source file, we need to copy the version to make sure we don't 178 emit a file that has 1.02 extensions but a claimed version of 1.01. 179 We will *not*, however, copy version info from mislabeled "2.01" files. } 180 181 if (srcinfo^.saw_JFIF_marker) then 182 begin 183 if (srcinfo^.JFIF_major_version = 1) then 184 begin 185 dstinfo^.JFIF_major_version := srcinfo^.JFIF_major_version; 186 dstinfo^.JFIF_minor_version := srcinfo^.JFIF_minor_version; 187 end; 188 dstinfo^.density_unit := srcinfo^.density_unit; 189 dstinfo^.X_density := srcinfo^.X_density; 190 dstinfo^.Y_density := srcinfo^.Y_density; 191 end; 192end; 193 194 195{ Master selection of compression modules for transcoding. 196 This substitutes for jcinit.c's initialization of the full compressor. } 197 198{LOCAL} 199procedure transencode_master_selection (cinfo : j_compress_ptr; 200 coef_arrays : jvirt_barray_tbl_ptr); 201begin 202 { Although we don't actually use input_components for transcoding, 203 jcmaster.c's initial_setup will complain if input_components is 0. } 204 205 cinfo^.input_components := 1; 206 { Initialize master control (includes parameter checking/processing) } 207 jinit_c_master_control(cinfo, TRUE { transcode only }); 208 209 { Entropy encoding: either Huffman or arithmetic coding. } 210 if (cinfo^.arith_code) then 211 begin 212 ERREXIT(j_common_ptr(cinfo), JERR_ARITH_NOTIMPL); 213 end 214 else 215 begin 216 if (cinfo^.progressive_mode) then 217 begin 218{$ifdef C_PROGRESSIVE_SUPPORTED} 219 jinit_phuff_encoder(cinfo); 220{$else} 221 ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); 222{$endif} 223 end 224 else 225 jinit_huff_encoder(cinfo); 226 end; 227 228 { We need a special coefficient buffer controller. } 229 transencode_coef_controller(cinfo, coef_arrays); 230 231 jinit_marker_writer(cinfo); 232 233 { We can now tell the memory manager to allocate virtual arrays. } 234 cinfo^.mem^.realize_virt_arrays (j_common_ptr(cinfo)); 235 236 { Write the datastream header (SOI, JFIF) immediately. 237 Frame and scan headers are postponed till later. 238 This lets application insert special markers after the SOI. } 239 240 cinfo^.marker^.write_file_header (cinfo); 241end; 242 243 244{ The rest of this file is a special implementation of the coefficient 245 buffer controller. This is similar to jccoefct.c, but it handles only 246 output from presupplied virtual arrays. Furthermore, we generate any 247 dummy padding blocks on-the-fly rather than expecting them to be present 248 in the arrays. } 249 250{ Private buffer controller object } 251 252type 253 my_coef_ptr = ^my_coef_controller; 254 my_coef_controller = record 255 pub : jpeg_c_coef_controller; { public fields } 256 257 iMCU_row_num : JDIMENSION; { iMCU row # within image } 258 mcu_ctr : JDIMENSION; { counts MCUs processed in current row } 259 MCU_vert_offset : int; { counts MCU rows within iMCU row } 260 MCU_rows_per_iMCU_row : int; { number of such rows needed } 261 262 { Virtual block array for each component. } 263 whole_image : jvirt_barray_tbl_ptr; 264 265 { Workspace for constructing dummy blocks at right/bottom edges. } 266 dummy_buffer : array[0..C_MAX_BLOCKS_IN_MCU-1] of JBLOCKROW; 267 end; {my_coef_controller;} 268 269 270{LOCAL} 271procedure start_iMCU_row (cinfo : j_compress_ptr); 272{ Reset within-iMCU-row counters for a new row } 273var 274 coef : my_coef_ptr; 275begin 276 coef := my_coef_ptr (cinfo^.coef); 277 278 { In an interleaved scan, an MCU row is the same as an iMCU row. 279 In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. 280 But at the bottom of the image, process only what's left. } 281 282 if (cinfo^.comps_in_scan > 1) then 283 begin 284 coef^.MCU_rows_per_iMCU_row := 1; 285 end 286 else 287 begin 288 if (coef^.iMCU_row_num < (cinfo^.total_iMCU_rows-1)) then 289 coef^.MCU_rows_per_iMCU_row := cinfo^.cur_comp_info[0]^.v_samp_factor 290 else 291 coef^.MCU_rows_per_iMCU_row := cinfo^.cur_comp_info[0]^.last_row_height; 292 end; 293 294 coef^.mcu_ctr := 0; 295 coef^.MCU_vert_offset := 0; 296end; 297 298 299{ Initialize for a processing pass. } 300 301{METHODDEF} 302procedure start_pass_coef (cinfo : j_compress_ptr; 303 pass_mode : J_BUF_MODE); far; 304var 305 coef : my_coef_ptr; 306begin 307 coef := my_coef_ptr (cinfo^.coef); 308 309 if (pass_mode <> JBUF_CRANK_DEST) then 310 ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); 311 312 coef^.iMCU_row_num := 0; 313 start_iMCU_row(cinfo); 314end; 315 316 317{ Process some data. 318 We process the equivalent of one fully interleaved MCU row ("iMCU" row) 319 per call, ie, v_samp_factor block rows for each component in the scan. 320 The data is obtained from the virtual arrays and fed to the entropy coder. 321 Returns TRUE if the iMCU row is completed, FALSE if suspended. 322 323 NB: input_buf is ignored; it is likely to be a NIL pointer. } 324 325{METHODDEF} 326function compress_output (cinfo : j_compress_ptr; 327 input_buf : JSAMPIMAGE) : boolean; far; 328var 329 coef : my_coef_ptr; 330 MCU_col_num : JDIMENSION; { index of current MCU within row } 331 last_MCU_col : JDIMENSION; 332 last_iMCU_row : JDIMENSION; 333 blkn, ci, xindex, yindex, yoffset, blockcnt : int; 334 start_col : JDIMENSION; 335 buffer : array[0..MAX_COMPS_IN_SCAN-1] of JBLOCKARRAY; 336 MCU_buffer : array[0..C_MAX_BLOCKS_IN_MCU-1] of JBLOCKROW; 337 buffer_ptr : JBLOCKROW; 338 compptr : jpeg_component_info_ptr; 339begin 340 coef := my_coef_ptr (cinfo^.coef); 341 last_MCU_col := cinfo^.MCUs_per_row - 1; 342 last_iMCU_row := cinfo^.total_iMCU_rows - 1; 343 344 { Align the virtual buffers for the components used in this scan. } 345 for ci := 0 to pred(cinfo^.comps_in_scan) do 346 begin 347 compptr := cinfo^.cur_comp_info[ci]; 348 buffer[ci] := cinfo^.mem^.access_virt_barray 349 (j_common_ptr(cinfo), coef^.whole_image^[compptr^.component_index], 350 coef^.iMCU_row_num * compptr^.v_samp_factor, 351 JDIMENSION(compptr^.v_samp_factor), FALSE); 352 end; 353 354 { Loop to process one whole iMCU row } 355 for yoffset := coef^.MCU_vert_offset to pred(coef^.MCU_rows_per_iMCU_row) do 356 begin 357 for MCU_col_num := coef^.mcu_ctr to pred(cinfo^.MCUs_per_row) do 358 begin 359 { Construct list of pointers to DCT blocks belonging to this MCU } 360 blkn := 0; { index of current DCT block within MCU } 361 for ci := 0 to pred(cinfo^.comps_in_scan) do 362 begin 363 compptr := cinfo^.cur_comp_info[ci]; 364 start_col := MCU_col_num * compptr^.MCU_width; 365 if (MCU_col_num < last_MCU_col) then 366 blockcnt := compptr^.MCU_width 367 else 368 blockcnt := compptr^.last_col_width; 369 for yindex := 0 to pred(compptr^.MCU_height) do 370 begin 371 if (coef^.iMCU_row_num < last_iMCU_row) or 372 (yindex+yoffset < compptr^.last_row_height) then 373 begin 374 { Fill in pointers to real blocks in this row } 375 buffer_ptr := JBLOCKROW(@ buffer[ci]^[yindex+yoffset]^[start_col]); 376 for xindex := 0 to pred(blockcnt) do 377 begin 378 MCU_buffer[blkn] := buffer_ptr; 379 Inc(blkn); 380 Inc(JBLOCK_PTR(buffer_ptr)); 381 end; 382 xindex := blockcnt; 383 end 384 else 385 begin 386 { At bottom of image, need a whole row of dummy blocks } 387 xindex := 0; 388 end; 389 { Fill in any dummy blocks needed in this row. 390 Dummy blocks are filled in the same way as in jccoefct.c: 391 all zeroes in the AC entries, DC entries equal to previous 392 block's DC value. The init routine has already zeroed the 393 AC entries, so we need only set the DC entries correctly. } 394 395 while (xindex < compptr^.MCU_width) do 396 begin 397 MCU_buffer[blkn] := coef^.dummy_buffer[blkn]; 398 MCU_buffer[blkn]^[0][0] := MCU_buffer[blkn-1]^[0][0]; 399 Inc(xindex); 400 Inc(blkn); 401 end; 402 end; 403 end; 404 { Try to write the MCU. } 405 if (not cinfo^.entropy^.encode_mcu (cinfo, MCU_buffer)) then 406 begin 407 { Suspension forced; update state counters and exit } 408 coef^.MCU_vert_offset := yoffset; 409 coef^.mcu_ctr := MCU_col_num; 410 compress_output := FALSE; 411 exit; 412 end; 413 end; 414 { Completed an MCU row, but perhaps not an iMCU row } 415 coef^.mcu_ctr := 0; 416 end; 417 { Completed the iMCU row, advance counters for next one } 418 Inc(coef^.iMCU_row_num); 419 start_iMCU_row(cinfo); 420 compress_output := TRUE; 421end; 422 423 424{ Initialize coefficient buffer controller. 425 426 Each passed coefficient array must be the right size for that 427 coefficient: width_in_blocks wide and height_in_blocks high, 428 with unitheight at least v_samp_factor. } 429 430{LOCAL} 431procedure transencode_coef_controller (cinfo : j_compress_ptr; 432 coef_arrays : jvirt_barray_tbl_ptr); 433var 434 coef : my_coef_ptr; 435 buffer : JBLOCKROW; 436 i : int; 437begin 438 coef := my_coef_ptr( 439 cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, 440 SIZEOF(my_coef_controller))); 441 cinfo^.coef := jpeg_c_coef_controller_ptr (coef); 442 coef^.pub.start_pass := start_pass_coef; 443 coef^.pub.compress_data := compress_output; 444 445 { Save pointer to virtual arrays } 446 coef^.whole_image := coef_arrays; 447 448 { Allocate and pre-zero space for dummy DCT blocks. } 449 buffer := JBLOCKROW( 450 cinfo^.mem^.alloc_large (j_common_ptr(cinfo), JPOOL_IMAGE, 451 C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)) ); 452 jzero_far({FAR} voidp(buffer), C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); 453 for i := 0 to pred(C_MAX_BLOCKS_IN_MCU) do 454 begin 455 coef^.dummy_buffer[i] := JBLOCKROW(@ buffer^[i]); 456 end; 457end; 458 459end.