Category:
Author/Contact Info zentara
Description: This grabs a jpg image from /dev/video0 and displays it with Tk. It has an update button, and a save button, which saves the jpg named with a timestamp.

Update July 9 2003: I added some code to initialize the camera to NTSC,otherwise it would be garbled unless first initialized with xawtv.

#!/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 (0);
   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;
}