Search code examples
perlimagemagick-convertperlmagick

PerlMagick Chokes on ICO File?


I've been working on a script that retrieves favicons from sites, which is now mostly working, but I've run into a huge roadblock. When I call on the ImageMagick module in Perl, it doesn't seem to know what to do with the venerable favicon.ico file (everything is working great when a site has a non-ICO favicon). I can find lots of information on converting to ICO to create a favicon, but not much about converting from ICO.

After I retrieve the favicon, I use PerlMagick's ping function to figure out what kind of file I'm dealing with (so I'm not dependent on the icon's server to report accurately):

    use Image::Magick;
    my $im = Image::Magick->new();
    my ($width, $height, $size, $format) = $im->Ping( $saveFile );

When the file is an ICO file, $format comes back empty (the server I'm requesting it from reports it as image/x-icon). I also have a little subroutine that creates JPEG thumbnails of everything I download. It works great on non-ICO files, but ImageMagick creates a blank file when converting from an ICO:

    open my $file, $params->{'openFile'};
    my $imageData = do { local $/; <$file> };

    my $image = Image::Magick->new;
    $image->BlobToImage($imageData);
    $image->SetAttribute(quality => 80);
    $image->SetAttribute(compression => 'JPEG');
    $image->SetAttribute(geometry => $thumbnailWidth . "x" . $thumbnailHeight);
    $image->Thumbnail();

    my $thumbnailData = $image->ImageToBlob();


    open(my $file, '>', $params->{'saveFile'}) or die "Could not open file '" . $params->{'saveFile'} . "'.";
    print $file $thumbnailData;
    close $file;

Do I need to somehow coax ImageMagick into recognize the file? I've been saving the favicons I download and the initial file is a valid ICO, even though ImageMagick won't recognize it.

Update: Here is a link to one of the ico files that is acting up. All the ico files I've tried have acted up, however.

If I try the command line ImageMagick convert tool, here is the result:

[root@local favicons]# convert 1299 1299-jpg.jpg
convert: no decode delegate for this image format `' @ error/constitute.c/ReadImage/564.
convert: no images defined `1299-jpg.jpg' @ error/convert.c/ConvertImageCommand/3235.

Solution

  • Based on @MarkSetchell's comments, I can add code to deal with the issue laid out above. I had been depending on PerlMagick's ping function to determine the file type, hoping to avoid possible bad information from a server I connect to. What I've done now is examine the Content-type header if ImageMagick cannot determine the file type and return it in $format:

            if ((! $format) and (($mech->content_type() eq "image/x-icon") or ($mech->content_type() eq "image/vnd.microsoft.icon"))) {
                $format = "ICO";
            }
    

    I then manually pass along the ICO format to ImageMagick before giving it the file blob:

            my %imParam;
            %imParam = ( 'magick' => 'ico' ) if ($params->{'format'} eq "ICO");
            my $image = Image::Magick->new( %imParam );
    

    This seems to be working so far. Thankfully on GIF, PNG, SVG and JPEG, ImageMagick is working fine on its own, which is even better, since I'd rather trust ImageMagick than the remote server's headers.