JPEGGenerator.ccGo to the documentation of this file.00001 #include "JPEGGenerator.h"
00002 #include "InterleavedYUVGenerator.h"
00003 #include "Events/DataEvent.h"
00004 #include "Events/EventRouter.h"
00005 #include "Events/FilterBankEvent.h"
00006 #include "Wireless/Wireless.h"
00007 #include "Shared/Config.h"
00008 #include "Shared/WorldState.h"
00009
00010 #include "Shared/jpeg-6b/jpeg_mem_dest.h"
00011
00012 #include "Shared/debuget.h"
00013
00014 JPEGGenerator::JPEGGenerator(unsigned int mysid, FilterBankGenerator* fbg, EventBase::EventTypeID_t tid)
00015 : FilterBankGenerator("JPEGGenerator","JPEGGenerator",EventBase::visJPEGEGID,mysid,fbg,tid), srcMode(SRC_AUTO), curMode(SRC_AUTO), bytesUsed(NULL), cinfo(), jerr(), quality(-1U)
00016 {
00017 if(dynamic_cast<const InterleavedYUVGenerator*>(src)!=NULL)
00018 curMode=SRC_COLOR;
00019 else
00020 curMode=SRC_GRAYSCALE;
00021
00022
00023
00024
00025 cinfo.err = jpeg_std_error(&jerr);
00026 jpeg_create_compress(&cinfo);
00027
00028
00029 if(fbg!=NULL) {
00030 numLayers=numChannels=0;
00031 setNumImages(fbg->getNumLayers(),fbg->getNumChannels());
00032 }
00033 }
00034
00035 JPEGGenerator::JPEGGenerator(unsigned int mysid, src_mode_t mode, FilterBankGenerator* fbg, EventBase::EventTypeID_t tid)
00036 : FilterBankGenerator("JPEGGenerator","JPEGGenerator",EventBase::visJPEGEGID,mysid,fbg,tid), srcMode(mode), curMode(mode), bytesUsed(NULL), cinfo(), jerr(), quality(-1U)
00037 {
00038 if(srcMode==SRC_AUTO) {
00039 if(dynamic_cast<const InterleavedYUVGenerator*>(src)!=NULL)
00040 curMode=SRC_COLOR;
00041 else
00042 curMode=SRC_GRAYSCALE;
00043 }
00044
00045
00046
00047
00048 cinfo.err = jpeg_std_error(&jerr);
00049 jpeg_create_compress(&cinfo);
00050
00051
00052 if(fbg!=NULL) {
00053 numLayers=numChannels=0;
00054 setNumImages(fbg->getNumLayers(),fbg->getNumChannels());
00055 }
00056 }
00057
00058 JPEGGenerator::~JPEGGenerator() {
00059 freeCaches();
00060 destruct();
00061 jpeg_destroy_compress(&cinfo);
00062 }
00063
00064
00065
00066
00067
00068
00069 void
00070 JPEGGenerator::processEvent(const EventBase& event) {
00071 FilterBankGenerator::processEvent(event);
00072 if(event.getGeneratorID()==getListenGeneratorID() && event.getSourceID()==getListenSourceID()) {
00073 if(getSourceMode()==SRC_AUTO) {
00074 if(dynamic_cast<const InterleavedYUVGenerator*>(src)!=NULL)
00075 curMode=SRC_COLOR;
00076 else
00077 curMode=SRC_GRAYSCALE;
00078 }
00079 erouter->postEvent(new FilterBankEvent(this,getGeneratorID(),getSourceID(),EventBase::activateETID));
00080 erouter->postEvent(new FilterBankEvent(this,getGeneratorID(),getSourceID(),EventBase::statusETID));
00081 erouter->postEvent(new FilterBankEvent(this,getGeneratorID(),getSourceID(),EventBase::deactivateETID));
00082 }
00083 }
00084
00085 unsigned int
00086 JPEGGenerator::getBinSize() const {
00087 unsigned int used=FilterBankGenerator::getBinSize();
00088 used+=strlen("JPEGColor")+LoadSave::stringpad;
00089 if(bytesUsed[selectedSaveLayer][selectedSaveChannel]!=0)
00090 used+=bytesUsed[selectedSaveLayer][selectedSaveChannel];
00091 else
00092 used+=widths[selectedSaveLayer]*heights[selectedSaveLayer]*3+JPEG_HEADER_PAD;
00093 return used;
00094 }
00095
00096 unsigned int
00097 JPEGGenerator::LoadBuffer(const char buf[], unsigned int len) {
00098 unsigned int origlen=len;
00099 unsigned int used;
00100 std::string tmp;
00101 if(0==(used=FilterBankGenerator::LoadBuffer(buf,len))) return 0;
00102 len-=used; buf+=used;
00103 if(0==(used=decode(tmp,buf,len))) return 0;
00104 len-=used; buf+=used;
00105 if(tmp!="JPEGColor" && tmp!="JPEGGray") {
00106 serr->printf("Unhandled image type for JPEGGenerator: %s",tmp.c_str());
00107 return 0;
00108 } else {
00109 if(tmp=="JPEGColor" && getCurrentSourceFormat()==SRC_GRAYSCALE)
00110 serr->printf("Warning: loading grayscale into color image");
00111 if(tmp=="JPEGGrayscale" && getCurrentSourceFormat()==SRC_COLOR)
00112 serr->printf("Warning: loading color into grayscale image");
00113 unsigned int tmpL;
00114 if(0==(used=decode(tmpL,buf,len))) return 0;
00115 len-=used; buf+=used;
00116 if(tmpL>len)
00117 return 0;
00118 if(images[selectedSaveLayer][selectedSaveChannel]!=NULL)
00119 delete [] images[selectedSaveLayer][selectedSaveChannel];
00120 images[selectedSaveLayer][selectedSaveChannel]=createImageCache(selectedSaveLayer,selectedSaveChannel);
00121 used=bytesUsed[selectedSaveLayer][selectedSaveChannel]=tmpL;
00122 unsigned char* img=getImage(selectedSaveLayer,selectedSaveChannel);
00123 if(img==NULL)
00124 return 0;
00125 memcpy(img,buf,used);
00126 len-=used; buf+=used;
00127 imageValids[selectedSaveLayer][selectedSaveChannel]=true;
00128 return origlen-len;
00129 }
00130 }
00131
00132 unsigned int
00133 JPEGGenerator::SaveBuffer(char buf[], unsigned int len) const {
00134 unsigned int origlen=len;
00135 unsigned int used;
00136 if(0==(used=FilterBankGenerator::SaveBuffer(buf,len))) return 0;
00137 len-=used; buf+=used;
00138
00139 char * type;
00140 if(getCurrentSourceFormat()==SRC_COLOR)
00141 type="JPEGColor";
00142 else if(getCurrentSourceFormat()==SRC_GRAYSCALE)
00143 type="JPEGGrayscale";
00144 else {
00145 serr->printf("SaveBuffer failed - unsuitable or unknown mode/generator pair");
00146 return 0;
00147 }
00148 if(0==(used=encode(type,buf,len))) return 0;
00149 len-=used; buf+=used;
00150
00151 if(images[selectedSaveLayer][selectedSaveChannel]==NULL) {
00152 serr->printf("JPEGGenerator::SaveBuffer() failed because selected image is NULL -- call selectSaveImage first to make sure it's up to date\n");
00153 return 0;
00154 }
00155 if(!imageValids[selectedSaveLayer][selectedSaveChannel]) {
00156 serr->printf("JPEGGenerator::SaveBuffer() failed because selected image is invalid -- call selectSaveImage first to make sure it's up to date\n");
00157 return 0;
00158 }
00159 unsigned char* img=images[selectedSaveLayer][selectedSaveChannel];
00160 if(img==NULL)
00161 return 0;
00162 if(0==(used=encode(bytesUsed[selectedSaveLayer][selectedSaveChannel],buf,len))) return 0;
00163 len-=used; buf+=used;
00164 used=bytesUsed[selectedSaveLayer][selectedSaveChannel];
00165 if(used>len)
00166 return 0;
00167 memcpy(buf,img,used);
00168 len-=used;
00169 return origlen-len;
00170 }
00171
00172 void
00173 JPEGGenerator::setNumImages(unsigned int nLayers, unsigned int nChannels) {
00174 if(nLayers==numLayers && nChannels==numChannels)
00175 return;
00176 FilterBankGenerator::setNumImages(nLayers,nChannels);
00177 for(unsigned int i=0; i<numLayers; i++)
00178 strides[i]=skips[i]=0;
00179 bytesUsed=new unsigned int*[numLayers];
00180 for(unsigned int res=0; res<numLayers; res++) {
00181 increments[res]=3;
00182 bytesUsed[res]=new unsigned int[numChannels];
00183 for(unsigned int i=0; i<numChannels; i++)
00184 bytesUsed[res][i]=0;
00185 }
00186 }
00187
00188 unsigned char *
00189 JPEGGenerator::createImageCache(unsigned int layer, unsigned int ) const {
00190 return new unsigned char[widths[layer]*heights[layer]*3+JPEG_HEADER_PAD];
00191 }
00192
00193
00194
00195
00196
00197
00198
00199 void
00200 JPEGGenerator::calcImage(unsigned int layer, unsigned int chan) {
00201 PROFSECTION("JPEGGenerator::calcImage(...)",state->mainProfile);
00202 try {
00203
00204 jpeg_mem_dest(&cinfo, images[layer][chan], widths[layer]*heights[layer]*3+JPEG_HEADER_PAD);
00205
00206
00207 cinfo.image_width = widths[layer];
00208 cinfo.image_height = heights[layer];
00209 if(getCurrentSourceFormat()==SRC_COLOR ) {
00210 cinfo.input_components = 3;
00211 cinfo.in_color_space = JCS_YCbCr;
00212 } else if(getCurrentSourceFormat()==SRC_GRAYSCALE) {
00213 cinfo.input_components = 1;
00214 cinfo.in_color_space = JCS_GRAYSCALE;
00215 } else {
00216 serr->printf("%s %s Compression failed - unsuitable or unknown mode/generator pair",getClassName().c_str(),getName().c_str());
00217 jpeg_destroy_compress(&cinfo);
00218 return;
00219 }
00220
00221
00222 jpeg_set_defaults(&cinfo);
00223 unsigned int qual=(quality==-1U?config->vision.rawcam_compress_quality:quality);
00224 jpeg_set_quality(&cinfo, qual, false);
00225 cinfo.dct_method=config->vision.jpeg_dct_method;
00226 if(cinfo.in_color_space==JCS_GRAYSCALE && src->getIncrement(layer)!=1) {
00227
00228 jpeg_start_compress(&cinfo, TRUE);
00229 unsigned int row_stride = src->getStride(layer);
00230 JSAMPROW row_pointer[1] = { new JSAMPLE[src->getWidth(layer)] };
00231 unsigned char * curpos=src->getImage(layer,chan);
00232 const unsigned int inc=src->getIncrement(layer);
00233 while (cinfo.next_scanline < cinfo.image_height) {
00234 for(unsigned int x=0; x<src->getWidth(layer); x++)
00235 row_pointer[0][x] = curpos[x*inc];
00236 jpeg_write_scanlines(&cinfo, row_pointer, 1);
00237 curpos+=row_stride;
00238 }
00239 jpeg_finish_compress(&cinfo);
00240
00241 } else {
00242 if(cinfo.in_color_space==JCS_YCbCr) {
00243 unsigned int ysamp=1;
00244 unsigned int uvsamp=1;
00245 const unsigned int maxsamp=2;
00246 if(config->vision.rawcam_y_skip>config->vision.rawcam_uv_skip) {
00247 uvsamp=config->vision.rawcam_y_skip-config->vision.rawcam_uv_skip+1;
00248 if(uvsamp>maxsamp)
00249 uvsamp=maxsamp;
00250 } else {
00251 ysamp=config->vision.rawcam_uv_skip-config->vision.rawcam_y_skip+1;
00252 if(ysamp>maxsamp)
00253 ysamp=maxsamp;
00254 }
00255 cinfo.comp_info[0].h_samp_factor=ysamp;
00256 cinfo.comp_info[0].v_samp_factor=ysamp;
00257 cinfo.comp_info[1].h_samp_factor=uvsamp;
00258 cinfo.comp_info[1].v_samp_factor=uvsamp;
00259 cinfo.comp_info[2].h_samp_factor=uvsamp;
00260 cinfo.comp_info[2].v_samp_factor=uvsamp;
00261 }
00262
00263
00264 jpeg_start_compress(&cinfo, TRUE);
00265 unsigned int row_stride = src->getStride(layer);
00266 JSAMPROW row_pointer[1] = { const_cast<JSAMPROW>(src->getImage(layer,chan)) };
00267 while (cinfo.next_scanline < cinfo.image_height) {
00268 jpeg_write_scanlines(&cinfo, row_pointer, 1);
00269 row_pointer[0]+=row_stride;
00270 }
00271 jpeg_finish_compress(&cinfo);
00272 }
00273
00274
00275 bytesUsed[layer][chan]=jpeg_mem_size(&cinfo);
00276 imageValids[layer][chan]=true;
00277 } catch(const std::exception& ex) {
00278 std::cerr << "Exception while compressing JPEG: " << ex.what() << std::endl;
00279 std::cerr << "layer==" << layer << " channel==" << chan << " image==" << (void*)images[layer][chan] << std::endl;
00280 std::cerr << "width==" << widths[layer] << " height==" << heights[layer] << std::endl;
00281 std::cerr << "row_stride==" << src->getStride(layer) << " next_scanline==" << (void*)cinfo.next_scanline << " image_height==" << cinfo.image_height << std::endl;
00282 jpeg_destroy_compress(&cinfo);
00283 }
00284 }
00285
00286 void
00287 JPEGGenerator::destruct() {
00288 FilterBankGenerator::destruct();
00289 for(unsigned int res=0; res<numLayers; res++)
00290 delete [] bytesUsed[res];
00291 delete [] bytesUsed;
00292 bytesUsed=NULL;
00293 }
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
|