schweini has asked for the wisdom of the Perl Monks concerning the following question:

Dearly beloved,

I need to integrate the functionality of reading the current picture from a webcam that is connected to a PC into my Tk app - if at all possible, in a cross-platformy kind of way.
I haven't done it yet, but on linux, simply (ab)using vidcat for this looks as if it's going to be quite trivial - and if not, there's always Video::Capture::V4l (even though the documentation is a bit 'lacking'). Now, how can i do this on Windows in a minimalistic way? Is there a vidcat-equivalent for Windows somewhere? Is there some really easy way to tell DirectX (or VfW, or whatever - I've never 'talked' to Windows components before) to simply give me the data for the current picture? I could live without this program running on windows, but if there's a really simple to do this, I'd obviously prefer to maintain Windows compatability...

thanks for any pointers,


Replies are listed 'Best First'.
Re: Cross platform webcam-capturing?
by zentara (Archbishop) on Apr 22, 2005 at 22:12 UTC
    I don't know about windows, but this may help you with your V4l on linux. Notice, if your webcam has a tuner, you have to watch which channel you use. Your composite will be on channel(1) if your card has a tv tuner, otherwise channel(0). Also notice the need to convert from BGR to RGB.
    #!/usr/bin/perl use warnings; use strict; use Video::Capture::V4l; use Imager; use Tk; use Tk::JPEG; use MIME::Base64; my $timestamp; my $temp = ''; sub grab_one { $temp = ''; $timestamp = scalar(localtime); $timestamp =~ tr/ /_/; $| = 1; my $grab = new Video::Capture::V4l or die "Unable to open Videodevice: $!"; # the following initializes the camera for NTSC my $channel = $grab->channel(1); #1 is composite 0 is for tuner my $tuner = $grab->tuner(0); $tuner->mode(1); $channel->norm(1); $tuner->set; $channel->set; my $frame = 0; my $fr = $grab->capture( $frame, 320, 240 ); my $count = 0; for ( 0 .. 1 ) { my $nfr = $grab->capture( 1 - $frame, 320, 240 ); $grab->sync($frame) or die "unable to sync"; unless ( $count == 0 ) { # save $fr now, as it contains the raw BGR data $temp = ''; open( JP, '>', \$temp ) or die $!; print JP "P6\n320 240\n255\n"; #header $nfr = reverse $nfr; print JP $nfr; close JP; my $img = Imager->new(); $img->read( data => $temp, type => 'pnm' ) or warn $img->errstr(); $img->flip( dir => "hv" ); $img->write( data => \$temp, type => 'jpeg' ) or warn $img->errstr; } $count++; $frame = 1 - $frame; $fr = $nfr; } } grab_one(); my $mw = MainWindow->new(); my $image = $mw->Photo( -data => encode_base64($temp) ); $mw->Label( -image => $image )->pack( -expand => 1, -fill => 'both' ); my $label = $mw->Label( -text => $timestamp )->pack( -side => 'top', -padx => 3 +); my $center = $mw->Frame->pack( -anchor => 'center' ); $center->Button( -text => 'Quit', -command => [ destroy => $mw ] ) ->pack( -side => 'left', -padx => 3 ); $center->Button( -text => 'Update', -command => \&update ) ->pack( -side => 'left', -padx => 3 ); $center->Button( -text => 'Save', -command => \&save_it ) ->pack( -side => 'left', -padx => 3 ); MainLoop; sub save_it { open( JP, "> $timestamp.jpg" ) or die $!; print JP $temp; close JP; $label->configure( -text => "$timestamp.jpg SAVED" ); $label->update; } sub update { grab_one(); $label->configure( -text => "$timestamp" ); $label->update; $image->configure( -data => encode_base64($temp) ); $image->update; $mw->update; }

    I'm not really a human, but I play one on earth. flash japh
      thanks - even though maybe i should've made clear that i'm trying to access a cheapo-USB-webcam, and was kind of looking for a solution along the lines of:
      use Device::Webcam; # pity this on doesn't exist my $wc = Device::Webcam->init('/dev/video/0', '800x600'); my $jpeg = $wc->capture( format => 'jpeg' );
      hmmm....if i'd actually start a Device::Webcam, that does nothing more than wrap around vidcat on linux (v4l) systems, would that be worth putting on CPAN?
        Sure, put it on CPAN, if you have tested it, and are sure it works with all of the different possible setups. Otherwise, just post it here in the snippets, or code sections.

        I'm not really a human, but I play one on earth. flash japh