Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

RawCameraGenerator.cc

Go to the documentation of this file.
00001 #include "RawCameraGenerator.h"
00002 #include "Events/DataEvent.h"
00003 #include "Events/EventRouter.h"
00004 #include "Events/FilterBankEvent.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 #include <float.h>
00016 
00017 RawCameraGenerator::RawCameraGenerator(unsigned int numRawLayers, unsigned int numCalcLayers, unsigned int mysid, EventBase::EventGeneratorID_t gid, unsigned int sid)
00018   : FilterBankGenerator("RawCameraGenerator",EventBase::visRawCameraEGID,mysid,gid,sid), numRealLayers(numRawLayers), layers(NULL), imageInfos(NULL)
00019 {
00020   /* As a root stage, we need to listen to all incoming image
00021    * events, even if we don't currently have listeners of our own --
00022    * This is just in case user code directly accesses a generator
00023    * and we have to retroactively go back and dig up the previous
00024    * frame */
00025   unsetAutoListen();
00026   
00027   setNumImages(numCalcLayers,NUM_CHANNELS);
00028 }
00029 
00030 /*! The const casts in this function are regretable but necessary
00031  *  since the OPEN-R OFbkImage constructor requires mutable
00032  *  arguments, even though it shouldn't be modifying the data
00033  */
00034 void
00035 RawCameraGenerator::doEvent() {
00036   if(event->getGeneratorID()!=getListenGeneratorID() || event->getSourceID()!=getListenSourceID())
00037     return;
00038   if(event->getTypeID()==EventBase::activateETID) {
00039     typedef DataEvent<const OFbkImageVectorData*> OFbkEvent;
00040     const OFbkEvent& fbkevent=dynamic_cast<const OFbkEvent& >(*event);
00041     OFbkImageVectorData& fbkdat=*const_cast<OFbkImageVectorData*>(fbkevent.getData());
00042     for(unsigned int res=0; res<numRealLayers; res++) {
00043       layers[numLayers-2-res] = fbkdat.GetData(res);
00044       imageInfos[numLayers-2-res] = fbkdat.GetInfo(res);
00045     }
00046     {
00047       const OFbkImage img(const_cast<OFbkImageInfo*>(imageInfos[numLayers-2]), const_cast<unsigned char*>(layers[numLayers-2]), ofbkimageBAND_Y);
00048       //I have to do this crazy thing because apparently img.FieldCounter() doesn't work
00049       sysFrameNumber=frameNumber=*(int*)(img.Pointer()+(img.Height()-1)*(img.Skip()+img.Width()));
00050     }
00051     unsigned int numNotRealLayers=numLayers-1-numRealLayers;
00052     bool dimchange=false;
00053     for(unsigned int res=numNotRealLayers; res<numLayers-1; res++) {
00054       if(widths[res]!=imageInfos[res]->width || heights[res]!=imageInfos[res]->height) {
00055         dimchange=true;
00056         serr->printf("WARNING: the image dimensions changed, now %dx%d\n",widths[numLayers-1],heights[numLayers-1]);
00057         widths[res] = imageInfos[res]->width;
00058         heights[res] = imageInfos[res]->height;
00059       }
00060 
00061       const OFbkImage img(const_cast<OFbkImageInfo*>(imageInfos[res]), const_cast<unsigned char*>(layers[res]), ofbkimageBAND_Y);
00062       skips[res]=img.Skip();
00063       strides[res]=skips[res]+widths[res];
00064 
00065       ASSERT(static_cast<unsigned int>(img.Width())==getWidth(res),"Widths don't agree for layer "<<res);
00066       ASSERT(static_cast<unsigned int>(img.Height())==getHeight(res),"Heights don't agree for layer "<<res);
00067     }
00068     if(widths[numLayers-2]*2!=widths[numLayers-1] || heights[numLayers-2]*2!=heights[numLayers-1]) {
00069       //|| widths[numLayers-2-numRealLayers]*2!=widths[numNotRealLayers]
00070       //|| heights[numLayers-2-numRealLayers]*2!=heights[numNotRealLayers]) {
00071       //set the width and height of non-real layers (since they don't match what they should be)
00072       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]);
00073       freeCaches();
00074       dimchange=true;
00075     } else if(strides[numLayers-1]==0) {
00076       // first frame
00077       dimchange=true;
00078     }
00079     if(dimchange)
00080       setDimensions();
00081     float testaspect=widths[numLayers-2]/(float)heights[numLayers-2];
00082     if(fabs(testaspect-config->vision.aspectRatio)>FLT_EPSILON) {
00083       serr->printf("WARNING: the image aspect ratio changed, was %g, now %g (diff %g)\n",*config->vision.aspectRatio,testaspect,testaspect-*config->vision.aspectRatio);
00084       config->vision.aspectRatio=testaspect;
00085     }
00086     
00087     invalidateCaches(); 
00088     framesProcessed++;
00089   }
00090   erouter->postEvent(FilterBankEvent(this,getGeneratorID(),getSourceID(),event->getTypeID()));
00091 }
00092 
00093 unsigned int
00094 RawCameraGenerator::getBinSize() const {
00095   unsigned int used=FilterBankGenerator::getBinSize();
00096   used+=strlen("RawImage")+LoadSave::stringpad;
00097   used+=widths[selectedSaveLayer]*heights[selectedSaveLayer];
00098   return used;
00099 }
00100 
00101 unsigned int
00102 RawCameraGenerator::loadBuffer(const char buf[], unsigned int len, const char* filename) {
00103   unsigned int origlen=len;
00104   std::string tmp;
00105   if(!checkInc(FilterBankGenerator::loadBuffer(buf,len,filename),buf,len)) return 0;
00106   if(!decodeInc(tmp,buf,len)) return 0;
00107   if(tmp!="RawImage") {
00108     serr->printf("Unhandled image type for RawCameraGenerator: %s",tmp.c_str());
00109     return 0;
00110   } else if(selectedSaveLayer!=numLayers-1) {
00111     serr->printf("Can't load into RawCameraGenerator layer %d!=%d",selectedSaveLayer,numLayers-1);
00112     return 0;
00113   } else {
00114     if(images[selectedSaveLayer][selectedSaveChannel]==NULL)
00115       images[selectedSaveLayer][selectedSaveChannel]=createImageCache(selectedSaveLayer,selectedSaveChannel);
00116     unsigned char* img=images[selectedSaveLayer][selectedSaveChannel];
00117     unsigned int used=widths[selectedSaveLayer]*heights[selectedSaveLayer];
00118     ASSERTRETVAL(used<=len,"buffer too small",0);
00119     memcpy(img,buf,used);
00120     len-=used; buf+=used;
00121     imageValids[selectedSaveLayer][selectedSaveChannel]=true;
00122     return origlen-len; 
00123   }
00124 }
00125 
00126 unsigned int
00127 RawCameraGenerator::saveBuffer(char buf[], unsigned int len) const {
00128   unsigned int origlen=len;
00129   if(!checkInc(FilterBankGenerator::saveBuffer(buf,len),buf,len)) return 0;
00130   if(!encodeInc("RawImage",buf,len)) return 0;
00131   
00132   if(images[selectedSaveLayer][selectedSaveChannel]==NULL) {
00133     serr->printf("RawCameraGenerator::saveBuffer() failed because selected image is NULL -- call selectSaveImage first to make sure it's up to date\n");
00134     return 0;
00135   }
00136   if(!imageValids[selectedSaveLayer][selectedSaveChannel]) {
00137     serr->printf("RawCameraGenerator::saveBuffer() failed because selected image is invalid -- call selectSaveImage first to make sure it's up to date\n");
00138     return 0;
00139   }
00140   unsigned char* img=images[selectedSaveLayer][selectedSaveChannel];
00141   unsigned int used=widths[selectedSaveLayer]*heights[selectedSaveLayer];
00142   ASSERTRETVAL(used<=len,"buffer too small",0);
00143   unsigned int inc=getIncrement(selectedSaveLayer);
00144   if(inc==1) {
00145     //special case, straight copy
00146     for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
00147       memcpy(buf,img,widths[selectedSaveLayer]);
00148       buf+=widths[selectedSaveLayer];
00149       img+=getStride(selectedSaveLayer);
00150     }
00151   } else {
00152     //otherwise, interleaved or subsampling
00153     for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
00154       unsigned char* const rowend=img+widths[selectedSaveLayer]*inc;
00155       while(img!=rowend) {
00156         *buf++=*img;
00157         img+=inc;
00158       }
00159       img+=getSkip(selectedSaveLayer);
00160     }
00161   }
00162   len-=used;
00163   
00164   return origlen-len;
00165 }
00166 
00167 unsigned int
00168 RawCameraGenerator::saveFileStream(FILE * f) const {
00169   unsigned int totalused=0;
00170   unsigned int used;
00171   { //sigh, inheritance has failed me (I wouldn't want FilterBankGenerator::saveFileStream() to call the virtuals...)
00172     unsigned int sz=FilterBankGenerator::getBinSize();
00173     char * buf = new char[sz];
00174     memset(buf,0xF0,sz);
00175     if(buf==NULL) {
00176       std::cout << "*** WARNING could not allocate " << sz << " bytes for loadFile";
00177       return 0;
00178     }
00179     unsigned int resp=FilterBankGenerator::saveBuffer(buf,sz);
00180     if(resp==0) {
00181       std::cout << "*** WARNING saveBuffer didn't write any data (possibly due to overflow or other error)" << std::endl;
00182       fwrite(buf,1,sz,f);
00183     } else {
00184       unsigned int wrote=fwrite(buf,1,resp,f);
00185       if(wrote!=resp)
00186         std::cout << "*** WARNING short write (wrote " << wrote << ", expected " << resp << ")" << std::endl;
00187     }
00188     delete [] buf;
00189     used=resp;
00190   }
00191   if(0==used) return 0;
00192   totalused+=used;
00193   if(0==(used=encode("RawImage",f))) return 0;
00194   totalused+=used;
00195   
00196   if(images[selectedSaveLayer][selectedSaveChannel]==NULL) {
00197     serr->printf("RawCameraGenerator::saveBuffer() failed because selected image is NULL -- call selectSaveImage first to make sure it's up to date\n");
00198     return 0;
00199   }
00200   if(!imageValids[selectedSaveLayer][selectedSaveChannel]) {
00201     serr->printf("RawCameraGenerator::saveBuffer() failed because selected image is invalid -- call selectSaveImage first to make sure it's up to date\n");
00202     return 0;
00203   }
00204   unsigned char* img=images[selectedSaveLayer][selectedSaveChannel];
00205   used=widths[selectedSaveLayer]*heights[selectedSaveLayer];
00206   unsigned int inc=getIncrement(selectedSaveLayer);
00207   if(inc==1) {
00208     //special case, straight copy
00209     sout->printf("Saving %d by %d\n",widths[selectedSaveLayer],heights[selectedSaveLayer]);
00210     for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
00211       if(fwrite(img,widths[selectedSaveLayer],1,f)==0) {
00212         serr->printf("short write on image data - ran out of space?\n");
00213         return 0;
00214       }
00215       img+=getStride(selectedSaveLayer);
00216     }
00217   } else {
00218     //otherwise, interleaved or subsampling
00219     for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
00220       unsigned char* const rowend=img+widths[selectedSaveLayer]*inc;
00221       while(img!=rowend) {
00222         if(fputc(*img,f)==EOF) {
00223           serr->printf("short write on image data - ran out of space?\n");
00224           return 0;
00225         }
00226         img+=inc;
00227       }
00228       img+=getSkip(selectedSaveLayer);
00229     }
00230   }
00231   totalused+=used;
00232   
00233   return totalused;
00234 }
00235 
00236 void
00237 RawCameraGenerator::setDimensions() {
00238   freeCaches();
00239   unsigned int numNotRealLayers=numLayers-1-numRealLayers;
00240   for(unsigned int res=0; res<numNotRealLayers; res++) {
00241     widths[res] = imageInfos[numNotRealLayers]->width>>(numNotRealLayers-res);
00242     heights[res] = imageInfos[numNotRealLayers]->height>>(numNotRealLayers-res);
00243     ASSERT(widths[res]*increments[res]==widths[numNotRealLayers],"widths*increments doesn't match total width");
00244     strides[res]=strides[numNotRealLayers]*increments[res];
00245     skips[res]=skips[numNotRealLayers]+strides[res]-strides[numNotRealLayers];
00246   }
00247   strides[numLayers-1]=widths[numLayers-1]=widths[numLayers-2]*2;
00248   heights[numLayers-1]=heights[numLayers-2]*2;
00249 }
00250 
00251 void 
00252 RawCameraGenerator::freeCaches() {
00253 #ifdef PLATFORM_APERIOS
00254   const unsigned int numRefLayers=numLayers;
00255 #else
00256   const unsigned int numRefLayers=numLayers-1;
00257 #endif
00258   for(unsigned int i=0; i<numRefLayers; i++) {
00259     for(unsigned int j=0; j<numChannels; j++) {
00260       images[i][j]=NULL;
00261       imageValids[i][j]=false;
00262     }
00263   }
00264   FilterBankGenerator::freeCaches();
00265 }
00266 
00267 void
00268 RawCameraGenerator::setNumImages(unsigned int nLayers, unsigned int nChannels) {
00269   if(nLayers==numLayers && nChannels==numChannels)
00270     return;
00271   FilterBankGenerator::setNumImages(nLayers,nChannels);
00272   layers=new unsigned char*[numLayers];
00273   imageInfos=new const OFbkImageInfo*[numLayers];
00274   unsigned int numNotRealLayers=numLayers-1-numRealLayers;
00275   for(unsigned int res=0; res<numLayers; res++) {
00276     layers[res]=NULL;
00277     imageInfos[res]=NULL;
00278     if(res<numNotRealLayers)
00279       increments[res]=1<<(numNotRealLayers-res);
00280   }
00281 }
00282 
00283 unsigned char *
00284 RawCameraGenerator::createImageCache(unsigned int layer, unsigned int chan) const {
00285   if(layer==numLayers-1) {
00286 #ifdef PLATFORM_APERIOS
00287     return const_cast<unsigned char*>(&dblRes[chan][0][0]);
00288 #else
00289     return new unsigned char[widths[layer]*heights[layer]]; 
00290 #endif
00291   } else
00292     return NULL; // calcImage will set the cache itself
00293 }
00294 
00295 void
00296 RawCameraGenerator::calcImage(unsigned int layer, unsigned int chan) {
00297   PROFSECTION("RawCameraGenerator::calcImage(...)",*mainProfiler);
00298   unsigned int numNotRealLayers=numLayers-1-numRealLayers;
00299   if(layer==numLayers-1) {
00300     //This is the only layer for which we calculate and store any data of our own...
00301     if(chan==CHAN_Y)
00302       reconstructImage();
00303     else
00304       upsampleImage(static_cast<channel_id_t>(chan));
00305   } else {
00306     if(layer>=numNotRealLayers) {
00307       unsigned int fbkdatChan=mapChannelID(static_cast<channel_id_t>(chan));
00308       const OFbkImage img(const_cast<OFbkImageInfo*>(imageInfos[layer]), const_cast<unsigned char*>(layers[layer]), fbkdatChan);
00309       images[layer][chan]=img.Pointer();
00310 
00311       //this part restores pixels over written with the CDT table and
00312       //frame count.  Yes, we are modifying the original image passed
00313       //from the system here...
00314       if(config->vision.restore_image) {
00315         const unsigned int numPix=16;
00316         if(layer==numLayers-2) {
00317           unsigned char * s=images[layer][chan]+getStride(layer)*(getHeight(layer)-2);
00318           unsigned char * d=images[layer][chan]+getStride(layer)*(getHeight(layer)-1);
00319           for(unsigned int i=0; i<numPix; i++)
00320             *d++=*s++;
00321         } else {
00322           unsigned int inc=1<<(numLayers-2-layer);
00323           unsigned char * s;
00324           //unsigned char * s=getImage(numLayers-2,chan)+getStride(numLayers-2)*(getHeight(numLayers-2)-inc);
00325           //...or an attempt to possibly avoid a trivial amount of recomputation....
00326           if(!imageValids[numLayers-2][chan]) {
00327             const OFbkImage simg(const_cast<OFbkImageInfo*>(imageInfos[numLayers-2]), const_cast<unsigned char*>(layers[numLayers-2]), fbkdatChan);
00328             s=simg.Pointer();
00329           } else {
00330             s=images[numLayers-2][chan];
00331           }
00332           s+=getStride(numLayers-2)*(getHeight(numLayers-2)-inc);
00333           unsigned char * d=images[layer][chan]+getStride(layer)*(getHeight(layer)-1);
00334           for(unsigned int i=0; i<numPix; i++) {
00335             *d++=*s;
00336             s+=inc;
00337           }
00338         }
00339       }
00340     } else {
00341       //we don't need to do the restoration in the previous section
00342       //here because these layers skip the last row
00343       unsigned int fbkdatChan=mapChannelID(static_cast<channel_id_t>(chan));
00344       const OFbkImage img(const_cast<OFbkImageInfo*>(imageInfos[numNotRealLayers]), const_cast<unsigned char*>(layers[numNotRealLayers]), fbkdatChan);
00345       images[layer][chan]=img.Pointer();
00346     }
00347   }
00348   imageValids[layer][chan]=true;
00349 }
00350 
00351 void
00352 RawCameraGenerator::destruct() {
00353   FilterBankGenerator::destruct();
00354   delete [] layers;
00355   layers=NULL;
00356   delete [] imageInfos;
00357   imageInfos=NULL;
00358 }
00359 
00360 unsigned int
00361 RawCameraGenerator::mapChannelID(channel_id_t chan) {
00362   switch(chan) {
00363   case CHAN_Y:
00364     return ofbkimageBAND_Y;
00365   case CHAN_U:
00366     return ofbkimageBAND_Cb;
00367   case CHAN_V:
00368     return ofbkimageBAND_Cr;
00369   case CHAN_Y_DY:
00370     return ofbkimageBAND_Y_LH;
00371   case CHAN_Y_DX:
00372     return ofbkimageBAND_Y_HL;
00373   case CHAN_Y_DXDY:
00374     return ofbkimageBAND_Y_HH;
00375   default:
00376     std::cout << "RawCameraGenerator::mapChannelID bad channel" << std::endl;
00377     return ofbkimageBAND_Y;;
00378   }
00379 }
00380 
00381 void
00382 RawCameraGenerator::upsampleImage(channel_id_t chan) {
00383   const unsigned int dblLayer=numLayers-1;
00384   const unsigned int srcLayer=dblLayer-1;
00385   const unsigned int width=widths[dblLayer];
00386   const unsigned int height=heights[dblLayer];
00387 
00388   unsigned char * cur=images[dblLayer][chan];
00389   ASSERTRET(cur!=NULL,"destination layer is NULL");
00390   unsigned char * orig=getImage(srcLayer,chan);
00391   ASSERTRET(orig!=NULL,"source layer is NULL");
00392 
00393   unsigned char * const imgend=cur+width*height;
00394   while(cur!=imgend) {
00395     unsigned char * const row=cur;
00396     unsigned char * const rowend=cur+width;
00397     while(cur!=rowend) {
00398       *cur++=*orig;
00399       *cur++=*orig++;
00400     }
00401     memcpy(cur,row,width);
00402     cur+=width;
00403     orig+=getSkip(srcLayer);
00404   }
00405 }
00406 
00407 
00408 
00409 /*! This function is lifted from Sony's ImageObserver sample code.
00410     Here's Sony's original license for the file (ImageObserver.cc) that contained this function:
00411     <pre>
00412     Copyright 2002,2003 Sony Corporation 
00413     
00414     Permission to use, copy, modify, and redistribute this software for
00415     non-commercial use is hereby granted.
00416     
00417     This software is provided "as is" without warranty of any kind,
00418     either expressed or implied, including but not limited to the
00419     implied warranties of fitness for a particular purpose.
00420     </pre>
00421 */
00422 void
00423 RawCameraGenerator::reconstructImage() {
00424   byte* yLLPtr = getImage(numLayers-2,CHAN_Y);
00425   byte* yLHPtr = getImage(numLayers-2,CHAN_Y_DY);
00426   byte* yHLPtr = getImage(numLayers-2,CHAN_Y_DX);
00427   byte* yHHPtr = getImage(numLayers-2,CHAN_Y_DXDY);
00428   
00429   unsigned int w = getWidth(numLayers-2);
00430   unsigned int h = getWidth(numLayers-2);
00431   unsigned int skip = getSkip(numLayers-2);
00432   
00433   unsigned char* img = images[numLayers-1][CHAN_Y];
00434   ASSERTRET(img!=NULL,"image destination NULL");
00435 
00436   unsigned char* iptr0 = img;
00437   unsigned char* iptr1 = iptr0 + 2*w;
00438     
00439   for (unsigned int y = 0; y < h; y++) {
00440     for (unsigned int x = 0; x < w; x++) {
00441       //
00442       // yLH, yHL, yHH : offset binary [0, 255] -> signed int [-128, 127]
00443       //
00444       short yLL = (short)*yLLPtr++;
00445       short yLH = (short)*yLHPtr++ - 128;
00446       short yHL = (short)*yHLPtr++ - 128;
00447       short yHH = (short)*yHHPtr++ - 128;
00448 
00449       short a = yLL + yLH + yHL + yHH; // ypix11
00450       short b = 2 * (yLL + yLH);       // ypix11 + ypix01
00451       short c = 2 * (yLL + yHL);       // ypix11 + ypix10
00452       short d = 2 * (yLL + yHH);       // ypix11 + ypix00
00453             
00454       *iptr0++ = clipRange(d - a);
00455       *iptr0++ = clipRange(c - a);
00456       *iptr1++ = clipRange(b - a);
00457       *iptr1++ = clipRange(a);
00458     }
00459     yLLPtr += skip;
00460     yLHPtr += skip;
00461     yHLPtr += skip;
00462     yHHPtr += skip;
00463     iptr0  = iptr1;
00464     iptr1  += 2*w;
00465   }
00466 }
00467 
00468 
00469 /*! @file
00470  * @brief Implements RawCameraGenerator, which generates FilterBankEvents containing raw camera images
00471  * @author ejt (Creator)
00472  */
00473 

Tekkotsu v5.1CVS
Generated Tue Jan 31 04:32:05 2012 by Doxygen 1.6.3