Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
[linux-2.6] / Documentation / video4linux / v4lgrab.c
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 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 }