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(getSourceMode()==SRC_AUTO) { //if not auto, curMode was already set when srcMode was set
00051     if(dynamic_cast<const InterleavedYUVGenerator*>(src)!=NULL)
00052       curMode=SRC_COLOR;
00053     else
00054       curMode=SRC_GRAYSCALE;
00055   }
00056   erouter->postEvent(new FilterBankEvent(this,getGeneratorID(),getSourceID()));
00057 }
00058 
00059 unsigned int
00060 JPEGGenerator::getBinSize() const {
00061   unsigned int used=FilterBankGenerator::getBinSize();
00062   used+=strlen("JPEGColor")+LoadSave::stringpad;
00063   if(bytesUsed[selectedSaveLayer][selectedSaveChannel]!=0)
00064     used+=bytesUsed[selectedSaveLayer][selectedSaveChannel];
00065   else
00066     used+=widths[selectedSaveLayer]*heights[selectedSaveLayer]*3+JPEG_HEADER_PAD;
00067   return used;
00068 }
00069 
00070 unsigned int
00071 JPEGGenerator::LoadBuffer(const char buf[], unsigned int len) {
00072   unsigned int origlen=len;
00073   unsigned int used;
00074   std::string tmp;
00075   if(0==(used=FilterBankGenerator::LoadBuffer(buf,len))) return 0;
00076   len-=used; buf+=used;
00077   if(0==(used=decode(tmp,buf,len))) return 0;
00078   len-=used; buf+=used;
00079   if(tmp!="JPEGColor" && tmp!="JPEGGray") {
00080     serr->printf("Unhandled image type for JPEGGenerator: %s",tmp.c_str());
00081     return 0;
00082   } else {
00083     if(tmp=="JPEGColor" && getCurrentSourceFormat()==SRC_GRAYSCALE)
00084       serr->printf("Warning: loading grayscale into color image");
00085     if(tmp=="JPEGGrayscale" && getCurrentSourceFormat()==SRC_COLOR)
00086       serr->printf("Warning: loading color into grayscale image");
00087     unsigned int tmpL;
00088     if(0==(used=decode(tmpL,buf,len))) return 0;
00089     len-=used; buf+=used;
00090     if(tmpL>len)
00091       return 0;
00092     if(images[selectedSaveLayer][selectedSaveChannel]!=NULL)
00093       delete [] images[selectedSaveLayer][selectedSaveChannel];
00094     images[selectedSaveLayer][selectedSaveChannel]=createImageCache(selectedSaveLayer,selectedSaveChannel);
00095     used=bytesUsed[selectedSaveLayer][selectedSaveChannel]=tmpL;
00096     unsigned char* img=getImage(selectedSaveLayer,selectedSaveChannel);
00097     if(img==NULL)
00098       return 0;
00099     memcpy(img,buf,used);
00100     len-=used; buf+=used;
00101     imageValids[selectedSaveLayer][selectedSaveChannel]=true;
00102     return origlen-len; 
00103   }
00104 }
00105 
00106 unsigned int
00107 JPEGGenerator::SaveBuffer(char buf[], unsigned int len) const {
00108   unsigned int origlen=len;
00109   unsigned int used;
00110   if(0==(used=FilterBankGenerator::SaveBuffer(buf,len))) return 0;
00111   len-=used; buf+=used;
00112 
00113   char * type;
00114   if(getCurrentSourceFormat()==SRC_COLOR)
00115     type="JPEGColor";
00116   else if(getCurrentSourceFormat()==SRC_GRAYSCALE)
00117     type="JPEGGrayscale";
00118   else {
00119     serr->printf("SaveBuffer failed - unsuitable or unknown mode/generator pair");
00120     return 0;
00121   }
00122   if(0==(used=encode(type,buf,len))) return 0;
00123   len-=used; buf+=used;
00124   
00125   unsigned char* img=getImage(selectedSaveLayer,selectedSaveChannel);
00126   if(img==NULL)
00127     return 0;
00128   if(0==(used=encode(bytesUsed[selectedSaveLayer][selectedSaveChannel],buf,len))) return 0;
00129   len-=used; buf+=used;
00130   used=bytesUsed[selectedSaveLayer][selectedSaveChannel];
00131   if(used>len)
00132     return 0;
00133   memcpy(buf,img,used);
00134   len-=used;
00135   return origlen-len;
00136 }
00137 
00138 void
00139 JPEGGenerator::setNumImages(unsigned int nLayers, unsigned int nChannels) {
00140   if(nLayers==numLayers && nChannels==numChannels)
00141     return;
00142   FilterBankGenerator::setNumImages(nLayers,nChannels);
00143   for(unsigned int i=0; i<numLayers; i++)
00144     strides[i]=skips[i]=0;
00145   bytesUsed=new unsigned int*[numLayers];
00146   for(unsigned int res=0; res<numLayers; res++) {
00147     increments[res]=3;
00148     bytesUsed[res]=new unsigned int[numChannels];
00149     for(unsigned int i=0; i<numChannels; i++)
00150       bytesUsed[res][i]=0;
00151   }
00152 }
00153 
00154 unsigned char *
00155 JPEGGenerator::createImageCache(unsigned int layer, unsigned int /*chan*/) const {
00156   return new unsigned char[widths[layer]*heights[layer]*3+JPEG_HEADER_PAD];
00157 }
00158 
00159 /*! This function is taken pretty directly from the write_jpeg_mem()
00160  *  function from Sony's W3AIBO sample code.
00161  *
00162  *  I have adapted it for this object, and added the ability to
00163  *  process greyscale images as well as color.
00164  */
00165 void
00166 JPEGGenerator::calcImage(unsigned int layer, unsigned int chan) const {
00167   PROFSECTION("JPEGGenerator::calcImage(...)",state->mainProfile);
00168 
00169   //pass the destination buffer and buffer size here
00170   jpeg_mem_dest(&cinfo, images[layer][chan], widths[layer]*heights[layer]*3+JPEG_HEADER_PAD);
00171 
00172   // mode setup
00173   cinfo.image_width = widths[layer];
00174   cinfo.image_height = heights[layer];
00175   if(getCurrentSourceFormat()==SRC_COLOR ) {
00176     cinfo.input_components = 3;   /* # of color components per pixel */
00177     cinfo.in_color_space = JCS_YCbCr; /* colorspace of input image */
00178   } else if(getCurrentSourceFormat()==SRC_GRAYSCALE) {
00179     cinfo.input_components = 1;   /* # of color components per pixel */
00180     cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */
00181   } else {
00182     serr->printf("Compression failed - unsuitable or unknown mode/generator pair");
00183     jpeg_destroy_compress(&cinfo);
00184     return;
00185   }
00186 
00187   // parameter setup
00188   jpeg_set_defaults(&cinfo);
00189   unsigned int qual=(quality==-1U?config->vision.rawcam_compress_quality:quality);
00190   jpeg_set_quality(&cinfo, qual, false); /* limit to baseline-JPEG values */
00191   cinfo.dct_method=config->vision.jpeg_dct_method;
00192   if(cinfo.in_color_space==JCS_YCbCr) {
00193     unsigned int ysamp=1;
00194     unsigned int uvsamp=1;
00195     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"
00196     if(config->vision.rawcam_y_skip>config->vision.rawcam_uv_skip) {
00197       uvsamp=config->vision.rawcam_y_skip-config->vision.rawcam_uv_skip+1;
00198       if(uvsamp>maxsamp)
00199         uvsamp=maxsamp;
00200     } else {
00201       ysamp=config->vision.rawcam_uv_skip-config->vision.rawcam_y_skip+1;
00202       if(ysamp>maxsamp)
00203         ysamp=maxsamp;
00204     }
00205     cinfo.comp_info[0].h_samp_factor=ysamp;
00206     cinfo.comp_info[0].v_samp_factor=ysamp;
00207     cinfo.comp_info[1].h_samp_factor=uvsamp;
00208     cinfo.comp_info[1].v_samp_factor=uvsamp;
00209     cinfo.comp_info[2].h_samp_factor=uvsamp;
00210     cinfo.comp_info[2].v_samp_factor=uvsamp;
00211   }
00212 
00213   // compression
00214   jpeg_start_compress(&cinfo, TRUE);
00215   unsigned int row_stride = src->getStride(layer);  /* JSAMPLEs per row in image_buffer */
00216   JSAMPROW row_pointer[1] = { const_cast<JSAMPROW>(src->getImage(layer,chan)) };
00217   while (cinfo.next_scanline < cinfo.image_height) {
00218     jpeg_write_scanlines(&cinfo, row_pointer, 1);
00219     row_pointer[0]+=row_stride;
00220   }
00221   jpeg_finish_compress(&cinfo);
00222 
00223   // results
00224   bytesUsed[layer][chan]=jpeg_mem_size(&cinfo);
00225   imageValids[layer][chan]=true;
00226 }
00227 
00228 void
00229 JPEGGenerator::destruct() {
00230   FilterBankGenerator::destruct();
00231   for(unsigned int res=0; res<numLayers; res++)
00232     delete [] bytesUsed[res];
00233   delete [] bytesUsed;
00234   bytesUsed=NULL;
00235 }
00236 
00237 /*! @file
00238  * @brief Implements JPEGGenerator, which generates FilterBankEvents containing JPEG compressed images
00239  * @author ejt (Creator)
00240  *
00241  * $Author: ejt $
00242  * $Name: tekkotsu-2_1 $
00243  * $Revision: 1.8 $
00244  * $State: Exp $
00245  * $Date: 2004/02/18 21:13:32 $
00246  */
00247 

Tekkotsu v2.1
Generated Tue Mar 16 23:19:13 2004 by Doxygen 1.3.5