00001 #include <stdlib.h>
00002 #include <stdio.h>
00003 #include <unistd.h>
00004 #include <sys/ioctl.h>
00005 #include <sys/types.h>
00006 #include <sys/stat.h>
00007 #include <fcntl.h>
00008 #include <math.h>
00009
00010 #include <asm/elphel/autoexp.h>
00011 #include <asm/elphel/hist.h>
00012
00013 #include <sys/mman.h>
00014 #include <asm/elphel/c313a.h>
00015
00016
00017
00018 #include "libpng/png.h"
00019
00020 #define HIST_SIZE 256 * 4 * 4
00021
00022 #define HPNG_PLOT_BARS 1
00023 #define HPNG_CONNECT_DOTS 2
00024 #define HPNG_FILL_ZEROS 4
00025 #define HPNG_LIN_INTERP 8
00026 #define HPNG_RUN_SQRT 16
00027 struct autoexp_t autoexp;
00028 int write_png(char *file_name, int height, int data[1024], int mode, int colors);
00029 int main(argc, argv)
00030 int argc;
00031 char *argv[];
00032 {
00033 int hists[1536];
00034 int rava[256];
00035
00036 int autoexp_fd;
00037 int i,j,k,a,l;
00038
00039 double dscale,dcoeff;
00040 int coeff;
00041 int png_height;
00042 int ww,wh;
00043 int devfd;
00044 int mode;
00045 int colors=57;
00046 int lastmiddle_i,newmiddle_i;
00047 int rav=0;
00048 int z;
00049 void *_map;
00050 const char colors_calc[]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,0xa,0xb,0xc,0xd,0xe,0xf,
00051 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,
00052 6, 7, 6, 7, 6, 7, 6, 7,0xe,0xf,0xe,0xf,0xe,0xf,0xe,0xf,
00053 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf};
00054 if (argc<5) {printf("pnghist height scale mode colors average"); return 0;}
00055 png_height=atoi(argv[1]);
00056 if (png_height>256) png_height=256;
00057 dscale=atof(argv[2]);
00058 mode=atoi(argv[3]);
00059 colors=atoi(argv[4]) & 0x3f;
00060
00061
00062 rav=atoi(argv[5]);
00063
00064
00065 if ((devfd = open("/dev/ccam_img", O_RDONLY)) < 0) {printf("Device busy (%s)\r\n", "/dev/ccam_img"); return -1;}
00066
00067 ww=ioctl(devfd, _CCCMD( CCAM_RPARS , P_ACTUAL_WIDTH), 0);
00068 wh=ioctl(devfd, _CCCMD( CCAM_RPARS , P_ACTUAL_HEIGHT), 0);
00069 close (devfd);
00070
00071
00072
00073 autoexp_fd = open(AUTOEXP_DEV_NAME, O_RDONLY);
00074 if(autoexp_fd < 0) {
00075 printf("open %s failed - may be busy, or not started\r\n", AUTOEXP_DEV_NAME);
00076 return -1;
00077 }
00078 z = ioctl(autoexp_fd, _IO(IOC_AUTOEXP_GET, 0x00), &autoexp);
00079
00080
00081
00082 if((_map = mmap(NULL, HIST_SIZE, PROT_READ, MAP_FIXED | MAP_SHARED, autoexp_fd, 0)) == MAP_FAILED) {
00083 printf("mmap %s failed - may be busy, or not started\r\n", AUTOEXP_DEV_NAME);
00084 return -1;
00085 }
00086 memcpy (hists,_map,HIST_SIZE);
00087 close (autoexp_fd);
00088 #if 0
00089 fd = open("/tmp/histogram", O_RDONLY);
00090 if(fd <= 0) {
00091 printf("No histogram file (%s)\r\n", "/tmp/histogram");
00092 return -1;
00093 }
00094 read(fd, hsz, 4);
00095 ww=(ww*hsz[0])/100;
00096 wh=(wh*hsz[1])/100;
00097 read(fd, hists, HIST_SIZE);
00098 close (fd);
00099 #endif
00100 ww=(ww*autoexp.width)/100;
00101 wh=(wh*autoexp.height)/100;
00102 dcoeff=(png_height*1024)/(dscale*ww*wh);
00103 coeff=dcoeff*65536;
00104 #ifdef PNGHISTDEBUG
00105 printf ("w=%d, h=%d\n",ww,wh);
00106 for (i=0;i<1024;i++) {
00107 printf ("%5d ",hists[i]);
00108 if ((i & 0x0f)== 0x0f) printf ("\n");
00109 if ((i & 0xff) == 0xff) printf ("-----------------------------------------------\n");
00110
00111 }
00112 printf ("===============================================\n");
00113 #endif
00114
00115
00116
00117 if ((mode & (HPNG_FILL_ZEROS | HPNG_LIN_INTERP)) | (rav>1)) {
00118 for (j=0;j<4;j++) if (colors_calc[colors] & (1<<j)) {
00119 lastmiddle_i=255;
00120 i=255;
00121 while ((hists[i+(j<<8)]==0) && (i>0)) i--;
00122 while (i>0) {
00123 k=i;
00124 i--;
00125 while ((i>=0) && (hists[i+(j<<8)]==0)) i--;
00126 if ((k-i)>1) {
00127 a=hists[k+(j<<8)]/(k-i);
00128 for (l=k;l>i;l--) hists[l+(j<<8)] = a;
00129 }
00130 if ((mode & HPNG_LIN_INTERP) | (rav>1)) {
00131 newmiddle_i= (k+i+1)/2;
00132 for (l=lastmiddle_i-1;l>newmiddle_i;l--) {
00133 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);
00134 }
00135 lastmiddle_i=newmiddle_i;
00136
00137 }
00138 }
00139
00140 if (rav>0) {
00141 k=0;
00142 l=0;
00143 for (i=0;i<256;i++) {
00144 rava[i]=hists[i+(j<<8)];
00145 k+=rava[i];
00146 if ((i-rav)>=0) k-=rava[i-rav];
00147 else l++;
00148 hists[i+(j<<8)]=k/l;
00149 }
00150 }
00151
00152
00153 }
00154 }
00155
00156 if (colors & 0x10) for (i=0;i<256;i++) hists[i+1024]=(hists[i]+hists[i+256]+hists[i+512]+hists[i+768])>>2;
00157
00158 if (colors & 0x20) for (i=0;i<256;i++) hists[i+1280]=(hists[i+256]+hists[i+512])>>1;
00159
00160 if (mode & HPNG_RUN_SQRT) {
00161 dcoeff=sqrt((32768.0*png_height)/coeff);
00162 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;
00163 }
00164
00165 for (j=0;j<6;j++) if (colors & (1 << j)) for (i=0;i<256;i++) {
00166 hists[i+(j<<8)]=(hists[i+(j<<8)]*coeff) >> 16;
00167 if (hists[i+(j<<8)] > (png_height-1)) hists[i+(j<<8)] = png_height-1;
00168 }
00169
00170 #ifdef PNGHISTDEBUG
00171 printf ("w=%d, h=%d\n",ww,wh);
00172 for (i=0;i<1536;i++) {
00173 printf ("%5d ",hists[i]);
00174 if ((i & 0x0f)== 0x0f) printf ("\n");
00175 }
00176 #endif
00177
00178
00179 write_png("/var/html/hist.png", png_height, hists, mode, colors);
00180
00181 return 0;
00182 }
00183 #define ERROR -1
00184 #define OK 0
00185
00186
00187
00188
00189 int write_png(char *file_name, int png_height, int data[1536], int mode, int colors)
00190 {
00191 FILE *fp;
00192 png_structp png_ptr;
00193 png_infop info_ptr;
00194
00195 const char clrs[]={1,2,2,4,7,2};
00196
00197 unsigned char cpalette[]= {0, 0, 0,
00198 0xff,0, 0,
00199 0, 0xff,0,
00200 0xff,0xff,0,
00201 0, 0, 0xff,
00202 0xff,0, 0xff,
00203 0, 0xff,0xff,
00204 0xff,0xff,0xff,
00205 0, 0, 0,
00206 0x80,0, 0,
00207 0, 0x80,0,
00208 0x80,0x80,0,
00209 0, 0, 0x80,
00210 0x80,0, 0x80,
00211 0, 0x80,0x80,
00212 0x80,0x80,0x80};
00213 unsigned char ctransparency[]={0, 255,255,255,255,255,255,255,
00214 255,255,255,255,255,255,255,255};
00215 png_bytep trans = (png_bytep) ctransparency;
00216
00217 png_colorp palette = (png_colorp ) cpalette;
00218
00219
00220 png_uint_32 k;
00221 png_uint_32 height=png_height;
00222 png_uint_32 width=256;
00223 png_uint_32 bytes_per_pixel=1;
00224 png_byte image[256][256];
00225 png_bytep row_pointers[256];
00226 int i,j,c0,c,d,l,last;
00227 if (height>256) height=256;
00228
00229 memset(image, 0, sizeof(image));
00230 for (j=0;j<6;j++) if (colors & (1 << j)){
00231 c0= clrs[j];
00232 last=png_height-1;
00233 for (i=0;i<256;i++) {
00234 c=c0 << ((i&1)?0:4);
00235 d=png_height-1-data[i+(j<<8)];
00236 if (d<=0) d=0;
00237 if (d>=png_height) d=png_height-1;
00238 image[d][i>>1] |= c;
00239 if (mode & 1){
00240
00241
00242
00243
00244 for (l=d+1; l<png_height; l++)image[l][i>>1] |= c;
00245
00246 } else if (mode & 2) {
00247 for (l=d+1; l<last; l++) image[l][i>>1] |= c;
00248 for (l=d-1; l>last; l--) image[l][i>>1] |= c;
00249 last=d;
00250
00251 }
00252
00253 }
00254 }
00255
00256
00257 fp = fopen(file_name, "wb");
00258 if (fp == NULL)
00259 return (ERROR);
00260
00261
00262
00263
00264
00265
00266
00267 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
00268 NULL,NULL,NULL);
00269
00270 if (png_ptr == NULL)
00271 {
00272 fclose(fp);
00273 return (ERROR);
00274 }
00275
00276
00277 info_ptr = png_create_info_struct(png_ptr);
00278 if (info_ptr == NULL)
00279 {
00280 fclose(fp);
00281 png_destroy_write_struct(&png_ptr, png_infopp_NULL);
00282 return (ERROR);
00283 }
00284
00285
00286
00287
00288 if (setjmp(png_jmpbuf(png_ptr)))
00289 {
00290
00291 fclose(fp);
00292 png_destroy_write_struct(&png_ptr, &info_ptr);
00293 return (ERROR);
00294 }
00295
00296
00297
00298
00299 png_init_io(png_ptr, fp);
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 png_set_IHDR(png_ptr,
00319 info_ptr,
00320 256,
00321 png_height,
00322 4,
00323 PNG_COLOR_TYPE_PALETTE,
00324 PNG_INTERLACE_NONE,
00325 PNG_COMPRESSION_TYPE_BASE,
00326 PNG_FILTER_TYPE_BASE);
00327
00328
00329
00330
00331
00332 png_set_PLTE(png_ptr,
00333 info_ptr,
00334 palette,
00335 PNG_MAX_PALETTE_LENGTH);
00336 png_set_tRNS(png_ptr,
00337 info_ptr,
00338 trans,
00339 sizeof(trans),
00340 NULL);
00341
00342
00343
00344
00345
00346
00347 #if 0
00348 sig_bit.gray = 1;
00349
00350 sig_bit.red = 1;
00351 sig_bit.green = 1;
00352 sig_bit.blue = 1;
00353
00354 sig_bit.alpha = 1;
00355 png_set_sBIT(png_ptr, info_ptr, sig_bit);
00356 #endif
00357
00358
00359
00360
00361
00362
00363
00364 #if 0
00365 text_ptr[0].key = "Title";
00366 text_ptr[0].text = "Histogram";
00367 text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
00368 text_ptr[1].key = "Author";
00369 text_ptr[1].text = "Elphel";
00370 text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
00371 text_ptr[2].key = "Description";
00372 text_ptr[2].text = "color histograms for the camera image/video";
00373 text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt;
00374 #ifdef PNG_iTXt_SUPPORTED
00375 text_ptr[0].lang = NULL;
00376 text_ptr[1].lang = NULL;
00377 text_ptr[2].lang = NULL;
00378 #endif
00379 png_set_text(png_ptr, info_ptr, text_ptr, 3);
00380 #endif
00381
00382
00383
00384
00385
00386
00387 png_write_info(png_ptr, info_ptr);
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439 #if 0
00440 if (interlacing)
00441 number_passes = png_set_interlace_handling(png_ptr);
00442 else
00443 number_passes = 1;
00444 #endif
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
00455 png_error (png_ptr, "Image is too tall to process in memory");
00456
00457 for (k = 0; k < height; k++)
00458 row_pointers[k] = (png_bytep) image + k*width*bytes_per_pixel;
00459
00460
00461 png_write_image(png_ptr, row_pointers);
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471 png_write_end(png_ptr, info_ptr);
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 png_destroy_write_struct(&png_ptr, &info_ptr);
00489
00490
00491 fclose(fp);
00492
00493
00494 return (OK);
00495 }