v4lgrab.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. #include <unistd.h>
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include <fcntl.h>
  19. #include <stdio.h>
  20. #include <sys/ioctl.h>
  21. #include <stdlib.h>
  22. #include <linux/types.h>
  23. #include <linux/videodev.h>
  24. #define FILE "/dev/video0"
  25. /* Stole this from tvset.c */
  26. #define READ_VIDEO_PIXEL(buf, format, depth, r, g, b) \
  27. { \
  28. switch (format) \
  29. { \
  30. case VIDEO_PALETTE_GREY: \
  31. switch (depth) \
  32. { \
  33. case 4: \
  34. case 6: \
  35. case 8: \
  36. (r) = (g) = (b) = (*buf++ << 8);\
  37. break; \
  38. \
  39. case 16: \
  40. (r) = (g) = (b) = \
  41. *((unsigned short *) buf); \
  42. buf += 2; \
  43. break; \
  44. } \
  45. break; \
  46. \
  47. \
  48. case VIDEO_PALETTE_RGB565: \
  49. { \
  50. unsigned short tmp = *(unsigned short *)buf; \
  51. (r) = tmp&0xF800; \
  52. (g) = (tmp<<5)&0xFC00; \
  53. (b) = (tmp<<11)&0xF800; \
  54. buf += 2; \
  55. } \
  56. break; \
  57. \
  58. case VIDEO_PALETTE_RGB555: \
  59. (r) = (buf[0]&0xF8)<<8; \
  60. (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8; \
  61. (b) = ((buf[1] << 2 ) & 0xF8)<<8; \
  62. buf += 2; \
  63. break; \
  64. \
  65. case VIDEO_PALETTE_RGB24: \
  66. (r) = buf[0] << 8; (g) = buf[1] << 8; \
  67. (b) = buf[2] << 8; \
  68. buf += 3; \
  69. break; \
  70. \
  71. default: \
  72. fprintf(stderr, \
  73. "Format %d not yet supported\n", \
  74. format); \
  75. } \
  76. }
  77. int get_brightness_adj(unsigned char *image, long size, int *brightness) {
  78. long i, tot = 0;
  79. for (i=0;i<size*3;i++)
  80. tot += image[i];
  81. *brightness = (128 - tot/(size*3))/3;
  82. return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130);
  83. }
  84. int main(int argc, char ** argv)
  85. {
  86. int fd = open(FILE, O_RDONLY), f;
  87. struct video_capability cap;
  88. struct video_window win;
  89. struct video_picture vpic;
  90. unsigned char *buffer, *src;
  91. int bpp = 24, r, g, b;
  92. unsigned int i, src_depth;
  93. if (fd < 0) {
  94. perror(FILE);
  95. exit(1);
  96. }
  97. if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
  98. perror("VIDIOGCAP");
  99. fprintf(stderr, "(" FILE " not a video4linux device?)\n");
  100. close(fd);
  101. exit(1);
  102. }
  103. if (ioctl(fd, VIDIOCGWIN, &win) < 0) {
  104. perror("VIDIOCGWIN");
  105. close(fd);
  106. exit(1);
  107. }
  108. if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) {
  109. perror("VIDIOCGPICT");
  110. close(fd);
  111. exit(1);
  112. }
  113. if (cap.type & VID_TYPE_MONOCHROME) {
  114. vpic.depth=8;
  115. vpic.palette=VIDEO_PALETTE_GREY; /* 8bit grey */
  116. if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
  117. vpic.depth=6;
  118. if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
  119. vpic.depth=4;
  120. if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
  121. fprintf(stderr, "Unable to find a supported capture format.\n");
  122. close(fd);
  123. exit(1);
  124. }
  125. }
  126. }
  127. } else {
  128. vpic.depth=24;
  129. vpic.palette=VIDEO_PALETTE_RGB24;
  130. if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
  131. vpic.palette=VIDEO_PALETTE_RGB565;
  132. vpic.depth=16;
  133. if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
  134. vpic.palette=VIDEO_PALETTE_RGB555;
  135. vpic.depth=15;
  136. if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
  137. fprintf(stderr, "Unable to find a supported capture format.\n");
  138. return -1;
  139. }
  140. }
  141. }
  142. }
  143. buffer = malloc(win.width * win.height * bpp);
  144. if (!buffer) {
  145. fprintf(stderr, "Out of memory.\n");
  146. exit(1);
  147. }
  148. do {
  149. int newbright;
  150. read(fd, buffer, win.width * win.height * bpp);
  151. f = get_brightness_adj(buffer, win.width * win.height, &newbright);
  152. if (f) {
  153. vpic.brightness += (newbright << 8);
  154. if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
  155. perror("VIDIOSPICT");
  156. break;
  157. }
  158. }
  159. } while (f);
  160. fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height);
  161. src = buffer;
  162. for (i = 0; i < win.width * win.height; i++) {
  163. READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b);
  164. fputc(r>>8, stdout);
  165. fputc(g>>8, stdout);
  166. fputc(b>>8, stdout);
  167. }
  168. close(fd);
  169. return 0;
  170. }