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
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
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;
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
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
00127
00128
00129
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
00143
00144
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
00179
00180
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)) {
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--;
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
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
00261
00262
00263
00264 int write_png(int png_height, int data[1536], int mode, int colors)
00265 {
00266
00267 png_structp png_ptr;
00268 png_infop info_ptr;
00269
00270 const char clrs[]={1,2,2,4,7,2};
00271
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
00313
00314
00315
00316 for (l=d+1; l<png_height; l++)image[l][i>>1] |= c;
00317
00318 } else if (mode & 2) {
00319 for (l=d+1; l<last; l++) image[l][i>>1] |= c;
00320 for (l=d-1; l>last; l--) image[l][i>>1] |= c;
00321 last=d;
00322
00323 }
00324
00325 }
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
00342 NULL,NULL,NULL);
00343
00344 if (png_ptr == NULL)
00345 {
00346
00347 return (ERROR);
00348 }
00349
00350
00351 info_ptr = png_create_info_struct(png_ptr);
00352 if (info_ptr == NULL)
00353 {
00354
00355 png_destroy_write_struct(&png_ptr, png_infopp_NULL);
00356 return (ERROR);
00357 }
00358
00359
00360
00361
00362 if (setjmp(png_jmpbuf(png_ptr)))
00363 {
00364
00365
00366 png_destroy_write_struct(&png_ptr, &info_ptr);
00367 return (ERROR);
00368 }
00369
00370
00371
00372
00373
00374 png_init_io(png_ptr, stdout);
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 png_set_IHDR(png_ptr,
00394 info_ptr,
00395 256,
00396 png_height,
00397 4,
00398 PNG_COLOR_TYPE_PALETTE,
00399 PNG_INTERLACE_NONE,
00400 PNG_COMPRESSION_TYPE_BASE,
00401 PNG_FILTER_TYPE_BASE);
00402
00403
00404
00405
00406
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),
00415 NULL);
00416
00417
00418
00419
00420
00421
00422 #if 0
00423 sig_bit.gray = 1;
00424
00425 sig_bit.red = 1;
00426 sig_bit.green = 1;
00427 sig_bit.blue = 1;
00428
00429 sig_bit.alpha = 1;
00430 png_set_sBIT(png_ptr, info_ptr, sig_bit);
00431 #endif
00432
00433
00434
00435
00436
00437
00438
00439 #if 0
00440 text_ptr[0].key = "Title";
00441 text_ptr[0].text = "Histogram";
00442 text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
00443 text_ptr[1].key = "Author";
00444 text_ptr[1].text = "Elphel";
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";
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
00458
00459
00460
00461
00462 png_write_info(png_ptr, info_ptr);
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
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
00522
00523
00524
00525
00526
00527
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
00536 png_write_image(png_ptr, row_pointers);
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546 png_write_end(png_ptr, info_ptr);
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 png_destroy_write_struct(&png_ptr, &info_ptr);
00564
00565
00566
00567
00568
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]){
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;
00594 }
00595
00596 char * paramValue(struct key_value * params, char * skey) {
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 }