in reply to capturing raw video with v4l

Here's a way to use Image::Magick to create PNGs from the raw RGB data.

Untested code:

#!/usr/bin/perl die "Usage: $0 image1 .. imageN\nDo not include the .raw extension.\n" + unless (@ARGV); use Image::Magick; my $depth = 8; # or 16 or 24 or ... my $size = '640x480'; foreach my $file (@ARGV) { my $image = Image::Magick->new; my $x; $x = $image->Read( filename => "rgb:$file.raw", size => '640x480', depth => $depth ); warn "$x" if "$x"; # from the examples but looks funny to me ;-) $x = $image->Write("$file.png"); # or jpg or whatever warn "$x" if "$x"; }

Alternately, you could include this in your video capture script. That would enable you to save a step by converting the raw data stored in the $nfr scalar to PNG.

Replies are listed 'Best First'.
Re: Re: capturing raw video with v4l
by zentara (Cardinal) on Jul 04, 2003 at 21:00 UTC
    Well thanks, you got me on the right track. As usual, I make advances by making "educated guesses". :-) I noticed that the output of videodog's raw frame, and a pnm frame was the same except for a header. So I added a header to each frame and renamed it pnm. Now another problem arises....the raw data is actually BGR not RGB ( I thought it was a typo, but it's not). So now I need to figure out how to quickly process the frame to change it from BGR to RGB.

    New code which outputs blue-tinted pnm's.

    #!/usr/bin/perl use Video::Capture::V4l; $grab = new Video::Capture::V4l or die "Unable to open Videodevice: $!"; $|=1; my $frame=0; my $fr=$grab->capture ($frame, 320, 240); my $count=0; for(1..5) { my $nfr = $grab->capture (1-$frame, 320, 240); $grab->sync($frame) or die "unable to sync"; # save $fr now, as it contains the raw BGR data open (JP,">z$count.pnm") or die $!; print JP "P6\n320 240\n255\n"; #header print JP $nfr; close JP; print "."; $count++; $frame = 1-$frame; $fr = $nfr; }
      Don't know how quick it is, but here's my stab at converting from BGR to RGB.
      sub convert_to_rgb { my $bgr = shift; my $bgrLen = length($bgr); #Unpacking the BGR data gives use easy access to individual bytes. my @bgrArray = unpack("C$bgrLen",$bgr); my @rgbArray; my $ct=0; while ($ct < $bgrLen) { $rgbArray[$ct] = $bgrArray[$ct+2]; $rgbArray[$ct+1] = $bgrArray[$ct+1]; $rgbArray[$ct+2] = $bgrArray[$ct]; $ct+=3; } #Pack the data to match the input format. my $rgb = pack("C$bgrLen",@rgbArray); return $rgb; }
      Pass the code $nfr and the returned value can be written to file in place of $nfr.
        Hi, that's a nice pure perl snippet, however it still would be faster to let Imager do it, since it uses xs and C to do the same thing, and faster too for big image files.

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