core/vil/file_formats/vil_jpeg_source_mgr.cxx
Go to the documentation of this file.
00001 // This is core/vil/file_formats/vil_jpeg_source_mgr.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author fsm
00008 // \verbatim
00009 //  Modifications
00010 //     11 Oct 2002 Ian Scott - converted to vil
00011 //\endverbatim
00012 
00013 #include "vil_jpeg_source_mgr.h"
00014 #include <vcl_cassert.h>
00015 #include <vcl_cstddef.h> // for vcl_size_t
00016 #include <vcl_limits.h> //for vcl_numeric_limits
00017 #include <vil/vil_stream.h>
00018 
00019 #define STATIC /*static*/
00020 
00021 // In ANSI C, and indeed any rational implementation, vcl_size_t is also the
00022 // type returned by sizeof().  However, it seems there are some irrational
00023 // implementations out there, in which sizeof() returns an int even though
00024 // vcl_size_t is defined as long or unsigned long.  To ensure consistent results
00025 // we always use this SIZEOF() macro in place of using sizeof() directly.
00026 //
00027 #define SIZEOF(object) ((vcl_size_t) sizeof(object))
00028 
00029 // Implement a jpeg_source_manager for vil_stream *.
00030 // Adapted by fsm from the FILE * version in jdatasrc.c
00031 
00032 #define vil_jpeg_INPUT_BUF_SIZE  4096 // choose an efficiently fread'able size
00033 typedef vil_jpeg_stream_source_mgr *vil_jpeg_srcptr;
00034 
00035 
00036 // * Initialize source --- called by jpeg_read_header
00037 // * before any data is actually read.
00038 STATIC
00039 void
00040 vil_jpeg_init_source (j_decompress_ptr cinfo)
00041 {
00042   vil_jpeg_srcptr src = ( vil_jpeg_srcptr )( cinfo->src );
00043 
00044 #ifdef DEBUG
00045   vcl_cerr << "vil_jpeg_init_source() " << src << '\n';
00046 #endif
00047 
00048   // We reset the empty-input-file flag for each image,
00049   // but we don't clear the input buffer.
00050   // This is correct behavior for reading a series of images from one source.
00051   src->start_of_file = TRUE;
00052 }
00053 
00054 //: Fill the input buffer --- called whenever buffer is emptied.
00055 // 
00056 //  In typical applications, this should read fresh data into the buffer
00057 //  (ignoring the current state of next_input_byte & bytes_in_buffer),
00058 //  reset the pointer & count to the start of the buffer, and return TRUE
00059 //  indicating that the buffer has been reloaded.  It is not necessary to
00060 //  fill the buffer entirely, only to obtain at least one more byte.
00061 // 
00062 //  There is no such thing as an EOF return.  If the end of the file has been
00063 //  reached, the routine has a choice of ERREXIT() or inserting fake data into
00064 //  the buffer.  In most cases, generating a warning message and inserting a
00065 //  fake EOI marker is the best course of action --- this will allow the
00066 //  decompressor to output however much of the image is there.  However,
00067 //  the resulting error message is misleading if the real problem is an empty
00068 //  input file, so we handle that case specially.
00069 // 
00070 //  In applications that need to be able to suspend compression due to input
00071 //  not being available yet, a FALSE return indicates that no more data can be
00072 //  obtained right now, but more may be forthcoming later.  In this situation,
00073 //  the decompressor will return to its caller (with an indication of the
00074 //  number of scanlines it has read, if any).  The application should resume
00075 //  decompression after it has loaded more data into the input buffer.  Note
00076 //  that there are substantial restrictions on the use of suspension --- see
00077 //  the documentation.
00078 // 
00079 //  When suspending, the decompressor will back up to a convenient restart point
00080 //  (typically the start of the current MCU). next_input_byte & bytes_in_buffer
00081 //  indicate where the restart point will be if the current call returns FALSE.
00082 //  Data beyond this point must be rescanned after resumption, so move it to
00083 //  the front of the buffer rather than discarding it.
00084 STATIC
00085 jpeg_boolean
00086 vil_jpeg_fill_input_buffer (j_decompress_ptr cinfo)
00087 {
00088   vil_jpeg_srcptr src = ( vil_jpeg_srcptr )( cinfo->src );
00089 
00090   vil_streampos nbytes = src->stream->read(src->buffer, vil_jpeg_INPUT_BUF_SIZE);
00091 
00092   if (nbytes <= 0) {
00093     if (src->start_of_file) // Treat empty input file as fatal error
00094       ERREXIT(cinfo, JERR_INPUT_EMPTY);
00095     WARNMS(cinfo, JWRN_JPEG_EOF);
00096     // Insert a fake EOI marker
00097     src->buffer[0] = (JOCTET) 0xFF;
00098     src->buffer[1] = (JOCTET) JPEG_EOI;
00099     nbytes = 2;
00100   }
00101 
00102   src->base.next_input_byte = src->buffer;
00103   //original JPEG (non-j2k) files aren't usually very big
00104   //so this assert should be no problem
00105   assert( (vcl_size_t)nbytes <= vcl_numeric_limits< vcl_size_t >::max() );
00106   src->base.bytes_in_buffer = (vcl_size_t)nbytes;
00107   src->start_of_file = FALSE;
00108 
00109   return TRUE;
00110 }
00111 
00112 //: Skip data --- used to skip over a potentially large amount of uninteresting data (such as an APPn marker).
00113 // 
00114 //  Writers of suspendable-input applications must note that skip_input_data
00115 //  is not granted the right to give a suspension return.  If the skip extends
00116 //  beyond the data currently in the buffer, the buffer can be marked empty so
00117 //  that the next read will cause a fill_input_buffer call that can suspend.
00118 //  Arranging for additional bytes to be discarded before reloading the input
00119 //  buffer is the application writer's problem.
00120 STATIC
00121 void
00122 vil_jpeg_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
00123 {
00124   vil_jpeg_srcptr src = ( vil_jpeg_srcptr )( cinfo->src );
00125 
00126   // Just a dumb implementation for now.  Could use fseek() except
00127   // it doesn't work on pipes.  Not clear that being smart is worth
00128   // any trouble anyway --- large skips are infrequent.
00129   //
00130   if (num_bytes > 0) {
00131     while (num_bytes > (long) src->base.bytes_in_buffer) {
00132       num_bytes -= (long) src->base.bytes_in_buffer;
00133       vil_jpeg_fill_input_buffer(cinfo);
00134       // note we assume that fill_input_buffer will never return FALSE,
00135       // so suspension need not be handled.
00136     }
00137     src->base.next_input_byte += (vcl_size_t) num_bytes;
00138     src->base.bytes_in_buffer -= (vcl_size_t) num_bytes;
00139   }
00140 }
00141 
00142 
00143 //: Terminate source --- called by jpeg_finish_decompress after all data has been read.  Often a no-op.
00144 // 
00145 //  \note \e not called by jpeg_abort or jpeg_destroy; surrounding
00146 //  application must deal with any cleanup that should happen even
00147 //  for error exit.
00148 STATIC
00149 void
00150 vil_jpeg_term_source (j_decompress_ptr /*cinfo*/)
00151 {
00152   // no work necessary here
00153 }
00154 
00155 STATIC
00156 void
00157 vil_jpeg_stream_src_set (j_decompress_ptr cinfo, vil_stream *vs)
00158 {
00159   // The source object and input buffer are made permanent so that a series
00160   // of JPEG images can be read from the same file by calling vil_jpeg_stream_src
00161   // only before the first one.  (If we discarded the buffer at the end of
00162   // one image, we'd likely lose the start of the next one.)
00163   // This makes it unsafe to use this manager and a different source
00164   // manager serially with the same JPEG object.  Caveat programmer.
00165   assert(! ( vil_jpeg_srcptr )( cinfo->src )); // check unused
00166 
00167 #ifdef DEBUG
00168   vcl_cerr << "vil_jpeg_stream_src_set() : creating new data source\n";
00169 #endif
00170 
00171   vil_jpeg_srcptr src = (vil_jpeg_srcptr) // allocate
00172     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo,
00173                                 JPOOL_PERMANENT,
00174                                 SIZEOF(vil_jpeg_stream_source_mgr));
00175   // set pointer in cinfo
00176   cinfo->src = reinterpret_cast<struct jpeg_source_mgr *>(src);
00177 
00178   // set fields in src :
00179   src->stream = vs;
00180 
00181   src->buffer = (JOCTET *)
00182     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo,
00183                                 JPOOL_PERMANENT,
00184                                 vil_jpeg_INPUT_BUF_SIZE * SIZEOF(JOCTET));
00185 
00186   src->start_of_file = TRUE;
00187 
00188   // fill in methods in base class :
00189   src->base.init_source       = vil_jpeg_init_source;
00190   src->base.fill_input_buffer = vil_jpeg_fill_input_buffer;
00191   src->base.skip_input_data   = vil_jpeg_skip_input_data;
00192   src->base.resync_to_restart =     jpeg_resync_to_restart; // use default method
00193   src->base.term_source       = vil_jpeg_term_source;
00194 }
00195 
00196 STATIC
00197 void
00198 vil_jpeg_stream_src_rewind(j_decompress_ptr cinfo, vil_stream *vs)
00199 {
00200   // verify
00201   assert((vil_jpeg_srcptr)(cinfo->src) != 0);
00202   assert(((vil_jpeg_srcptr)(cinfo->src))->stream == vs);
00203 
00204   cinfo->src->bytes_in_buffer = 0; // forces fill_input_buffer on first read
00205   cinfo->src->next_input_byte = 0; // until buffer loaded
00206 
00207   vs->seek(0L);
00208 }
00209