JPEGUtil.C
00001 #include "Image/JPEGUtil.H"
00002
00003
00004 #include <vector>
00005 #include <math.h>
00006
00007 #define INPUT_BUF_SIZE 4096LU
00008
00009
00010
00011 #define OUTPUT_BUF_SIZE 100000
00012
00013
00014 namespace IIDC_NS
00015 {
00016 typedef struct
00017 {
00018
00019 struct jpeg_source_mgr pub;
00020
00021
00022 std::vector<unsigned char>* src_vec;
00023 int curr_src_pos;
00024
00025
00026 JOCTET* buffer;
00027
00028 } buff_src_mgr;
00029
00030
00031
00032
00033
00034
00035 METHODDEF(void)
00036 init_source (j_decompress_ptr cinfo)
00037 {
00038 buff_src_mgr* src = (buff_src_mgr*) cinfo->src;
00039 src->curr_src_pos = 0;
00040 }
00041
00042
00043
00044
00045 METHODDEF(boolean)
00046 fill_input_buffer (j_decompress_ptr cinfo)
00047 {
00048
00049 buff_src_mgr* src = (buff_src_mgr*) cinfo->src;
00050
00051 size_t nbytes;
00052
00053 nbytes = std::min(INPUT_BUF_SIZE, (long unsigned int)(src->src_vec->size() - src->curr_src_pos));
00054 unsigned char* src_base = &((*(src->src_vec))[0]);
00055
00056
00057 src->pub.next_input_byte = src_base + src->curr_src_pos;
00058 src->pub.bytes_in_buffer = nbytes;
00059 src->curr_src_pos += nbytes;
00060
00061 return TRUE;
00062 }
00063
00064
00065
00066
00067
00068 METHODDEF(void)
00069 skip_input_data (j_decompress_ptr cinfo, long num_bytes)
00070 {
00071 buff_src_mgr* src = (buff_src_mgr*) cinfo->src;
00072
00073 src->curr_src_pos += num_bytes;
00074
00075 src->pub.next_input_byte += (size_t) num_bytes;
00076 src->pub.bytes_in_buffer -= (size_t) num_bytes;
00077 }
00078
00079
00080
00081
00082 METHODDEF(void)
00083 term_source (j_decompress_ptr cinfo)
00084 {
00085
00086 }
00087
00088 }
00089
00090 namespace IIC_NS
00091 {
00092 typedef struct {
00093
00094 struct jpeg_destination_mgr pub;
00095
00096
00097 JOCTET* in_buffer;
00098
00099
00100 std::vector<unsigned char>* out_buffer;
00101
00102 } buff_dest_mgr;
00103
00104
00105
00106
00107
00108 METHODDEF(void) init_destination(j_compress_ptr cinfo)
00109 {
00110
00111 buff_dest_mgr* dest = (buff_dest_mgr*) cinfo->dest;
00112
00113
00114 dest->in_buffer = (JOCTET *)
00115 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00116 OUTPUT_BUF_SIZE * sizeof(JOCTET));
00117
00118
00119 dest->pub.next_output_byte = dest->in_buffer;
00120 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
00121 }
00122
00123
00124
00125
00126 METHODDEF(boolean) empty_output_buffer (j_compress_ptr cinfo)
00127 {
00128
00129 buff_dest_mgr* dest = (buff_dest_mgr*) cinfo->dest;
00130
00131
00132 dest->out_buffer->insert(dest->out_buffer->end(),
00133 dest->in_buffer,
00134 dest->in_buffer+OUTPUT_BUF_SIZE);
00135
00136
00137 dest->pub.next_output_byte = dest->in_buffer;
00138 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
00139
00140 return TRUE;
00141 }
00142
00143
00144
00145
00146
00147 METHODDEF(void) term_destination (j_compress_ptr cinfo)
00148 {
00149
00150 buff_dest_mgr* dest = (buff_dest_mgr*) cinfo->dest;
00151
00152
00153 size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
00154
00155
00156 dest->out_buffer->insert(dest->out_buffer->end(),
00157 dest->in_buffer,
00158 dest->in_buffer+datacount);
00159 }
00160
00161
00162 }
00163
00164
00165
00166
00167 JPEGDecompressor::JPEGDecompressor()
00168 { }
00169
00170
00171
00172
00173
00174
00175 Image<PixRGB<byte> > JPEGDecompressor::DecompressImage(std::vector<unsigned char> &source_buffer)
00176 {
00177
00178
00179
00180 cinfo.err = jpeg_std_error(&jerr);
00181
00182
00183 jpeg_create_decompress(&cinfo);
00184
00185 InitImageSource(&source_buffer);
00186
00187 int ret = jpeg_read_header(&cinfo, TRUE);
00188 if (ret != JPEG_HEADER_OK)
00189 return Image<PixRGB<byte> >();
00190
00191 (void) jpeg_start_decompress(&cinfo);
00192
00193
00194 assert(cinfo.output_components == 3);
00195 Image<PixRGB<byte> > outputImg(cinfo.output_width, cinfo.output_height, NO_INIT);
00196 JSAMPLE* img_ptr = reinterpret_cast<JSAMPLE*>(outputImg.getArrayPtr());
00197
00198 int row_stride = cinfo.output_width * cinfo.output_components;
00199
00200 JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)
00201 ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
00202
00203 while(cinfo.output_scanline < cinfo.output_height)
00204 {
00205 (void) jpeg_read_scanlines(&cinfo, buffer, 1);
00206 std::memcpy(img_ptr, *buffer, row_stride);
00207 img_ptr+=row_stride;
00208 }
00209
00210
00211 (void) jpeg_finish_decompress(&cinfo);
00212 jpeg_destroy_decompress(&cinfo);
00213
00214 return outputImg;
00215 }
00216
00217
00218
00219
00220
00221
00222
00223 GLOBAL(void) JPEGDecompressor::InitImageSource(std::vector<unsigned char>* source_buffer)
00224 {
00225 IIDC_NS::buff_src_mgr* src;
00226
00227
00228 if (cinfo.src == NULL)
00229 {
00230
00231 cinfo.src = (struct jpeg_source_mgr *)
00232 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
00233 sizeof(IIDC_NS::buff_src_mgr));
00234
00235 src = (IIDC_NS::buff_src_mgr*) cinfo.src;
00236
00237 src->buffer = (JOCTET *)
00238 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
00239 INPUT_BUF_SIZE * sizeof(JOCTET));
00240 }
00241
00242
00243 src = (IIDC_NS::buff_src_mgr*) cinfo.src;
00244 src->pub.init_source = IIDC_NS::init_source;
00245 src->pub.fill_input_buffer = IIDC_NS::fill_input_buffer;
00246 src->pub.skip_input_data = IIDC_NS::skip_input_data;
00247 src->pub.resync_to_restart = jpeg_resync_to_restart;
00248 src->pub.term_source = IIDC_NS::term_source;
00249 src->pub.bytes_in_buffer = 0;
00250 src->pub.next_input_byte = NULL;
00251
00252 src->src_vec = source_buffer;
00253 src->curr_src_pos = 0;
00254
00255 }
00256
00257
00258 JPEGCompressor::JPEGCompressor()
00259 {
00260
00261
00262
00263
00264 cinfo.err = jpeg_std_error(&jerr);
00265
00266
00267 jpeg_create_compress(&cinfo);
00268
00269 }
00270
00271 std::vector<unsigned char> JPEGCompressor::compressImage(Image<PixRGB<byte> >& input)
00272 {
00273 std::vector<unsigned char> jpeg_buffer;
00274
00275
00276 InitImageDest(&jpeg_buffer);
00277
00278
00279 cinfo.image_width = input.getWidth();
00280 cinfo.image_height = input.getHeight();
00281 cinfo.input_components = 3;
00282 cinfo.in_color_space = JCS_RGB;
00283 jpeg_set_defaults(&cinfo);
00284
00285
00286 jpeg_start_compress(&cinfo, TRUE);
00287
00288
00289
00290
00291
00292 JSAMPLE* p_start = reinterpret_cast<JSAMPLE*>(input.getArrayPtr());
00293
00294
00295
00296 for(int row_idx=0; row_idx<input.getHeight(); row_idx++)
00297 {
00298 JSAMPLE* p = (p_start + (row_idx * input.getWidth()*3) );
00299 jpeg_write_scanlines(&cinfo, &p, 1);
00300 }
00301
00302
00303 jpeg_finish_compress(&cinfo);
00304
00305 return jpeg_buffer;
00306
00307 }
00308
00309 GLOBAL(void) JPEGCompressor::InitImageDest(std::vector<unsigned char>* destination_buffer)
00310 {
00311
00312 IIC_NS::buff_dest_mgr* dest;
00313
00314 if(cinfo.dest == NULL)
00315 {
00316
00317 cinfo.dest = (struct jpeg_destination_mgr *)
00318 (*(cinfo.mem->alloc_small)) ((j_common_ptr) &cinfo, JPOOL_PERMANENT, sizeof(IIC_NS::buff_dest_mgr));
00319 }
00320
00321
00322
00323 dest = (IIC_NS::buff_dest_mgr*) cinfo.dest;
00324 dest->pub.init_destination = IIC_NS::init_destination;
00325 dest->pub.empty_output_buffer = IIC_NS::empty_output_buffer;
00326 dest->pub.term_destination = IIC_NS::term_destination;
00327 dest->out_buffer = destination_buffer;
00328
00329 }
00330
00331
00332