2
$\begingroup$

When I try to import any .ico file, I get the following error

IcNames = FileNames[{"*.ico"}, "c:\\Users\\gal\\Documents\\D0\\ikone\\"];
Import[IcNames[[26]]  ]

enter image description here

How to fix it?

$\endgroup$
2
  • $\begingroup$ Does this work? Import["ExampleData/mathematica3.ico"]? What version of Mathematica are you running? $\endgroup$ May 3, 2021 at 18:28
  • $\begingroup$ It works. Looks like it works for small icons, but I'm not sure. I'm using 12.1 $\endgroup$ May 3, 2021 at 19:59

1 Answer 1

5
$\begingroup$

It looks like Mathematica's importer for .ico files doesn't implement the latest standard. Specifically, it doesn't support images in PNG format. Luckily, PNG files are embedded in their entirety, so it is quite straightforward to patch the .ico importer to support PNG files:

Quiet@ImportString["", "ICO"];
Begin["System`Convert`ICODump`"];
Once[
 DownValues@`ImportIconResource = DownValues@`ImportIconResource /.
    w_Which :> If[`width == 169478669,
      SetStreamPosition[`strm, Last@`entry];
      `data = ImportByteArray[ByteArray@BinaryReadList[`strm, "Byte", `entry[[-2]]], "PNG"];
      Sow[ImageData@`data, "Data"];
      Sow[ImageDimensions@`data, "ImageSize"],
      w
      ];
 ]
End[];

This works by patching the relevant definition System`Convert`ICODump`ImportIconResource:

  • We are only interested in the part of the code handling the individual data blocks, as the header is read properly. This means we can add our patch after the header of the data block has been read
  • First, we check whether the first 8 bytes of the data block match the PNG signature. We only check the last 4 bytes (which are stored into width) since the first 4 are discarded, but since width should never be bigger than 256, this shouldn't pose any issues.
  • If we have a PNG entry, we simply read the relevant part of the file and pass it to ImportByteArray, and interpret it as a PNG.
  • Finally, we extract the dimensions and image data
  • If the data are in the BMP format, we don't need to do anything, and can simply use the existing code

Before and after the fix: enter image description here

$\endgroup$
1
  • $\begingroup$ Thanks, this works. $\endgroup$ May 4, 2021 at 11:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.