views:

135

answers:

1

This is a cross post from Perl Monks and Mahalo answers, where I have not received a satisfactory response yet. Thanks for your time and spirit:

Why do I get this error message from perl:

Can't call method "scaleY" on an undefined value at C:/strawberry/perl +/site/lib/ Image/Seek.pm line 137?

I am getting the error in the title when calling the Image::Seek module from my script. My script is basically a rehash of the module's suggested code.

Here's the error again:

Can't call method "scaleY" on an undefined value at C:/strawberry/perl +/site/lib/ Image/Seek.pm line 137.

Here's my code:

#!/usr/local/bin/perl 
use Imager;
use Image::Seek qw(loaddb add_image query_id savedb);

loaddb("haar.db");
my $img = Imager->new("photo-1.jpg")
or  die Imager->errstr;

# my $img = Imager->new();
# $img->open(file => "photo-1.jpg")or die Imager->errstr;

add_image($img, 1);
savedb("haar.db");

Here's the section of the Image::Seek module causing the issue:

sub add_image_imager {
    my ($img, $id) = @_;
    my ($reds, $blues, $greens);
    require Imager;
    my $thumb = $img->scaleX(pixels => 128)->scaleY(pixels => 128);
    for my $y (0..127) {
        my @cols = $thumb->getscanline(y => $y);
        for (@cols) {
            my ($r, $g, $b) = $_->rgba;
            $reds .= chr($r); $blues .= chr($b); $greens .= chr($g);
        }
    }
    addImage($id, $reds, $greens, $blues); }

Line 137 is:

my $thumb = $img->scaleX(pixels => 128)->scaleY(pixels => 128);

If I remove

->scaleY(pixels => 128)

then line 129:

my @cols = $thumb->getscanline(y => $y);

gives me essentially the same error.

At this point I'm just trying to add one image to the database. There is an image in the directory where I'm running the script to add the image, named "photo-216.jpg". If I change the name to "photo-1.jpg" or "photo-0.jpg" and change the corresponding "add_image" and "query_id" to respectively 1 or 0, it's the same result.

I do have a database that is 385 KB big that comes from running makedb.pl below, but it is filled with null characters. I renamed this "haar.db". This is the database that gives me the error. If I recreate the haar.db file as an empty one, then the script hangs and after a couple of minutes, it give this different message:

"This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information."

If there is no "haar.db" the file still gives me the error in this post's title and unlike running makedb.pl, gives me no database named "haar.db".

By the way I get multiple examples of this post's title error also when trying to run this database filling script: http://www.drk7.jp/pub/imgseek/t/makedb.pl.txt/, which I was alluding to before. I obviously removed the .txt extension before trying it. The makedb.pl script is from this Japanese site: http://www.drk7.jp/MT/archives/001258.html.

If I run makedb.pl in a directory of 2423 scanned collectible postage stamps images, I get 362 instances of the error. The 2423 stamps is the number I have after removing the "small" thumbnail versions which I orignally thought might be causing the issue.

Could it be, that some of the images are less than 128 pixels and that is the issue? However if this is true why does the database get filled with null characters?...Unless they are not really null even though the editor I'm using, Notebook++, says they are.

Also note my images are of stamps which are only sometimes perfect squares. Otherwise, sometimes they are "landscape" sometimes "portrait". Maybe the issue is when the "landscape" scaled images get an X axis of 128 pixels and then their Y axis ends up less or much less. Could this be?

Thanks much

+2  A: 

Update: Answer completely re-organized.

Image::Seek is not checking if scaleX returned error. In your case, for some images, scaleX is failing. You seem to know for which images scaleX is failing. So, leave your current code aside, and put together a short test script:

#!/usr/bin/perl

use strict;
use warnings;

use Imager;

die "Specify image file name\n" unless @ARGV;

my ($imgfile) = @ARGV;

my $img = Imager->new;
$img->read( file => $imgfile )
    or die "Cannot read '$imgfile': ", $img->errstr;

my $x_scaled = $img->scaleX( pixels => 128 )
    or die 'scaleX failed: ', $img->errstr;

my $thumb = $x_scaled->scaleY( pixels => 128 )
    or die 'scaleY failed: ', $x_scaled->errstr;

__END__

Running this test script, you got the error message:

Cannot read 'photo-1.jpg': format 'jpeg' not supported - formats bmp,
ico, pnm, raw, sgi, tga available for reading 

indicating the underlying problem: When you installed Imager via Strawberry Perl's cpan, the libraries for png, jpg etc were not installed. One solution is to build those libraries with the gcc compiler provided with Strawberry Perl.

First, you will need zlib.

C:\Temp\zlib-1.2.3> copy win32\Makefile.gcc Makefile

Set prefix = /strawberry/c/local in the Makefile. Compile. You may have to manually copy the files zlib.h and zconf.h to C:\strawberry\c\local\include and zlib1.dll, libz.a and libzdll.a to C:\strawberry\c\local\lib (I don't know because I do not use Strawberry Perl very often and my Strawberry environment is very neglected.)

Then, get libpng. I used the source archive without config script.

C:\Temp\libpng-1.2.38> copy scripts\makefile.mingw Makefile
C:\Temp\libpng-1.2.38> make prefix=/strawberry/c/local ZLIBLIB=/strawberry/c/local/lib ZLIBINC=/strawberry/c/local/include

This built the PNG library. Again, you may have to manually copy the .dll, .a and .h files to the appropriate directories. I did because of my less than perfect Strawberry environment.

Finally, get the JPEG library.

C:\Temp\jpeg-7> copy Makefile.ansi Makefile

Make sure to edit this file and set CC=gcc. Customize jconfig.h according to the instructions in jconfig.txt. I used jconfig.dj as a basis.

You might also want to set

CFLAGS= -O2
SYSDEPMEM= jmemansi.o

in Makefile, and

#define DEFAULT_MAX_MEM 4*1024*1024

in jconfig.h. After running make, again copy the files as needed (and as explained by install.txt).

Once the libraries are installed, you can

C:\Temp> SET IM_INCPATH=C:\strawberry\c\local\include
C:\Temp> SET IM_LIBPATH=C:\strawberry\c\local\lib
C:\Temp> cpan
cpan> force install Imager

which yields:

      gif: includes not found - libraries not found
    ungif: includes not found - libraries not found
     jpeg: includes found - libraries found
      png: includes found - libraries found
     tiff: includes not found - libraries not found
freetype2: includes not found - libraries not found
freetype2: not available
 T1-fonts: includes not found - libraries not found
 TT-fonts: includes not found - libraries not found
      w32: includes found - libraries found

If all of this is too much work, it is ... sigh I just realized the binaries are available at GnuWin32.

Sinan Ünür
I get this error now with my custom module: Global symbol "$xscaled" requires explicit package name at C:/strawberry/perl/site/lib/Image/SeekPDP.pm line 146.BEGIN not safe after errors--compilation aborted at C:/strawberry/perl/site/lib/Thanks for the help. Image/SeekPDP.pm line 161.Compilation failed in require at processimage.pl line 3.BEGIN failed--compilation aborted at processimage.pl line 3.
socrtwo
@socrtwo I meant modify the code in `Image/Seek.pm`. Anyway, I updated my answer to clarify.
Sinan Ünür
Yes, I updated the code in Seek.pm. Just to be sure that it is not an issue, I made it into a custom module named Image::SeekPDP with only the changes you suggested. I then installed the custom module per the instructions here: http://springfield.pm.org/meetings/modules.html. I got the new error as mentioned. Thanks so much for the help...
socrtwo
@socrtwo There was a typo in my code earlier ... `$xscaled` should have been `$x_scaled`.
Sinan Ünür
Ahh, we are getting somewhere...I got this error with your test script: "Cannot read 'photo-1.jpg': format 'jpeg' not supported - formats bmp, ico, pnm,raw, sgi, tga available for reading at testSinan.pl line 13."I wll convert the JPG images all to PNG and try again :-))
socrtwo
What version of `Imager` do you have? The latest version is 0.67 and that seems to have no problem with JPEGs.
Sinan Ünür
OK, I will look for the latest version. By the way, changing the scripts to PNG files and converting all my images to that format gives the same errors.
socrtwo
Installing 0.67 manually still gives me both JPEG and PNG library not found messages. I installed the GNUWin32 library for JPEG as Tony Cook suggested, however I don't know where or how to change Imager's Makefile.PL to point to the libraries. It does not seem obvious.
socrtwo
Where is Imager looking for JPEG and PNG libraries so I can copy the library files there or install the libraries to those folders or folder?
socrtwo
OK I did what you said the lines are a little better but now:"jpeg: includes found - libraries not found png: includes found - libraries not found"Here is the dir of the C:\strawberry\c\local\lib folder:http://pastebin.com/m6992fa60
socrtwo
This was excellent help. I followed the directions and with some minor changes got the jpeg, zlib and png libraries installed. But I still got the same error. Luckily enough I saw a Chinese programmer using bmps in his Image::Seek script for some strange reason, so I tried them and this was the key. So now the processing and database creation work fine. So of course I will convert user uploaded images to bmps first, which I'm hoping will be a trivial exercise. Thanks for the extended and well organized help :-). Working togethor here kept me going.
socrtwo