commit 869b4415ed08771acef515a3da3acd185fb893d4
parent ead765cb05a444c720f1395cc1b413044622a708
Author: Andy Williams <andy@andy.xyz>
Date: Mon, 13 Apr 2020 11:21:52 +0100
Fix parsing of some modern ICNS files (#2)
* Fix parsing to skip complete sections
TOC is variable length
Icons that are not recognised should be skipped as well
Fixes rendering of Apple Mail and other modern icons
* Don't even try to parse JPEG2000 images
* Tidy up code for skipping JPEG2000
* Clean up naming
Diffstat:
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/reader.go b/reader.go
@@ -11,6 +11,8 @@ import (
"github.com/pkg/errors"
)
+var jpeg2000header = []byte{0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20}
+
// Decode finds the largest icon listed in the icns file and returns it,
// ignoring all other sizes. The format returned will be whatever the icon data
// is, typically jpeg or png.
@@ -31,17 +33,28 @@ func Decode(r io.Reader) (image.Image, error) {
read += 4
switch string(next) {
case "TOC ":
- read += 4
+ tocSize := binary.BigEndian.Uint32(data[read : read+4])
+ read += tocSize-4 // size includes header and size fields
continue
case "icnV":
read += 4
continue
}
+
+ dataSize := binary.BigEndian.Uint32(data[read : read+4])
+ read += 4
+ if dataSize == 0 {
+ continue // no content, we're not interested
+ }
+
+ iconData := data[read : read+dataSize-8]
+ read += dataSize-8 // size includes header and size fields
+
if isOsType(string(next)) {
- iconSize := binary.BigEndian.Uint32(data[read : read+4])
- read += 4
- iconData := data[read : read+iconSize]
- read += iconSize
+ if bytes.Equal(iconData[:8], jpeg2000header) {
+ continue // skipping JPEG2000
+ }
+
icons = append(icons, iconReader{
OsType: osTypeFromID(string(next)),
r: bytes.NewBuffer(iconData),