Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

CDTGenerator.cc

Go to the documentation of this file.
00001 #include "CDTGenerator.h"
00002 #include "Events/DataEvent.h"
00003 #include "Events/EventRouter.h"
00004 #include "Events/SegmentedColorFilterBankEvent.h"
00005 #include "Wireless/Wireless.h"
00006 #include "Shared/Config.h"
00007 #include "Shared/Profiler.h"
00008 #include "Shared/ProjectInterface.h"
00009 
00010 #include "Shared/ODataFormats.h"
00011 #include "OFbkImage.h"
00012 
00013 #include "Shared/debuget.h"
00014 
00015 CDTGenerator::CDTGenerator(unsigned int numRawLayers, unsigned int numCalcLayers, unsigned int mysid, EventBase::EventGeneratorID_t gid, unsigned int sid)
00016   : FilterBankGenerator("CDTGenerator",EventBase::visSegmentEGID,mysid,gid,sid), numRealLayers(numRawLayers), layers(NULL), imageInfos(NULL)
00017 {
00018   /* As a root stage, we need to listen to all incoming image
00019    * events, even if we don't currently have listeners of our own --
00020    * This is just in case user code directly accesses a generator
00021    * and we have to retroactively go back and dig up the previous
00022    * frame */
00023   unsetAutoListen();
00024   
00025   setNumImages(numCalcLayers,NUM_CHANNELS);
00026 }
00027 
00028 /*! The const casts in this function are regretable but necessary
00029  *  since the OPEN-R OFbkImage constructor requires mutable
00030  *  arguments, even though it shouldn't be modifying the data
00031  */
00032 void
00033 CDTGenerator::doEvent() {
00034   if(event->getGeneratorID()!=getListenGeneratorID() || event->getSourceID()!=getListenSourceID())
00035     return;
00036   if(event->getTypeID()==EventBase::activateETID) {
00037     typedef DataEvent<const OFbkImageVectorData*> OFbkEvent;
00038     const OFbkEvent& fbkevent=dynamic_cast<const OFbkEvent& >(*event);
00039     OFbkImageVectorData& fbkdat=*const_cast<OFbkImageVectorData*>(fbkevent.getData());
00040     for(unsigned int res=0; res<numRealLayers; res++) {
00041       layers[numLayers-1-res] = fbkdat.GetData(res);
00042       imageInfos[numLayers-1-res] = fbkdat.GetInfo(res);
00043     }
00044     {
00045       const OFbkImage img(const_cast<OFbkImageInfo*>(imageInfos[numLayers-2]), const_cast<unsigned char*>(layers[numLayers-2]), ofbkimageBAND_CDT);
00046       //I have to do this crazy thing because apparently img.FieldCounter() doesn't work
00047       sysFrameNumber=frameNumber=*(int*)(img.Pointer()+(img.Height()-1)*(img.Skip()+img.Width()));
00048     }
00049     unsigned int numNotRealLayers=numLayers-numRealLayers;
00050     bool dimchange=false;
00051     for(unsigned int res=numNotRealLayers; res<numLayers; res++) {
00052       if(widths[res]!=imageInfos[res]->width || heights[res]!=imageInfos[res]->height) {
00053         dimchange=true;
00054         serr->printf("WARNING: the image dimensions changed, now %dx%d\n",widths[numLayers-1],heights[numLayers-1]);
00055         widths[res] = imageInfos[res]->width;
00056         heights[res] = imageInfos[res]->height;
00057       }
00058 
00059       const OFbkImage img(const_cast<OFbkImageInfo*>(imageInfos[res]), const_cast<unsigned char*>(layers[res]), ofbkimageBAND_CDT);
00060       skips[res]=img.Skip();
00061       strides[res]=skips[res]+widths[res];
00062 
00063       ASSERT(static_cast<unsigned int>(img.Width())==getWidth(res),"Widths don't match");
00064       ASSERT(static_cast<unsigned int>(img.Height())==getHeight(res),"Heights don't match");
00065     }
00066     if(numNotRealLayers>0) {
00067       if(widths[numNotRealLayers-1]*2!=widths[numNotRealLayers] || heights[numNotRealLayers]*2!=heights[numNotRealLayers]) {
00068         //|| widths[numLayers-2-numRealLayers]*2!=widths[numNotRealLayers]
00069         //|| heights[numLayers-2-numRealLayers]*2!=heights[numNotRealLayers]) {
00070         //set the width and height of non-real layers (since they don't match what they should be)
00071         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]);
00072         dimchange=true;
00073       } else if(strides[0]==0) {
00074         dimchange=true;
00075       }
00076     }
00077     if(dimchange)
00078       setDimensions();
00079 
00080     invalidateCaches();
00081     framesProcessed++;
00082   }
00083   // todo - i wish we had some color infomation to pass here so we could use the event for CMVision's RLE, etc.
00084   erouter->postEvent(SegmentedColorFilterBankEvent(this,getGeneratorID(),getSourceID(),event->getTypeID(),NULL,0,NULL,NULL));
00085 }
00086 
00087 unsigned int
00088 CDTGenerator::getBinSize() const {
00089   unsigned int used=FilterBankGenerator::getBinSize();
00090   // todo - once we have color information - we could make this interoperable with SegmentedColorGenerator
00091   // by following the same serialization format
00092   used+=strlen("CDTImage")+LoadSave::stringpad;
00093   used+=widths[selectedSaveLayer]*heights[selectedSaveLayer];
00094   return used;
00095 }
00096 
00097 unsigned int
00098 CDTGenerator::loadBuffer(const char [] /*buf*/, unsigned int /*len*/, const char* filename) {
00099   //all our memory is in system controlled buffers - we probably shouldn't overwrite it...
00100   serr->printf("Can't load into CDTGenerator: %s",filename);
00101   return 0;
00102 }
00103 
00104 unsigned int
00105 CDTGenerator::saveBuffer(char buf[], unsigned int len) const {
00106   unsigned int origlen=len;
00107   unsigned int used;
00108   if(0==(used=FilterBankGenerator::saveBuffer(buf,len))) return 0;
00109   len-=used; buf+=used;
00110   // todo - once we have color information - we could make this interoperable with SegmentedColorGenerator
00111   // by following the same serialization format
00112   if(0==(used=encode("CDTImage",buf,len))) return 0;
00113   len-=used; buf+=used;
00114   
00115   if(images[selectedSaveLayer][selectedSaveChannel]==NULL) {
00116     serr->printf("CDTImage::saveBuffer() failed because selected image is NULL -- call selectSaveImage first to make sure it's up to date\n");
00117     return 0;
00118   }
00119   if(!imageValids[selectedSaveLayer][selectedSaveChannel]) {
00120     serr->printf("CDTImage::saveBuffer() failed because selected image is invalid -- call selectSaveImage first to make sure it's up to date\n");
00121     return 0;
00122   }
00123   unsigned char* img=images[selectedSaveLayer][selectedSaveChannel];
00124   used=widths[selectedSaveLayer]*heights[selectedSaveLayer];
00125   if(used>len)
00126     return 0;
00127   unsigned int inc=getIncrement(selectedSaveLayer);
00128   if(inc==1) {
00129     //special case, straight copy
00130     for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
00131       unsigned char* const rowend=img+widths[selectedSaveLayer];
00132       while(img!=rowend)
00133         *buf++=*img++;
00134       img+=getSkip(selectedSaveLayer);
00135     }
00136   } else {
00137     //otherwise, interleaved or subsampling
00138     for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
00139       unsigned char* const rowend=img+widths[selectedSaveLayer]*inc;
00140       while(img!=rowend) {
00141         *buf++=*img;
00142         img+=inc;
00143       }
00144       img+=getSkip(selectedSaveLayer);
00145     }
00146   }
00147   len-=used;
00148   
00149   return origlen-len;
00150 }
00151 
00152 void
00153 CDTGenerator::setDimensions() {
00154   freeCaches();
00155   unsigned int numNotRealLayers=numLayers-numRealLayers;
00156   for(unsigned int res=0; res<numNotRealLayers; res++) {
00157     widths[res] = imageInfos[numNotRealLayers]->width>>(numNotRealLayers-res);
00158     heights[res] = imageInfos[numNotRealLayers]->height>>(numNotRealLayers-res);
00159     ASSERT(widths[res]*increments[res]==widths[numNotRealLayers],"widths*increments doesn't match total width");
00160     strides[res]=strides[numNotRealLayers]*increments[res];
00161     skips[res]=skips[numNotRealLayers]+strides[res]-strides[numNotRealLayers];
00162   }
00163   strides[numLayers-1]=widths[numLayers-1]=widths[numLayers-2]*2;
00164   heights[numLayers-1]=heights[numLayers-2]*2;
00165 }
00166 
00167 void 
00168 CDTGenerator::freeCaches() {
00169   for(unsigned int i=0; i<numLayers; i++) {
00170     for(unsigned int j=0; j<numChannels; j++) {
00171       images[i][j]=NULL;
00172       imageValids[i][j]=false;
00173     }
00174   }
00175   FilterBankGenerator::freeCaches();
00176 }
00177 
00178 void
00179 CDTGenerator::setNumImages(unsigned int nLayers, unsigned int nChannels) {
00180   if(nLayers==numLayers && nChannels==numChannels)
00181     return;
00182   FilterBankGenerator::setNumImages(nLayers,nChannels);
00183   layers=new unsigned char*[numLayers];
00184   imageInfos=new const OFbkImageInfo*[numLayers];
00185   unsigned int numNotRealLayers=numLayers-numRealLayers;
00186   for(unsigned int res=0; res<numLayers; res++) {
00187     layers[res]=NULL;
00188     imageInfos[res]=NULL;
00189     if(res<numNotRealLayers)
00190       increments[res]=1<<(numNotRealLayers-res);
00191   }
00192 }
00193 
00194 unsigned char *
00195 CDTGenerator::createImageCache(unsigned int /*layer*/, unsigned int /*chan*/) const {
00196   return NULL; // calcImage will set the cache itself
00197 }
00198 
00199 void
00200 CDTGenerator::calcImage(unsigned int layer, unsigned int chan) {
00201   PROFSECTION("CDTGenerator::calcImage(...)",*mainProfiler);
00202   unsigned int numNotRealLayers=numLayers-numRealLayers;
00203   if(layer>=numNotRealLayers) {
00204     unsigned int fbkdatChan=ofbkimageBAND_CDT;
00205     const OFbkImage img(const_cast<OFbkImageInfo*>(imageInfos[layer]), const_cast<unsigned char*>(layers[layer]), fbkdatChan);
00206     images[layer][chan]=img.Pointer();
00207 
00208     //I'm not sure if this is needed for CDT images themselves - haven't used it yet
00209     //so this section is commented out for now just in case.
00210     /*
00211       //this part restores pixels over written with the CDT table and
00212       //frame count.  Yes, we are modifying the original image passed
00213       //from the system here...
00214       if(config->vision.restore_image) {
00215         const unsigned int numPix=16;
00216         if(layer==numLayers-2) {
00217           unsigned char * s=images[layer][chan]+getStride(layer)*(getHeight(layer)-2);
00218           unsigned char * d=images[layer][chan]+getStride(layer)*(getHeight(layer)-1);
00219           for(unsigned int i=0; i<numPix; i++)
00220             *d++=*s++;
00221         } else {
00222           unsigned int inc=1<<(numLayers-2-layer);
00223           unsigned char * s;
00224           //unsigned char * s=getImage(numLayers-2,chan)+getStride(numLayers-2)*(getHeight(numLayers-2)-inc);
00225           //...or an attempt to possibly avoid a trivial amount of recomputation....
00226           if(!imageValids[numLayers-2][chan]) {
00227             const OFbkImage simg(const_cast<OFbkImageInfo*>(imageInfos[numLayers-2]), const_cast<unsigned char*>(layers[numLayers-2]), fbkdatChan);
00228             s=simg.Pointer();
00229           } else {
00230             s=images[numLayers-2][chan];
00231           }
00232           s+=getStride(numLayers-2)*(getHeight(numLayers-2)-inc);
00233           unsigned char * d=images[layer][chan]+getStride(layer)*(getHeight(layer)-1);
00234           for(unsigned int i=0; i<numPix; i++) {
00235             *d++=*s;
00236             s+=inc;
00237           }
00238         }
00239       }
00240     */
00241   } else {
00242     //we don't need to do the restoration in the previous section
00243     //here because these layers skip the last row
00244     unsigned int fbkdatChan=ofbkimageBAND_CDT;
00245     const OFbkImage img(const_cast<OFbkImageInfo*>(imageInfos[numNotRealLayers]), const_cast<unsigned char*>(layers[numNotRealLayers]), fbkdatChan);
00246     images[layer][chan]=img.Pointer();
00247   }
00248   imageValids[layer][chan]=true;
00249 }
00250 
00251 void
00252 CDTGenerator::destruct() {
00253   FilterBankGenerator::destruct();
00254   delete [] layers;
00255   layers=NULL;
00256   delete [] imageInfos;
00257   imageInfos=NULL;
00258 }
00259 
00260 /*! @file
00261  * @brief Implements CDTGenerator, which generates SegmentedColorFilterBankEvents with images provided from the system
00262  * @author ejt (Creator)
00263  */
00264 

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:36 2016 by Doxygen 1.6.3