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