Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

BufferedImageGenerator.cc

Go to the documentation of this file.
00001 #include "BufferedImageGenerator.h"
00002 #include "Events/DataEvent.h"
00003 #include "Events/FilterBankEvent.h"
00004 #include "Wireless/Socket.h"
00005 #include "Events/EventRouter.h"
00006 #include "Shared/debuget.h"
00007 #ifndef PLATFORM_APERIOS
00008 #  include "IPC/MessageReceiver.h"
00009 #endif
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     accessed=false;
00019     const DataEvent<ImageSource>* data=dynamic_cast<const DataEvent<ImageSource>*>(&event);
00020     if(data==NULL) {
00021       serr->printf("Error: %s(%s) received event of the wrong type",getClassName().c_str(),getName().c_str());
00022       return;
00023     }
00024     if(imgsrc.layer!=data->getData().layer || imgsrc.channels!=data->getData().channels) {
00025       //can "quietly" switch the layer of transmission as long as the width and height were scaled properly
00026       //just need to reset the increments if a different layer is being used.
00027       for(unsigned int i=0; i<=data->getData().layer; i++) {
00028         increments[i] = (1<<(data->getData().layer-i))*data->getData().channels;
00029         strides[i]=(1<<(data->getData().layer-i))*data->getData().width*data->getData().channels;
00030         skips[i]=strides[i]-data->getData().width*data->getData().channels;
00031       }
00032       for(unsigned int i=data->getData().layer+1; i<numLayers; i++) {
00033         increments[i] = 1;
00034         strides[i]=data->getData().width*(1<<(i-data->getData().layer));
00035         skips[i]=0;
00036       }
00037     }
00038     imgsrc=data->getData();
00039     sysFrameNumber=frameNumber=imgsrc.frameIndex;
00040     // -- invalidate dependant images: --
00041     //images in every channel beyond the received channels is invalid
00042     for(unsigned int i=0; i<numLayers; i++)
00043       for(unsigned int j=imgsrc.channels; j<numChannels; j++) {
00044         if(!isAllocated[i][j]) //in case the imgsrc layer changes
00045           images[i][j]=NULL;
00046         imageValids[i][j]=false;
00047       }
00048     //images in every layer above the received layer is invalid
00049     for(unsigned int i=imgsrc.layer+1; i<numLayers; i++)
00050       for(unsigned int j=0; j<imgsrc.channels; j++) { //already covered src.channels to numChannels in previous loop
00051         if(!isAllocated[i][j]) //in case the imgsrc layer changes
00052           images[i][j]=NULL;
00053         imageValids[i][j]=false;
00054       }
00055     // -- check if the size has changed: --
00056     if(numLayers>0) {
00057       if(imgsrc.width!=getWidth(imgsrc.layer) || imgsrc.height!=getHeight(imgsrc.layer)) {
00058         freeCaches();
00059         setDimensions();
00060         serr->printf("WARNING: the image dimensions don't match values predicted by RobotInfo consts, now %dx%d\n",widths[numLayers-1],heights[numLayers-1]);
00061       } else if(strides[numLayers-1]==0) {
00062         // first frame, set it anyway
00063         setDimensions();
00064       }
00065     }
00066     // -- reassign to the new buffer: --
00067     for(unsigned int i=imgsrc.layer; i!=-1U; i--) {
00068       for(unsigned int j=0; j<imgsrc.channels; j++) {
00069         if(isAllocated[i][j]) { //in case the imgsrc layer changes
00070           delete [] images[i][j];
00071           images[i][j]=NULL;
00072           isAllocated[i][j]=false;
00073         }
00074         imageValids[i][j]=true;
00075       }
00076       images[i][RawCameraGenerator::CHAN_Y]=imgsrc.img+0;
00077       images[i][RawCameraGenerator::CHAN_U]=imgsrc.img+2; //note U is *third*
00078       images[i][RawCameraGenerator::CHAN_V]=imgsrc.img+1; //note V is *second*
00079     }
00080     framesProcessed++;
00081   }
00082   erouter->postEvent(new FilterBankEvent(this,getGeneratorID(),getSourceID(),event.getTypeID()));
00083 }
00084 
00085 unsigned int
00086 BufferedImageGenerator::getBinSize() const {
00087   unsigned int used=FilterBankGenerator::getBinSize();
00088   used+=strlen("RawImage")+LoadSave::stringpad;
00089   used+=widths[selectedSaveLayer]*heights[selectedSaveLayer];
00090   return used;
00091 }
00092 
00093 unsigned int
00094 BufferedImageGenerator::LoadBuffer(const char buf[], unsigned int len) {
00095   unsigned int origlen=len;
00096   unsigned int used;
00097   std::string tmp;
00098   if(0==(used=FilterBankGenerator::LoadBuffer(buf,len))) return 0;
00099   len-=used; buf+=used;
00100   if(0==(used=decode(tmp,buf,len))) return 0;
00101   len-=used; buf+=used;
00102   if(tmp!="RawImage") {
00103     serr->printf("Unhandled image type for BufferedImageGenerator: %s",tmp.c_str());
00104     return 0;
00105   } else if(selectedSaveLayer!=numLayers-1) {
00106     serr->printf("Can't load into BufferedImageGenerator layer %d!=%d",selectedSaveLayer,numLayers-1);
00107     return 0;
00108   } else {
00109     if(images[selectedSaveLayer][selectedSaveChannel]==NULL)
00110       images[selectedSaveLayer][selectedSaveChannel]=createImageCache(selectedSaveLayer,selectedSaveChannel);
00111     unsigned char* img=images[selectedSaveLayer][selectedSaveChannel];
00112     used=widths[selectedSaveLayer]*heights[selectedSaveLayer];
00113     ASSERTRETVAL(used<=len,"buffer too small",0);
00114     memcpy(img,buf,used);
00115     len-=used; buf+=used;
00116     imageValids[selectedSaveLayer][selectedSaveChannel]=true;
00117     return origlen-len; 
00118   }
00119 }
00120 
00121 unsigned int
00122 BufferedImageGenerator::SaveBuffer(char buf[], unsigned int len) const {
00123   unsigned int origlen=len;
00124   unsigned int used;
00125   if(0==(used=FilterBankGenerator::SaveBuffer(buf,len))) return 0;
00126   len-=used; buf+=used;
00127   if(0==(used=encode("RawImage",buf,len))) return 0;
00128   len-=used; buf+=used;
00129   
00130   if(images[selectedSaveLayer][selectedSaveChannel]==NULL) {
00131     serr->printf("BufferedImageGenerator::SaveBuffer() failed because selected image is NULL -- call selectSaveImage first to make sure it's up to date\n");
00132     return 0;
00133   }
00134   if(!imageValids[selectedSaveLayer][selectedSaveChannel]) {
00135     serr->printf("BufferedImageGenerator::SaveBuffer() failed because selected image is invalid -- call selectSaveImage first to make sure it's up to date\n");
00136     return 0;
00137   }
00138   unsigned char* img=images[selectedSaveLayer][selectedSaveChannel];
00139   used=widths[selectedSaveLayer]*heights[selectedSaveLayer];
00140   ASSERTRETVAL(used<=len,"buffer too small",0);
00141   unsigned int inc=getIncrement(selectedSaveLayer);
00142   if(inc==1) {
00143     //special case, straight copy
00144     for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
00145       memcpy(buf,img,widths[selectedSaveLayer]);
00146       buf+=widths[selectedSaveLayer];
00147       img+=getStride(selectedSaveLayer);
00148     }
00149   } else {
00150     //otherwise, interleaved or subsampling
00151     for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
00152       unsigned char* const rowend=img+widths[selectedSaveLayer]*inc;
00153       while(img!=rowend) {
00154         *buf++=*img;
00155         img+=inc;
00156       }
00157       img+=getSkip(selectedSaveLayer);
00158     }
00159   }
00160   len-=used;
00161   
00162   return origlen-len;
00163 }
00164 
00165 unsigned int
00166 BufferedImageGenerator::SaveFileStream(FILE * f) const {
00167   unsigned int totalused=0;
00168   unsigned int used;
00169   { //sigh, inheritance has failed me (I wouldn't want FilterBankGenerator::SaveFileStream() to call the virtuals...)
00170     unsigned int sz=FilterBankGenerator::getBinSize();
00171     char * buf = new char[sz];
00172     memset(buf,0xF0,sz);
00173     if(buf==NULL) {
00174       std::cout << "*** WARNING could not allocate " << sz << " bytes for LoadFile";
00175       return 0;
00176     }
00177     unsigned int resp=FilterBankGenerator::SaveBuffer(buf,sz);
00178     if(resp==0) {
00179       std::cout << "*** WARNING SaveBuffer didn't write any data (possibly due to overflow or other error)" << std::endl;
00180       fwrite(buf,1,sz,f);
00181     } else {
00182       unsigned int wrote=fwrite(buf,1,resp,f);
00183       if(wrote!=resp)
00184         std::cout << "*** WARNING short write (wrote " << wrote << ", expected " << resp << ")" << std::endl;
00185     }
00186     delete [] buf;
00187     used=resp;
00188   }
00189   if(0==used) return 0;
00190   totalused+=used;
00191   if(0==(used=encode("RawImage",f))) return 0;
00192   totalused+=used;
00193   
00194   if(images[selectedSaveLayer][selectedSaveChannel]==NULL) {
00195     serr->printf("BufferedImageGenerator::SaveBuffer() failed because selected image is NULL -- call selectSaveImage first to make sure it's up to date\n");
00196     return 0;
00197   }
00198   if(!imageValids[selectedSaveLayer][selectedSaveChannel]) {
00199     serr->printf("BufferedImageGenerator::SaveBuffer() failed because selected image is invalid -- call selectSaveImage first to make sure it's up to date\n");
00200     return 0;
00201   }
00202   unsigned char* img=images[selectedSaveLayer][selectedSaveChannel];
00203   used=widths[selectedSaveLayer]*heights[selectedSaveLayer];
00204   unsigned int inc=getIncrement(selectedSaveLayer);
00205   if(inc==1) {
00206     //special case, straight copy
00207     sout->printf("Saving %d by %d\n",widths[selectedSaveLayer],heights[selectedSaveLayer]);
00208     for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
00209       if(fwrite(img,widths[selectedSaveLayer],1,f)==0) {
00210         serr->printf("short write on image data - ran out of space?\n");
00211         return 0;
00212       }
00213       img+=getStride(selectedSaveLayer);
00214     }
00215   } else {
00216     //otherwise, interleaved or subsampling
00217     for(unsigned int y=0; y<heights[selectedSaveLayer]; y++) {
00218       unsigned char* const rowend=img+widths[selectedSaveLayer]*inc;
00219       while(img!=rowend) {
00220         if(fputc(*img,f)==EOF) {
00221           serr->printf("short write on image data - ran out of space?\n");
00222           return 0;
00223         }
00224         img+=inc;
00225       }
00226       img+=getSkip(selectedSaveLayer);
00227     }
00228   }
00229   totalused+=used;
00230   
00231   return totalused;
00232 }
00233 
00234 unsigned char * BufferedImageGenerator::getImage(unsigned int layer, unsigned int channel) {
00235   if(!accessed && imgsrc.receiver!=NULL) {
00236     accessed=true;
00237 #ifndef PLATFORM_APERIOS
00238     imgsrc.receiver->markRead();
00239 #endif
00240   }
00241   return FilterBankGenerator::getImage(layer,channel);
00242 }
00243 
00244 void BufferedImageGenerator::freeCaches() {
00245   FilterBankGenerator::freeCaches();
00246   for(unsigned int i=0; i<numLayers; i++)
00247     for(unsigned int j=0; j<numChannels; j++)
00248       isAllocated[i][j]=false;
00249 }
00250 
00251 void BufferedImageGenerator::invalidateCaches() {
00252   for(unsigned int i=0; i<numLayers; i++)
00253     for(unsigned int j=0; j<numChannels; j++) {
00254       if(!isAllocated[i][j])
00255         images[i][j]=NULL;
00256       imageValids[i][j]=false;
00257     }
00258 }
00259 
00260 unsigned char * BufferedImageGenerator::createImageCache(unsigned int layer, unsigned int channel) const {
00261   isAllocated[layer][channel]=true;
00262   return new unsigned char[widths[layer]*heights[layer]];
00263 }
00264 void BufferedImageGenerator::calcImage(unsigned int layer, unsigned int channel) {
00265   //cout << "BufferedImageGenerator::calcImage(" << layer << ',' << channel << ')' << endl;
00266   switch(channel) {
00267     case RawCameraGenerator::CHAN_Y:
00268       upsampleImage(imgsrc.layer,channel,layer); break;
00269     case RawCameraGenerator::CHAN_U:
00270     case RawCameraGenerator::CHAN_V:
00271       if(imgsrc.channels>1)
00272         upsampleImage(imgsrc.layer,channel,layer);
00273       else
00274         memset(images[layer][channel],128,widths[layer]*heights[layer]);
00275       break;
00276     case RawCameraGenerator::CHAN_Y_DY:
00277     case RawCameraGenerator::CHAN_Y_DX:
00278     case RawCameraGenerator::CHAN_Y_DXDY:
00279       if(layer<=imgsrc.layer) {
00280         //todo
00281         memset(images[layer][channel],128,widths[layer]*heights[layer]);
00282       } else if(layer>imgsrc.layer) {
00283         getImage(imgsrc.layer,channel);
00284         upsampleImage(imgsrc.layer,channel,layer);
00285       }
00286       break;
00287     default:
00288       cerr << "Bad layer selection!" << endl;
00289   }
00290 }
00291 void BufferedImageGenerator::setDimensions() {
00292   if(imgsrc.img==NULL) //don't have an image to set from
00293     return;
00294   // set dimensions of layers below and including the input layer
00295   for(unsigned int i=0; i<=imgsrc.layer; i++) {
00296     //s is the scaling factor -- 2 means *half* size
00297     unsigned int s=(1<<(imgsrc.layer-i));
00298     //width and height are scaled down (divide by s)
00299     widths[i]=imgsrc.width/s;
00300     heights[i]=imgsrc.height/s;
00301     //need to skip rows to make good on promised height (multiply by s)
00302     strides[i]=imgsrc.width*imgsrc.channels*s;
00303     skips[i]=strides[i]-imgsrc.width*imgsrc.channels;
00304     cout << "setDimensions() " << widths[i] << ' ' << skips[i] << ' ' << strides[i] << endl;
00305   }
00306   //set dimensions for layers above the input layer, these are not interleaved
00307   for(unsigned int i=imgsrc.layer+1; i<numLayers; i++) {
00308     //s is the scaling factor -- 2 means *double* size
00309     unsigned int s=(1<<(i-imgsrc.layer));
00310     //multiply by s
00311     widths[i]=strides[i]=imgsrc.width*s;
00312     heights[i]=imgsrc.height*s;
00313     //stride is same as width (set above) -- we allocate these layers, don't skip rows
00314     skips[i]=0;
00315   }
00316 }
00317 void BufferedImageGenerator::destruct() {
00318   FilterBankGenerator::destruct();
00319   for(unsigned int i=0; i<numLayers; i++)
00320     delete [] isAllocated[i];
00321   delete [] isAllocated;
00322   isAllocated=NULL;
00323 }
00324 void BufferedImageGenerator::setNumImages(unsigned int nLayers, unsigned int nChannels) {
00325   if(nLayers==numLayers && nChannels==numChannels)
00326     return;
00327   FilterBankGenerator::setNumImages(nLayers,nChannels);
00328   isAllocated=new bool*[numLayers];
00329   for(unsigned int i=0; i<numLayers; i++)
00330     isAllocated[i]=new bool[numChannels];
00331   setDimensions();
00332 }
00333 
00334 void BufferedImageGenerator::upsampleImage(unsigned int srcLayer, unsigned int chan, unsigned int destLayer) {
00335   unsigned char * cur=images[destLayer][chan];
00336   ASSERTRET(cur!=NULL,"destination layer is NULL");
00337   unsigned char * orig=getImage(srcLayer,chan);
00338   ASSERTRET(orig!=NULL,"source layer is NULL");
00339   unsigned int width=widths[destLayer];
00340   unsigned int height=heights[destLayer];
00341   unsigned int inc=getIncrement(srcLayer);
00342   int power=destLayer-srcLayer;
00343   ASSERTRET(power>0,"upsampleImage attempting to downsample")
00344   
00345   unsigned char * const imgend=cur+width*height;
00346   while(cur!=imgend) {
00347     unsigned char * const row=cur;
00348     unsigned char * const rowend=cur+width;
00349     //upsample pixels within one row
00350     while(cur!=rowend) {
00351       for(int p=power; p>=0; p--)
00352         *cur++=*orig;
00353       orig+=inc;
00354     }
00355     //now replicate that row 1<<power times, doubling each time
00356     for(int p=0; p<power; p++) {
00357       unsigned int avail=width*(1<<p);
00358       memcpy(cur,row,avail);
00359       cur+=avail;
00360     }
00361     orig+=getSkip(srcLayer);
00362   }
00363 }
00364 
00365 
00366 /*! @file
00367  * @brief 
00368  * @author Ethan Tira-Thompson (ejt) (Creator)
00369  *
00370  * $Author: ejt $
00371  * $Name: tekkotsu-2_4_1 $
00372  * $Revision: 1.12 $
00373  * $State: Exp $
00374  * $Date: 2005/08/15 23:19:01 $
00375  */

Tekkotsu v2.4.1
Generated Tue Aug 16 16:32:46 2005 by Doxygen 1.4.4