00001 #ifndef ICEIMAGEDECOMPRESSOR_C 00002 #define ICEIMAGEDECOMPRESSOR_C 00003 00004 #include "Ice/IceImageDecompressor.H" 00005 #include <vector> 00006 #include <jpeglib.h> 00007 #include <jerror.h> 00008 00009 #define INPUT_BUF_SIZE 4096LU 00010 00011 namespace IIDC_NS 00012 { 00013 typedef struct 00014 { 00015 //The public fields common to source managers 00016 struct jpeg_source_mgr pub; 00017 00018 //The compressed image source base pointer 00019 std::vector<unsigned char>* src_vec; 00020 int curr_src_pos; 00021 00022 //The output buffer pointer 00023 JOCTET* buffer; 00024 00025 } buff_src_mgr; 00026 00027 00028 //////////////////////////////////////////////////////////////// 00029 // Initialize the source -- called by jpeg_read_header before 00030 // any data is actually read 00031 //////////////////////////////////////////////////////////////// 00032 METHODDEF(void) 00033 init_source (j_decompress_ptr cinfo) 00034 { 00035 buff_src_mgr* src = (buff_src_mgr*) cinfo->src; 00036 src->curr_src_pos = 0; 00037 } 00038 00039 //////////////////////////////////////////////////////////////// 00040 // Fill the input buffer -- called whenever bytes_in_buffer is 0 00041 //////////////////////////////////////////////////////////////// 00042 METHODDEF(boolean) 00043 fill_input_buffer (j_decompress_ptr cinfo) 00044 { 00045 00046 buff_src_mgr* src = (buff_src_mgr*) cinfo->src; 00047 00048 size_t nbytes; 00049 00050 nbytes = std::min(INPUT_BUF_SIZE, src->src_vec->size() - src->curr_src_pos); 00051 unsigned char* src_base = &((*(src->src_vec))[0]); 00052 00053 00054 src->pub.next_input_byte = src_base + src->curr_src_pos; 00055 src->pub.bytes_in_buffer = nbytes; 00056 src->curr_src_pos += nbytes; 00057 00058 return TRUE; 00059 } 00060 00061 //////////////////////////////////////////////////////////////// 00062 // Skip input data -- Skips num_bytes worth of data without 00063 // putting it into the buffer 00064 //////////////////////////////////////////////////////////////// 00065 METHODDEF(void) 00066 skip_input_data (j_decompress_ptr cinfo, long num_bytes) 00067 { 00068 buff_src_mgr* src = (buff_src_mgr*) cinfo->src; 00069 00070 src->curr_src_pos += num_bytes; 00071 00072 src->pub.next_input_byte += (size_t) num_bytes; 00073 src->pub.bytes_in_buffer -= (size_t) num_bytes; 00074 } 00075 00076 //////////////////////////////////////////////////////////////// 00077 // Terminate source -- Nothing to do here 00078 //////////////////////////////////////////////////////////////// 00079 METHODDEF(void) 00080 term_source (j_decompress_ptr cinfo) 00081 { 00082 /* no work necessary here */ 00083 } 00084 00085 } 00086 00087 // constuctor does nothing, maybe that needs FIXME 00088 IceImageDecompressor::IceImageDecompressor() 00089 { } 00090 00091 //////////////////////////////////////////////////////////////// 00092 // Decompress an Image -- Pass this function an std::vector 00093 // filled with data from a compressed jpeg image, and it will 00094 // return to you an uncompressed Image< PixRGB<byte> > 00095 //////////////////////////////////////////////////////////////// 00096 Image<PixRGB<byte> > IceImageDecompressor::DecompressImage(std::vector<unsigned char> &source_buffer) 00097 { 00098 //Initialize our jpeg error handler to the default 00099 //(spit out non-fatal error messages on cerr, and 00100 // exit() on fatal errors) 00101 cinfo.err = jpeg_std_error(&jerr); 00102 00103 //Create our jpeg decompression object 00104 jpeg_create_decompress(&cinfo); 00105 00106 InitImageIceSource(&source_buffer); 00107 00108 (void) jpeg_read_header(&cinfo, TRUE); 00109 (void) jpeg_start_decompress(&cinfo); 00110 00111 00112 assert(cinfo.output_components == 3); 00113 Image<PixRGB<byte> > outputImg(cinfo.output_width, cinfo.output_height, NO_INIT); 00114 JSAMPLE* img_ptr = reinterpret_cast<JSAMPLE*>(outputImg.getArrayPtr()); 00115 00116 int row_stride = cinfo.output_width * cinfo.output_components; 00117 00118 JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray) 00119 ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); 00120 00121 while(cinfo.output_scanline < cinfo.output_height) 00122 { 00123 (void) jpeg_read_scanlines(&cinfo, buffer, 1); 00124 std::memcpy(img_ptr, *buffer, row_stride); 00125 img_ptr+=row_stride; 00126 } 00127 00128 00129 (void) jpeg_finish_decompress(&cinfo); 00130 jpeg_destroy_decompress(&cinfo); 00131 00132 return outputImg; 00133 } 00134 00135 00136 //////////////////////////////////////////////////////////////// 00137 // Initialize image source -- Just set up some variables and 00138 // allocate some buffer space (if necessary) for the 00139 // decompressor 00140 //////////////////////////////////////////////////////////////// 00141 GLOBAL(void) IceImageDecompressor::InitImageIceSource(std::vector<unsigned char>* source_buffer) 00142 { 00143 IIDC_NS::buff_src_mgr* src; 00144 00145 //Allocate the source buffer 00146 if (cinfo.src == NULL) 00147 { /* first time for this JPEG object? */ 00148 00149 cinfo.src = (struct jpeg_source_mgr *) 00150 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT, 00151 sizeof(IIDC_NS::buff_src_mgr)); 00152 00153 src = (IIDC_NS::buff_src_mgr*) cinfo.src; 00154 00155 src->buffer = (JOCTET *) 00156 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT, 00157 INPUT_BUF_SIZE * sizeof(JOCTET)); 00158 } 00159 00160 00161 src = (IIDC_NS::buff_src_mgr*) cinfo.src; 00162 src->pub.init_source = IIDC_NS::init_source; 00163 src->pub.fill_input_buffer = IIDC_NS::fill_input_buffer; 00164 src->pub.skip_input_data = IIDC_NS::skip_input_data; 00165 src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ 00166 src->pub.term_source = IIDC_NS::term_source; 00167 src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ 00168 src->pub.next_input_byte = NULL; /* until buffer loaded */ 00169 00170 src->src_vec = source_buffer; 00171 src->curr_src_pos = 0; 00172 00173 } 00174 #endif