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