icns

Easily create .icns files (Mac Icons) with this Go library or the included CLI.
Log | Files | Refs | LICENSE

commit 56bd4e8ba5a555d192d0bad277c3a736c9906991
parent a0554fe76cb70ad063a045dcbe2428a7f0c38dbd
Author: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Date:   Fri, 18 Sep 2026 16:09:32 -0400

cmd/shell-extension: decode only the icon it needs

Explorer asks for one thumbnail at a time, and the provider decoded every
icon in the file to return one of them. Files now carry more elements than
they did, so the waste grew with them.

Diffstat:
Mcmd/shell-extension/internal/provider/provider.go | 25++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/cmd/shell-extension/internal/provider/provider.go b/cmd/shell-extension/internal/provider/provider.go @@ -198,16 +198,31 @@ func Thumbnail(r io.Reader, cx int) (*image.RGBA, error) { if cx <= 0 { return nil, fmt.Errorf("invalid thumbnail size %d", cx) } - images, err := icns.DecodeAll(r) // Sorted largest first. + d, err := icns.NewDecoder(r) if err != nil { return nil, err } - chosen := images[0] - for _, img := range images { - if side(img) < cx { + // The icons arrive largest first, so the last one still at least cx wide + // is the smallest that does not need upscaling. Only that one is decoded. + var ( + best icns.Entry + found bool + ) + for _, icon := range d.Icons() { + if icon.ImageFormat == icns.ImageFormatJPEG2000 { + continue + } + if found && int(icon.Size) < cx { break } - chosen = img + best, found = icon, true + } + if !found { + return nil, fmt.Errorf("no icon in a format this build can decode") + } + chosen, err := best.Decode() + if err != nil { + return nil, err } // Normalise to premultiplied RGBA, which is what a GDI ARGB bitmap // wants, shrinking the icon to fit the cx square on the way if needed.