apps/png/pnghist.c

Go to the documentation of this file.
00001 /*
00002 ** -----------------------------------------------------------------------------**
00003 ** pnghist.c
00004 **
00005 ** Copyright (C) 2006 Elphel, Inc.
00006 **
00007 ** -----------------------------------------------------------------------------**
00008 **  This program is free software: you can redistribute it and/or modify
00009 **  it under the terms of the GNU General Public License as published by
00010 **  the Free Software Foundation, either version 3 of the License, or
00011 **  (at your option) any later version.
00012 **
00013 **  This program is distributed in the hope that it will be useful,
00014 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 **  GNU General Public License for more details.
00017 **
00018 **  You should have received a copy of the GNU General Public License
00019 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00020 ** -----------------------------------------------------------------------------**
00021 */
00022 
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <unistd.h>
00026 #include <sys/stat.h>
00027 #include <sys/ioctl.h>
00028 #include <sys/types.h>
00029 #include <sys/stat.h>
00030 #include <fcntl.h>
00031 #include <math.h>
00032 
00033 #include <asm/elphel/autoexp.h>
00034 #include <asm/elphel/hist.h>
00035 
00036 #include <sys/mman.h>
00037 #include <asm/elphel/c313a.h>
00038 
00039  
00040 //#include "zlib.h"
00041 #include "libpng/png.h"
00042 //#define PNGHISTDEBUG 1
00043 #define HIST_SIZE 256 * 4 * 4
00044 
00045 #define HPNG_PLOT_BARS    1
00046 #define HPNG_CONNECT_DOTS 2
00047 #define HPNG_FILL_ZEROS   4
00048 #define HPNG_LIN_INTERP   8
00049 #define HPNG_RUN_SQRT     16
00050 
00051 #define QRY_MAXPARAMS 64
00052 
00053 char  copyQuery [4096];
00054 const char *uri;
00055 const char *method;
00056 const char *query;
00057 
00058 struct key_value {
00059         char *key;
00060         char *value;
00061 };
00062 
00063 struct key_value gparams[QRY_MAXPARAMS+1];
00064 
00065 int unescape(char *, int);
00066 int hexdigit(char);
00067 char * paramValue(struct key_value *, char *);
00068 int parseQuery(struct key_value *, char *);
00069 
00070 
00071 struct autoexp_t autoexp;
00072 int write_png(int height, int data[1024], int mode, int colors);
00073 int main(argc, argv)
00074     int argc;
00075     char *argv[];
00076 {
00077   int hists[1536];
00078   int rava[256];
00079 //  int fd;
00080   int autoexp_fd;
00081   int i,j,k,a,l;
00082 //  short int hsz[2];
00083   
00084   int png_height=256;
00085   double dscale=3.0;
00086   int mode=14;
00087   int colors=57; // colors 1 - r, 2 - g1, 4 - g2, 8 - b, 16 - w, 32 - g1+g2 
00088   int rav=0; // running average
00089   
00090   double dcoeff;
00091   int coeff;
00092   int ww,wh;
00093   int devfd;
00094   int lastmiddle_i,newmiddle_i;
00095   int z;
00096   void *_map;  
00097   const char colors_calc[]={  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,0xa,0xb,0xc,0xd,0xe,0xf,
00098                       0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,
00099                         6,  7,  6,  7,  6,  7,  6,  7,0xe,0xf,0xe,0xf,0xe,0xf,0xe,0xf,
00100                       0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf};
00101   char * v;                    
00102 #if 0                      
00103   if (argc<5) {printf("pnghist height scale mode colors average"); return 0;}
00104  
00105   rav=atoi(argv[5]);
00106   png_height=atoi(argv[1]);
00107   if (png_height>256) png_height=256;
00108   dscale=atof(argv[2]);
00109   mode=atoi(argv[3]);
00110   colors=atoi(argv[4]) & 0x3f;
00111 #endif 
00112 //  struct stat buf;
00113  
00114   method = getenv("REQUEST_METHOD");
00115   query = getenv("QUERY_STRING");
00116   uri = getenv("REQUEST_URI");
00117 
00118   i= (query)? strlen (query):0;
00119 //  fprintf(stderr,"querry length=%d\n", i);
00120 
00121   if (i>(sizeof(copyQuery)-1)) i= sizeof(copyQuery)-1;
00122   if (i>0) strncpy(copyQuery,query, i);
00123   copyQuery[i]=0;
00124   unescape(copyQuery,sizeof(copyQuery));
00125 
00126   if (method == NULL)
00127   {
00128   /* Not a CGI! */
00129      printf("This program should be run as a CGI from the web server!\n");
00130      exit(1);
00131   }
00132 
00133   parseQuery(gparams, copyQuery);
00134   #define HPNG_PLOT_BARS    1
00135 //#define HPNG_CONNECT_DOTS 2
00136 //#define HPNG_FILL_ZEROS   4
00137 //#define HPNG_LIN_INTERP   8
00138 //#define HPNG_RUN_SQRT     16
00139 
00140 
00141   if((v = paramValue(gparams, "height"))   != NULL) png_height=atoi(v);
00142   if((v = paramValue(gparams, "draw"))     != NULL) mode= (mode & 0xfc) | (atoi(v) & 3);
00143   if((v = paramValue(gparams, "fillz"))    != NULL) mode= (mode & (~HPNG_FILL_ZEROS)) | (atoi(v)?HPNG_FILL_ZEROS:0);
00144   if((v = paramValue(gparams, "linterpz")) != NULL) mode= (mode & (~HPNG_LIN_INTERP)) | (atoi(v)?HPNG_LIN_INTERP:0);
00145   if((v = paramValue(gparams, "sqrt"))     != NULL) mode= (mode & (~HPNG_RUN_SQRT))   | (atoi(v)?HPNG_RUN_SQRT:0);
00146   if((v = paramValue(gparams, "colors"))   != NULL) colors=atoi(v);
00147   if((v = paramValue(gparams, "average"))  != NULL) rav=atoi(v);
00148   if((v = paramValue(gparams, "scale"))    != NULL) dscale=atof(v);
00149   
00150  
00151  
00152  
00153   if ((devfd = open("/dev/ccam_img", O_RDONLY)) < 0) {
00154 //     fprintf(stdout, "HTTP/1.0 200 OK\n");
00155      fprintf(stdout, "Pragma: no-cache\n");
00156      fprintf(stdout, "Content-Type: text/plain\n\n");
00157      fprintf(stdout, "Device busy (%s)\r\n", "/dev/ccam_img");
00158      fflush(stdout);
00159      return -1;
00160   }
00161 
00162   ww=ioctl(devfd, _CCCMD( CCAM_RPARS , P_ACTUAL_WIDTH), 0);
00163   wh=ioctl(devfd, _CCCMD( CCAM_RPARS , P_ACTUAL_HEIGHT), 0);
00164   close (devfd);
00165 //  printf ("w=%d, h=%d\n",ww,wh);
00166   
00167 //  autoexp_fd = open(AUTOEXP_DEV_NAME, O_RDWR);
00168   int retr=10000;
00169   autoexp_fd=-1;
00170   while ( (((autoexp_fd = open(AUTOEXP_DEV_NAME, O_RDONLY)))<0) && (retr>0)) retr--;
00171   if(autoexp_fd < 0) {
00172 //     fprintf(stdout, "HTTP/1.0 200 OK\n");
00173      fprintf(stdout, "Pragma: no-cache\n");
00174      fprintf(stdout, "Content-Type: text/plain\n\n");
00175      fprintf(stdout, "open %s failed - may be busy, or not started\r\n", AUTOEXP_DEV_NAME);
00176      fflush(stdout);
00177      return -1;
00178   }
00179   z = ioctl(autoexp_fd, _IO(IOC_AUTOEXP_GET, 0x00), &autoexp);
00180   
00181   
00182 //  if((_map = mmap(NULL, HIST_SIZE, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, autoexp_fd, 0)) == MAP_FAILED) {
00183   if((_map = mmap(NULL, HIST_SIZE, PROT_READ, MAP_FIXED | MAP_SHARED, autoexp_fd, 0)) == MAP_FAILED) {
00184 //      fprintf(stdout, "HTTP/1.0 200 OK\n");
00185       fprintf(stdout, "Pragma: no-cache\n");
00186       fprintf(stdout, "Content-Type: text/plain\n\n");
00187       fprintf(stdout, "broken mmap: %s !!!\n", AUTOEXP_DEV_NAME);
00188       fflush(stdout);
00189       return -1;
00190   }
00191   memcpy (hists,_map,HIST_SIZE);
00192   close (autoexp_fd);
00193   
00194   ww=(ww*autoexp.width)/100;
00195   wh=(wh*autoexp.height)/100;
00196   dcoeff=(png_height*1024)/(dscale*ww*wh);
00197   coeff=dcoeff*65536;
00198 #ifdef PNGHISTDEBUG
00199   printf ("w=%d, h=%d\n",ww,wh);
00200   for (i=0;i<1024;i++) {
00201     printf ("%5d ",hists[i]);
00202     if ((i & 0x0f)== 0x0f) printf ("\n");
00203   if ((i & 0xff) == 0xff) printf ("-----------------------------------------------\n");
00204     
00205   }
00206   printf ("===============================================\n");
00207 #endif  
00208 
00209   
00210 
00211   if ((mode & (HPNG_FILL_ZEROS | HPNG_LIN_INTERP)) | (rav>1)) { // spread between zeros - needed at high digital gains (near black with low gammas)
00212     for (j=0;j<4;j++)  if (colors_calc[colors] & (1<<j)) {
00213       lastmiddle_i=255;
00214       i=255;
00215       while ((hists[i+(j<<8)]==0) && (i>0)) i--;// skip high zeros
00216       while (i>0) {
00217        k=i;
00218        i--;
00219        while ((i>=0) && (hists[i+(j<<8)]==0)) i--;
00220        if ((k-i)>1) {
00221          a=hists[k+(j<<8)]/(k-i);
00222          for (l=k;l>i;l--) hists[l+(j<<8)] = a;
00223        }
00224        if ((mode & HPNG_LIN_INTERP) | (rav>1)) { //linear interpolation - also for high digital gains (near black with low gammas)
00225          newmiddle_i= (k+i+1)/2;
00226          for (l=lastmiddle_i-1;l>newmiddle_i;l--) { 
00227             hists[l+(j<<8)]= hists[newmiddle_i+(j<<8)] + ((l-newmiddle_i)* (hists[lastmiddle_i+(j<<8)]-hists[newmiddle_i+(j<<8)]))/(lastmiddle_i-newmiddle_i);
00228          }   
00229          lastmiddle_i=newmiddle_i;
00230        
00231        }
00232       }
00233 // apply running average (if any)
00234       if (rav>0) {
00235         k=0;
00236         l=0;
00237         for (i=0;i<256;i++) {
00238          rava[i]=hists[i+(j<<8)];
00239          k+=rava[i];
00240          if ((i-rav)>=0) k-=rava[i-rav];
00241          else l++;
00242          hists[i+(j<<8)]=k/l;
00243         }
00244       } 
00245       
00246       
00247     }
00248   }
00249 // calculate white if needed
00250   if (colors & 0x10) for (i=0;i<256;i++) hists[i+1024]=(hists[i]+hists[i+256]+hists[i+512]+hists[i+768])>>2;
00251 // calculate green if needed
00252   if (colors & 0x20) for (i=0;i<256;i++) hists[i+1280]=(hists[i+256]+hists[i+512])>>1;
00253   
00254   if (mode & HPNG_RUN_SQRT) {
00255     dcoeff=sqrt((32768.0*png_height)/coeff);
00256     for (j=0;j<6;j++) if (colors & (1 << j)) for (i=0;i<256;i++) hists[i+(j<<8)]=sqrt(hists[i+(j<<8)])*dcoeff;
00257   }
00258 // now scale data
00259   for (j=0;j<6;j++) if (colors & (1 << j)) for (i=0;i<256;i++) {
00260    hists[i+(j<<8)]=(hists[i+(j<<8)]*coeff) >> 16;
00261    if (hists[i+(j<<8)] > (png_height-1)) hists[i+(j<<8)] = png_height-1;
00262   }   
00263 
00264 #ifdef PNGHISTDEBUG
00265   printf ("w=%d, h=%d\n",ww,wh);
00266   for (i=0;i<1536;i++) {
00267     printf ("%5d ",hists[i]);
00268     if ((i & 0x0f)== 0x0f) printf ("\n");
00269   }
00270 #endif  
00271 //      sq = state.width * state.height;
00272 
00273 
00274 //   fprintf(stdout, "HTTP/1.0 200 OK\n");
00275    fprintf(stdout, "Pragma: no-cache\n");
00276    fprintf(stdout, "Content-Type: image/png\n\n");
00277    write_png(png_height, hists, mode, colors);
00278    fflush(stdout);
00279   
00280   return 0;
00281 }
00282 #define ERROR -1
00283 #define OK 0
00284 //#define HPNG_PLOT_BARS    1
00285 //#define HPNG_CONNECT_DOTS 2
00286 
00287 
00288 int write_png(int png_height, int data[1536], int mode, int colors)
00289 {
00290 //   FILE *fp;
00291    png_structp png_ptr;
00292    png_infop info_ptr;
00293 //   const char clrs[]={1,2,2,4,15,2}; // dim white
00294    const char clrs[]={1,2,2,4,7,2}; // bright white
00295 //   png_colorp palette;
00296    unsigned char cpalette[]= {0,   0,   0,
00297                         0xff,0,   0,
00298                         0,   0xff,0,
00299                         0xff,0xff,0,
00300                         0,   0,   0xff,
00301                         0xff,0,   0xff,
00302                         0,   0xff,0xff,
00303                         0xff,0xff,0xff,
00304                         0,   0,   0,
00305                         0x80,0,   0,
00306                         0,   0x80,0,
00307                         0x80,0x80,0,
00308                         0,   0,   0x80,
00309                         0x80,0,   0x80,
00310                         0,   0x80,0x80,
00311                         0x80,0x80,0x80};
00312   png_colorp  palette = (png_colorp ) cpalette;
00313   unsigned char ctransparency[]={0,  255,255,255,255,255,255,255,
00314                                  255,255,255,255,255,255,255,255};
00315   png_bytep   trans =   (png_bytep) ctransparency;
00316    png_uint_32 k;
00317    png_uint_32 height=png_height;
00318    png_uint_32 width=256;
00319    png_uint_32 bytes_per_pixel=1;
00320    png_byte image[256][256];
00321    png_bytep row_pointers[256];
00322    int i,j,c0,c,d,l,last;
00323    if (height>256) height=256;
00324    
00325    memset(image, 0, sizeof(image));
00326    for (j=0;j<6;j++) if (colors & (1 << j)){
00327      c0= clrs[j];
00328      last=png_height-1;
00329      for (i=0;i<256;i++) {
00330        c=c0 << ((i&1)?0:4);
00331        d=png_height-1-data[i+(j<<8)];
00332        if (d<=0) d=0;
00333        if (d>=png_height) d=png_height-1;
00334        image[d][i>>1] |= c;
00335        if (mode & 1){
00336 //         l=d-mode;
00337 //         if ((i&0x10)==0) l-=mode;
00338 //         l-= (i & 0xf);
00339 //         if (l<0) l=0;
00340          for (l=d+1; l<png_height; l++)image[l][i>>1] |= c;
00341 //         for (l=png_height; l>d; l--)image[l][i] |= c;
00342        } else if (mode & 2) {
00343          for (l=d+1; l<last; l++) image[l][i>>1] |= c; // only one of "for " can fire
00344          for (l=d-1; l>last; l--) image[l][i>>1] |= c; 
00345          last=d;
00346        
00347        }
00348        
00349      }
00350    }
00351    
00352    /* open the file */
00353 /*
00354    fp = fopen(file_name, "wb");
00355   
00356    if (fp == NULL)
00357       return (ERROR);
00358 */
00359    /* Create and initialize the png_struct with the desired error handler
00360     * functions.  If you want to use the default stderr and longjump method,
00361     * you can supply NULL for the last three parameters.  We also check that
00362     * the library version is compatible with the one used at compile time,
00363     * in case we are using dynamically linked libraries.  REQUIRED.
00364     */
00365    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
00366       NULL,NULL,NULL);
00367 
00368    if (png_ptr == NULL)
00369    {
00370 //      fclose(fp);
00371       return (ERROR);
00372    }
00373 
00374    /* Allocate/initialize the image information data.  REQUIRED */
00375    info_ptr = png_create_info_struct(png_ptr);
00376    if (info_ptr == NULL)
00377    {
00378 //      fclose(fp);
00379       png_destroy_write_struct(&png_ptr,  png_infopp_NULL);
00380       return (ERROR);
00381    }
00382 
00383    /* Set error handling.  REQUIRED if you aren't supplying your own
00384     * error handling functions in the png_create_write_struct() call.
00385     */
00386    if (setjmp(png_jmpbuf(png_ptr)))
00387    {
00388       /* If we get here, we had a problem reading the file */
00389 //      fclose(fp);
00390       png_destroy_write_struct(&png_ptr, &info_ptr);
00391       return (ERROR);
00392    }
00393 
00394    /* One of the following I/O initialization functions is REQUIRED */
00395 //#ifdef streams /* I/O initialization method 1 */
00396    /* set up the output control if you are using standard C streams */
00397 //   png_init_io(png_ptr, fp);
00398    png_init_io(png_ptr, stdout);
00399 //#else  no_streams /* I/O initialization method 2 */
00400    /* If you are using replacement read functions, instead of calling
00401     * png_init_io() here you would call */
00402 //   png_set_write_fn(png_ptr, (void *)user_io_ptr, user_write_fn,
00403 //      user_IO_flush_function);
00404    /* where user_io_ptr is a structure you want available to the callbacks */
00405 //#endif// no_streams /* only use one initialization method */
00406 
00407    /* This is the hard way */
00408 
00409    /* Set the image information here.  Width and height are up to 2^31,
00410     * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
00411     * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
00412     * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
00413     * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
00414     * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
00415     * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
00416     */
00417    png_set_IHDR(png_ptr,
00418                 info_ptr,
00419                 256, // width
00420                 png_height, // height
00421                 4,          // bit_depth,
00422                 PNG_COLOR_TYPE_PALETTE, //PNG_COLOR_TYPE_???,
00423                 PNG_INTERLACE_NONE, //PNG_INTERLACE_????,
00424                 PNG_COMPRESSION_TYPE_BASE,
00425                 PNG_FILTER_TYPE_BASE);
00426 
00427    /* set the palette if there is one.  REQUIRED for indexed-color images */
00428 //   palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH
00429 //             * png_sizeof (png_color));
00430    /* ... set palette colors ... */
00431    png_set_PLTE(png_ptr,
00432                 info_ptr,
00433                 palette,
00434                 PNG_MAX_PALETTE_LENGTH);
00435     png_set_tRNS(png_ptr,
00436                 info_ptr,
00437                 trans,
00438                 sizeof(trans), //16,
00439                 NULL); //, png_color_16p trans_values)                
00440   /* You must not free palette here, because png_set_PLTE only makes a link to
00441       the palette that you malloced.  Wait until you are about to destroy
00442       the png structure. */
00443 
00444    /* optional significant bit chunk */
00445    /* if we are dealing with a grayscale image then */
00446 #if 0   
00447    sig_bit.gray = 1; //true_bit_depth;
00448    /* otherwise, if we are dealing with a color image then */
00449    sig_bit.red = 1; //true_red_bit_depth;
00450    sig_bit.green = 1; //true_green_bit_depth;
00451    sig_bit.blue = 1; //true_blue_bit_depth;
00452    /* if the image has an alpha channel then */
00453    sig_bit.alpha = 1; //true_alpha_bit_depth;
00454    png_set_sBIT(png_ptr, info_ptr, sig_bit);
00455 #endif
00456 
00457    /* Optional gamma chunk is strongly suggested if you have any guess
00458     * as to the correct gamma of the image.
00459     */
00460 //   png_set_gAMA(png_ptr, info_ptr, gamma);
00461 
00462    /* Optionally write comments into the image */
00463 #if 0  
00464    text_ptr[0].key = "Title";
00465    text_ptr[0].text = "Histogram";// "Mona Lisa";
00466    text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
00467    text_ptr[1].key = "Author";
00468    text_ptr[1].text = "Elphel"; //"Leonardo DaVinci";
00469    text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
00470    text_ptr[2].key = "Description";
00471    text_ptr[2].text = "color histograms for the camera image/video"; //"<long text>";
00472    text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt;
00473 #ifdef PNG_iTXt_SUPPORTED
00474    text_ptr[0].lang = NULL;
00475    text_ptr[1].lang = NULL;
00476    text_ptr[2].lang = NULL;
00477 #endif
00478    png_set_text(png_ptr, info_ptr, text_ptr, 3);
00479 #endif
00480 
00481    /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
00482    /* note that if sRGB is present the gAMA and cHRM chunks must be ignored
00483     * on read and must be written in accordance with the sRGB profile */
00484 
00485    /* Write the file header information.  REQUIRED */
00486    png_write_info(png_ptr, info_ptr);
00487 
00488    /* If you want, you can write the info in two steps, in case you need to
00489     * write your private chunk ahead of PLTE:
00490     *
00491     *   png_write_info_before_PLTE(write_ptr, write_info_ptr);
00492     *   write_my_chunk();
00493     *   png_write_info(png_ptr, info_ptr);
00494     *
00495     * However, given the level of known- and unknown-chunk support in 1.1.0
00496     * and up, this should no longer be necessary.
00497     */
00498 
00499    /* Once we write out the header, the compression type on the text
00500     * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
00501     * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again
00502     * at the end.
00503     */
00504 
00505    /* set up the transformations you want.  Note that these are
00506     * all optional.  Only call them if you want them.
00507     */
00508 
00509    /* invert monochrome pixels */
00510 //   png_set_invert_mono(png_ptr);
00511 
00512    /* Shift the pixels up to a legal bit depth and fill in
00513     * as appropriate to correctly scale the image.
00514     */
00515 //   png_set_shift(png_ptr, &sig_bit);
00516 
00517    /* pack pixels into bytes */
00518 //   png_set_packing(png_ptr);
00519 
00520    /* swap location of alpha bytes from ARGB to RGBA */
00521 //   png_set_swap_alpha(png_ptr);
00522 
00523    /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
00524     * RGB (4 channels -> 3 channels). The second parameter is not used.
00525     */
00526 //   png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
00527 
00528    /* flip BGR pixels to RGB */
00529 //   png_set_bgr(png_ptr);
00530 
00531    /* swap bytes of 16-bit files to most significant byte first */
00532 //   png_set_swap(png_ptr);
00533 
00534    /* swap bits of 1, 2, 4 bit packed pixel formats */
00535 //   png_set_packswap(png_ptr);
00536 
00537    /* turn on interlace handling if you are not using png_write_image() */
00538 #if 0   
00539    if (interlacing)
00540       number_passes = png_set_interlace_handling(png_ptr);
00541    else
00542       number_passes = 1;
00543 #endif   
00544 
00545    /* The easiest way to write the image (you may have a different memory
00546     * layout, however, so choose what fits your needs best).  You need to
00547     * use the first method if you aren't handling interlacing yourself.
00548     */
00549 //   png_uint_32 k, height, width;
00550 //   png_byte image[height][width*bytes_per_pixel];
00551 //   png_bytep row_pointers[height];
00552 
00553    if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
00554      png_error (png_ptr, "Image is too tall to process in memory");
00555 
00556    for (k = 0; k < height; k++)
00557      row_pointers[k] = (png_bytep) image + k*width*bytes_per_pixel;
00558 
00559    /* One of the following output methods is REQUIRED */
00560    png_write_image(png_ptr, row_pointers);
00561 
00562 
00563    /* You can write optional chunks like tEXt, zTXt, and tIME at the end
00564     * as well.  Shouldn't be necessary in 1.1.0 and up as all the public
00565     * chunks are supported and you can use png_set_unknown_chunks() to
00566     * register unknown chunks into the info structure to be written out.
00567     */
00568 
00569    /* It is REQUIRED to call this to finish writing the rest of the file */
00570    png_write_end(png_ptr, info_ptr);
00571 
00572    /* If you png_malloced a palette, free it here (don't free info_ptr->palette,
00573       as recommended in versions 1.0.5m and earlier of this example; if
00574       libpng mallocs info_ptr->palette, libpng will free it).  If you
00575       allocated it with malloc() instead of png_malloc(), use free() instead
00576       of png_free(). */
00577 //   png_free(png_ptr, palette);
00578 //   palette=NULL;
00579 
00580    /* Similarly, if you png_malloced any data that you passed in with
00581       png_set_something(), such as a hist or trans array, free it here,
00582       when you can be sure that libpng is through with it. */
00583 //   png_free(png_ptr, trans);
00584 //   trans=NULL;
00585 
00586    /* clean up after the write, and free any memory allocated */
00587    png_destroy_write_struct(&png_ptr, &info_ptr);
00588 
00589    /* close the file */
00590 //   fclose(fp);
00591 
00592    /* that's it */
00593    return (OK);
00594 }
00595 
00596 int unescape (char * s, int l) {
00597   int i=0;
00598   int j=0;
00599   while ((i<l) && s[i]) {
00600     if ((s[i]=='%') && (i<(l-2)) && s[i+1]){ // behavior from Mozilla
00601       s[j++]=(hexdigit(s[i+1])<<4) | hexdigit(s[i+2]);
00602       i+=3;
00603     } else s[j++]=s[i++];
00604   }
00605   if (i<l) s[j]=0;
00606   return j;
00607 }
00608 
00609 int hexdigit (char c) {
00610   int i;
00611   i=c-'0';
00612   if ((i>=0) && (i<10)) return i;
00613   i=c-'a'+10;
00614   if ((i>=10) && (i<16)) return i;
00615   i=c-'A'+10;
00616   if ((i>=10) && (i<16)) return i;
00617   return 0; // could be -1??
00618 }
00619 
00620 char * paramValue(struct key_value * params, char * skey) { // returns pointer to parameter value, NULL if not defined
00621   int i=0;
00622   if (skey)
00623    while ((i<QRY_MAXPARAMS) && (params[i].key)) {
00624     if (strcmp(skey,params[i].key)==0) return   params[i].value;
00625 
00626     i++;
00627    }
00628   return NULL;
00629 }
00630 
00631 int parseQuery(struct key_value * params, char * qry) {
00632   char * cp;
00633   int l=0;
00634   cp=strtok(qry,"=");
00635   while ((cp) && (l<QRY_MAXPARAMS)) {
00636     params[l].key=cp;
00637     cp=strtok(NULL,"&");
00638     params[l++].value=cp;
00639     if (cp) cp=strtok(NULL,"=");
00640   }
00641  params[l].key=NULL;
00642  return l;
00643 }

Generated on Thu Aug 7 16:18:59 2008 for elphel by  doxygen 1.5.1