Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options

Feeding video data to Imager

by saintmike (Vicar)
on Mar 26, 2006 at 19:35 UTC ( #539316=perlquestion: print w/replies, xml ) Need Help??
saintmike has asked for the wisdom of the Perl Monks concerning the following question:

When feeding RGB (or, more accurately, BGR) data from a video source to Imager, a wise perlmonk once suggested to use this trick:
use Imager; my $i = Imager->new(); $nfr = reverse $nfr; $i->read( type => "pnm", data => "P6\n$width $height\n255\n" . $nfr ); $i->flip(dir => "hv");
Is this still the best way to do it? It seems awkward that the mighty Imager wouldn't allow feeding it RGB data directly.

Replies are listed 'Best First'.
Re: Feeding video data to Imager
by tonyc (Pilgrim) on Mar 27, 2006 at 00:01 UTC

    There's a few ways you could do it:

    • format the data as PPM as above, or perhaps raw would be better.
    • use the setscanline() method to write data a scanline at a time to the image. Unfortunately this expects data in a particular format, so you'll still need to adjust the data a bit.
    • # untested my $im = Imager->new(xsize=>$width, ysize=>$height); my $per_line = $width * 4; # adjust the data to the format setscanline() takes $nfr =~ s/(.)(.)(.)/$3$2$1\xFF/gs; # paint it for my $y (0..$height-1) { $im->setscanline(y=>$y, pixels => substr($nfr, $y * per_line, $per_line)); }
    • if performance is an issue you could use Inline::C or an XS module to reformat the data and draw it using i_plin() at the C level. Here's some Inline C code to do the job:
    • use Imager 0.48; # this assumes you've created an image of the right # size first. # if you call it with too large an image for the data # supplied then it will crash use Inline C => <<'EOS' => WITH => 'Imager'; void capture2image(Imager::ImgRaw out, unsigned char *data) { i_color *line_buf = mymalloc(sizeof(i_color) * out->xsize); i_color *pixelp; int x, y; for (y = 0; y < out->ysize; ++y) { pixelp = line_buf; for (x = 0; x < out->xsize; ++x) { pixelp->rgba.b = *data++; pixelp->rgba.g = *data++; pixelp->rgba.r = *data++; ++pixelp; } i_plin(out, 0, out->xsize, y, line_buf); } myfree(line_buf); } EOS

    Perhaps Imager needs a more general data to image method, but I haven't had much feedback on setscanline() and friends yet.

    Edit: added the Inline C code, hard to test without video capture data though.

Re: Feeding video data to Imager
by zentara (Archbishop) on Mar 27, 2006 at 12:37 UTC
    Is this still the best way to do it? It seems awkward that the mighty Imager wouldn't allow feeding it RGB data directly.

    I chose to do it that way, because I thought it was faster than the direct way which Imager allows, which is matrix transformation. Read "perldoc Imager::Transformations, where the following matrix method is shown

    # Swap red/green channel $new = $img->convert(matrix=>[ [ 0, 1, 0 ], [ 1, 0, 0 ], [ 0, 0, 1 ] ]);
    but, I think you will find that reversing is faster, although it will only work for swapping R and B, plus you need to invert it afterwards. But let us know, if you find otherwise.

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

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://539316]
Approved by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (6)
As of 2018-03-24 14:31 GMT
Find Nodes?
    Voting Booth?
    When I think of a mole I think of:

    Results (299 votes). Check out past polls.