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

Hi there, module Imager reads and operates on images. In my case I have the image in memory already (after downloading it with LWPL::UserAgent) and would like to auto-crop it before saving it to disk. It does not seem to me that Imager provides this option. Imager::Simple does provide it but then it does not seem to provide autocrop() (which is implemented in Imager::Filter::Autocrop).

For example, this complains about not finding autocrop():

use strict; use warnings; use Imager::Simple; use Imager::Filter::Autocrop; my $imgdata = undef; open(IN, '<', 'example.jpg'); binmode(IN); { local $/ = undef; $imgdata = <IN> } close(IN); my $img = Imager::Simple->new(); $img->read(\$imgdata) or die "read: ".$img->errstr(); $img->autocrop(fuzz=>20) or die "autocrop: ".$img->errstr(); $img->write('out.jpg') or die "writing: ".$img->errstr();

As a possible workaround, I thought I can register a reader using Imager's register_reader() but that was a long shot as I have the suspicion that one needs to decode the image residing in the scalar first... The code below fails because it still thinks $img is a filename (after registering a reader):

use Imager; use Imager::Filter::Autocrop; my $imgdata = undef; open(IN, '<', 'example.jpg'); binmode(IN); { local $/ = undef; $imgdata = <IN> } close(IN); my $img = Imager->new(); $img->register_reader( type => 'scalar', single => sub { my ($im, $io, %hsh) = @_; $im->{IMG} = $io; return $im }, ) or die "register_reader: ".$img->errstr(); $img->read(type=>'scalar', file=>$imgdata) or die "read: ".$img->errst +r(); $img->autocrop(fuzz=>20) or die "autocrop: ".$img->errstr(); $img->write(file=>'out.jpg') or die "writing: ".$img->errstr();

So, can anyone suggest a way to apply sensible and flexible (e.g. with a fuzziness factor etc.) auto-crop to an image already in memory? It does not need to be using Imager.

I am talking about several thousand images here and I would hate to download them, save them to file, read them back to memory, auto-crop them and save them back to disk... That would be awful. Thanks, bliako

Replies are listed 'Best First'.
Re: Imager : read image from scalar (not from file)
by LanX (Saint) on Aug 20, 2018 at 22:53 UTC
    Tldr, but did you try to open from a scalar ref instead of a filename?

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      I did ... but not in the way it is specified in the manual of Imager::Files. Thanks for hinting it is possible as I was convinced it wasn't and did not perservere with the manuals ... (maybe they should put this important info under the heading read() or in the Description section of mod:://Imager). The following works for me:

      use strict; use warnings; use Imager; use Imager::Filter::Autocrop; my $imgdata = undef; open(IN, '<', 'example.jpg'); binmode(IN); { local $/ = undef; $imgdata = <IN> } close(IN); my $img = Imager->new(); # possible params are 'file', 'data' and 'fd' $img->read(data=>\$imgdata) or die "read: ".$img->errstr(); $img->filter(type=>'autocrop', fuzz=>20) or die "autocrop: ".$img->err +str(); $img->write(file=>'out.jpg') or die "writing: ".$img->errstr();

      Edit: actually it is not documented in Imager::Files that data is a recognised input param name for read(). It is only mentioned in the write(). Anyway, all well now.

        The section on Input and output in Imager::Files describes the I/O options you can supply for read(), write(), read_multi() and write_multi().

        There's an example using read() from a scalar in the Imager::Files SYNOPSIS.

        It's documented for open °

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

        °) i.e. I was guessing.