• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
get_brightness_adj(unsigned char * image,long size,int * brightness)92 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 
main(int argc,char ** argv)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, g, b;
109   unsigned int i, src_depth;
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 }
202