Based on kernel version 2.6.37. Page generated on 2011-03-22 21:57 EST.
1 /* Simple Video4Linux image grabber. */ 2 /* 3 * Video4Linux Driver Test/Example Framegrabbing Program 4 * 5 * Compile with: 6 * gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab 7 * Use as: 8 * v4lgrab >image.ppm 9 * 10 * Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org> 11 * Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c 12 * with minor modifications (Dave Forrest, drf5n@virginia.edu). 13 * 14 * 15 * For some cameras you may need to pre-load libv4l to perform 16 * the necessary decompression, e.g.: 17 * 18 * export LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so 19 * ./v4lgrab >image.ppm 20 * 21 * see http://hansdegoede.livejournal.com/3636.html for details. 22 * 23 */ 24 25 #include <unistd.h> 26 #include <sys/types.h> 27 #include <sys/stat.h> 28 #include <fcntl.h> 29 #include <stdio.h> 30 #include <sys/ioctl.h> 31 #include <stdlib.h> 32 33 #include <linux/types.h> 34 #include <linux/videodev.h> 35 36 #define VIDEO_DEV "/dev/video0" 37 38 /* Stole this from tvset.c */ 39 40 #define READ_VIDEO_PIXEL(buf, format, depth, r, g, b) \ 41 { \ 42 switch (format) \ 43 { \ 44 case VIDEO_PALETTE_GREY: \ 45 switch (depth) \ 46 { \ 47 case 4: \ 48 case 6: \ 49 case 8: \ 50 (r) = (g) = (b) = (*buf++ << 8);\ 51 break; \ 52 \ 53 case 16: \ 54 (r) = (g) = (b) = \ 55 *((unsigned short *) buf); \ 56 buf += 2; \ 57 break; \ 58 } \ 59 break; \ 60 \ 61 \ 62 case VIDEO_PALETTE_RGB565: \ 63 { \ 64 unsigned short tmp = *(unsigned short *)buf; \ 65 (r) = tmp&0xF800; \ 66 (g) = (tmp<<5)&0xFC00; \ 67 (b) = (tmp<<11)&0xF800; \ 68 buf += 2; \ 69 } \ 70 break; \ 71 \ 72 case VIDEO_PALETTE_RGB555: \ 73 (r) = (buf[0]&0xF8)<<8; \ 74 (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8; \ 75 (b) = ((buf[1] << 2 ) & 0xF8)<<8; \ 76 buf += 2; \ 77 break; \ 78 \ 79 case VIDEO_PALETTE_RGB24: \ 80 (r) = buf[0] << 8; (g) = buf[1] << 8; \ 81 (b) = buf[2] << 8; \ 82 buf += 3; \ 83 break; \ 84 \ 85 default: \ 86 fprintf(stderr, \ 87 "Format %d not yet supported\n", \ 88 format); \ 89 } \ 90 } 91 92 static int get_brightness_adj(unsigned char *image, long size, int *brightness) { 93 long i, tot = 0; 94 for (i=0;i<size*3;i++) 95 tot += image[i]; 96 *brightness = (128 - tot/(size*3))/3; 97 return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130); 98 } 99 100 int main(int argc, char ** argv) 101 { 102 int fd = open(VIDEO_DEV, O_RDONLY), f; 103 struct video_capability cap; 104 struct video_window win; 105 struct video_picture vpic; 106 107 unsigned char *buffer, *src; 108 int bpp = 24, r = 0, g = 0, b = 0; 109 unsigned int i, src_depth = 16; 110 111 if (fd < 0) { 112 perror(VIDEO_DEV); 113 exit(1); 114 } 115 116 if (ioctl(fd, VIDIOCGCAP, &cap) < 0) { 117 perror("VIDIOGCAP"); 118 fprintf(stderr, "(" VIDEO_DEV " not a video4linux device?)\n"); 119 close(fd); 120 exit(1); 121 } 122 123 if (ioctl(fd, VIDIOCGWIN, &win) < 0) { 124 perror("VIDIOCGWIN"); 125 close(fd); 126 exit(1); 127 } 128 129 if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) { 130 perror("VIDIOCGPICT"); 131 close(fd); 132 exit(1); 133 } 134 135 if (cap.type & VID_TYPE_MONOCHROME) { 136 vpic.depth=8; 137 vpic.palette=VIDEO_PALETTE_GREY; /* 8bit grey */ 138 if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { 139 vpic.depth=6; 140 if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { 141 vpic.depth=4; 142 if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { 143 fprintf(stderr, "Unable to find a supported capture format.\n"); 144 close(fd); 145 exit(1); 146 } 147 } 148 } 149 } else { 150 vpic.depth=24; 151 vpic.palette=VIDEO_PALETTE_RGB24; 152 153 if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { 154 vpic.palette=VIDEO_PALETTE_RGB565; 155 vpic.depth=16; 156 157 if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { 158 vpic.palette=VIDEO_PALETTE_RGB555; 159 vpic.depth=15; 160 161 if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { 162 fprintf(stderr, "Unable to find a supported capture format.\n"); 163 return -1; 164 } 165 } 166 } 167 } 168 169 buffer = malloc(win.width * win.height * bpp); 170 if (!buffer) { 171 fprintf(stderr, "Out of memory.\n"); 172 exit(1); 173 } 174 175 do { 176 int newbright; 177 read(fd, buffer, win.width * win.height * bpp); 178 f = get_brightness_adj(buffer, win.width * win.height, &newbright); 179 if (f) { 180 vpic.brightness += (newbright << 8); 181 if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { 182 perror("VIDIOSPICT"); 183 break; 184 } 185 } 186 } while (f); 187 188 fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height); 189 190 src = buffer; 191 192 for (i = 0; i < win.width * win.height; i++) { 193 READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b); 194 fputc(r>>8, stdout); 195 fputc(g>>8, stdout); 196 fputc(b>>8, stdout); 197 } 198 199 close(fd); 200 return 0; 201 }