perlimagemagickimagemagick-identify

Passing arguments to system commands from perl


I'm writing a perl script that uses some ImageMagick commands, specifically identify. The relevant code is here:

my $height = system("identify -format %h $curPic");
my $width = system("identify -format %w $curPic");

When I run the whole script,it gets hung up on these lines and this is the output:

identify: unable to open image 'if0W211.jpg': No such file or directory @ error/blob.c/OpenBlob/3323
identify: unable to open image 'if0W211.jpg': No such file or directory @ error/blob.c/OpenBlob/3323

At first, the problem was related to ImageMagick not have the correct format delegates to work with jpg images, but after fixing that, I'm still getting this error. I can't find any error documentation related to "error/blob.c/OpenBlob/3323". After writing some test code to see what the problem might be, I think I've determined that it has something to do with the way perl passes arguments to system commands, because when I write that system command identify -format %h xxxx.jpg in the terminal, it works just fine. I also noticed that when I print "$curPic\n, a 256 is prepended to the filename during the print. I don't know why this would be.

For reference, here is how I collect the filenames:

opendir DIR, $folder or die "Cannot open directory: $!";
my @files = readdir(DIR);
closedir(DIR);

And here is the full script:

#!/usr/bin/perl -w

use strict;
use diagnostics;
use File::Copy;

my $folder = "/media/sf_Pictures_from_Reddit";
my $oriFolder = "/media/sf_WrongOrientation";
my $resFolder = "/media/sf_LowRes";

#Collect all the files
opendir DIR, $folder or die "Cannot open directory: $!";
my @files = readdir(DIR);
closedir(DIR);

#Iterate through each file and check its orientation and resolution
foreach my $curPic (@files) {
    my $height = system("identify -format %h $curPic");
    my $width = system("identify -format %w $curPic");

    #move those that are vertically oriented to a different folder
    if ($height >= ($width*0.8)) {
    move($curPic, $oriFolder//$curPic) or die "The ori move operation     failed for image $curPic: $!";
        print "$curPic was not approved because of its orientation.";
        next;
    }
    #move those that are low res to a third folder
    elsif (($height < 1080) | ($width < 1920)) {
    move($curPic, $resFolder//$curPic) or die "The res move operation     failed for image $curPic: $!";
        print "$curPic was not approved because of its resolution.";
        next;
    }
    print "$curPic is approved as a desktop background";
}

EDIT: I'm switching to the recommended Image::Size library, so here is my updated script. It works for a time, giving me the output I want, but suddenly breaks and says the variables are uninitialized. "Use of uninitialized variable..." There's an error for $height and $width, but once again they both happen after about 20 successful iterations. And it seems to vary if I run the script multiple times back to back.

#!/usr/bin/perl -w

use strict;
use diagnostics;
use File::Copy;
use Image::Size;

my $folder = "/media/sf_Pictures_from_Reddit";
my $oriFolder = "/media/sf_WrongOrientation";
my $resFolder = "/media/sf_LowRes";

my $height = 0;
my $width = 0;

#Collect all the files
opendir DIR, $folder or die "Cannot open directory: $!";
my @files = readdir(DIR);
closedir(DIR);

#Iterate through each file and check its orientation and resolution
foreach my $curPic (@files) {
    ($width, $height) = imgsize("$folder/$curPic");

    #move those that are vertically oriented to a different folder
    if ($height >= ($width*0.8)) {
        move("$folder/$curPic", "$oriFolder/$curPic") or die "The ori move operation failed for image $curPic: $!";
        print "$curPic was not approved because of its orientation.\n";
        next;
    }
    #move those that are low res to a third folder
    elsif (($height < 1080) | ($width < 1920)) {
        move("$folder/$curPic", "$resFolder/$curPic") or die "The res move operation failed for image $curPic: $!";
        print "$curPic was not approved because of its resolution.\n";
        next;
    }
    print "$curPic is approved as a desktop background.\n";
}

Solution

  • As the message says, you are passing the path to a non-existent file. Instead of passing

    if0W211.jpg
    

    you should be passing

    /media/sf_Pictures_from_Reddit/if0W211.jpg
    

    That still leaves you with the following problems:

    All these can be fixed by using Image::Size instead.

    But if you insist on using identify,

    use IPC::System::Simple qw( capturex );
    
    my $dimensions = eval { capturex("identify", "-format", "%h,%w", "--", "$folder/$curPic") }
        or do {
           warn("Can't determine the dimensions of \"$folder/$curPic\": $@");
           next;
        };
    
    my ($height, $width) = $dimensions =~ /^(\d+),(\d+)$/
       or do {
           warn("Can't determine the dimensions of \"$folder/$curPic\": Unexpected output from \"identify\": $dimensions\n");
           next;
       };
    

    If your identify doesn't support -- (or even if it does), you can replace

    "--", "$folder/$curPic"
    

    with

    "$folder/$curPic" =~ s{^-}{./-}r