Homepage Demos Overview Downloads Tutorials Reference
Credits

JPEGGenerator.cc

Go to the documentation of this file.
00001 #include "JPEGGenerator.h"
00002 #include "InterleavedYUVGenerator.h"
00003 #include "Events/DataEvent.h"
00004 #include "Events/EventRouter.h"
00005 #include "Events/FilterBankEvent.h"
00006 #include "Wireless/Wireless.h"
00007 #include <write_jpeg.h>
00008 #include "Shared/Config.h"
00009 #include "Shared/WorldState.h"
00010 
00011 #include <jpeg_mem_dest.h>
00012 
00013 
00014 #include "Shared/debuget.h"
00015 
00016 JPEGGenerator::JPEGGenerator(EventBase::EventGeneratorID_t gid, unsigned int sid, unsigned int mysid)
00017   : FilterBankGenerator("JPEGGenerator",gid,sid,EventBase::visJPEGEGID,mysid), srcMode(SRC_AUTO), curMode(SRC_AUTO), bytesUsed(NULL), cinfo(), jerr(), quality(-1U)
00018 {
00019   // We set the err object before we create the compress...  the idea
00020   // is if the creation fails, we can still get the error as to why it
00021   // failed.
00022   cinfo.err = jpeg_std_error(&jerr);
00023   jpeg_create_compress(&cinfo);
00024 }
00025 
00026 JPEGGenerator::JPEGGenerator(EventBase::EventGeneratorID_t gid, unsigned int sid, unsigned int mysid, src_mode_t mode)
00027   : FilterBankGenerator("JPEGGenerator",gid,sid,EventBase::visJPEGEGID,mysid), srcMode(mode), curMode(SRC_AUTO), bytesUsed(NULL), cinfo(), jerr(), quality(-1U)
00028 {
00029   // We set the err object before we create the compress...  the idea
00030   // is if the creation fails, we can still get the error as to why it
00031   // failed.
00032   cinfo.err = jpeg_std_error(&jerr);
00033   jpeg_create_compress(&cinfo);
00034 }
00035 
00036 JPEGGenerator::~JPEGGenerator() {
00037   freeCaches();
00038   destruct();
00039   jpeg_destroy_compress(&cinfo);
00040 }
00041 
00042 
00043 /*! The const casts in this function are regretable but necessary
00044  *  since the corresponding OPEN-R functions require mutable
00045  *  arguments, even though they shouldn't be modifying the data
00046  */
00047 void
00048 JPEGGenerator::processEvent(const EventBase& event) {
00049   FilterBankGenerator::processEvent(event);
00050   if(event.getGeneratorID()==getListenGeneratorID() && event.getSourceID()==getListenSourceID()) {
00051     if(getSourceMode()==SRC_AUTO) { //if not auto, curMode was already set when srcMode was set
00052       if(dynamic_cast<const InterleavedYUVGenerator*>(src)!=NULL)
00053         curMode=SRC_COLOR;
00054       else
00055         curMode=SRC_GRAYSCALE;
00056     }
00057     erouter->postEvent(new FilterBankEvent(this,getGeneratorID(),getSourceID()));
00058   }
00059 }
00060 
00061 unsigned int
00062 JPEGGenerator::getBinSize() const {
00063   unsigned int used=FilterBankGenerator::getBinSize();
00064   used+=strlen("JPEGColor")+LoadSave::stringpad;
00065   if(bytesUsed[selectedSaveLayer][selectedSaveChannel]!=0)
00066     used+=bytesUsed[selectedSaveLayer][selectedSaveChannel];
00067   else
00068     used+=widths[selectedSaveLayer]*heights[selectedSaveLayer]*3+JPEG_HEADER_PAD;
00069   return used;
00070 }
00071 
00072 unsigned int
00073 JPEGGenerator::LoadBuffer(const char buf[], unsigned int len) {
00074   unsigned int origlen=len;
00075   unsigned int used;
00076   std::string tmp;
00077   if(0==(used=FilterBankGenerator::LoadBuffer(buf,len))) return 0;
00078   len-=used; buf+=used;
00079   if(0==(used=decode(tmp,buf,len))) return 0;
00080   len-=used; buf+=used;
00081   if(tmp!="JPEGColor" && tmp!="JPEGGray") {
00082     serr->printf("Unhandled image type for JPEGGenerator: %s",tmp.c_str());
00083     return 0;
00084   } else {
00085     if(tmp=="JPEGColor" && getCurrentSourceFormat()==SRC_GRAYSCALE)
00086       serr->printf("Warning: loading grayscale into color image");
00087     if(tmp=="JPEGGrayscale" && getCurrentSourceFormat()==SRC_COLOR)
00088       serr->printf("Warning: loading color into grayscale image");
00089     unsigned int tmpL;
00090     if(0==(used=decode(tmpL,buf,len))) return 0;
00091     len-=used; buf+=used;
00092     if(tmpL>len)
00093       return 0;
00094     if(images[selectedSaveLayer][selectedSaveChannel]!=NULL)
00095       delete [] images[selectedSaveLayer][selectedSaveChannel];
00096     images[selectedSaveLayer][selectedSaveChannel]=createImageCache(selectedSaveLayer,selectedSaveChannel);
00097     used=bytesUsed[selectedSaveLayer][selectedSaveChannel]=tmpL;
00098     unsigned char* img=getImage(selectedSaveLayer,selectedSaveChannel);
00099     if(img==NULL)
00100       return 0;
00101     memcpy(img,buf,used);
00102     len-=used; buf+=used;
00103     imageValids[selectedSaveLayer][selectedSaveChannel]=true;
00104     return origlen-len; 
00105   }
00106 }
00107 
00108 unsigned int
00109 JPEGGenerator::SaveBuffer(char buf[], unsigned int len) const {
00110   unsigned int origlen=len;
00111   unsigned int used;
00112   if(0==(used=FilterBankGenerator::SaveBuffer(buf,len))) return 0;
00113   len-=used; buf+=used;
00114 
00115   char * type;
00116   if(getCurrentSourceFormat()==SRC_COLOR)
00117     type="JPEGColor";
00118   else if(getCurrentSourceFormat()==SRC_GRAYSCALE)
00119     type="JPEGGrayscale";
00120   else {
00121     serr->printf("SaveBuffer failed - unsuitable or unknown mode/generator pair");
00122     return 0;
00123   }
00124   if(0==(used=encode(type,buf,len))) return 0;
00125   len-=used; buf+=used;
00126   
00127   unsigned char* img=getImage(selectedSaveLayer,selectedSaveChannel);
00128   if(img==NULL)
00129     return 0;
00130   if(0==(used=encode(bytesUsed[selectedSaveLayer][selectedSaveChannel],buf,len))) return 0;
00131   len-=used; buf+=used;
00132   used=bytesUsed[selectedSaveLayer][selectedSaveChannel];
00133   if(used>len)
00134     return 0;
00135   memcpy(buf,img,used);
00136   len-=used;
00137   return origlen-len;
00138 }
00139 
00140 void
00141 JPEGGenerator::setNumImages(unsigned int nLayers, unsigned int nChannels) {
00142   if(nLayers==numLayers && nChannels==numChannels)
00143     return;
00144   FilterBankGenerator::setNumImages(nLayers,nChannels);
00145   for(unsigned int i=0; i<numLayers; i++)
00146     strides[i]=skips[i]=0;
00147   bytesUsed=new unsigned int*[numLayers];
00148   for(unsigned int res=0; res<numLayers; res++) {
00149     increments[res]=3;
00150     bytesUsed[res]=new unsigned int[numChannels];
00151     for(unsigned int i=0; i<numChannels; i++)
00152       bytesUsed[res][i]=0;
00153   }
00154 }
00155 
00156 unsigned char *
00157 JPEGGenerator::createImageCache(unsigned int layer, unsigned int /*chan*/) const {
00158   return new unsigned char[widths[layer]*heights[layer]*3+JPEG_HEADER_PAD];
00159 }
00160 
00161 /*! This function is taken pretty directly from the write_jpeg_mem()
00162  *  function from Sony's W3AIBO sample code.
00163  *
00164  *  I have adapted it for this object, and added the ability to
00165  *  process greyscale images as well as color.
00166  */
00167 void
00168 JPEGGenerator::calcImage(unsigned int layer, unsigned int chan) const {
00169   PROFSECTION("JPEGGenerator::calcImage(...)",state->mainProfile);
00170 
00171   //pass the destination buffer and buffer size here
00172   jpeg_mem_dest(&cinfo, images[layer][chan], widths[layer]*heights[layer]*3+JPEG_HEADER_PAD);
00173 
00174   // mode setup
00175   cinfo.image_width = widths[layer];
00176   cinfo.image_height = heights[layer];
00177   if(getCurrentSourceFormat()==SRC_COLOR ) {
00178     cinfo.input_components = 3;   /* # of color components per pixel */
00179     cinfo.in_color_space = JCS_YCbCr; /* colorspace of input image */
00180   } else if(getCurrentSourceFormat()==SRC_GRAYSCALE) {
00181     cinfo.input_components = 1;   /* # of color components per pixel */
00182     cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */
00183   } else {
00184     serr->printf("Compression failed - unsuitable or unknown mode/generator pair");
00185     jpeg_destroy_compress(&cinfo);
00186     return;
00187   }
00188 
00189   // parameter setup
00190   jpeg_set_defaults(&cinfo);
00191   unsigned int qual=(quality==-1U?config->vision.rawcam_compress_quality:quality);
00192   jpeg_set_quality(&cinfo, qual, false); /* limit to baseline-JPEG values */
00193   cinfo.dct_method=config->vision.jpeg_dct_method;
00194   if(cinfo.in_color_space==JCS_YCbCr) {
00195     unsigned int ysamp=1;
00196     unsigned int uvsamp=1;
00197     const unsigned int maxsamp=2;  // according to jpeg docs, this should be able to go up to 4, but I get error: "Sampling factors too large for interleaved scan"
00198     if(config->vision.rawcam_y_skip>config->vision.rawcam_uv_skip) {
00199       uvsamp=config->vision.rawcam_y_skip-config->vision.rawcam_uv_skip+1;
00200       if(uvsamp>maxsamp)
00201         uvsamp=maxsamp;
00202     } else {
00203       ysamp=config->vision.rawcam_uv_skip-config->vision.rawcam_y_skip+1;
00204       if(ysamp>maxsamp)
00205         ysamp=maxsamp;
00206     }
00207     cinfo.comp_info[0].h_samp_factor=ysamp;
00208     cinfo.comp_info[0].v_samp_factor=ysamp;
00209     cinfo.comp_info[1].h_samp_factor=uvsamp;
00210     cinfo.comp_info[1].v_samp_factor=uvsamp;
00211     cinfo.comp_info[2].h_samp_factor=uvsamp;
00212     cinfo.comp_info[2].v_samp_factor=uvsamp;
00213   }
00214 
00215   // compression
00216   jpeg_start_compress(&cinfo, TRUE);
00217   unsigned int row_stride = src->getStride(layer);  /* JSAMPLEs per row in image_buffer */
00218   JSAMPROW row_pointer[1] = { const_cast<JSAMPROW>(src->getImage(layer,chan)) };
00219   while (cinfo.next_scanline < cinfo.image_height) {
00220     jpeg_write_scanlines(&cinfo, row_pointer, 1);
00221     row_pointer[0]+=row_stride;
00222   }
00223   jpeg_finish_compress(&cinfo);
00224 
00225   // results
00226   bytesUsed[layer][chan]=jpeg_mem_size(&cinfo);
00227   imageValids[layer][chan]=true;
00228 }
00229 
00230 void
00231 JPEGGenerator::destruct() {
00232   FilterBankGenerator::destruct();
00233   for(unsigned int res=0; res<numLayers; res++)
00234     delete [] bytesUsed[res];
00235   delete [] bytesUsed;
00236   bytesUsed=NULL;
00237 }
00238 
00239 /*! @file
00240  * @brief Implements JPEGGenerator, which generates FilterBankEvents containing JPEG compressed images
00241  * @author ejt (Creator)
00242  *
00243  * $Author: ejt $
00244  * $Name: tekkotsu-2_2_2 $
00245  * $Revision: 1.9 $
00246  * $State: Exp $
00247  * $Date: 2004/11/09 20:01:49 $
00248  */
00249 

Tekkotsu v2.2.2
Generated Tue Jan 4 15:43:14 2005 by Doxygen 1.4.0