php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #58515 ico format not working on Imagick::readImageBlob
Submitted: 2009-01-20 19:05 UTC Modified: 2009-06-17 19:38 UTC
From: guozheng dot ge at gmail dot com Assigned:
Status: Not a bug Package: imagick (PECL)
PHP Version: 5.2.5 OS: rhel-4.x
Private report: No CVE-ID: None
 [2009-01-20 19:05 UTC] guozheng dot ge at gmail dot com
Description:
------------
I am using imagick to overlay a favicon (favicon.ico) on top of another image. It seems that Imagick class cannot handle ico file content as binary string. However, if I create the Imagick object by providing a filename in the constructor, it works fine.

For example, this always gives exception on the line of readImageBlob:
<?php
try
{
    $imgStr = file_get_conents(?favicon.ico?);
    $im = new Imagick();
    $im->readImageBlob($imgStr);
    $im->setImageFormat(?png?);
    header(?Content-type: image/x-icon?);
    echo $im;
}
catch (Exception $ex)
{
    echo ?exception happened: \n?;
    print_r($ex);
}
?>

However, if I create an Imagick object directly using favicon.ico filename, it works fine:
<?php
try
{
    $im = new Imagick(?favicon.ico?);
    $im->setImageFormat(?png?);
    header(?Content-type: image/x-icon?);
    echo $im;
}
catch (Exception $ex)
{
    echo ?exception happened: \n?;
    print_r($ex);
}
?>

Reproduce code:
---------------
try
{
    $imgStr = file_get_conents(?favicon.ico?);
    $im = new Imagick();
    $im->readImageBlob($imgStr);
    $im->setImageFormat(?png?);
    header(?Content-type: image/x-icon?);
    echo $im;
}
catch (Exception $ex)
{
    echo ?exception happened: \n?;
    print_r($ex);
}

Expected result:
----------------
favicon.ico image will be returned

Actual result:
--------------
exception was thrown saying error at readImageBlob function

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-01-21 05:50 UTC] mkoppanen@php.net
Try calling $im->setFormat("ico"); before readImageBlob(). Does this help?
 [2009-01-21 17:32 UTC] guozheng dot ge at gmail dot com
tried to setImageFormat('ico') before readImageBlob, it 
returns an exception saying cannot perform it on an empty 
Imagick object.

exception happened ImagickException Object ( 
[message:protected] => Can not process empty Imagick object 
[string:private] => [code:protected] => 1 [file:protected] 
=> /home/y/share/htdocs/testimagick.php [line:protected] => 
24 [trace:private] => Array ( [0] => Array ( [file] => 
/home/y/share/htdocs/testimagick.php [line] => 24 [function] 
=> setimageformat [class] => Imagick [type] => ->  [args] => 
Array ( [0] => ico ) ) ) )
 [2009-01-21 18:37 UTC] mkoppanen@php.net
setFormat, not setImageFormat.
 [2009-01-22 13:20 UTC] guozheng dot ge at gmail dot com
Hi, Mikko

Thanks a lot for the quick replies and great work on imagick ;-)

I tried setFormat('ico'), now, I don't get "cannot process empty Imagick object" exception anymore. But still I cannot get the ico image output correctly. The output is an ugly looking image (maybe this is because ico has multiple images embedded inside?). Here is the code I tried:

        $imageStr = file_get_contents('favicon.ico');
        $im = new Imagick();
        $im->setFormat('ico');
        $im->readImageBlob($imageStr);
        $im->setImageFormat('png');
        header('Content-type: image/x-icon');
        echo $im; 

Previously, when I create an Imagick object from file using constructor and then setImageFormat('png'), it worked fine and I can get a 24x24 image. Here is the code that works for comparison:

        $im = new Imagick('favicon.ico');
        $im->setImageFormat('png');
        header('Content-type: image/x-icon');
        echo $im;

thanks!
 [2009-02-06 16:30 UTC] mkoppanen@php.net
Sorry, but your problem does not imply a bug in PECL itself.  For a
list of more appropriate places to ask for help using PECL, please
visit http://pecl.php.net/support.php as this bug system is not the
appropriate forum for asking support questions. 

Thank you for your interest in PECL.

Imagick passes the image to ImageMagick for processing and usually can not affect the quality of output except by setting some properties. Therefore I am closing this bug.
 [2009-06-17 14:06 UTC] guozheng dot ge at gmail dot com
Found a solution to this problem and does not need to write 
to a temp file and read from the file.

The problem is indeed with the ICO format. It contains 
multiple icons with different sizes. So you should treat it 
in a similar way to a GIF animation and grab one individual 
icon and output it.

I am not sure why reading from the file works though. So, I 
guess it is still better to be fixed inside Imagick library?

Here is the sample code that should fix the problem:

try
{
$im = new Imagick();
$im->setFormat(?ico?);
$im->readImageBlob($content); /* content contains the ico 
image string */
$idx = 0;
foreach($im as $frame)
{
  $idx += 1;
  if($idx == 1) /* use the 1st frame or other frames, 
Imagick::getNumberImages() returns the num of frames */  
  {
    /* process the frame, such as resize */
    $frame->setFormat(?png?);
    $imgStr = $frame->getImageBlob();
    header(?Content-Length: ? . strlen($imgStr));
    header(?Content-Type: image/png?);
    echo $imgStr;
    return;
  }
}
}catch (Exception $ex)
{
  /* handle exception */
}
 [2009-06-17 15:21 UTC] mkoppanen@php.net
I am not sure I fully understand what the problem is here.
 [2009-06-17 16:36 UTC] guozheng dot ge at gmail dot com
Thanks for the quick reply. 

I guess the problem here is that when you convert ICO image 
as a whole to other formats, it does not work and creates 
crappy results.

So, you need to get one of the images contained inside the 
ICO image and convert the individual image.

But I still don't understand why when you write the ICO 
image content to a file then read from the file, the 
conversion works fine.
 [2009-06-17 16:45 UTC] mkoppanen@php.net
Have you tried flattenImages to merge the layers? Image formats which have multiple images in them are presented in this way because it is the only way to access the individual frames if needs be.
 [2009-06-17 19:38 UTC] guozheng dot ge at gmail dot com
identify ../favicon.ico 
../favicon.ico[0] ICO 32x32 32x32+0+0 DirectClass 8-bit 
6.44336kb 
../favicon.ico[1] ICO 16x16 16x16+0+0 DirectClass 8-bit 
6.44336kb 
../favicon.ico[2] ICO 48x48 48x48+0+0 DirectClass 8-bit 
6.44336kb 
../favicon.ico[3] ICO 24x24 24x24+0+0 DirectClass 8-bit 
6.44336kb

create imagick obj from image string then do flattenImages, 
it returns a normal ICO image, but the result is the size of 
the first image inside the ICO, 32x32 in this case

If you open the ICO file in the browser directly, you get a 
different size, 16x16

I also tried to read from ICO file directly, it outputs the 
last image inside the ICO, 24x24

So, I guess either using flattenImages or traversing through 
individual images both will work. But not really sure what 
should be the correct size. Maybe it is upto the user 
requirement.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Mar 19 11:01:28 2024 UTC