summaryrefslogtreecommitdiff
path: root/packages/pasjpeg/src/jdatasrc.pas
diff options
context:
space:
mode:
Diffstat (limited to 'packages/pasjpeg/src/jdatasrc.pas')
-rw-r--r--packages/pasjpeg/src/jdatasrc.pas224
1 files changed, 224 insertions, 0 deletions
diff --git a/packages/pasjpeg/src/jdatasrc.pas b/packages/pasjpeg/src/jdatasrc.pas
new file mode 100644
index 0000000000..7408abfdcd
--- /dev/null
+++ b/packages/pasjpeg/src/jdatasrc.pas
@@ -0,0 +1,224 @@
+Unit JDataSrc;
+
+{ This file contains decompression data source routines for the case of
+ reading JPEG data from a file (or any stdio stream). While these routines
+ are sufficient for most applications, some will want to use a different
+ source manager.
+ IMPORTANT: we assume that fread() will correctly transcribe an array of
+ JOCTETs from 8-bit-wide elements on external storage. If char is wider
+ than 8 bits on your machine, you may need to do some tweaking. }
+
+{ jdatasrc.c ; Copyright (C) 1994-1996, Thomas G. Lane. }
+
+interface
+
+{$I jconfig.inc}
+
+{ this is not a core library module, so it doesn't define JPEG_INTERNALS }
+uses
+ jmorecfg,
+ jinclude,
+ jpeglib,
+ jdmarker,
+ jdeferr,
+ jerror;
+
+
+{ Prepare for input from a stdio stream.
+ The caller must have already opened the stream, and is responsible
+ for closing it after finishing decompression. }
+
+{GLOBAL}
+procedure jpeg_stdio_src (cinfo : j_decompress_ptr; infile : FILEptr);
+
+implementation
+
+{ Expanded data source object for stdio input }
+
+type
+ my_src_ptr = ^my_source_mgr;
+ my_source_mgr = record
+ pub : jpeg_source_mgr; { public fields }
+
+ infile : FILEPTR; { source stream }
+ buffer : JOCTET_FIELD_PTR; { start of buffer }
+ start_of_file : boolean; { have we gotten any data yet? }
+ end; {my_source_mgr;}
+
+const
+ INPUT_BUF_SIZE = 4096; { choose an efficiently fread'able size }
+
+
+{ Initialize source --- called by jpeg_read_header
+ before any data is actually read. }
+
+{METHODDEF}
+procedure init_source (cinfo : j_decompress_ptr); far;
+var
+ src : my_src_ptr;
+begin
+ src := my_src_ptr (cinfo^.src);
+
+ { We reset the empty-input-file flag for each image,
+ but we don't clear the input buffer.
+ This is correct behavior for reading a series of images from one source. }
+ src^.start_of_file := TRUE;
+end;
+
+
+{ Fill the input buffer --- called whenever buffer is emptied.
+
+ In typical applications, this should read fresh data into the buffer
+ (ignoring the current state of next_input_byte & bytes_in_buffer),
+ reset the pointer & count to the start of the buffer, and return TRUE
+ indicating that the buffer has been reloaded. It is not necessary to
+ fill the buffer entirely, only to obtain at least one more byte.
+
+ There is no such thing as an EOF return. If the end of the file has been
+ reached, the routine has a choice of ERREXIT() or inserting fake data into
+ the buffer. In most cases, generating a warning message and inserting a
+ fake EOI marker is the best course of action --- this will allow the
+ decompressor to output however much of the image is there. However,
+ the resulting error message is misleading if the real problem is an empty
+ input file, so we handle that case specially.
+
+ In applications that need to be able to suspend compression due to input
+ not being available yet, a FALSE return indicates that no more data can be
+ obtained right now, but more may be forthcoming later. In this situation,
+ the decompressor will return to its caller (with an indication of the
+ number of scanlines it has read, if any). The application should resume
+ decompression after it has loaded more data into the input buffer. Note
+ that there are substantial restrictions on the use of suspension --- see
+ the documentation.
+
+ When suspending, the decompressor will back up to a convenient restart point
+ (typically the start of the current MCU). next_input_byte & bytes_in_buffer
+ indicate where the restart point will be if the current call returns FALSE.
+ Data beyond this point must be rescanned after resumption, so move it to
+ the front of the buffer rather than discarding it. }
+
+{METHODDEF}
+function fill_input_buffer (cinfo : j_decompress_ptr) : boolean; far;
+var
+ src : my_src_ptr;
+ nbytes : size_t;
+begin
+ src := my_src_ptr(cinfo^.src);
+ nbytes := JFREAD(src^.infile, src^.buffer, INPUT_BUF_SIZE);
+
+ if (nbytes <= 0) then
+ begin
+ if (src^.start_of_file) then { Treat empty input file as fatal error }
+ ERREXIT(j_common_ptr(cinfo), JERR_INPUT_EMPTY);
+ WARNMS(j_common_ptr(cinfo), JWRN_JPEG_EOF);
+ { Insert a fake EOI marker }
+ src^.buffer^[0] := JOCTET ($FF);
+ src^.buffer^[1] := JOCTET (JPEG_EOI);
+ nbytes := 2;
+ end;
+
+ src^.pub.next_input_byte := JOCTETptr(src^.buffer);
+ src^.pub.bytes_in_buffer := nbytes;
+ src^.start_of_file := FALSE;
+
+ fill_input_buffer := TRUE;
+end;
+
+
+{ Skip data --- used to skip over a potentially large amount of
+ uninteresting data (such as an APPn marker).
+
+ Writers of suspendable-input applications must note that skip_input_data
+ is not granted the right to give a suspension return. If the skip extends
+ beyond the data currently in the buffer, the buffer can be marked empty so
+ that the next read will cause a fill_input_buffer call that can suspend.
+ Arranging for additional bytes to be discarded before reloading the input
+ buffer is the application writer's problem. }
+
+{METHODDEF}
+procedure skip_input_data (cinfo : j_decompress_ptr;
+ num_bytes : long); far;
+var
+ src : my_src_ptr;
+begin
+ src := my_src_ptr (cinfo^.src);
+
+ { Just a dumb implementation for now. Could use fseek() except
+ it doesn't work on pipes. Not clear that being smart is worth
+ any trouble anyway --- large skips are infrequent. }
+
+ if (num_bytes > 0) then
+ begin
+ while (num_bytes > long(src^.pub.bytes_in_buffer)) do
+ begin
+ Dec(num_bytes, long(src^.pub.bytes_in_buffer));
+ {void} fill_input_buffer(cinfo);
+ { note we assume that fill_input_buffer will never return FALSE,
+ so suspension need not be handled. }
+ end;
+ Inc( src^.pub.next_input_byte, size_t(num_bytes) );
+ Dec( src^.pub.bytes_in_buffer, size_t(num_bytes) );
+ end;
+end;
+
+
+{ An additional method that can be provided by data source modules is the
+ resync_to_restart method for error recovery in the presence of RST markers.
+ For the moment, this source module just uses the default resync method
+ provided by the JPEG library. That method assumes that no backtracking
+ is possible. }
+
+
+{ Terminate source --- called by jpeg_finish_decompress
+ after all data has been read. Often a no-op.
+
+ NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
+ application must deal with any cleanup that should happen even
+ for error exit. }
+
+{METHODDEF}
+procedure term_source (cinfo : j_decompress_ptr); far;
+begin
+ { no work necessary here }
+end;
+
+
+{ Prepare for input from a stdio stream.
+ The caller must have already opened the stream, and is responsible
+ for closing it after finishing decompression. }
+
+{GLOBAL}
+procedure jpeg_stdio_src (cinfo : j_decompress_ptr; infile : FILEptr);
+var
+ src : my_src_ptr;
+begin
+ { The source object and input buffer are made permanent so that a series
+ of JPEG images can be read from the same file by calling jpeg_stdio_src
+ only before the first one. (If we discarded the buffer at the end of
+ one image, we'd likely lose the start of the next one.)
+ This makes it unsafe to use this manager and a different source
+ manager serially with the same JPEG object. Caveat programmer. }
+
+ if (cinfo^.src = NIL) then
+ begin { first time for this JPEG object? }
+ cinfo^.src := jpeg_source_mgr_ptr(
+ cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_PERMANENT,
+ SIZEOF(my_source_mgr)) );
+ src := my_src_ptr (cinfo^.src);
+ src^.buffer := JOCTET_FIELD_PTR(
+ cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_PERMANENT,
+ INPUT_BUF_SIZE * SIZEOF(JOCTET)) );
+ end;
+
+ src := my_src_ptr (cinfo^.src);
+ src^.pub.init_source := init_source;
+ src^.pub.fill_input_buffer := fill_input_buffer;
+ src^.pub.skip_input_data := skip_input_data;
+ src^.pub.resync_to_restart := jpeg_resync_to_restart; { use default method }
+ src^.pub.term_source := term_source;
+ src^.infile := infile;
+ src^.pub.bytes_in_buffer := 0; { forces fill_input_buffer on first read }
+ src^.pub.next_input_byte := NIL; { until buffer loaded }
+end;
+
+end.