00001 #include "ImageStreamDriver.h"
00002 #include "Shared/get_time.h"
00003 #include "Shared/MarkScope.h"
00004 #include "Shared/RobotInfo.h"
00005 #include "Shared/Config.h"
00006 #include "Shared/ImageUtil.h"
00007 #include "Shared/debuget.h"
00008 #include "Shared/InverseMarkScope.h"
00009
00010 using namespace std;
00011
00012 const char * ImageStreamDriver::formatNames[NUM_FORMATS+1] = { "yuv", "png", "jpeg", "tekkotsu", NULL };
00013
00014
00015 INSTANTIATE_NAMEDENUMERATION_STATICS(ImageStreamDriver::format_t);
00016
00017 const std::string ImageStreamDriver::autoRegisterDriver = DeviceDriver::getRegistry().registerType<ImageStreamDriver>("ImageStream");
00018
00019 void ImageStreamDriver::plistValueChanged(const plist::PrimitiveBase& pl) {
00020 if(&pl==&format) {
00021 CommPort * comm = getComm(commName);
00022 if(comm!=NULL) {
00023 disconnect(comm);
00024 connect(comm);
00025 }
00026 } else {
00027 DataStreamDriver::plistValueChanged(pl);
00028 }
00029 }
00030
00031 bool ImageStreamDriver::readData(std::istream& is) {
00032 RCRegion * region=readImage(is);
00033 if(region==NULL)
00034 return false;
00035 if(!paceInput) try {
00036
00037 region->AddReference();
00038 char firstByte;
00039 while(is.readsome(&firstByte,1)>0 && is) {
00040 is.putback(firstByte);
00041 RCRegion * newRegion = readImage(is);
00042 if(newRegion!=NULL) {
00043 ASSERT(region!=newRegion,"ImageStreamDriver handed out same region twice");
00044
00045 region->RemoveReference();
00046 region=newRegion;
00047 region->AddReference();
00048 }
00049 testCancel();
00050 }
00051 region->RemoveReference();
00052 } catch(...) {
00053 region->RemoveReference();
00054 throw;
00055 }
00056 setImage(region);
00057 return true;
00058 }
00059
00060 RCRegion * ImageStreamDriver::readImage(std::istream& is) {
00061 format_t expectedFormat = format;
00062
00063
00064 char firstByte;
00065 is.get(firstByte);
00066 if(!is)
00067 return NULL;
00068 is.unget();
00069 testCancel();
00070 timestamp = get_time();
00071
00072 const size_t HEADER_SIZE = sizeof(ImageHeader);
00073
00074 RCRegion* region = (payloadSize==0) ? NULL : getUnusedRegion(payloadSize, 0);
00075
00076 unsigned int layer=0;
00077
00078 switch(expectedFormat) {
00079 case FORMAT_YUV: {
00080 size_t imgSize = CameraResolutionX*CameraResolutionY*3;
00081 payloadSize = HEADER_SIZE + imgSize;
00082 if(region==NULL) {
00083 region = getUnusedRegion(payloadSize, 0);
00084 } else if(region->Size()<payloadSize) {
00085
00086 region = getUnusedRegion(payloadSize, 0);
00087 }
00088 char * payload = region->Base();
00089 is.read(payload+HEADER_SIZE, imgSize);
00090 testCancel();
00091 if(!is)
00092 return NULL;
00093 new (payload) ImageHeader(0, layer, CameraResolutionX, CameraResolutionY, 3, ++frameNumber, timestamp, nextName());
00094 } break;
00095
00096 case FORMAT_PNG: {
00097 size_t w=0,h=0,c=0;
00098 if(region==NULL) {
00099
00100 if(!image_util::decodePNG(is,w,h,c)) {
00101 cerr << "ImageStreamDriver JPEG header decompression failed" << endl;
00102 return NULL;
00103 }
00104 payloadSize = HEADER_SIZE + w*h*c;
00105 region = getUnusedRegion(payloadSize, 0);
00106 }
00107 char * img=region->Base() + HEADER_SIZE;
00108 size_t imgSize=region->Size()-HEADER_SIZE;
00109
00110 if(!image_util::decodePNG(is,w,h,c,img,imgSize)) {
00111
00112 if(w*h*c<=imgSize) {
00113 cerr << "ImageStreamDriver PNG decompression failed" << endl;
00114 return NULL;
00115 }
00116
00117 payloadSize = HEADER_SIZE + w*h*c;
00118
00119 region = getUnusedRegion(payloadSize, 0);
00120 img=region->Base() + HEADER_SIZE;
00121 imgSize=region->Size()-HEADER_SIZE;
00122 if(!image_util::decodePNG(is,w,h,c,img,imgSize)) {
00123 cerr << "ImageStreamDriver PNG decompression failed after resize" << endl;
00124 return NULL;
00125 }
00126 }
00127 testCancel();
00128 payloadSize = HEADER_SIZE + w*h*c;
00129 new (region->Base()) ImageHeader(0, layer, w, h, c, ++frameNumber, timestamp, nextName());
00130 } break;
00131
00132 case FORMAT_JPEG: {
00133 size_t w=0,h=0,c=0;
00134 if(region==NULL) {
00135
00136 if(!image_util::decodeJPEG(is,w,h,c)) {
00137 cerr << "ImageStreamDriver JPEG header decompression failed" << endl;
00138 return NULL;
00139 }
00140 payloadSize = HEADER_SIZE + w*h*c;
00141 region = getUnusedRegion(payloadSize, 0);
00142 }
00143 char * img=region->Base() + HEADER_SIZE;
00144 size_t imgSize=region->Size()-HEADER_SIZE;
00145
00146 if(!image_util::decodeJPEG(is,w,h,c,img,imgSize)) {
00147
00148 if(w*h*c<=imgSize) {
00149 cerr << "ImageStreamDriver JPEG decompression failed" << endl;
00150 return NULL;
00151 }
00152
00153 payloadSize = HEADER_SIZE + w*h*c;
00154
00155 region = getUnusedRegion(payloadSize, 0);
00156 img=region->Base() + HEADER_SIZE;
00157 imgSize=region->Size()-HEADER_SIZE;
00158 if(!image_util::decodeJPEG(is,w,h,c,img,imgSize)) {
00159 cerr << "ImageStreamDriver JPEG decompression failed after resize" << endl;
00160 return NULL;
00161 }
00162 }
00163 testCancel();
00164 payloadSize = HEADER_SIZE + w*h*c;
00165 new (region->Base()) ImageHeader(0, layer, w, h, c, ++frameNumber, timestamp, nextName());
00166 } break;
00167
00168 case FORMAT_TEKKOTSU: {
00169
00170
00171
00172 unsigned int width=CameraResolutionX, height=CameraResolutionY, components=3;
00173
00174
00175 char tmp[256];
00176 unsigned int len;
00177 string fmt;
00178 is.read(tmp,LoadSave::getSerializedSize(len));
00179 LoadSave::decode(len,tmp,LoadSave::getSerializedSize(len));
00180 if(len!=13) {
00181 cerr << "Expecting Tekkotsu image format, but image header doesn't match! (len==" << len << ")" << endl;
00182 return NULL;
00183 }
00184 is.read(tmp,len+1);
00185 if(strncmp(tmp,"TekkotsuImage",len+1)!=0) {
00186 tmp[len+2]='\0';
00187 cerr << "Expecting Tekkotsu image format, but image header doesn't match! (" << tmp << ")" << endl;
00188 return NULL;
00189 }
00190
00191 int encoding;
00192 is.read(tmp,LoadSave::getSerializedSize(encoding));
00193 LoadSave::decode(encoding,tmp,LoadSave::getSerializedSize(encoding));
00194 if(encoding==Config::vision_config::ENCODE_SINGLE_CHANNEL)
00195 components=1;
00196 int compression;
00197 is.read(tmp,LoadSave::getSerializedSize(compression));
00198 LoadSave::decode(compression,tmp,LoadSave::getSerializedSize(compression));
00199 is.read(tmp,LoadSave::getSerializedSize(width));
00200 LoadSave::decode(width,tmp,LoadSave::getSerializedSize(width));
00201 is.read(tmp,LoadSave::getSerializedSize(height));
00202 LoadSave::decode(height,tmp,LoadSave::getSerializedSize(height));
00203 unsigned int remote_timestamp;
00204 is.read(tmp,LoadSave::getSerializedSize(remote_timestamp));
00205 LoadSave::decode(remote_timestamp,tmp,LoadSave::getSerializedSize(remote_timestamp));
00206 unsigned int fnum;
00207 is.read(tmp,LoadSave::getSerializedSize(fnum));
00208 LoadSave::decode(fnum,tmp,LoadSave::getSerializedSize(fnum));
00209
00210
00211 payloadSize = HEADER_SIZE + width*height*components;
00212 if(region==NULL) {
00213 region = getUnusedRegion(payloadSize, 0);
00214 } else if(region->Size() < payloadSize) {
00215
00216 region = getUnusedRegion(payloadSize, 0);
00217 }
00218
00219 unsigned int remain = width*height*components;
00220 char * b=region->Base()+HEADER_SIZE;
00221
00222 for(unsigned int i=0; i<components; ++i) {
00223
00224 is.read(tmp,LoadSave::getSerializedSize(len));
00225 LoadSave::decode(len,tmp,LoadSave::getSerializedSize(len));
00226 if(len!=8) {
00227 cerr << "Expecting FbkImage image format, but header doesn't match! (len==" << len << ")" << endl;
00228 return NULL;
00229 }
00230 is.read(tmp,len+1);
00231 if(strncmp(tmp,"FbkImage",len+1)!=0) {
00232 tmp[len+2]='\0';
00233 cerr << "Expecting FbkImage image format, but image header doesn't match! (" << tmp << ")" << endl;
00234 return NULL;
00235 }
00236 unsigned int lwidth;
00237 is.read(tmp,LoadSave::getSerializedSize(lwidth));
00238 LoadSave::decode(lwidth,tmp,LoadSave::getSerializedSize(lwidth));
00239 unsigned int lheight;
00240 is.read(tmp,LoadSave::getSerializedSize(lheight));
00241 LoadSave::decode(lheight,tmp,LoadSave::getSerializedSize(lheight));
00242 unsigned int lyr;
00243 is.read(tmp,LoadSave::getSerializedSize(lyr));
00244 LoadSave::decode(lyr,tmp,LoadSave::getSerializedSize(lyr));
00245 unsigned int chan_id;
00246 is.read(tmp,LoadSave::getSerializedSize(chan_id));
00247 LoadSave::decode(chan_id,tmp,LoadSave::getSerializedSize(chan_id));
00248
00249
00250 is.read(tmp,LoadSave::getSerializedSize(len));
00251 LoadSave::decode(len,tmp,LoadSave::getSerializedSize(len));
00252 is.read(tmp,len+1);
00253 if(strcmp(tmp,"blank")==0) {
00254 int useChan=(components==1)?i:chan_id;
00255 int off=useChan;
00256 for(unsigned int y=0; y<height; y++) {
00257 for(unsigned int x=0; x<width; x++) {
00258 b[off]=128;
00259 off+=components;
00260 }
00261 }
00262 } else if(strcmp(tmp,"RawImage")==0) {
00263 int useChan=(components==1)?i:chan_id;
00264 vector<char> chan(lwidth*lheight);
00265 is.read(&chan.front(),chan.size());
00266 copyImage(b,width,height,components,&chan.front(),lwidth,lheight,useChan);
00267
00268 } else if(strcmp(tmp,"JPEGGrayscale")==0) {
00269 int useChan=(components==1)?i:chan_id;
00270 is.read(tmp,LoadSave::getSerializedSize(len));
00271 LoadSave::decode(len,tmp,LoadSave::getSerializedSize(len));
00272 vector<char> jpeg(len);
00273 is.read(&jpeg.front(),jpeg.size());
00274 size_t jwidth,jheight,jcomp;
00275 image_util::decodeJPEG(&jpeg.front(), jpeg.size(), jwidth, jheight, jcomp);
00276 if(jcomp!=1) {
00277 cerr << "Got color image where grayscale was expected" << endl;
00278 return NULL;
00279 }
00280 vector<char> chan(jwidth*jheight);
00281 size_t tsize=chan.size();
00282 char* tchan=&chan.front();
00283 if(!image_util::decodeJPEG(&jpeg.front(), jpeg.size(), jwidth, jheight, jcomp, tchan, tsize)) {
00284 cerr << "JPEG decompression failed" << endl;
00285 return NULL;
00286 }
00287 copyImage(b,width,height,components,&chan.front(),lwidth,lheight,useChan);
00288
00289 } else if(strcmp(tmp,"JPEGColor")==0) {
00290 is.read(tmp,LoadSave::getSerializedSize(len));
00291 LoadSave::decode(len,tmp,LoadSave::getSerializedSize(len));
00292 vector<char> jpeg(len);
00293 is.read(&jpeg.front(),jpeg.size());
00294 size_t jwidth,jheight,jcomp;
00295 size_t tsize=remain;
00296 if(!image_util::decodeJPEG(&jpeg.front(), jpeg.size(), jwidth, jheight, jcomp, b, tsize)) {
00297 cerr << "JPEG decompression failed" << endl;
00298 return NULL;
00299 }
00300 i=components;
00301
00302 } else {
00303 cerr << "Unknown image generator " << tmp << endl;
00304 return NULL;
00305 }
00306 }
00307
00308 testCancel();
00309 if(!is)
00310 return NULL;
00311 new (region->Base()) ImageHeader(0, layer, width, height, components, ++frameNumber, timestamp, nextName());
00312 } break;
00313 }
00314 ASSERTRETVAL(region!=NULL,"image memory region is still NULL after reading, unknown format?",NULL);
00315 return region;
00316 }
00317
00318 void ImageStreamDriver::copyImage(char * buf, unsigned int width, unsigned int height, unsigned int channels, const char * chan, unsigned int lwidth, unsigned int lheight, unsigned int c) {
00319 if(lwidth==width && lheight==height) {
00320
00321 for(unsigned int y=0;y<height;y++) {
00322 unsigned int datarowstart=y*width*channels+c;
00323 unsigned int tmprowstart=y*lwidth;
00324 for(unsigned int x=0;x<width;x++)
00325 buf[datarowstart+x*channels]=chan[tmprowstart+x];
00326 }
00327 } else {
00328
00329
00330
00331
00332
00333
00334
00335 float xsc=(lwidth-1)/(float)(width-1);
00336 float ysc=(lheight-1)/(float)(height-1);
00337 for(unsigned int y=0;y<height-1;y++) {
00338 unsigned int datarowstart=y*width*channels+c;
00339 float ty=y*ysc;
00340 unsigned int ly=(int)ty;
00341 float fy=ty-ly;
00342 unsigned int tmprowstart=ly*lwidth;
00343 for(unsigned int x=0;x<width-1;x++) {
00344 float tx=x*xsc;
00345 unsigned int lx=(int)tx;
00346 float fx=tx-lx;
00347
00348 float lv=((int)chan[tmprowstart+lx]&0xFF)*(1-fx)+((int)chan[tmprowstart+lx+1]&0xFF)*fx;
00349 float uv=((int)chan[tmprowstart+lx+lwidth]&0xFF)*(1-fx)+((int)chan[tmprowstart+lx+1+lwidth]&0xFF)*fx;
00350 buf[datarowstart+x*channels]=(char)(lv*(1-fy)+uv*fy);
00351 }
00352 buf[datarowstart+(width-1)*channels]=chan[tmprowstart+lwidth-1];
00353 }
00354 unsigned int datarowstart=width*(height-1)*channels+c;
00355 unsigned int tmprowstart=lwidth*(lheight-1);
00356 for(unsigned int x=0;x<width-1;x++) {
00357 float tx=x*xsc;
00358 unsigned int lx=(int)tx;
00359 float fx=tx-lx;
00360 buf[datarowstart+x*channels]=(char)(((int)chan[tmprowstart+lx]&0xFF)*(1-fx)+((int)chan[tmprowstart+lx+1]&0xFF)*fx);
00361 }
00362 buf[datarowstart+(width-1)*channels]=chan[tmprowstart+lwidth-1];
00363 }
00364 }
00365
00366 void ImageStreamDriver::connect(CommPort* comm) {
00367 DataStreamDriver::connect(comm);
00368 format.addPrimitiveListener(this);
00369 }
00370
00371 void ImageStreamDriver::disconnect(CommPort* comm) {
00372 format.removePrimitiveListener(this);
00373 DataStreamDriver::disconnect(comm);
00374 }
00375
00376
00377
00378
00379