00001 #include "PNGGenerator.h"
00002 #include "InterleavedYUVGenerator.h"
00003 #include "Events/DataEvent.h"
00004 #include "Events/EventRouter.h"
00005 #include "Events/FilterBankEvent.h"
00006 #include "Shared/Profiler.h"
00007 #include "Wireless/Socket.h"
00008
00009
00010 using namespace std;
00011
00012 extern "C" {
00013
00014 struct png_write_mem_status {
00015 png_bytep buf;
00016 size_t bufsize;
00017 size_t offset;
00018 };
00019
00020 void user_write_png_data(png_structp png_ptr, png_bytep data, png_size_t length) {
00021 png_write_mem_status* status=(png_write_mem_status*)(png_get_io_ptr(png_ptr));
00022 size_t endoff=status->offset+length;
00023 if(endoff<=status->bufsize) {
00024 memcpy(status->buf+status->offset,data,length);
00025 status->offset=endoff;
00026 } else {
00027 png_error(png_ptr, "Write Error - ran out of file");
00028 }
00029 }
00030
00031 void user_flush_png_data(png_structp ) {}
00032 }
00033
00034
00035 PNGGenerator::PNGGenerator(unsigned int mysid, FilterBankGenerator* fbg, EventBase::EventTypeID_t tid)
00036 : FilterBankGenerator("PNGGenerator","PNGGenerator",EventBase::visPNGEGID,mysid,fbg,tid), srcMode(SRC_AUTO), curMode(SRC_AUTO), bytesUsed(NULL)
00037 {
00038 if(dynamic_cast<const InterleavedYUVGenerator*>(src)!=NULL)
00039 curMode=SRC_COLOR;
00040 else
00041 curMode=SRC_GRAYSCALE;
00042
00043
00044 if(fbg!=NULL) {
00045 numLayers=numChannels=0;
00046 setNumImages(fbg->getNumLayers(),fbg->getNumChannels());
00047 }
00048 }
00049
00050 PNGGenerator::PNGGenerator(unsigned int mysid, src_mode_t mode, FilterBankGenerator* fbg, EventBase::EventTypeID_t tid)
00051 : FilterBankGenerator("PNGGenerator","PNGGenerator",EventBase::visPNGEGID,mysid,fbg,tid), srcMode(mode), curMode(mode), bytesUsed(NULL)
00052 {
00053 if(srcMode==SRC_AUTO) {
00054 if(dynamic_cast<const InterleavedYUVGenerator*>(src)!=NULL)
00055 curMode=SRC_COLOR;
00056 else
00057 curMode=SRC_GRAYSCALE;
00058 }
00059
00060
00061 if(fbg!=NULL) {
00062 numLayers=numChannels=0;
00063 setNumImages(fbg->getNumLayers(),fbg->getNumChannels());
00064 }
00065 }
00066
00067 PNGGenerator::~PNGGenerator() {
00068 freeCaches();
00069 destruct();
00070 }
00071
00072
00073
00074
00075
00076
00077 void
00078 PNGGenerator::processEvent(const EventBase& event) {
00079 FilterBankGenerator::processEvent(event);
00080 if(event.getGeneratorID()==getListenGeneratorID() && event.getSourceID()==getListenSourceID()) {
00081 if(getSourceMode()==SRC_AUTO) {
00082 if(dynamic_cast<const InterleavedYUVGenerator*>(src)!=NULL)
00083 curMode=SRC_COLOR;
00084 else
00085 curMode=SRC_GRAYSCALE;
00086 }
00087 FilterBankEvent fbkev(this,getGeneratorID(),getSourceID(),EventBase::activateETID);
00088 erouter->postEvent(fbkev);
00089 fbkev.setTypeID(EventBase::statusETID);
00090 erouter->postEvent(fbkev);
00091 fbkev.setTypeID(EventBase::deactivateETID);
00092 erouter->postEvent(fbkev);
00093 }
00094 }
00095
00096 unsigned int
00097 PNGGenerator::getBinSize() const {
00098 unsigned int used=FilterBankGenerator::getBinSize();
00099 char * type;
00100 if(getCurrentSourceFormat()==SRC_COLOR)
00101 type="PNGColor";
00102 else if(getCurrentSourceFormat()==SRC_GRAYSCALE)
00103 type="PNGGrayscale";
00104 else {
00105 serr->printf("getBinSize failed - unsuitable or unknown mode/generator pair");
00106 return 0;
00107 }
00108 used+=strlen(type)+LoadSave::stringpad;
00109 if(bytesUsed[selectedSaveLayer][selectedSaveChannel]!=0)
00110 used+=bytesUsed[selectedSaveLayer][selectedSaveChannel];
00111 else
00112 used+=widths[selectedSaveLayer]*heights[selectedSaveLayer]*3+PNG_HEADER_PAD;
00113 return used;
00114 }
00115
00116 unsigned int
00117 PNGGenerator::loadBuffer(const char buf[], unsigned int len) {
00118 unsigned int origlen=len;
00119 if(!FilterBankGenerator::loadBuffer(buf,len)) return 0;
00120 std::string tmp;
00121 if(!decodeInc(tmp,buf,len)) return 0;
00122 if(tmp!="PNGColor" && tmp!="PNGGrayscale") {
00123 serr->printf("Unhandled image type for PNGGenerator: %s",tmp.c_str());
00124 return 0;
00125 } else {
00126 if(tmp=="PNGColor" && getCurrentSourceFormat()==SRC_GRAYSCALE)
00127 serr->printf("Warning: loading grayscale into color image");
00128 if(tmp=="PNGGrayscale" && getCurrentSourceFormat()==SRC_COLOR)
00129 serr->printf("Warning: loading color into grayscale image");
00130 unsigned int tmpL;
00131 if(!decodeInc(tmpL,buf,len)) return 0;
00132 if(tmpL>len)
00133 return 0;
00134 if(images[selectedSaveLayer][selectedSaveChannel]!=NULL)
00135 delete [] images[selectedSaveLayer][selectedSaveChannel];
00136 images[selectedSaveLayer][selectedSaveChannel]=createImageCache(selectedSaveLayer,selectedSaveChannel);
00137 unsigned int used=bytesUsed[selectedSaveLayer][selectedSaveChannel]=tmpL;
00138 unsigned char* img=getImage(selectedSaveLayer,selectedSaveChannel);
00139 if(img==NULL)
00140 return 0;
00141 memcpy(img,buf,used);
00142 len-=used; buf+=used;
00143 imageValids[selectedSaveLayer][selectedSaveChannel]=true;
00144 return origlen-len;
00145 }
00146 }
00147
00148 unsigned int
00149 PNGGenerator::saveBuffer(char buf[], unsigned int len) const {
00150 unsigned int origlen=len;
00151 if(!checkInc(FilterBankGenerator::saveBuffer(buf,len),buf,len)) return 0;
00152
00153 char * type;
00154 if(getCurrentSourceFormat()==SRC_COLOR)
00155 type="PNGColor";
00156 else if(getCurrentSourceFormat()==SRC_GRAYSCALE)
00157 type="PNGGrayscale";
00158 else {
00159 serr->printf("saveBuffer failed - unsuitable or unknown mode/generator pair");
00160 return 0;
00161 }
00162 if(!encodeInc(type,buf,len)) return 0;
00163
00164 if(images[selectedSaveLayer][selectedSaveChannel]==NULL) {
00165 serr->printf("PNGGenerator::saveBuffer() failed because selected image is NULL -- call selectSaveImage first to make sure it's up to date\n");
00166 return 0;
00167 }
00168 if(!imageValids[selectedSaveLayer][selectedSaveChannel]) {
00169 serr->printf("PNGGenerator::saveBuffer() failed because selected image is invalid -- call selectSaveImage first to make sure it's up to date\n");
00170 return 0;
00171 }
00172 unsigned char* img=images[selectedSaveLayer][selectedSaveChannel];
00173 if(img==NULL)
00174 return 0;
00175 if(!encodeInc(bytesUsed[selectedSaveLayer][selectedSaveChannel],buf,len)) return 0;
00176 unsigned int used=bytesUsed[selectedSaveLayer][selectedSaveChannel];
00177 if(used>len)
00178 return 0;
00179 memcpy(buf,img,used);
00180 len-=used;
00181 return origlen-len;
00182 }
00183
00184 void
00185 PNGGenerator::setNumImages(unsigned int nLayers, unsigned int nChannels) {
00186 if(nLayers==numLayers && nChannels==numChannels)
00187 return;
00188 FilterBankGenerator::setNumImages(nLayers,nChannels);
00189 for(unsigned int i=0; i<numLayers; i++)
00190 strides[i]=skips[i]=0;
00191 bytesUsed=new unsigned int*[numLayers];
00192 for(unsigned int res=0; res<numLayers; res++) {
00193 increments[res]=3;
00194 bytesUsed[res]=new unsigned int[numChannels];
00195 for(unsigned int i=0; i<numChannels; i++)
00196 bytesUsed[res][i]=0;
00197 }
00198 }
00199
00200 unsigned char *
00201 PNGGenerator::createImageCache(unsigned int layer, unsigned int ) const {
00202 return new unsigned char[widths[layer]*heights[layer]*3+PNG_HEADER_PAD];
00203 }
00204
00205 void
00206 PNGGenerator::calcImage(unsigned int layer, unsigned int chan) {
00207 PROFSECTION("PNGGenerator::calcImage(...)",*mainProfiler);
00208
00209 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00210 if (!png_ptr) {
00211 serr->printf("png_create_info_struct failed, %s unavailable.\n",getName().c_str());
00212 return;
00213 }
00214 png_infop info_ptr = png_create_info_struct(png_ptr);
00215 if (!info_ptr) {
00216 png_destroy_write_struct(&png_ptr, NULL);
00217 serr->printf("png_create_info_struct failed, %s unavailable.\n",getName().c_str());
00218 return;
00219 }
00220
00221 png_write_mem_status write_status;
00222 write_status.buf=images[layer][chan];
00223 write_status.bufsize=widths[layer]*heights[layer]*3+PNG_HEADER_PAD;
00224 write_status.offset=0;
00225 png_set_write_fn(png_ptr, &write_status, user_write_png_data, user_flush_png_data);
00226
00227 if(setjmp(png_jmpbuf(png_ptr))) {
00228 serr->printf("An error occurred during PNG compression\n");
00229 png_destroy_write_struct(&png_ptr, &info_ptr);
00230 return;
00231 }
00232 int bit_depth=8;
00233 int color_type;
00234 if(getCurrentSourceFormat()==SRC_COLOR)
00235 color_type=PNG_COLOR_TYPE_RGB;
00236 else if(getCurrentSourceFormat()==SRC_GRAYSCALE)
00237 color_type=PNG_COLOR_TYPE_GRAY;
00238 else {
00239 serr->printf("calcImage failed - unsuitable or unknown mode/generator pair\n");
00240 return;
00241 }
00242 png_set_IHDR(png_ptr, info_ptr, widths[layer], heights[layer], bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
00243 png_write_info(png_ptr, info_ptr);
00244 png_bytep row=reinterpret_cast<png_bytep>(src->getImage(layer,chan));
00245 const unsigned int inc=src->getIncrement(layer);
00246 #ifdef DEBUG
00247 if(getCurrentSourceFormat()==SRC_COLOR && inc!=3 || getCurrentSourceFormat()==SRC_GRAYSCALE && inc!=1) {
00248 serr->printf("PNGGenerator only supports color mode from sources with interleaving of 3 samples (increment==3), or grayscale from \"pure\" sources (increment==1)\n");
00249 png_write_end(png_ptr, NULL);
00250 return;
00251 }
00252 #endif
00253 unsigned int row_stride = src->getStride(layer);
00254 png_bytep endp=reinterpret_cast<png_bytep>(row+row_stride*heights[layer]);
00255 for(unsigned int h=0; h<heights[layer]; ++h) {
00256 if(row+row_stride>endp) {
00257 serr->printf("Ran out of src image -- bad height?\n");
00258 break;
00259 }
00260 png_write_row(png_ptr, row);
00261 row+=row_stride;
00262 }
00263 png_write_end(png_ptr, NULL);
00264 png_destroy_write_struct(&png_ptr, &info_ptr);
00265 bytesUsed[layer][chan]=write_status.offset;
00266 imageValids[layer][chan]=true;
00267 }
00268
00269 void
00270 PNGGenerator::destruct() {
00271 FilterBankGenerator::destruct();
00272 for(unsigned int res=0; res<numLayers; res++)
00273 delete [] bytesUsed[res];
00274 delete [] bytesUsed;
00275 bytesUsed=NULL;
00276 }
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287