[cpia] Do you know other applications using usb WebCamII?

Jacob Nikom nikom@merl.com
Mon, 08 May 2000 16:14:28 -0400


Hi Kali,

Thank you very much for your help. I was able to fix the problem
in the code and now the program communicates with the camera and 
saves the images in .ppm format.

Also, it became shorter. I got rid of duplicate operations and 
unnecessary include files, trying to get it simpler and shorter
(currently it has less than 100 lines):

//===== start of the file v4lgrab.c =====
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

#include <sys/ioctl.h>

#include <linux/videodev.h>

#include <errno.h>

#define IMAGE_DEPTH   24

#define IMAGE_WIDTH  352
#define IMAGE_HEIGHT 288

#define IMAGE_SIZE   (IMAGE_HEIGHT*IMAGE_WIDTH) * (IMAGE_DEPTH/8)

struct video_window     vid_win;
struct video_picture    vid_pic;
struct video_capability vid_caps;

int main()
{
  unsigned char buffer[IMAGE_SIZE];
  char header[100];
  int read_size;
  int dev, out_raw, write_raw_size;
  int out_ppm, write_ppm_size, write_ppm_header;

  if ((dev = open ("/dev/video", O_RDWR)) < 0)
  {
          perror("/dev/video");
          exit(1);
  }

  vid_pic.palette = VIDEO_PALETTE_RGB24; // from videodev.h
  vid_pic.depth = IMAGE_DEPTH;

  if (ioctl (dev, VIDIOCSPICT, &vid_pic))
  {
    perror("wrong palette/depth");
    exit( 1 );
  }

  vid_win.x = 0;
  vid_win.y = 0;
  vid_win.width  = IMAGE_WIDTH;
  vid_win.height = IMAGE_HEIGHT;

  if (ioctl (dev, VIDIOCSWIN, &vid_win) == -1) 
  {
    perror ("ioctl (VIDIOCSWIN)");
    exit( 1 );
  }

  errno = 0;
  if ((read_size = read(dev, buffer, IMAGE_SIZE)) <= 0 )
  {
    if (errno != 0 && errno != EINTR)
    {
      perror("Error read image\n");
      exit( 1 );
    }
  }

  // closing the video device
  close(dev);

  // create output file for .ppm format
  if ((out_ppm = open("outfile.ppm", O_WRONLY | O_CREAT, 0644)) == -1)
  {
    fprintf( stderr, "open outfile.ppm failed: %d\n", errno );
    exit( 1 );
  }

  // create .ppm header
  sprintf( header, "P6\n%d %d\n%d\n", vid_win.width, vid_win.height,
255);

  /* Write .ppm header to file */
  if ((write_ppm_header = write(out_ppm, header, strlen(header))) < 0)
  {
    fprintf( stderr, "write outfile.raw header failed: %d\n", errno );
    exit( 1 );
  }

  // write the image data to the .ppm file
  if ((write_ppm_size = write(out_ppm, buffer, read_size)) < 0)
  {
    fprintf( stderr, "write outfile.ppm failed: %d\n", errno );
    exit( 1 );
  }

  printf("write into file outfile.ppm : %d\n", write_ppm_size );

  // closing output .ppm file
  close(out_ppm);
}
// ==== end of the file v4lgrab.c ====

Do you think it could be simplify further?

Regards,

Jacob Nikom


Kali Griffin wrote:
> 
> How did you change it to make it produce a ppm file?
> 
> It produces RGB or BGR based on your hardware.
> 
> To change the RGB file to a ppm file you must run
> a program called: rawtoppm
> 
> usage:
> 
>    rawtoppm 352 288 output.raw > outty.ppm
> 
> The 352 and 288 are the image's width and height.
> 
> -kali
> 
> On Fri, 5 May 2000, Jacob Nikom wrote:
> 
> > Hi Kali,
> >
> > Thank you very much for your program.  I tried to use it
> > (I called it v4lcap.c).  I was able to compile and run it
> > successfully, however I got strange output.
> >
> > First, I changed it to produce .ppm file which I could
> > view using "display" or "xv". It produced the file, but
> > strange one. It looks like it is the  output from interlaced
> > camera with only one field captured.
> >
> > I changed it to use writeRGBStream routine, but it
> > did not change anything.  I attached this image file
> > converted to .gif format which I compared visually with
> > my .ppm file (they looked identically).
> >
> > I know my .ppm subroutine works correctly, so something
> > different should be with capture. Do you have such an
> > experience? Do you know what should I change to get
> > the correct image?
> >
> > Thank you very much,
> >
> > Jacob Nikom
> >
> > Here my attachment - output.gif file
> >
> > Kali Griffin wrote:
> > >
> > > here is a simple little program that outputs RGB.  Based on your
> > > hardware it may output BGR.  Youll know when you look at the picture.
> > >
> > > If you do get BGR, then you can replace the write() call with the
> > > function writeRGBStream() that I included and that will do the
> > > write()'s correctly.
> > >
> > > To convert it to a ppm use the program rawtoppm.  It should come with
> > > your linux distribution. If you need help with this part, then let me
> > > know.
> > >
> > > Then to view, look at the ppm file in the gimp or something.  if the color
> > > is screwed up, then youre gettin BGR.  Have fun.
> > >
> > > -kali
> > >
> > > On Fri, 5 May 2000, Jacob Nikom wrote:
> > >
> > > > Yes Kali,
> > > >
> > > > I think gqcam uses video4linux interface and I want to use it.
> > > > If you could provide the code of your short example, I would
> > > > appreciate it very much.
> > > >
> > > > Thank you,
> > > >
> > > > Jacob Nikom
> > > >
> > > >
> > > >
> > > > Kali Griffin wrote:
> > > > >
> > > > > do you want one using the video4linux interface?  if so, I have
> > > > > a very short program that does this, it serves as a good example.
> > > > > -kali
> > > > >
> > > > > On Thu, 4 May 2000, Jacob Nikom wrote:
> > > > >
> > > > > > Hi,
> > > > > >
> > > > > > I was able to install WebCamII on 2.3.99-pre5. The application,
> > > > > > gqcam runs now very well. Do you know other, simplier applcations
> > > > > > than gqcam (without so much GUI) which also use WebCamII?
> > > > > >
> > > > > > For example, simple one which takes one frame and saves it in .ppm.
> > > > > >
> > > > > > Thank you,
> > > > > >
> > > > > > Jacob
> > > > > >
> > > > > > _______________________________________________
> > > > > > cpia mailing list  -  cpia@risc.uni-linz.ac.at
> > > > > > http://mailman.risc.uni-linz.ac.at/mailman/cgi-bin/listinfo/cpia
> > > > > >
> > > >
> > >
> > >   ------------------------------------------------------------------------
> > > /*
> > >    Simple Video For Linux Capture Application
> > >    Author: Kali Griffin
> > >
> > > */
> > >
> > > #include <stdio.h>
> > >
> > > #include <sys/ioctl.h>
> > > #include <fcntl.h>
> > > #include <sys/types.h>
> > > #include <unistd.h>
> > > #include <linux/videodev.h>
> > > #include <signal.h>
> > >
> > > #define DEVICE_NAME "/dev/video"
> > > #define IMAGE_DEPTH 24
> > >
> > > #define IMAGE_WIDTH  352
> > > #define IMAGE_HEIGHT 288
> > > /*     176x144 QCIF
> > >        352x288 CIF   */
> > >
> > > #define IMAGE_PIXEL_FORMAT VIDEO_PALETTE_RGB24
> > > /*
> > >   Formats:
> > >   VIDEO_PALETTE_GREY      1        Linear greyscale
> > >   VIDEO_PALETTE_HI240     2        High 240 cube (BT848)
> > >   VIDEO_PALETTE_RGB565    3        565 16 bit RGB
> > >   VIDEO_PALETTE_RGB24     4        24bit RGB
> > >   VIDEO_PALETTE_RGB32     5        32bit RGB
> > >   VIDEO_PALETTE_RGB555    6        555 15bit RGB
> > >   VIDEO_PALETTE_YUV422    7        YUV422 capture
> > >   VIDEO_PALETTE_YUYV      8
> > >   VIDEO_PALETTE_UYVY      9        The great thing about standards is ...
> > >   VIDEO_PALETTE_YUV420    10
> > >   VIDEO_PALETTE_YUV411    11       YUV411 capture
> > >   VIDEO_PALETTE_RAW       12       RAW capture (BT848)
> > >   VIDEO_PALETTE_YUV422P   13       YUV 4:2:2 Planar
> > >   VIDEO_PALETTE_YUV411P   14       YUV 4:1:1 Planar
> > >   VIDEO_PALETTE_YUV420P   15       YUV 4:2:0 Planar
> > >   VIDEO_PALETTE_YUV410P   16       YUV 4:1:0 Planar
> > >   VIDEO_PALETTE_PLANAR    13       start of planar entries
> > >   VIDEO_PALETTE_COMPONENT 7        start of component entries
> > > */
> > >
> > > int setWindowParams(int fd) {
> > >
> > >   struct video_window winny;
> > >
> > >   if (ioctl (fd, VIDIOCGWIN, &winny) == -1) {
> > >     printf("error getting window params.\n");
> > >     return -1;
> > >   }
> > >
> > >   winny.width = IMAGE_WIDTH;
> > >   winny.height = IMAGE_HEIGHT;
> > >
> > >   if (ioctl (fd, VIDIOCSWIN, &winny) == -1) {
> > >     printf("error setting window params.\n");
> > >     return -1;
> > >   }
> > >
> > >   return 0;
> > > }
> > >
> > > int setImageParams(int fd) {
> > >
> > >   struct video_picture image;
> > >
> > >   if (ioctl (fd, VIDIOCGPICT, &image) == -1) {
> > >     printf("error getting picture params.\n");
> > >     return -1;
> > >   }
> > >
> > >   image.depth = IMAGE_DEPTH;
> > >   image.palette = IMAGE_PIXEL_FORMAT;
> > >
> > >   if (ioctl (fd, VIDIOCSPICT, &image) == -1) {
> > >     printf("error setting picture params.\n");
> > >     return -1;
> > >   }
> > >
> > >   return 0;
> > > }
> > >
> > > /*
> > >   I have to do this sometimes because sometimes I
> > >    get BGR byte ordering instead of RGB
> > > */
> > > void writeRGBStream(int fd, char *buffer, int size){
> > >   int i;
> > >   char *rgbBuf;
> > >   rgbBuf =  (char *)malloc (size);
> > >
> > >   for (i = 0; i < size; i+=3) {
> > >     rgbBuf[i] = buffer[i+2];
> > >     rgbBuf[i+1] = buffer[i+1];
> > >     rgbBuf[i+2] = buffer[i];
> > >   }
> > >   write (fd, rgbBuf, size);
> > > }
> > >
> > > void signal_handler(int err){
> > >   printf("caught sigalarm, bye\n");
> > >   exit(0);
> > > }
> > >
> > > int main() {
> > >   int vidfd, outfd;
> > >   int size;
> > >   int captureMode;
> > >   char *buffer;
> > >   int readLength;
> > >   char *outputFile = "output.raw";
> > >
> > >   signal(SIGALRM, signal_handler);
> > >
> > >   size = (IMAGE_HEIGHT*IMAGE_WIDTH) * (IMAGE_DEPTH/8);
> > >
> > >   if ((vidfd = open (DEVICE_NAME, O_RDONLY)) == -1) {
> > >     printf("error opening %s\n",DEVICE_NAME);
> > >     exit(0);
> > >   }
> > >   printf("opened device\n");
> > >
> > >
> > >   if (setWindowParams(vidfd) == -1) {
> > >     printf("error in setWindowParams()\n");
> > >   }
> > >
> > >   if (setImageParams(vidfd) == -1) {
> > >     printf("error in setImageParams()\n");
> > >   }
> > >
> > >   buffer = (char *)malloc(size);
> > >
> > >   if ((outfd = open (outputFile, O_WRONLY | O_CREAT)) == -1) {
> > >     printf("Error opening output file\n");
> > >     exit(0);
> > >   }
> > >
> > >   readLength = read (vidfd, buffer, size);
> > >   printf("read one frame of %d bytes\n", readLength);
> > >
> > >   write(outfd, buffer, readLength);
> > >
> > >   close(vidfd);
> > >   close(outfd);
> > >   chmod(outputFile, 0600);
> > >
> > > }