2

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.
Timothy R. Butler
  • 1,097
  • 7
  • 20
  • Maybe you can share the URL of a site/icon that doesn't work? – Mark Setchell Sep 17 '20 at 16:54
  • Did you try to convert **ico** file with _image magic_ command line? What `magic convert favicon.ico favicon.png` returns? – Polar Bear Sep 17 '20 at 18:04
  • @PolarBear Please note that `magick` (the v7 command) should almost never be run as `magick convert ...` unless you have very specific reason to want old v6 functionality from new v7 version. Just use `magick INPUT ... processing .... OUTPUT`. Explanation here... https://stackoverflow.com/a/61208844/2836621 – Mark Setchell Sep 17 '20 at 18:16
  • @MarkSetchell -- I did not use _image magic_ probably longer than 10 years (there wasn't need for that), my past knowledge gets _outdated_. My point was if previous command will produce desired output file -- then input is good and it require to look into perl code why it does not produce desired result (input _ico_ file validation). – Polar Bear Sep 17 '20 at 18:51
  • @MarkSetchell -- I've checked my remote web server does not have header files to verify `Image::Magic` perl code (I do not have control over remote server -- perl module installation fails due absence of header file). – Polar Bear Sep 17 '20 at 18:54
  • @MarkSetchell added a link to one of the files at the end of the question. Thanks! – Timothy R. Butler Sep 17 '20 at 20:57
  • @PolarBear I'll add that into the question. – Timothy R. Butler Sep 17 '20 at 21:09
  • If your file is really just called `1299` with no extension, try prefixing its name with `ICO:` So I mean `convert ICO:1299 1299.jpg` or renaming it with `.ico` suffix. – Mark Setchell Sep 17 '20 at 21:19
  • If you can't arrange either of the above, you can hopefully work out the Perl equivalent of this which sends the icon file (i.e. your blob) to ImageMagick on its `stdin` whilst advising it's an icon file `cat 1299 | convert ICO:- 1299.jpg` – Mark Setchell Sep 17 '20 at 21:56
  • I think you can maybe preset the magick prior to unblobbing... `$image=Image::Magick->new(magick=>'ico');` – Mark Setchell Sep 17 '20 at 22:05
  • @MarkSetchell That prefix works! Thank you. The files started out without filenames because I was relying on Image::Magick to determine the format rather than counting on the server giving me reliable format information in the MIME Type. As a fallback, though... – Timothy R. Butler Sep 17 '20 at 22:33

1 Answers1

3

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.

Timothy R. Butler
  • 1,097
  • 7
  • 20