[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);
> > >
> > > }