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

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