seedhammer-v1-companion/image/alpha4/alpha4.go
mineracks 9261cf368a Lift composer substrate from upstream v1.3.0
Twelve packages lifted from seedhammer/seedhammer @ v1.3.0
(commit 2f071c1d8f23eb7fd39b15fc0acb8874113f801e):

  address/     — bitcoin address parsing
  backup/      — v1 plate dimensions + UR-coded multi-plate backup
  bc/          — Blockchain Commons: ur, fountain, bytewords, urtypes,
                 xoshiro256 (5 subpkgs)
  bip32/       — HD-key derivation
  bip39/       — mnemonic seed phrases + 2048-word wordlist
  engrave/     — text/QR → MoveTo/LineTo command stream conversion
  seedqr/      — SeedQR / CompactSeedQR encoders
  image/       — paletted, rgb565, alpha4, ninepatch image formats
  nonstandard/ — bitcoin descriptor + script parsing
  font/        — bitmap + vector font runtime
  font/{comfortaa,poppins,constant,bitmap,vector}/  — actual fonts
  driver/mjolnir/  — MarkingWay USB-serial engraver driver

Plus an earlier-aside backup_test.go restored (its deps are now lifted).

Import paths globally rewritten seedhammer.com → mineracks namespace
via single sed pass; verified no orphan refs remain. go.mod adopts
upstream's full dep set plus the replace-directive for the patched
kortschak/qr fork.

  go build ./...     clean (all 27 packages)
  go test ./...      clean (12 packages with tests, all passing)

NOT lifted in this commit:
  - driver/{wshat,drm,libcamera}  (hardware-specific GPIO/LCD/camera —
    will be platform-v1/-shaped abstractions instead)
  - gui/                (depends on the above; lifts in Phase 2)
  - cmd/{controller,...} (Pi binary entrypoints — not needed for the
    companion repo)
  - zbar/               (QR scanner — needs libcamera)

Next:
  - Write the SH1E reference encoder/decoder in engrave/wire/sh1e/
  - Lift Gangleri42's cmd/webnfc/ shell + retune to v1 plates
  - First buildable composer WASM with a working preview

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 18:36:40 +10:00

79 lines
1.6 KiB
Go

// Package alpha4 implements an [image.Alpha] replacement
// with compact 4-bit alpha values.
package alpha4
import (
"image"
"image/color"
)
type Image struct {
Pix []byte
Rect Rectangle
}
type Rectangle struct {
MinX, MinY, MaxX, MaxY int8
}
func New(r Rectangle) *Image {
npixels := int(r.MaxX-r.MinX) * int(r.MaxY-r.MinY)
return &Image{
Pix: make([]byte, (npixels+1)/2),
Rect: r,
}
}
func (p *Image) ColorModel() color.Model { panic("not implemented") }
func (p *Image) Bounds() image.Rectangle { return p.Rect.Rect() }
func (p *Image) At(x, y int) color.Color {
return p.AlphaAt(x, y)
}
func (p *Image) RGBA64At(x, y int) color.RGBA64 {
a := uint16(p.AlphaAt(x, y).A)
a |= a << 8
return color.RGBA64{a, a, a, a}
}
func (p *Image) AlphaAt(x, y int) color.Alpha {
if !(image.Point{x, y}.In(p.Rect.Rect())) {
return color.Alpha{}
}
i := p.PixOffset(x, y)
a2 := p.Pix[i/2]
return color.Alpha{alpha4(i, a2)}
}
func alpha4(i int, a2 byte) byte {
a := (a2 >> ((^i & 0b1) * 4)) & 0b1111
return a<<4 | a
}
func (p *Image) PixOffset(x, y int) int {
return (y-int(p.Rect.MinY))*int(p.Rect.MaxX-p.Rect.MinX) + (x - int(p.Rect.MinX))
}
func (r Rectangle) Rect() image.Rectangle {
return image.Rect(int(r.MinX), int(r.MinY), int(r.MaxX), int(r.MaxY))
}
func (p *Image) Set(x, y int, c color.Color) {
panic("not implemented")
}
func (p *Image) SetRGBA64(x, y int, c color.RGBA64) {
if !(image.Point{x, y}).In(p.Rect.Rect()) {
return
}
i := p.PixOffset(x, y)
a2 := p.Pix[i/2]
mask := byte(0b1111) << ((i & 0b1) * 4)
a2 &= mask
a := byte(c.A >> 12)
a <<= ((^i & 0b1) * 4)
p.Pix[i/2] = a2 | a
}