📄 qcset.c
字号:
/* }}} *//* {{{ [fold] void pnm_close(void) */void pnm_close(void){ fclose(pnm_file); pnm_file = NULL;}/* }}} *//* {{{ [fold] void pnm_getpixel(unsigned char *r, unsigned char *g, unsigned char *b) */void pnm_getpixel(unsigned char *r, unsigned char *g, unsigned char *b){ *r = getc(pnm_file); *g = getc(pnm_file); *b = getc(pnm_file);}/* }}} *//* {{{ [fold] void compute_lut(unsigned int (*hist)[256], unsigned char (*lut)[256]) *//* Compute lookup-table `lut' (256 elements) for image equalization * based on given image color histogram `hist'. The LUT is also smoothed and normalized. */void compute_lut(unsigned int (*hist)[256], unsigned char *lut){ static const int len = 64; /* Smoothing kernel length, must be less than 255 */ static const double p = 3.0 - 1; /* Smoothing kernel order */ unsigned int sum; double dlut[256]; double min, max; double norm, v, r; int i,j; /* Compute lookup-table based on the histogram */ sum = 0; for (i=0; i<256; i++) { dlut[i] = sum; sum += (*hist)[i]; } /* Normalize lookup-table */ norm = 255.0 / dlut[255]; for (i=0; i<256; i++) { dlut[i] *= norm; } /* Compute normalization factor for smoothing kernel */ norm = 0.0; for (j=-len; j<=len; j++) { norm += pow(j+len, p) * pow(len-j, p); } norm = 1.0 / norm; /* Smooth the lookup table, handle edges with point-symmetric reflections */ min = dlut[0]; max = dlut[255]; for (i=0; i<256; i++) { r = 0.0; for (j=-len; j<=len; j++) { int x = i + j; if (x<0) { v = min - dlut[-x]; } else if (x>255) { v = 2*max - dlut[511-x]; } else { v = dlut[x]; } r += v * norm * pow(j+len, p) * pow(len-j, p); } lut[i] = (unsigned char)CLIP(r+0.5, 0.0, 255.0); }}/* }}} *//* {{{ [fold] main() */int main(int argc, char *argv[]){ int fd = 0,i,j,r,l,l2,c; char *device = "/dev/video0"; /* Default should not be /dev/video which may be subdir */ char *argp; struct video_capability vidcap; struct video_window vidwin; struct video_channel vidchan; struct video_picture vidpic; if (argc<=1) help(); if (argv && argv[0]) progname = argv[0]; if (argv && argv[0] && argv[1] && argv[1][0]=='-' && argv[1][1]=='h') help(); while (*++argv) { if (argv[0][0]=='/' || argv[0][0]=='.') { /* Device filename given */ if (fd) close(fd); device = argv[0]; fd = 0; } else { if (fd==0 && (argv[0][0]!='-' && argv[0][1]!='G') ) { /* Open the device, if it wasn't yet opened. * Do not try to modify any settings, because if other applications have * already the camera open and are capturing, it might disturb them under 2.6.x */ fd = open(device,O_RDWR); if (fd==-1) error("can not open %s",device); r = ioctl(fd, VIDIOCGCAP, &vidcap); if (r != 0) error("ioctl VIDIOCGCAP"); r = ioctl(fd, VIDIOCGWIN, &vidwin); if (r != 0) error("ioctl VIDIOCGWIN"); vidchan.channel = 0; r = ioctl(fd, VIDIOCGCHAN, &vidchan); if (r != 0) error("ioctl VIDIOCGCHAN"); r = ioctl(fd, VIDIOCGPICT, &vidpic); if (r != 0) error("ioctl VIDIOCGPICT"); } if (argv[0][0]=='-') { /* Option given */ argp = NULL; c = 0; if (argv[0][1] && argv[0][2]) { argp = &argv[0][2]; } else { if (argv[1]) { argp = argv[1]; c = 1; } } i = argp ? atoi(argp) : 0; switch (argv[0][1]) { case 'h': /* Help */ help(); /* Never returns */ case 'i': /* Information */ print_cap(&vidcap,&vidwin,&vidchan,&vidpic); break; case 'r': /* Dump known chip registers */ print_regs(fd, 0); break; case 'a': /* Dump all chip registers */ print_regs(fd, 1); break; case 'b': /* Brightness */ if (!argp) error("missing brightness value"); vidpic.brightness = i; r = ioctl(fd, VIDIOCSPICT, &vidpic); if (r!=0) error("ioctl VIDIOCSPICT"); argv += c; break; case 'u': /* Hue */ if (!argp) error("missing hue value"); vidpic.hue = i; r = ioctl(fd, VIDIOCSPICT, &vidpic); if (r!=0) error("ioctl VIDIOCSPICT"); argv += c; break; case 'o': /* Color */ if (!argp) error("missing color value"); vidpic.colour = i; r = ioctl(fd, VIDIOCSPICT, &vidpic); if (r!=0) error("ioctl VIDIOCSPICT"); argv += c; break; case 'c': /* Contrast */ if (!argp) error("missing contrast value"); vidpic.contrast = i; r = ioctl(fd, VIDIOCSPICT, &vidpic); if (r!=0) error("ioctl VIDIOCSPICT"); argv += c; break; case 'w': /* Whiteness */ if (!argp) error("missing whiteness value"); vidpic.whiteness = i; r = ioctl(fd, VIDIOCSPICT, &vidpic); if (r!=0) error("ioctl VIDIOCSPICT"); argv += c; break; case 's': /* Shutter */ if (!argp) error("missing shutter value"); r = ioctl(fd, VIDIOCQCSSHUTTERVAL, &i); if (r!=0) error("ioctl VIDIOCQCSSHUTTERVAL"); argv += c; break; case 'g': case 'e': { struct qc_userlut userlut; memset(&userlut, 0, sizeof(userlut)); if (!argp) error("missing parameter to option `-%c'", argv[0][1]); switch (argp[0]) { case '?': /* Display software lut settings */ userlut.flags |= QC_USERLUT_VALUES; r = ioctl(fd, VIDIOCQCGUSERLUT, &userlut); if (r!=0) error("ioctl VIDIOCGUSERLUT"); printf("Software lookup-table status: %s\n", (userlut.flags & QC_USERLUT_ENABLE) ? "Enabled" : "Disabled"); printf("\tRed table:\n"); for (i=0; i<256; i++) { printf("%i", userlut.lut[QC_LUT_RED + i]); if (i!=255) printf(","); if (((i+1) % 20)==0 || i==255) printf("\n"); } printf("\tGreen table:\n"); for (i=0; i<256; i++) { printf("%i", userlut.lut[QC_LUT_GREEN + i]); if (i!=255) printf(","); if (((i+1) % 20)==0 || i==255) printf("\n"); } printf("\tBlue table:\n"); for (i=0; i<256; i++) { printf("%i", userlut.lut[QC_LUT_BLUE + i]); if (i!=255) printf(","); if (((i+1) % 20)==0 || i==255) printf("\n"); } break; case '+': /* Enable lookup-table */ userlut.flags |= QC_USERLUT_ENABLE; /* Continue */ case '-': /* Disable lookup-table */ r = ioctl(fd, VIDIOCQCSUSERLUT, &userlut); if (r!=0) error("ioctl VIDIOCSUSERLUT"); break; default: switch (argv[0][1]) { case 'g': { /* Gamma */ double gr = 0.55; double gg = 0.55; double gb = 0.55; double wr = 1.0; double wg = 1.0; double wb = 1.0; r = sscanf(argp, "%lg:%lg:%lg:%lg:%lg:%lg", &gr, &gg, &gb, &wr, &wg, &wb); if (r!=1 && r!=3 && r!=6) error("bad number of arguments for -g (must be 1, 3, or 6)"); if (r < 3) { gg = gr; gb = gr; } for (i=0; i<256; i++) { userlut.lut[QC_LUT_RED + i] = (unsigned char)CLIP(pow(i/256.0, gr)*256.0*wr+0.5, 0.0, 255.0); userlut.lut[QC_LUT_GREEN + i] = (unsigned char)CLIP(pow(i/256.0, gg)*256.0*wg+0.5, 0.0, 255.0); userlut.lut[QC_LUT_BLUE + i] = (unsigned char)CLIP(pow(i/256.0, gb)*256.0*wb+0.5, 0.0, 255.0); } userlut.flags |= QC_USERLUT_ENABLE | QC_USERLUT_VALUES; r = ioctl(fd, VIDIOCQCSUSERLUT, &userlut); if (r!=0) error("ioctl VIDIOCSUSERLUT"); } case 'e': { /* Static equalization */ unsigned int width, height; unsigned char r, g, b; unsigned int cnt_red[256], cnt_green[256], cnt_blue[256]; memset(cnt_red, 0, sizeof(cnt_red)); memset(cnt_green, 0, sizeof(cnt_green)); memset(cnt_blue, 0, sizeof(cnt_blue)); pnm_open(argp, &width, &height); /* Compute histograms for each color channel */ for (i=0; i<height; i++) for (j=0; j<width; j++) { pnm_getpixel(&r, &g, &b); cnt_red [r]++; cnt_green[g]++; cnt_blue [b]++; } pnm_close(); /* Compute lookup tables based on the histograms */ compute_lut(&cnt_red, &userlut.lut[QC_LUT_RED]); compute_lut(&cnt_green, &userlut.lut[QC_LUT_GREEN]); compute_lut(&cnt_blue, &userlut.lut[QC_LUT_BLUE]); /* Send the new lookup table to the driver */ userlut.flags |= QC_USERLUT_ENABLE | QC_USERLUT_VALUES; r = ioctl(fd, VIDIOCQCSUSERLUT, &userlut); if (r!=0) error("ioctl VIDIOCSUSERLUT"); break; } default: error("this can't happen"); } } argv += c; break; } case 'G': { struct qc_userlut userlut; double gr = 0.55; double gg = 0.55; double gb = 0.55; double wr = 1.0; double wg = 1.0; double wb = 1.0; if(!argp) error("Missing r:g:b:r:g:b options"); memset(&userlut, 0, sizeof(userlut)); r = sscanf(argp, "%lg:%lg:%lg:%lg:%lg:%lg", &gr, &gg, &gb, &wr, &wg, &wb); if (r!=1 && r!=3 && r!=6) error("bad number of arguments for -G (must be 1, 3, or 6)"); if (r < 3) { gg = gr; gb = gr; } for (i=0; i<256; i++) { userlut.lut[QC_LUT_RED + i] = (unsigned char)CLIP(pow(i/256.0, gr)*256.0*wr+0.5, 0.0, 255.0); userlut.lut[QC_LUT_GREEN + i] = (unsigned char)CLIP(pow(i/256.0, gg)*256.0*wg+0.5, 0.0, 255.0); userlut.lut[QC_LUT_BLUE + i] = (unsigned char)CLIP(pow(i/256.0, gb)*256.0*wb+0.5, 0.0, 255.0); } printf("Software lookup-table status: %s\n", (userlut.flags & QC_USERLUT_ENABLE) ? "Enabled" : "Disabled"); printf("static unsigned char userlut_contents[QC_LUT_SIZE] = {\n/* Red */\n"); for (i=0; i<256; i++) { printf("%4i,", userlut.lut[QC_LUT_RED + i]); if (((i+1) % 12)==0) printf("\n"); if (i==255) printf("\n"); } printf("/* Green */\n"); for (i=0; i<256; i++) { printf("%4i,", userlut.lut[QC_LUT_GREEN + i]); if (((i+1) % 12)==0) printf("\n"); if (i==255) printf("\n"); } printf("/* Blue */\n"); for (i=0; i<256; i++) { printf("%4i", userlut.lut[QC_LUT_BLUE + i]); if (i!=255) printf(","); if (((i+1) % 12)==0) printf("\n"); //if (i==255) printf("\n"); } printf("\n};\n"); exit(0); } default: error("invalid option"); } } else { /* Configuration given */ for (l=0; argv[0][l]!=0 && argv[0][l]!='=' && argv[0][l]!='?'; l++); for (i=0; i<SIZE(ioctlinfo); i++) { if (memcmp(ioctlinfo[i].name, argv[0], MIN(l,strlen(ioctlinfo[i].name)))==0) break; } if (i>=SIZE(ioctlinfo)) error("invalid configuration name"); if(!strncmp(argv[0], "reg", 3)) { int add, val; if(sscanf(argv[0], "reg%X=%X", &add, &val) == 2) { printf("set reg%X = %X", add, val); add &= 0xFFFF; add |= ((val & 0xFFFF) << 16); printf("add = %08X\n", add); r = ioctl(fd, VIDIOCQCSSTV, &add); if (r != 0) error("error\n"); else printf("\n"); } else if(sscanf(argv[0], "reg%X", &add) == 1) { printf("get reg%X = ", add); r = ioctl(fd, VIDIOCQCGSTV, &add); if (r != 0) error("error\n"); else { printf(" %02X\n", add >> 16); } } } else if (argv[0][l]=='?') { /* Display configuration */ r = ioctl(fd, ioctlinfo[i].get, &c); if (r != 0) error("ioctl get %s", ioctlinfo[i].name); r = 0; /* Not first flag? */ if (ioctlinfo[i].flags!=NULL) { for (j=0; ioctlinfo[i].flags[j].name!=NULL; j++) { l2 = ioctlinfo[i].flags[j].val; if (c==l2 || (ioctlinfo[i].bitfield && l2!=0 && (c&l2)==l2)) { if (r!=0) printf(","); r = 1; printf(ioctlinfo[i].flags[j].name); if (ioctlinfo[i].bitfield) c &= ~l2; } } } if (r==0 || (ioctlinfo[i].bitfield && c!=0)) printf("%i", c); printf("\n"); } else if (argv[0][l]=='=') { /* Set configuration */ c = 0; while (argv[0][l]!=0) { r = 0; /* Is it a recognized string? */ for (l2=l+1; argv[0][l2]!=0 && argv[0][l2]!=','; l2++); if (ioctlinfo[i].flags!=NULL) { for (j=0; ioctlinfo[i].flags[j].name!=NULL; j++) { if (strlen(ioctlinfo[i].flags[j].name)==(l2-l-1) && memcmp(ioctlinfo[i].flags[j].name, &argv[0][l+1], l2-l-1)==0) { c |= ioctlinfo[i].flags[j].val; r = 1; break; } } } if (r==0) { if (!isdigit(argv[0][l+1])) error("unrecognized option parameter"); c |= atoi(&argv[0][l+1]); } l = l2; if (!ioctlinfo[i].bitfield && argv[0][l]!=0) error("multiple flags given for a non-bitfield option"); } r = ioctl(fd, ioctlinfo[i].set, &c); if (r != 0) error("ioctl set %s", ioctlinfo[i].name); printf("%i\n", c); } else { error("invalid configuration request type"); } } } } close(fd); return 0;}/* }}} *//* End of file */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -