Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid PNG metadata when ICONDIRENTRY has a bitCount of zero #13

Open
rosasurfer opened this issue May 8, 2019 · 2 comments
Open

Invalid PNG metadata when ICONDIRENTRY has a bitCount of zero #13

rosasurfer opened this issue May 8, 2019 · 2 comments

Comments

@rosasurfer
Copy link

rosasurfer commented May 8, 2019

Thank you for this little libray. I face an issue with a specific icon which has mixed BMP and PNG images. In this case it's a 256x256 PNG contained in ResourceHacker's main executable:
http://angusj.com/resourcehacker/

If an icon contains a PNG image and in ICONDIRENTRY the PNG's bitCount is set to zero the value in IconImage is not updated to the PNG's real bit depth.

How to reproduce:

$service = new IcoFileService();
$icon = $service->from(file_get_contents('http://rosasurfer.com/.intern/mixed.ico'));
/** @var IconImage $image */
foreach ($icon as $image) {
    echo $image->getDescription().PHP_EOL;
}

Expected result:

256x256 pixel PNG @ 32 bits/pixel
64x64 pixel BMP @ 32 bits/pixel
48x48 pixel BMP @ 32 bits/pixel
40x40 pixel BMP @ 32 bits/pixel
32x32 pixel BMP @ 32 bits/pixel
24x24 pixel BMP @ 32 bits/pixel
20x20 pixel BMP @ 32 bits/pixel
16x16 pixel BMP @ 32 bits/pixel

Actual result:

256x256 pixel PNG @ 0 bits/pixel
64x64 pixel BMP @ 32 bits/pixel
48x48 pixel BMP @ 32 bits/pixel
40x40 pixel BMP @ 32 bits/pixel
32x32 pixel BMP @ 32 bits/pixel
24x24 pixel BMP @ 32 bits/pixel
20x20 pixel BMP @ 32 bits/pixel
16x16 pixel BMP @ 32 bits/pixel

I worked around it by adding the following snippet to IconParser::parseIconDirEntries() but I don't know the header format good enough and suspect I break cases where a bitCount of zero has a different valid meaning.

if ($icoDirEntry['bitCount'] == 0) {
    $icoDirEntry['bitCount'] = 32;
}

Wouldn't it be better to parse the actual PNG header instead of using possibly conflicting ICONDIRENTRY values? I use this little library which only needs to read the first 29 bytes of a PNG:
https://github.com/ktomk/Miscellaneous/tree/master/get_png_imageinfo

Another note: All internal parser methods are private and there is no way to re-use your class. Can you consider making them protected?

Thank you again.

@lordelph
Copy link
Owner

lordelph commented May 8, 2019

Thanks for the detailed report - much appreciated. It looks like what should happen is that if the bit depth is 0, the image data is inspected to determine the bit depth. I'll come up with a fix for that.

Re the private methods, what were you hoping to override?

@rosasurfer
Copy link
Author

rosasurfer commented May 9, 2019

Re the private methods: As I didn't want to modify your code I intended to fix the issue by passing an extended version of your parser into the IcoFileService constructor, until I realized that I can't and that I have to duplicate and rewrite your class.
In my experience it's best OOP practice to make any non-public api protected instead of private, especially in open source. You never know what strange ideas other people come up with. :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants