PHP ICO to PNG conversion

12 comments

Posted on 17th February 2009 by admin in Computers | Web Development

, , , , ,

A few posts ago I wrote about using a PHP class to convert an ICO image to a PNG (or GIF or JPG). I just discovered a bug in the class.

I ran into a problem where some red and orange ICO images turned blue during the conversion. Reading this forum post made me realize that the red and blue values were switched somewhere in class.ico.php. With some experimentation I found it:

In class.ico.php, lines 264-267 need to be changed from

$c[$i] = $this->AllocateColor($im, $this->formats[$index]['colors'][$i]['red'],
         $this->formats[$index]['colors'][$i]['green'],
         $this->formats[$index]['colors'][$i]['blue'],
         round($this->formats[$index]['colors'][$i]['reserved'] / 255 * 127));

to

$c[$i] = $this->AllocateColor($im, $this->formats[$index]['colors'][$i]['blue'],
         $this->formats[$index]['colors'][$i]['green'],
         $this->formats[$index]['colors'][$i]['red'],
         round($this->formats[$index]['colors'][$i]['reserved'] / 255 * 127));

(Note that the blue and red values are indeed switched.) After changing this, it works like a charm for me.

  • Share/Bookmark
12 Comments
  1. secret :) says:

    Great! keep the good work!

    For the convenient of others, here’s a quote from the first post:
    ————
    Here’s how you use the class:
    GetIcon(0))) die(“Could not load ICO.”);
    else {
    header(“Content-Type: image/png”);
    imagepng($r);
    }
    ?>
    ————

    And I’ve modified a bit your class, sometimes I just want to get the best quality icon (that’s usually the last icon in the file) so I’ve replaced this:
    ———–
    function &GetIcon($index) {
    if (!isset($this->formats[$index])) {
    ———–
    with this:
    ———–
    function &GetIcon($index=null) {
    if (is_null($index)) {
    $index = count($this->formats)-1;
    }
    if (!isset($this->formats[$index])) {
    ———–
    so I can omit the $index parameter and get the best icon (assuming he’s the last one)

    Good luck everyone!

    17th February 2009 at 4:25 pm

  2. Dp76 says:

    Hello, First of all thanks for your work :)
    But, please, update zip file as well.
    Your zip file have previous version without fixes.

    17th February 2009 at 9:57 am

  3. GarykPatton says:

    Hello, can you please post some more information on this topic? I would like to read more.

    17th February 2009 at 7:42 am

  4. CrisBetewsky says:

    I’m glad that after surfing the web for uch a long time I have found out this information. I’m really lucky.

    17th February 2009 at 2:29 pm

  5. KonstantinMiller says:

    I have been looking looking around for this kind of information. Will you post some more in future? I’ll be grateful if you will.

    17th February 2009 at 4:32 pm

  6. Vahan says:

    wanna see something cool?

    < ?php
    error_reporting(0);
    require 'class.ico.php';
    // load the .ico
    $ico = new Ico('favicon.ico');
    // now we're going to find the highest quality icon! first we need to know about each icon's image quality...
    for($index = 0; $index TotalIcons(); $index++){
    $icon = $ico->GetIconInfo($index);
    $icons[$index]['width'] = $icon['Width'];
    $icons[$index]['bitcount'] = $icon['BitCount'];
    }
    // sort by width, then bitcount (ascending). you can change the priority if you like by switching them around above
    asort($icons);
    // get the key of the last icon (highest quality) in the sorted list
    $best = end(array_keys($icons));
    // now make a png
    if(!($png=$ico->GetIcon($best))) die(“Could not load ICO.”);
    else {
    header(“Content-Type: image/png”);
    imagepng($png);
    }
    // win!
    ?>

    with a bit more effort, i use this to generate image preview tooltips in apache’s autoindex [=

    17th February 2009 at 12:25 am

  7. Vahan says:

    wordpress broke my loop! anyway it should be:
    for($index = 0; $index LESSTHAN $ico->TotalIcons(); $index++){

    17th February 2009 at 12:29 am

  8. Tony says:

    wanna see something cool?

    GetIconInfo($index);
    $icons[$index]['width'] = $icon['Width'];
    $icons[$index]['bitcount'] = $icon['BitCount'];
    }
    // sort by width, then bitcount (ascending). you can change the priority if you like by switching them around above
    asort($icons);
    // get the key of the last icon (highest quality) in the sorted list
    $best = end(array_keys($icons));
    // now make a png
    if(!($png=$ico->GetIcon($best))) die(“Could not load ICO.”);
    else {
    header(“Content-Type: image/png”);
    imagepng($png);
    }
    // win!
    ?>

    with a bit more effort, i use this to generate image preview tooltips in apache’s autoindex [=

    17th February 2009 at 2:57 am

  9. Flashsnake says:

    What should I do if I need to save the png image as a file? I tried to use:

    imagepng($png, “sample.png”);

    But the image turns out to be blank.

    Thanks,

    17th February 2009 at 7:56 pm

  10. admin says:

    imagepng($png, “filename.png”);
    should work…

    If not, I would check:
    - that you have the GD library installed and available on your system
    - that it’s not a file permissions issue (php not allowed to write to the directory you’re working in)
    - that the original .ico you’re converting isn’t blank or malformed

    When all else fails, try some troubleshooting. See if imagegif($png, “filename.gif”); works, etc.

    17th February 2009 at 2:09 am

  11. edward de leau says:

    I sometimes get the following notice on some icons:

    Notice: Uninitialized string offset: 64 in class.ico.php on line 296

    Im using the class in my WordPress plugin so it loads thousands of different ico’s on some I get this error.

    17th February 2009 at 9:12 am

  12. Edward de Leau says:

    XOR ing the icon sometimes goes wrong on line 298: $bits .= str_pad(decbin(ord($this->formats[$index]['data'][$offset + $i])), 8, ‘0′, STR_PAD_LEFT);

    e.g. with icon found here: http://www.slatch.com/ as favicon

    17th February 2009 at 7:50 pm

Leave a comment

*

WP SlimStat