root / Imaging / JpegLib / imjcapimin.pas @ 0:95bd93c28625
History | View | Annotate | Download (13.2 kB)
| 1 | unit imjcapimin;
|
|---|---|
| 2 | {$N+}
|
| 3 | { This file contains application interface code for the compression half
|
| 4 | of the JPEG library. These are the "minimum" API routines that may be |
| 5 | needed in either the normal full-compression case or the transcoding-only |
| 6 | case. |
| 7 | |
| 8 | Most of the routines intended to be called directly by an application |
| 9 | are in this file or in jcapistd.c. But also see jcparam.c for |
| 10 | parameter-setup helper routines, jcomapi.c for routines shared by |
| 11 | compression and decompression, and jctrans.c for the transcoding case. } |
| 12 | |
| 13 | { jcapimin.c ; Copyright (C) 1994-1998, Thomas G. Lane. }
|
| 14 | |
| 15 | |
| 16 | interface
|
| 17 | |
| 18 | {$I imjconfig.inc}
|
| 19 | |
| 20 | uses
|
| 21 | imjmorecfg, |
| 22 | imjinclude, |
| 23 | imjdeferr, |
| 24 | imjerror, |
| 25 | imjpeglib, |
| 26 | imjcomapi, |
| 27 | imjmemmgr, |
| 28 | imjcmarker; |
| 29 | |
| 30 | { Initialization of JPEG compression objects.
|
| 31 | Nomssi: This is a macro in the original code. |
| 32 | |
| 33 | jpeg_create_compress() and jpeg_create_decompress() are the exported |
| 34 | names that applications should call. These expand to calls on |
| 35 | jpeg_CreateCompress and jpeg_CreateDecompress with additional information |
| 36 | passed for version mismatch checking. |
| 37 | NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. } |
| 38 | |
| 39 | procedure jpeg_create_compress(cinfo : j_compress_ptr);
|
| 40 | |
| 41 | |
| 42 | { Initialization of a JPEG compression object.
|
| 43 | The error manager must already be set up (in case memory manager fails). } |
| 44 | |
| 45 | {GLOBAL}
|
| 46 | procedure jpeg_CreateCompress (cinfo : j_compress_ptr;
|
| 47 | version : int; |
| 48 | structsize : size_t); |
| 49 | |
| 50 | { Destruction of a JPEG compression object }
|
| 51 | |
| 52 | {GLOBAL}
|
| 53 | procedure jpeg_destroy_compress (cinfo : j_compress_ptr);
|
| 54 | |
| 55 | |
| 56 | { Abort processing of a JPEG compression operation,
|
| 57 | but don't destroy the object itself. } |
| 58 | |
| 59 | {GLOBAL}
|
| 60 | procedure jpeg_abort_compress (cinfo : j_compress_ptr);
|
| 61 | |
| 62 | |
| 63 | { Forcibly suppress or un-suppress all quantization and Huffman tables.
|
| 64 | Marks all currently defined tables as already written (if suppress) |
| 65 | or not written (if !suppress). This will control whether they get emitted |
| 66 | by a subsequent jpeg_start_compress call. |
| 67 | |
| 68 | This routine is exported for use by applications that want to produce |
| 69 | abbreviated JPEG datastreams. It logically belongs in jcparam.c, but |
| 70 | since it is called by jpeg_start_compress, we put it here --- otherwise |
| 71 | jcparam.o would be linked whether the application used it or not. } |
| 72 | |
| 73 | {GLOBAL}
|
| 74 | procedure jpeg_suppress_tables (cinfo : j_compress_ptr;
|
| 75 | suppress : boolean); |
| 76 | |
| 77 | |
| 78 | { Finish JPEG compression.
|
| 79 | |
| 80 | If a multipass operating mode was selected, this may do a great deal of |
| 81 | work including most of the actual output. } |
| 82 | |
| 83 | {GLOBAL}
|
| 84 | procedure jpeg_finish_compress (cinfo : j_compress_ptr);
|
| 85 | |
| 86 | { Write a special marker.
|
| 87 | This is only recommended for writing COM or APPn markers. |
| 88 | Must be called after jpeg_start_compress() and before |
| 89 | first call to jpeg_write_scanlines() or jpeg_write_raw_data(). } |
| 90 | |
| 91 | {GLOBAL}
|
| 92 | procedure jpeg_write_marker (cinfo : j_compress_ptr;
|
| 93 | marker : int; |
| 94 | dataptr : JOCTETptr; |
| 95 | datalen : uInt); |
| 96 | |
| 97 | {GLOBAL}
|
| 98 | procedure jpeg_write_m_header (cinfo : j_compress_ptr;
|
| 99 | marker : int; |
| 100 | datalen : uint); |
| 101 | {GLOBAL}
|
| 102 | procedure jpeg_write_m_byte (cinfo : j_compress_ptr; val : int);
|
| 103 | |
| 104 | { Alternate compression function: just write an abbreviated table file.
|
| 105 | Before calling this, all parameters and a data destination must be set up. |
| 106 | |
| 107 | To produce a pair of files containing abbreviated tables and abbreviated |
| 108 | image data, one would proceed as follows: |
| 109 | |
| 110 | initialize JPEG object |
| 111 | set JPEG parameters |
| 112 | set destination to table file |
| 113 | jpeg_write_tables(cinfo); |
| 114 | set destination to image file |
| 115 | jpeg_start_compress(cinfo, FALSE); |
| 116 | write data... |
| 117 | jpeg_finish_compress(cinfo); |
| 118 | |
| 119 | jpeg_write_tables has the side effect of marking all tables written |
| 120 | (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress |
| 121 | will not re-emit the tables unless it is passed write_all_tables=TRUE. } |
| 122 | |
| 123 | |
| 124 | |
| 125 | {GLOBAL}
|
| 126 | procedure jpeg_write_tables (cinfo : j_compress_ptr);
|
| 127 | |
| 128 | implementation
|
| 129 | |
| 130 | procedure jpeg_create_compress(cinfo : j_compress_ptr);
|
| 131 | begin
|
| 132 | jpeg_CreateCompress(cinfo, JPEG_LIB_VERSION, |
| 133 | size_t(sizeof(jpeg_compress_struct))); |
| 134 | end;
|
| 135 | |
| 136 | { Initialization of a JPEG compression object.
|
| 137 | The error manager must already be set up (in case memory manager fails). } |
| 138 | |
| 139 | {GLOBAL}
|
| 140 | procedure jpeg_CreateCompress (cinfo : j_compress_ptr;
|
| 141 | version : int; |
| 142 | structsize : size_t); |
| 143 | var
|
| 144 | i : int; |
| 145 | var
|
| 146 | err : jpeg_error_mgr_ptr; |
| 147 | client_data : voidp; |
| 148 | begin
|
| 149 | |
| 150 | { Guard against version mismatches between library and caller. }
|
| 151 | cinfo^.mem := NIL; { so jpeg_destroy knows mem mgr not called } |
| 152 | if (version <> JPEG_LIB_VERSION) then |
| 153 | ERREXIT2(j_common_ptr(cinfo), JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); |
| 154 | if (structsize <> SIZEOF(jpeg_compress_struct)) then |
| 155 | ERREXIT2(j_common_ptr(cinfo), JERR_BAD_STRUCT_SIZE, |
| 156 | int(SIZEOF(jpeg_compress_struct)), int(structsize)); |
| 157 | |
| 158 | { For debugging purposes, we zero the whole master structure.
|
| 159 | But the application has already set the err pointer, and may have set |
| 160 | client_data, so we have to save and restore those fields. |
| 161 | Note: if application hasn't set client_data, tools like Purify may |
| 162 | complain here. } |
| 163 | |
| 164 | err := cinfo^.err; |
| 165 | client_data := cinfo^.client_data; { ignore Purify complaint here }
|
| 166 | MEMZERO(cinfo, SIZEOF(jpeg_compress_struct)); |
| 167 | cinfo^.err := err; |
| 168 | cinfo^.is_decompressor := FALSE; |
| 169 | |
| 170 | { Initialize a memory manager instance for this object }
|
| 171 | jinit_memory_mgr(j_common_ptr(cinfo)); |
| 172 | |
| 173 | { Zero out pointers to permanent structures. }
|
| 174 | cinfo^.progress := NIL;
|
| 175 | cinfo^.dest := NIL;
|
| 176 | |
| 177 | cinfo^.comp_info := NIL;
|
| 178 | |
| 179 | for i := 0 to pred(NUM_QUANT_TBLS) do |
| 180 | cinfo^.quant_tbl_ptrs[i] := NIL;
|
| 181 | |
| 182 | for i := 0 to pred(NUM_HUFF_TBLS) do |
| 183 | begin
|
| 184 | cinfo^.dc_huff_tbl_ptrs[i] := NIL;
|
| 185 | cinfo^.ac_huff_tbl_ptrs[i] := NIL;
|
| 186 | end;
|
| 187 | |
| 188 | cinfo^.script_space := NIL;
|
| 189 | |
| 190 | cinfo^.input_gamma := 1.0; { in case application forgets } |
| 191 | |
| 192 | { OK, I'm ready }
|
| 193 | cinfo^.global_state := CSTATE_START; |
| 194 | end;
|
| 195 | |
| 196 | |
| 197 | { Destruction of a JPEG compression object }
|
| 198 | |
| 199 | {GLOBAL}
|
| 200 | procedure jpeg_destroy_compress (cinfo : j_compress_ptr);
|
| 201 | begin
|
| 202 | jpeg_destroy(j_common_ptr(cinfo)); { use common routine }
|
| 203 | end;
|
| 204 | |
| 205 | |
| 206 | { Abort processing of a JPEG compression operation,
|
| 207 | but don't destroy the object itself. } |
| 208 | |
| 209 | {GLOBAL}
|
| 210 | procedure jpeg_abort_compress (cinfo : j_compress_ptr);
|
| 211 | begin
|
| 212 | jpeg_abort(j_common_ptr(cinfo)); { use common routine }
|
| 213 | end;
|
| 214 | |
| 215 | |
| 216 | { Forcibly suppress or un-suppress all quantization and Huffman tables.
|
| 217 | Marks all currently defined tables as already written (if suppress) |
| 218 | or not written (if !suppress). This will control whether they get emitted |
| 219 | by a subsequent jpeg_start_compress call. |
| 220 | |
| 221 | This routine is exported for use by applications that want to produce |
| 222 | abbreviated JPEG datastreams. It logically belongs in jcparam.c, but |
| 223 | since it is called by jpeg_start_compress, we put it here --- otherwise |
| 224 | jcparam.o would be linked whether the application used it or not. } |
| 225 | |
| 226 | {GLOBAL}
|
| 227 | procedure jpeg_suppress_tables (cinfo : j_compress_ptr;
|
| 228 | suppress : boolean); |
| 229 | var
|
| 230 | i : int; |
| 231 | qtbl : JQUANT_TBL_PTR; |
| 232 | htbl : JHUFF_TBL_PTR; |
| 233 | begin
|
| 234 | for i := 0 to pred(NUM_QUANT_TBLS) do |
| 235 | begin
|
| 236 | qtbl := cinfo^.quant_tbl_ptrs[i]; |
| 237 | if (qtbl <> NIL) then |
| 238 | qtbl^.sent_table := suppress; |
| 239 | end;
|
| 240 | |
| 241 | for i := 0 to pred(NUM_HUFF_TBLS) do |
| 242 | begin
|
| 243 | htbl := cinfo^.dc_huff_tbl_ptrs[i]; |
| 244 | if (htbl <> NIL) then |
| 245 | htbl^.sent_table := suppress; |
| 246 | htbl := cinfo^.ac_huff_tbl_ptrs[i]; |
| 247 | if (htbl <> NIL) then |
| 248 | htbl^.sent_table := suppress; |
| 249 | end;
|
| 250 | end;
|
| 251 | |
| 252 | |
| 253 | { Finish JPEG compression.
|
| 254 | |
| 255 | If a multipass operating mode was selected, this may do a great deal of |
| 256 | work including most of the actual output. } |
| 257 | |
| 258 | {GLOBAL}
|
| 259 | procedure jpeg_finish_compress (cinfo : j_compress_ptr);
|
| 260 | var
|
| 261 | iMCU_row : JDIMENSION; |
| 262 | begin
|
| 263 | if (cinfo^.global_state = CSTATE_SCANNING) or |
| 264 | (cinfo^.global_state = CSTATE_RAW_OK) then
|
| 265 | begin
|
| 266 | { Terminate first pass }
|
| 267 | if (cinfo^.next_scanline < cinfo^.image_height) then |
| 268 | ERREXIT(j_common_ptr(cinfo), JERR_TOO_LITTLE_DATA); |
| 269 | cinfo^.master^.finish_pass (cinfo); |
| 270 | end
|
| 271 | else
|
| 272 | if (cinfo^.global_state <> CSTATE_WRCOEFS) then |
| 273 | ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); |
| 274 | { Perform any remaining passes }
|
| 275 | while (not cinfo^.master^.is_last_pass) do |
| 276 | begin
|
| 277 | cinfo^.master^.prepare_for_pass (cinfo); |
| 278 | for iMCU_row := 0 to pred(cinfo^.total_iMCU_rows) do |
| 279 | begin
|
| 280 | if (cinfo^.progress <> NIL) then |
| 281 | begin
|
| 282 | cinfo^.progress^.pass_counter := long (iMCU_row); |
| 283 | cinfo^.progress^.pass_limit := long (cinfo^.total_iMCU_rows); |
| 284 | cinfo^.progress^.progress_monitor (j_common_ptr(cinfo)); |
| 285 | end;
|
| 286 | { We bypass the main controller and invoke coef controller directly;
|
| 287 | all work is being done from the coefficient buffer. } |
| 288 | |
| 289 | if (not cinfo^.coef^.compress_data (cinfo, JSAMPIMAGE(NIL))) then |
| 290 | ERREXIT(j_common_ptr(cinfo), JERR_CANT_SUSPEND); |
| 291 | end;
|
| 292 | cinfo^.master^.finish_pass (cinfo); |
| 293 | end;
|
| 294 | { Write EOI, do final cleanup }
|
| 295 | cinfo^.marker^.write_file_trailer (cinfo); |
| 296 | cinfo^.dest^.term_destination (cinfo); |
| 297 | { We can use jpeg_abort to release memory and reset global_state }
|
| 298 | jpeg_abort(j_common_ptr(cinfo)); |
| 299 | end;
|
| 300 | |
| 301 | |
| 302 | { Write a special marker.
|
| 303 | This is only recommended for writing COM or APPn markers. |
| 304 | Must be called after jpeg_start_compress() and before |
| 305 | first call to jpeg_write_scanlines() or jpeg_write_raw_data(). } |
| 306 | |
| 307 | {GLOBAL}
|
| 308 | procedure jpeg_write_marker (cinfo : j_compress_ptr;
|
| 309 | marker : int; |
| 310 | dataptr : JOCTETptr; |
| 311 | datalen : uInt); |
| 312 | var
|
| 313 | write_marker_byte : procedure(info : j_compress_ptr; val : int);
|
| 314 | begin
|
| 315 | if (cinfo^.next_scanline <> 0) or |
| 316 | ((cinfo^.global_state <> CSTATE_SCANNING) and
|
| 317 | (cinfo^.global_state <> CSTATE_RAW_OK) and
|
| 318 | (cinfo^.global_state <> CSTATE_WRCOEFS)) then
|
| 319 | ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); |
| 320 | |
| 321 | cinfo^.marker^.write_marker_header (cinfo, marker, datalen); |
| 322 | write_marker_byte := cinfo^.marker^.write_marker_byte; { copy for speed }
|
| 323 | while (datalen <> 0) do |
| 324 | begin
|
| 325 | Dec(datalen); |
| 326 | write_marker_byte (cinfo, dataptr^); |
| 327 | Inc(dataptr); |
| 328 | end;
|
| 329 | end;
|
| 330 | |
| 331 | { Same, but piecemeal. }
|
| 332 | |
| 333 | {GLOBAL}
|
| 334 | procedure jpeg_write_m_header (cinfo : j_compress_ptr;
|
| 335 | marker : int; |
| 336 | datalen : uint); |
| 337 | begin
|
| 338 | if (cinfo^.next_scanline <> 0) or |
| 339 | ((cinfo^.global_state <> CSTATE_SCANNING) and
|
| 340 | (cinfo^.global_state <> CSTATE_RAW_OK) and
|
| 341 | (cinfo^.global_state <> CSTATE_WRCOEFS)) then
|
| 342 | ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); |
| 343 | |
| 344 | cinfo^.marker^.write_marker_header (cinfo, marker, datalen); |
| 345 | end;
|
| 346 | |
| 347 | {GLOBAL}
|
| 348 | procedure jpeg_write_m_byte (cinfo : j_compress_ptr; val : int);
|
| 349 | begin
|
| 350 | cinfo^.marker^.write_marker_byte (cinfo, val); |
| 351 | end;
|
| 352 | |
| 353 | |
| 354 | { Alternate compression function: just write an abbreviated table file.
|
| 355 | Before calling this, all parameters and a data destination must be set up. |
| 356 | |
| 357 | To produce a pair of files containing abbreviated tables and abbreviated |
| 358 | image data, one would proceed as follows: |
| 359 | |
| 360 | initialize JPEG object |
| 361 | set JPEG parameters |
| 362 | set destination to table file |
| 363 | jpeg_write_tables(cinfo); |
| 364 | set destination to image file |
| 365 | jpeg_start_compress(cinfo, FALSE); |
| 366 | write data... |
| 367 | jpeg_finish_compress(cinfo); |
| 368 | |
| 369 | jpeg_write_tables has the side effect of marking all tables written |
| 370 | (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress |
| 371 | will not re-emit the tables unless it is passed write_all_tables=TRUE. } |
| 372 | |
| 373 | {GLOBAL}
|
| 374 | procedure jpeg_write_tables (cinfo : j_compress_ptr);
|
| 375 | begin
|
| 376 | if (cinfo^.global_state <> CSTATE_START) then |
| 377 | ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); |
| 378 | |
| 379 | { (Re)initialize error mgr and destination modules }
|
| 380 | cinfo^.err^.reset_error_mgr (j_common_ptr(cinfo)); |
| 381 | cinfo^.dest^.init_destination (cinfo); |
| 382 | { Initialize the marker writer ... bit of a crock to do it here. }
|
| 383 | jinit_marker_writer(cinfo); |
| 384 | { Write them tables! }
|
| 385 | cinfo^.marker^.write_tables_only (cinfo); |
| 386 | { And clean up. }
|
| 387 | cinfo^.dest^.term_destination (cinfo); |
| 388 | |
| 389 | { In library releases up through v6a, we called jpeg_abort() here to free
|
| 390 | any working memory allocated by the destination manager and marker |
| 391 | writer. Some applications had a problem with that: they allocated space |
| 392 | of their own from the library memory manager, and didn't want it to go |
| 393 | away during write_tables. So now we do nothing. This will cause a |
| 394 | memory leak if an app calls write_tables repeatedly without doing a full |
| 395 | compression cycle or otherwise resetting the JPEG object. However, that |
| 396 | seems less bad than unexpectedly freeing memory in the normal case. |
| 397 | An app that prefers the old behavior can call jpeg_abort for itself after |
| 398 | each call to jpeg_write_tables(). } |
| 399 | end;
|
| 400 | |
| 401 | end.
|