apps/png/pnghist.c

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

Generated on Fri Nov 28 00:06:22 2008 for elphel by  doxygen 1.5.1