123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505 |
- Unit JdAPImin;
- {$N+} { Nomssi: cinfo^.output_gamma }
- { This file contains application interface code for the decompression half
- of the JPEG library. These are the "minimum" API routines that may be
- needed in either the normal full-decompression case or the
- transcoding-only case.
- Most of the routines intended to be called directly by an application
- are in this file or in jdapistd.c. But also see jcomapi.c for routines
- shared by compression and decompression, and jdtrans.c for the transcoding
- case. }
- { Original : jdapimin.c ; Copyright (C) 1994-1998, Thomas G. Lane. }
- interface
- {$I jconfig.inc}
- uses
- jmorecfg,
- jinclude,
- jdeferr,
- jerror,
- jpeglib,
- jmemmgr, jdmarker, jdinput, jcomapi;
- { Nomssi }
- procedure jpeg_create_decompress(cinfo : j_decompress_ptr);
- { Initialization of a JPEG decompression object.
- The error manager must already be set up (in case memory manager fails). }
- {GLOBAL}
- procedure jpeg_CreateDecompress (cinfo : j_decompress_ptr;
- version : int;
- structsize : size_t);
- { Destruction of a JPEG decompression object }
- {GLOBAL}
- procedure jpeg_destroy_decompress (cinfo : j_decompress_ptr);
- { Decompression startup: read start of JPEG datastream to see what's there.
- Need only initialize JPEG object and supply a data source before calling.
- This routine will read as far as the first SOS marker (ie, actual start of
- compressed data), and will save all tables and parameters in the JPEG
- object. It will also initialize the decompression parameters to default
- values, and finally return JPEG_HEADER_OK. On return, the application may
- adjust the decompression parameters and then call jpeg_start_decompress.
- (Or, if the application only wanted to determine the image parameters,
- the data need not be decompressed. In that case, call jpeg_abort or
- jpeg_destroy to release any temporary space.)
- If an abbreviated (tables only) datastream is presented, the routine will
- return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then
- re-use the JPEG object to read the abbreviated image datastream(s).
- It is unnecessary (but OK) to call jpeg_abort in this case.
- The JPEG_SUSPENDED return code only occurs if the data source module
- requests suspension of the decompressor. In this case the application
- should load more source data and then re-call jpeg_read_header to resume
- processing.
- If a non-suspending data source is used and require_image is TRUE, then the
- return code need not be inspected since only JPEG_HEADER_OK is possible.
- This routine is now just a front end to jpeg_consume_input, with some
- extra error checking. }
- {GLOBAL}
- function jpeg_read_header (cinfo : j_decompress_ptr;
- require_image : boolean) : int;
- { Consume data in advance of what the decompressor requires.
- This can be called at any time once the decompressor object has
- been created and a data source has been set up.
- This routine is essentially a state machine that handles a couple
- of critical state-transition actions, namely initial setup and
- transition from header scanning to ready-for-start_decompress.
- All the actual input is done via the input controller's consume_input
- method. }
- {GLOBAL}
- function jpeg_consume_input (cinfo : j_decompress_ptr) : int;
- { Have we finished reading the input file? }
- {GLOBAL}
- function jpeg_input_complete (cinfo : j_decompress_ptr) : boolean;
- { Is there more than one scan? }
- {GLOBAL}
- function jpeg_has_multiple_scans (cinfo : j_decompress_ptr) : boolean;
- { Finish JPEG decompression.
- This will normally just verify the file trailer and release temp storage.
- Returns FALSE if suspended. The return value need be inspected only if
- a suspending data source is used. }
- {GLOBAL}
- function jpeg_finish_decompress (cinfo : j_decompress_ptr) : boolean;
- implementation
- procedure jpeg_create_decompress(cinfo : j_decompress_ptr);
- begin
- jpeg_CreateDecompress(cinfo, JPEG_LIB_VERSION,
- size_t(sizeof(jpeg_decompress_struct)));
- end;
- { Initialization of a JPEG decompression object.
- The error manager must already be set up (in case memory manager fails). }
- {GLOBAL}
- procedure jpeg_CreateDecompress (cinfo : j_decompress_ptr;
- version : int;
- structsize : size_t);
- var
- i : int;
- var
- err : jpeg_error_mgr_ptr;
- client_data : voidp;
- begin
- { Guard against version mismatches between library and caller. }
- cinfo^.mem := NIL; { so jpeg_destroy knows mem mgr not called }
- if (version <> JPEG_LIB_VERSION) then
- ERREXIT2(j_common_ptr(cinfo), JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
- if (structsize <> SIZEOF(jpeg_decompress_struct)) then
- ERREXIT2(j_common_ptr(cinfo), JERR_BAD_STRUCT_SIZE,
- int(SIZEOF(jpeg_decompress_struct)), int(structsize));
- { For debugging purposes, we zero the whole master structure.
- But the application has already set the err pointer, and may have set
- client_data, so we have to save and restore those fields.
- Note: if application hasn't set client_data, tools like Purify may
- complain here. }
- begin
- err := cinfo^.err;
- client_data := cinfo^.client_data; { ignore Purify complaint here }
- MEMZERO(j_common_ptr(cinfo), SIZEOF(jpeg_decompress_struct));
- cinfo^.err := err;
- cinfo^.client_data := client_data;
- end;
- cinfo^.is_decompressor := TRUE;
- { Initialize a memory manager instance for this object }
- jinit_memory_mgr(j_common_ptr(cinfo));
- { Zero out pointers to permanent structures. }
- cinfo^.progress := NIL;
- cinfo^.src := NIL;
- for i := 0 to pred(NUM_QUANT_TBLS) do
- cinfo^.quant_tbl_ptrs[i] := NIL;
- for i := 0 to pred(NUM_HUFF_TBLS) do
- begin
- cinfo^.dc_huff_tbl_ptrs[i] := NIL;
- cinfo^.ac_huff_tbl_ptrs[i] := NIL;
- end;
- { Initialize marker processor so application can override methods
- for COM, APPn markers before calling jpeg_read_header. }
- cinfo^.marker_list := NIL;
- jinit_marker_reader(cinfo);
- { And initialize the overall input controller. }
- jinit_input_controller(cinfo);
- { OK, I'm ready }
- cinfo^.global_state := DSTATE_START;
- end;
- { Destruction of a JPEG decompression object }
- {GLOBAL}
- procedure jpeg_destroy_decompress (cinfo : j_decompress_ptr);
- begin
- jpeg_destroy(j_common_ptr(cinfo)); { use common routine }
- end;
- { Abort processing of a JPEG decompression operation,
- but don't destroy the object itself. }
- {GLOBAL}
- procedure jpeg_abort_decompress (cinfo : j_decompress_ptr);
- begin
- jpeg_abort(j_common_ptr(cinfo)); { use common routine }
- end;
- { Set default decompression parameters. }
- {LOCAL}
- procedure default_decompress_parms (cinfo : j_decompress_ptr);
- var
- cid0 : int;
- cid1 : int;
- cid2 : int;
- begin
- { Guess the input colorspace, and set output colorspace accordingly. }
- { (Wish JPEG committee had provided a real way to specify this...) }
- { Note application may override our guesses. }
- case (cinfo^.num_components) of
- 1: begin
- cinfo^.jpeg_color_space := JCS_GRAYSCALE;
- cinfo^.out_color_space := JCS_GRAYSCALE;
- end;
- 3: begin
- if (cinfo^.saw_JFIF_marker) then
- begin
- cinfo^.jpeg_color_space := JCS_YCbCr; { JFIF implies YCbCr }
- end
- else
- if (cinfo^.saw_Adobe_marker) then
- begin
- case (cinfo^.Adobe_transform) of
- 0: cinfo^.jpeg_color_space := JCS_RGB;
- 1: cinfo^.jpeg_color_space := JCS_YCbCr;
- else
- begin
- WARNMS1(j_common_ptr(cinfo), JWRN_ADOBE_XFORM, cinfo^.Adobe_transform);
- cinfo^.jpeg_color_space := JCS_YCbCr; { assume it's YCbCr }
- end;
- end;
- end
- else
- begin
- { Saw no special markers, try to guess from the component IDs }
- cid0 := cinfo^.comp_info^[0].component_id;
- cid1 := cinfo^.comp_info^[1].component_id;
- cid2 := cinfo^.comp_info^[2].component_id;
- if (cid0 = 1) and (cid1 = 2) and (cid2 = 3) then
- cinfo^.jpeg_color_space := JCS_YCbCr { assume JFIF w/out marker }
- else
- if (cid0 = 82) and (cid1 = 71) and (cid2 = 66) then
- cinfo^.jpeg_color_space := JCS_RGB { ASCII 'R', 'G', 'B' }
- else
- begin
- {$IFDEF DEBUG}
- TRACEMS3(j_common_ptr(cinfo), 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2);
- {$ENDIF}
- cinfo^.jpeg_color_space := JCS_YCbCr; { assume it's YCbCr }
- end;
- end;
- { Always guess RGB is proper output colorspace. }
- cinfo^.out_color_space := JCS_RGB;
- end;
- 4: begin
- if (cinfo^.saw_Adobe_marker) then
- begin
- case (cinfo^.Adobe_transform) of
- 0: cinfo^.jpeg_color_space := JCS_CMYK;
- 2: cinfo^.jpeg_color_space := JCS_YCCK;
- else
- begin
- WARNMS1(j_common_ptr(cinfo), JWRN_ADOBE_XFORM, cinfo^.Adobe_transform);
- cinfo^.jpeg_color_space := JCS_YCCK; { assume it's YCCK }
- end;
- end;
- end
- else
- begin
- { No special markers, assume straight CMYK. }
- cinfo^.jpeg_color_space := JCS_CMYK;
- end;
- cinfo^.out_color_space := JCS_CMYK;
- end;
- else
- begin
- cinfo^.jpeg_color_space := JCS_UNKNOWN;
- cinfo^.out_color_space := JCS_UNKNOWN;
- end;
- end;
- { Set defaults for other decompression parameters. }
- cinfo^.scale_num := 1; { 1:1 scaling }
- cinfo^.scale_denom := 1;
- cinfo^.output_gamma := 1.0;
- cinfo^.buffered_image := FALSE;
- cinfo^.raw_data_out := FALSE;
- cinfo^.dct_method := JDCT_DEFAULT;
- cinfo^.do_fancy_upsampling := TRUE;
- cinfo^.do_block_smoothing := TRUE;
- cinfo^.quantize_colors := FALSE;
- { We set these in case application only sets quantize_colors. }
- cinfo^.dither_mode := JDITHER_FS;
- {$ifdef QUANT_2PASS_SUPPORTED}
- cinfo^.two_pass_quantize := TRUE;
- {$else}
- cinfo^.two_pass_quantize := FALSE;
- {$endif}
- cinfo^.desired_number_of_colors := 256;
- cinfo^.colormap := NIL;
- { Initialize for no mode change in buffered-image mode. }
- cinfo^.enable_1pass_quant := FALSE;
- cinfo^.enable_external_quant := FALSE;
- cinfo^.enable_2pass_quant := FALSE;
- end;
- { Decompression startup: read start of JPEG datastream to see what's there.
- Need only initialize JPEG object and supply a data source before calling.
- This routine will read as far as the first SOS marker (ie, actual start of
- compressed data), and will save all tables and parameters in the JPEG
- object. It will also initialize the decompression parameters to default
- values, and finally return JPEG_HEADER_OK. On return, the application may
- adjust the decompression parameters and then call jpeg_start_decompress.
- (Or, if the application only wanted to determine the image parameters,
- the data need not be decompressed. In that case, call jpeg_abort or
- jpeg_destroy to release any temporary space.)
- If an abbreviated (tables only) datastream is presented, the routine will
- return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then
- re-use the JPEG object to read the abbreviated image datastream(s).
- It is unnecessary (but OK) to call jpeg_abort in this case.
- The JPEG_SUSPENDED return code only occurs if the data source module
- requests suspension of the decompressor. In this case the application
- should load more source data and then re-call jpeg_read_header to resume
- processing.
- If a non-suspending data source is used and require_image is TRUE, then the
- return code need not be inspected since only JPEG_HEADER_OK is possible.
- This routine is now just a front end to jpeg_consume_input, with some
- extra error checking. }
- {GLOBAL}
- function jpeg_read_header (cinfo : j_decompress_ptr;
- require_image : boolean) : int;
- var
- retcode : int;
- begin
- if (cinfo^.global_state <> DSTATE_START) and
- (cinfo^.global_state <> DSTATE_INHEADER) then
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
- retcode := jpeg_consume_input(cinfo);
- case (retcode) of
- JPEG_REACHED_SOS:
- retcode := JPEG_HEADER_OK;
- JPEG_REACHED_EOI:
- begin
- if (require_image) then { Complain if application wanted an image }
- ERREXIT(j_common_ptr(cinfo), JERR_NO_IMAGE);
- { Reset to start state; it would be safer to require the application to
- call jpeg_abort, but we can't change it now for compatibility reasons.
- A side effect is to free any temporary memory (there shouldn't be any). }
- jpeg_abort(j_common_ptr(cinfo)); { sets state := DSTATE_START }
- retcode := JPEG_HEADER_TABLES_ONLY;
- end;
- JPEG_SUSPENDED: ; { no work }
- end;
- jpeg_read_header := retcode;
- end;
- { Consume data in advance of what the decompressor requires.
- This can be called at any time once the decompressor object has
- been created and a data source has been set up.
- This routine is essentially a state machine that handles a couple
- of critical state-transition actions, namely initial setup and
- transition from header scanning to ready-for-start_decompress.
- All the actual input is done via the input controller's consume_input
- method. }
- {GLOBAL}
- function jpeg_consume_input (cinfo : j_decompress_ptr) : int;
- var
- retcode : int;
- begin
- retcode := JPEG_SUSPENDED;
- { NB: every possible DSTATE value should be listed in this switch }
- if (cinfo^.global_state) = DSTATE_START then
- begin {work around the FALLTHROUGH}
- { Start-of-datastream actions: reset appropriate modules }
- cinfo^.inputctl^.reset_input_controller (cinfo);
- { Initialize application's data source module }
- cinfo^.src^.init_source (cinfo);
- cinfo^.global_state := DSTATE_INHEADER;
- end;
- case (cinfo^.global_state) of
- DSTATE_START,
- DSTATE_INHEADER:
- begin
- retcode := cinfo^.inputctl^.consume_input (cinfo);
- if (retcode = JPEG_REACHED_SOS) then
- begin { Found SOS, prepare to decompress }
- { Set up default parameters based on header data }
- default_decompress_parms(cinfo);
- { Set global state: ready for start_decompress }
- cinfo^.global_state := DSTATE_READY;
- end;
- end;
- DSTATE_READY:
- { Can't advance past first SOS until start_decompress is called }
- retcode := JPEG_REACHED_SOS;
- DSTATE_PRELOAD,
- DSTATE_PRESCAN,
- DSTATE_SCANNING,
- DSTATE_RAW_OK,
- DSTATE_BUFIMAGE,
- DSTATE_BUFPOST,
- DSTATE_STOPPING:
- retcode := cinfo^.inputctl^.consume_input (cinfo);
- else
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
- end;
- jpeg_consume_input := retcode;
- end;
- { Have we finished reading the input file? }
- {GLOBAL}
- function jpeg_input_complete (cinfo : j_decompress_ptr) : boolean;
- begin
- { Check for valid jpeg object }
- if (cinfo^.global_state < DSTATE_START) or
- (cinfo^.global_state > DSTATE_STOPPING) then
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
- jpeg_input_complete := cinfo^.inputctl^.eoi_reached;
- end;
- { Is there more than one scan? }
- {GLOBAL}
- function jpeg_has_multiple_scans (cinfo : j_decompress_ptr) : boolean;
- begin
- { Only valid after jpeg_read_header completes }
- if (cinfo^.global_state < DSTATE_READY) or
- (cinfo^.global_state > DSTATE_STOPPING) then
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
- jpeg_has_multiple_scans := cinfo^.inputctl^.has_multiple_scans;
- end;
- { Finish JPEG decompression.
- This will normally just verify the file trailer and release temp storage.
- Returns FALSE if suspended. The return value need be inspected only if
- a suspending data source is used. }
- {GLOBAL}
- function jpeg_finish_decompress (cinfo : j_decompress_ptr) : boolean;
- begin
- if ((cinfo^.global_state = DSTATE_SCANNING) or
- (cinfo^.global_state = DSTATE_RAW_OK) and (not cinfo^.buffered_image)) then
- begin
- { Terminate final pass of non-buffered mode }
- if (cinfo^.output_scanline < cinfo^.output_height) then
- ERREXIT(j_common_ptr(cinfo), JERR_TOO_LITTLE_DATA);
- cinfo^.master^.finish_output_pass (cinfo);
- cinfo^.global_state := DSTATE_STOPPING;
- end
- else
- if (cinfo^.global_state = DSTATE_BUFIMAGE) then
- begin
- { Finishing after a buffered-image operation }
- cinfo^.global_state := DSTATE_STOPPING;
- end
- else
- if (cinfo^.global_state <> DSTATE_STOPPING) then
- begin
- { STOPPING := repeat call after a suspension, anything else is error }
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state);
- end;
- { Read until EOI }
- while (not cinfo^.inputctl^.eoi_reached) do
- begin
- if (cinfo^.inputctl^.consume_input (cinfo) = JPEG_SUSPENDED) then
- begin
- jpeg_finish_decompress := FALSE; { Suspend, come back later }
- exit;
- end;
- end;
- { Do final cleanup }
- cinfo^.src^.term_source (cinfo);
- { We can use jpeg_abort to release memory and reset global_state }
- jpeg_abort(j_common_ptr(cinfo));
- jpeg_finish_decompress := TRUE;
- end;
- end.
|