commit 23ec0ba0840b4bef57b45266e6ea7482080dce46
parent 335a96d4f5a847f6dba50f5572b012bc2909d756
Author: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Date: Fri, 18 Sep 2026 16:09:33 -0400
docs: describe per-slot encoding and single icon decoding
Neither entry point is discoverable from the existing examples, and the slot
rather than pixel size keying needs saying: it is the part a reader would
otherwise get wrong. Payload is also the only route to a JPEG 2000 icon.
Diffstat:
2 files changed, 45 insertions(+), 0 deletions(-)
diff --git a/doc.go b/doc.go
@@ -15,6 +15,11 @@
// using this library from the command line. It supports piping, which is
// something `iconutil` does not do, making it substantially easier to wrap.
//
+// Encode resizes one image into every size. EncodeSlots takes a drawing per
+// slot, as an iconset directory holds, and resizes only the slots left empty.
+// NewDecoder reads the other way, identifying the icons in a file so that a
+// caller can decode only the size it wants.
+//
// Note: icns files are written with an icon at every size macOS draws, the
// retina OSTypes for the larger ones and the colour and mask pair Apple still
// uses at 16 and 32 pixels.
diff --git a/readme.md b/readme.md
@@ -98,6 +98,10 @@ Standard
`icnsify -i icon.icns -o icon.png`
+From an iconset directory, which uses each drawing where it is given instead of resizing one image for every size
+
+`icnsify -i MyIcon.iconset -o MyIcon.icns`
+
## Library
`go get github.com/jackmordaunt/icns/v4`
@@ -124,6 +128,42 @@ func main() {
}
```
+### Per-size artwork
+
+Icons are usually hand tuned at the small sizes rather than reduced from the large one. `EncodeSlots` takes a drawing per slot and resizes only the slots left empty, filling them from the largest image given.
+
+```go
+images := map[icns.Slot]image.Image{
+ {Points: 16, Scale: 1}: small, // icon_16x16.png
+ {Points: 512, Scale: 2}: large, // icon_512x512@2x.png
+}
+if err := icns.NewEncoder(dest).EncodeSlots(images); err != nil {
+ log.Fatalf("encoding icns: %v", err)
+}
+```
+
+A slot is a size and a display scale, because 16x16@2x and 32x32 are both 32 pixels of artwork but fill different elements. `icns.Slots()` lists the ten a file holds and `icns.ParseSlot` reads iconset file names.
+
+### Reading one size
+
+`NewDecoder` identifies the icons without decoding any of them, so reading a single size does not pay for the rest.
+
+```go
+d, err := icns.NewDecoder(src)
+if err != nil {
+ log.Fatalf("reading icns: %v", err)
+}
+for _, icon := range d.Icons() { // Largest first.
+ if icon.Size > 128 {
+ continue
+ }
+ img, err := icon.Decode()
+ ...
+}
+```
+
+`Entry.Payload` returns the bytes the file stores, which is how to reach a JPEG 2000 icon: this package identifies that format but cannot decode it.
+
## Development
The repository is a Go workspace of three modules: