Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

BufferedImageGenerator.cc

Go to the documentation of this file.
00001 #ifndef PLATFORM_APERIOS
00002 
00003 #include "BufferedImageGenerator.h"
00004 #include "Events/DataEvent.h"
00005 #include "Events/FilterBankEvent.h"
00006 #include "Wireless/Socket.h"
00007 #include "Events/EventRouter.h"
00008 #include "Shared/debuget.h"
00009 #include "Shared/ProjectInterface.h"
00010 
00011 using namespace std;
00012 
00013 void BufferedImageGenerator::processEvent(const EventBase & event) {
00014   EventGeneratorBase::processEvent(event);
00015   if(event.getGeneratorID()!=getListenGeneratorID() || event.getSourceID()!=getListenSourceID())
00016     return;
00017   if(event.getTypeID()==EventBase::activateETID) {
00018     const DataEvent<ImageSource>* data=dynamic_cast<const DataEvent<ImageSource>*>(&event);
00019     if(data==NULL) {
00020       serr->printf("Error: %s(%s) received event of the wrong type",getClassName().c_str(),getName().c_str());
00021       return;
00022     }
00023     if(imgsrc.layer!=data->getData().layer || imgsrc.channels!=data->getData().channels) {
00024       //can "quietly" switch the layer of transmission as long as the width and height were scaled properly
00025       //just need to reset the increments if a different layer is being used.
00026       unsigned int i;
00027       for(i=0; i<data->getData().layer; i++) {
00028         increments[i] = 1;
00029         strides[i]=data->getData().width>>(data->getData().layer-i);
00030         skips[i]=0;
00031       }
00032       increments[i] = data->getData().channels;
00033       strides[i]=data->getData().width*data->getData().channels;
00034       skips[i]=0;
00035       for(++i; i<numLayers; i++) {
00036         increments[i] = 1;
00037         strides[i]=data->getData().width<<(i-data->getData().layer);
00038         skips[i]=0;
00039       }
00040     }
00041     imgsrc=data->getData();
00042     sysFrameNumber=frameNumber=imgsrc.frameIndex;
00043     invalidateCaches(); //mark everything invalid
00044     if(numLayers>0) {
00045       // have images, check if the dimensions have changed
00046       if(imgsrc.width!=getWidth(imgsrc.layer) || imgsrc.height!=getHeight(imgsrc.layer)) {
00047         freeCaches();
00048         setDimensions();
00049         serr->printf("WARNING: the image dimensions don't match values predicted by RobotInfo consts, \"full\" layer now %dx%d\n",widths[ProjectInterface::fullLayer],heights[ProjectInterface::fullLayer]);
00050       } else if(strides[numLayers-1]==0) {
00051         // first frame, set it anyway
00052         setDimensions();
00053       }
00054     }
00055     // -- reassign to the new buffer: --
00056     unsigned int i=imgsrc.layer;
00057     for(unsigned int j=0; j<imgsrc.channels; j++) {
00058       if(isAllocated[i][j]) { //in case the imgsrc layer changes
00059         delete [] images[i][j];
00060         images[i][j]=NULL;
00061         isAllocated[i][j]=false;
00062       }
00063       imageValids[i][j]=true;
00064     }
00065     images[i][RawCameraGenerator::CHAN_Y]=imgsrc.img+0;
00066     images[i][RawCameraGenerator::CHAN_U]=imgsrc.img+1;
00067     images[i][RawCameraGenerator::CHAN_V]=imgsrc.img+2;
00068     framesProcessed++;
00069   }
00070   erouter->postEvent(FilterBankEvent(this,getGeneratorID(),getSourceID(),event.getTypeID()));
00071 }
00072 
00073 unsigned int
00074 BufferedImageGenerator::getBinSize() const {
00075   unsigned int used=FilterBankGenerator::getBinSize();
00076   used+=getSerializedSize("RawImage");
00077   used+=widths[selectedSaveLayer]*heights[selectedSaveLayer];
00078   return used;
00079 }
00080 
00081 unsigned int
00082 BufferedImageGenerator::loadBuffer(const char buf[], unsigned int len) {
00083   unsigned int origlen=len;
00084   if(!checkInc(FilterBankGenerator::loadBuffer(buf,len),buf,len)) return 0;
00085   std::string tmp;
00086   if(decode(tmp,buf,len)) return 0;
00087   if(tmp!="RawImage") {
00088     serr->printf("Unhandled image type for BufferedImageGenerator: %s",tmp.c_str());
00089     return 0;
00090   } else if(selectedSaveLayer!=numLayers-1) {
00091     serr->printf("Can't load into BufferedImageGenerator layer %d!=%d",selectedSaveLayer,numLayers-1);
00092     return 0;
00093   } else {
00094     if(images[selectedSaveLayer][selectedSaveChannel]==NULL)
00095       images[selectedSaveLayer][selectedSaveChannel]=createImageCache(selectedSaveLayer,selectedSaveChannel);
00096     unsigned char* img=images[selectedSaveLayer][selectedSaveChannel];
00097     unsigned int used=widths[selectedSaveLayer]*heights[selectedSaveLayer];
00098     ASSERTRETVAL(used<=len,"buffer too small",0);
00099     memcpy(img,buf,used);
00100     len-=used; buf+=used;
00101     imageValids[selectedSaveLayer][selectedSaveChannel]=true;
00102     return origlen-len; 
00103   }
00104 }
00105 
00106 unsigned int
00107 BufferedImageGenerator::saveBuffer(char buf[], unsigned int len) const {
00108   unsigned int origlen=len;
00109   if(!checkInc(FilterBankGenerator::saveBuffer(buf,len),buf,len)) return 0;
00110   if(!encodeInc("RawImage",buf,len)) return 0;
00111   
00112   if(images[selectedSaveLayer][selectedSaveChannel]==NULL) {
00113     serr->printf("BufferedImageGenerator::saveBuffer() failed because selected image is NULL -- call selectSaveImage first to make sure it's up to date\n");
00114     return 0;
00115   }
00116   if(!imageValids[selectedSaveLayer][selectedSaveChannel]) {
00117     serr->printf("BufferedImageGenerator::saveBuffer() failed because selected image is invalid -- call selectSaveImage first to make sure it's up to date\n");
00118     return 0;
00119   }
00120   unsigned char* img=images[selectedSaveLayer][selectedSaveChannel];
00121   unsigned int used=widths[selectedSaveLayer]*heights[selectedSaveLayer];
00122   ASSERTRETVAL(used<=len,"buffer too small",0);
00123   unsigned int inc=getIncrement(selectedSaveLayer);
00124   if(inc==1) {
00125     //special case, straight copy
00126     for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
00127       memcpy(buf,img,widths[selectedSaveLayer]);
00128       buf+=widths[selectedSaveLayer];
00129       img+=getStride(selectedSaveLayer);
00130     }
00131   } else {
00132     //otherwise, interleaved or subsampling
00133     for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
00134       unsigned char* const rowend=img+widths[selectedSaveLayer]*inc;
00135       while(img!=rowend) {
00136         *buf++=*img;
00137         img+=inc;
00138       }
00139       img+=getSkip(selectedSaveLayer);
00140     }
00141   }
00142   len-=used;
00143   
00144   return origlen-len;
00145 }
00146 
00147 unsigned int
00148 BufferedImageGenerator::saveFileStream(FILE * f) const {
00149   unsigned int totalused=0;
00150   unsigned int used;
00151   { //sigh, inheritance has failed me (I wouldn't want FilterBankGenerator::saveFileStream() to call the virtuals...)
00152     unsigned int sz=FilterBankGenerator::getBinSize();
00153     char * buf = new char[sz];
00154     memset(buf,0xF0,sz);
00155     if(buf==NULL) {
00156       std::cout << "*** WARNING could not allocate " << sz << " bytes for loadFile";
00157       return 0;
00158     }
00159     unsigned int resp=FilterBankGenerator::saveBuffer(buf,sz);
00160     if(resp==0) {
00161       std::cout << "*** WARNING saveBuffer didn't write any data (possibly due to overflow or other error)" << std::endl;
00162       fwrite(buf,1,sz,f);
00163     } else {
00164       unsigned int wrote=fwrite(buf,1,resp,f);
00165       if(wrote!=resp)
00166         std::cout << "*** WARNING short write (wrote " << wrote << ", expected " << resp << ")" << std::endl;
00167     }
00168     delete [] buf;
00169     used=resp;
00170   }
00171   if(0==used) return 0;
00172   totalused+=used;
00173   if(0==(used=encode("RawImage",f))) return 0;
00174   totalused+=used;
00175   
00176   if(images[selectedSaveLayer][selectedSaveChannel]==NULL) {
00177     serr->printf("BufferedImageGenerator::saveBuffer() failed because selected image is NULL -- call selectSaveImage first to make sure it's up to date\n");
00178     return 0;
00179   }
00180   if(!imageValids[selectedSaveLayer][selectedSaveChannel]) {
00181     serr->printf("BufferedImageGenerator::saveBuffer() failed because selected image is invalid -- call selectSaveImage first to make sure it's up to date\n");
00182     return 0;
00183   }
00184   unsigned char* img=images[selectedSaveLayer][selectedSaveChannel];
00185   used=widths[selectedSaveLayer]*heights[selectedSaveLayer];
00186   unsigned int inc=getIncrement(selectedSaveLayer);
00187   if(inc==1) {
00188     //special case, straight copy
00189     sout->printf("Saving %d by %d\n",widths[selectedSaveLayer],heights[selectedSaveLayer]);
00190     for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
00191       if(fwrite(img,widths[selectedSaveLayer],1,f)==0) {
00192         serr->printf("short write on image data - ran out of space?\n");
00193         return 0;
00194       }
00195       img+=getStride(selectedSaveLayer);
00196     }
00197   } else {
00198     //otherwise, interleaved or subsampling
00199     for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
00200       unsigned char* const rowend=img+widths[selectedSaveLayer]*inc;
00201       while(img!=rowend) {
00202         if(fputc(*img,f)==EOF) {
00203           serr->printf("short write on image data - ran out of space?\n");
00204           return 0;
00205         }
00206         img+=inc;
00207       }
00208       img+=getSkip(selectedSaveLayer);
00209     }
00210   }
00211   totalused+=used;
00212   
00213   return totalused;
00214 }
00215 
00216 void BufferedImageGenerator::freeCaches() {
00217   FilterBankGenerator::freeCaches();
00218   for(unsigned int i=0; i<numLayers; i++)
00219     for(unsigned int j=0; j<numChannels; j++)
00220       isAllocated[i][j]=false;
00221 }
00222 
00223 void BufferedImageGenerator::invalidateCaches() {
00224   for(unsigned int i=0; i<numLayers; i++)
00225     for(unsigned int j=0; j<numChannels; j++) {
00226       if(!isAllocated[i][j])
00227         images[i][j]=NULL;
00228       imageValids[i][j]=false;
00229     }
00230 }
00231 
00232 unsigned char * BufferedImageGenerator::createImageCache(unsigned int layer, unsigned int channel) const {
00233   if(layer!=imgsrc.layer || imgsrc.channels==1) {
00234     isAllocated[layer][channel]=true;
00235     return new unsigned char[widths[layer]*heights[layer]];
00236   } else {
00237     ASSERT(channel>=imgsrc.channels,"createImageCache for image that should come from src")
00238     // increment is set to imgsrc.channels, so we need to allocate multiple images at once for the generate channels
00239     unsigned int base=(channel/imgsrc.channels)*imgsrc.channels; // round down to nearest multiple of imgsrc.channels
00240     if(images[layer][base]==NULL)
00241       images[layer][base]=new unsigned char[widths[layer]*heights[layer]*imgsrc.channels];
00242     for(unsigned int i=base+1; i<base+imgsrc.channels; ++i) {
00243       ASSERT(!isAllocated[layer][i],"createImageCache for image already allocated!");
00244       ASSERT(images[layer][i]==NULL,"createImageCache for image already assigned!");
00245       images[layer][i]=images[layer][i-1]+1;
00246     }
00247     isAllocated[layer][base]=true;
00248     return images[layer][channel];
00249   }
00250 }
00251 void BufferedImageGenerator::calcImage(unsigned int layer, unsigned int channel) {
00252   //cout << "BufferedImageGenerator::calcImage(" << layer << ',' << channel << ')' << endl;
00253   ASSERTRET(layer!=imgsrc.layer || channel>=imgsrc.channels, "calcImage on src channel?");
00254   switch(channel) {
00255     case RawCameraGenerator::CHAN_Y:
00256       if(layer>imgsrc.layer) upsampleImage(imgsrc.layer,channel,layer);
00257       else downsampleImage(layer,channel);
00258       break;
00259     case RawCameraGenerator::CHAN_U:
00260     case RawCameraGenerator::CHAN_V:
00261       if(imgsrc.channels>1) {
00262         if(layer>imgsrc.layer) upsampleImage(imgsrc.layer,channel,layer);
00263         else downsampleImage(layer,channel);
00264       } else //grayscale image, use blank U and V channels
00265         memset(images[layer][channel],128,widths[layer]*heights[layer]);
00266       break;
00267     case RawCameraGenerator::CHAN_Y_DX:
00268       calcDx(layer);
00269       break;
00270     case RawCameraGenerator::CHAN_Y_DY:
00271       calcDy(layer);
00272       break;
00273     case RawCameraGenerator::CHAN_Y_DXDY:
00274       calcDxDy(layer);
00275       break;
00276     default:
00277       cerr << "Bad layer selection!" << endl;
00278   }
00279 }
00280 void BufferedImageGenerator::setDimensions() {
00281   if(imgsrc.img==NULL) //don't have an image to set from
00282     return;
00283   // set dimensions of layers below and including the input layer
00284   for(unsigned int i=0; i<=imgsrc.layer; i++) {
00285     //s is the scaling factor -- 2 means *half* size
00286     unsigned int s=(1<<(imgsrc.layer-i));
00287     //width and height are scaled down (divide by s)
00288     widths[i]=imgsrc.width/s;
00289     heights[i]=imgsrc.height/s;
00290     //need to skip rows to make good on promised height (multiply by s)
00291     strides[i]=imgsrc.width*imgsrc.channels*s;
00292     skips[i]=strides[i]-imgsrc.width*imgsrc.channels;
00293     //cout << "setDimensions() " << widths[i] << ' ' << skips[i] << ' ' << strides[i] << endl;
00294   }
00295   //set dimensions for layers above the input layer, these are not interleaved
00296   for(unsigned int i=imgsrc.layer+1; i<numLayers; i++) {
00297     //s is the scaling factor -- 2 means *double* size
00298     unsigned int s=(1<<(i-imgsrc.layer));
00299     //multiply by s
00300     widths[i]=strides[i]=imgsrc.width*s;
00301     heights[i]=imgsrc.height*s;
00302     //stride is same as width (set above) -- we allocate these layers, don't skip rows
00303     skips[i]=0;
00304   }
00305 }
00306 void BufferedImageGenerator::destruct() {
00307   FilterBankGenerator::destruct();
00308   for(unsigned int i=0; i<numLayers; i++)
00309     delete [] isAllocated[i];
00310   delete [] isAllocated;
00311   isAllocated=NULL;
00312 }
00313 void BufferedImageGenerator::setNumImages(unsigned int nLayers, unsigned int nChannels) {
00314   if(nLayers==numLayers && nChannels==numChannels)
00315     return;
00316   FilterBankGenerator::setNumImages(nLayers,nChannels);
00317   isAllocated=new bool*[numLayers];
00318   for(unsigned int i=0; i<numLayers; i++) {
00319     isAllocated[i]=new bool[numChannels];
00320     for(unsigned int j=0; j<numChannels; j++)
00321       isAllocated[i][j]=false;
00322   }
00323   setDimensions();
00324 }
00325 
00326 void BufferedImageGenerator::upsampleImage(unsigned int srcLayer, unsigned int chan, unsigned int destLayer) {
00327   ASSERTRET(destLayer!=imgsrc.layer,"upsample into source layer")
00328   unsigned char * cur=images[destLayer][chan];
00329   ASSERTRET(cur!=NULL,"destination layer is NULL");
00330   unsigned char * orig=getImage(srcLayer,chan);
00331   ASSERTRET(orig!=NULL,"source layer is NULL");
00332   unsigned int width=widths[destLayer];
00333   unsigned int height=heights[destLayer];
00334   unsigned int inc=getIncrement(srcLayer);
00335   int power=destLayer-srcLayer;
00336   ASSERTRET(power>0,"upsampleImage attempting to downsample")
00337   
00338   unsigned char * const imgend=cur+width*height;
00339   while(cur!=imgend) {
00340     unsigned char * const row=cur;
00341     unsigned char * const rowend=cur+width;
00342     //upsample pixels within one row
00343     while(cur<rowend) {
00344       for(int p=1<<power; p>0; p--)
00345         *cur++=*orig;
00346       orig+=inc;
00347     }
00348     //now replicate that row 1<<power times, doubling each time
00349     for(int p=0; p<power; p++) {
00350       unsigned int avail=width*(1<<p);
00351       memcpy(cur,row,avail);
00352       cur+=avail;
00353     }
00354     orig+=getSkip(srcLayer);
00355   }
00356   imageValids[destLayer][chan]=true;
00357 }
00358 
00359 void BufferedImageGenerator::downsampleImage(unsigned int destLayer, unsigned int chan) {
00360   ASSERTRET(destLayer!=imgsrc.layer,"downsample into source layer")
00361   // find closest available layer to source from
00362   unsigned int layer=destLayer;
00363   while(layer<numLayers && !imageValids[layer][chan])
00364     layer++;
00365   ASSERTRET(layer<numLayers,"valid layer to downsample from could not be found!");
00366   // we'll compute in-between layers as we go (easier computation and might be able to reuse them anyway)
00367   // layer is the current layer we're downsampling into (layer+1 is the one we're sampling from)
00368   for(unsigned int srcL=layer--; layer>=destLayer; srcL=layer--) {
00369     unsigned int srcInc=getIncrement(srcL); // destination increment is guaranteed to be 1, but source increment isn't
00370     unsigned char * s=getImage(srcL,chan);
00371     if(images[layer][chan]==NULL)
00372       images[layer][chan]=createImageCache(layer,chan);
00373     unsigned char * dst=images[layer][chan];
00374     unsigned char * const dstEnd=dst+widths[layer]*heights[layer];
00375     while(dst!=dstEnd) {
00376       unsigned char * const rowEnd=dst+widths[layer];
00377       while(dst!=rowEnd) {
00378         unsigned short x=*s;
00379         x+=*(s+strides[srcL]);
00380         s+=srcInc;
00381         x+=*s;
00382         x+=*(s+strides[srcL]);
00383         s+=srcInc;
00384         *dst++ = x/4;
00385       }
00386       s+=strides[srcL];
00387     }
00388     imageValids[layer][chan]=true;
00389   }
00390 }
00391 
00392 void BufferedImageGenerator::calcDx(unsigned int layer, unsigned int srcChan/*=RawCameraGenerator::CHAN_Y*/, unsigned int dstChan/*=RawCameraGenerator::CHAN_Y_DX*/) {
00393   unsigned char * s=getImage(layer,srcChan);
00394   unsigned char * dst=images[layer][dstChan];
00395   unsigned int inc=getIncrement(layer);
00396   unsigned int skip=getSkip(layer)+inc;
00397   unsigned char * const dstEnd=dst+getStride(layer)*heights[layer];
00398   unsigned int sc=2;  // i think this should be 1, but this is to provide better compatability with the OPEN-R implementation
00399   while(dst!=dstEnd) {
00400     unsigned char * const rowEnd=dst+widths[layer]*inc-inc;
00401     unsigned char left,right;
00402     while(dst!=rowEnd) {
00403       left=(*s)>>sc;
00404       s+=inc;
00405       right=(*s)>>sc;
00406       *dst=right+128-left;
00407       dst+=inc;
00408     }
00409     *dst=128; //rightmost column is always 128 to retain image dimensions
00410     dst+=skip;
00411     s+=skip;
00412   }
00413   imageValids[layer][dstChan]=true;
00414 }
00415 void BufferedImageGenerator::calcDy(unsigned int layer, unsigned int srcChan/*=RawCameraGenerator::CHAN_Y*/, unsigned int dstChan/*=RawCameraGenerator::CHAN_Y_DY*/) {
00416   unsigned char * s=getImage(layer,srcChan);
00417   unsigned char * dst=images[layer][dstChan];
00418   unsigned int inc=getIncrement(layer);
00419   unsigned int stride=getStride(layer);
00420   unsigned char * const dstEnd=dst+widths[layer]*inc;
00421   unsigned int sc=2;  // i think this should be 1, but this is to provide better compatability with the OPEN-R implementation
00422   while(dst!=dstEnd) {
00423     unsigned char * const colEnd=dst+heights[layer]*stride-stride;
00424     unsigned char top,bottom;
00425     while(dst!=colEnd) {
00426       top=(*s)>>sc;
00427       s+=stride;
00428       bottom=(*s)>>sc;
00429       *dst=bottom+128-top;
00430       dst+=stride;
00431     }
00432     *dst=128; //bottommost column is always 128 to retain image dimensions
00433     dst-=heights[layer]*stride-stride;
00434     s-=heights[layer]*stride-stride;
00435     dst+=inc;
00436     s+=inc;
00437   }
00438   imageValids[layer][dstChan]=true;
00439 }
00440 void BufferedImageGenerator::calcDxDy(unsigned int layer) {
00441   // if one of the dx or dy channel is already available, go from there
00442   if(imageValids[layer][RawCameraGenerator::CHAN_Y_DX]) {
00443     calcDy(layer,RawCameraGenerator::CHAN_Y_DX,RawCameraGenerator::CHAN_Y_DXDY);
00444     imageValids[layer][RawCameraGenerator::CHAN_Y_DXDY]=true;
00445   } else if(imageValids[layer][RawCameraGenerator::CHAN_Y_DY]) {
00446     calcDx(layer,RawCameraGenerator::CHAN_Y_DY,RawCameraGenerator::CHAN_Y_DXDY);
00447     imageValids[layer][RawCameraGenerator::CHAN_Y_DXDY]=true;
00448   } else {
00449     // if neither are available, calculate one of them (dx), and then the other from that
00450     getImage(layer,RawCameraGenerator::CHAN_Y_DX);
00451     calcDy(layer,RawCameraGenerator::CHAN_Y_DX,RawCameraGenerator::CHAN_Y_DXDY);
00452   }
00453 }
00454 
00455 
00456 /*! @file
00457  * @brief Implements BufferedImageGenerator, which receives camera frames as they are loaded by the simulator -- or eventually other sources
00458  * @author Ethan Tira-Thompson (ejt) (Creator)
00459  *
00460  * $Author: ejt $
00461  * $Name: tekkotsu-3_0 $
00462  * $Revision: 1.23 $
00463  * $State: Exp $
00464  * $Date: 2006/09/11 23:05:19 $
00465  */
00466 
00467 #endif

Tekkotsu v3.0
Generated Wed Oct 4 00:03:42 2006 by Doxygen 1.4.7