limage - indexedalpha.go
1 package limage
2
3 import (
4 "image"
5 "image/color"
6
7 "vimagination.zapto.org/limage/lcolor"
8 )
9
10 // PalettedAlpha represents a paletted image with an alpha channel.
11 type PalettedAlpha struct {
12 Pix []lcolor.IndexedAlpha
13 Stride int
14 Rect image.Rectangle
15 Palette lcolor.AlphaPalette
16 }
17
18 // NewPalettedAlpha creates a new image that uses a palette with an alpha channel.
19 func NewPalettedAlpha(r image.Rectangle, p lcolor.AlphaPalette) *PalettedAlpha {
20 w, h := r.Dx(), r.Dy()
21
22 return &PalettedAlpha{
23 Pix: make([]lcolor.IndexedAlpha, w*h),
24 Stride: w,
25 Rect: r,
26 Palette: p,
27 }
28 }
29
30 // At returns the color of the pixel at the given coords.
31 func (p *PalettedAlpha) At(x, y int) color.Color {
32 if p.Palette == nil {
33 return nil
34 }
35
36 ia := p.IndexAlphaAt(x, y)
37 r, g, b, _ := p.Palette[ia.I].RGBA()
38
39 return color.NRGBA{
40 R: uint8(r >> 8),
41 G: uint8(g >> 8),
42 B: uint8(b >> 8),
43 A: ia.A,
44 }
45 }
46
47 // Bounds returns the limits of the image.
48 func (p *PalettedAlpha) Bounds() image.Rectangle {
49 return p.Rect
50 }
51
52 // ColorModel a color model to transform arbitrary colors to one in the palette.
53 func (p *PalettedAlpha) ColorModel() color.Model {
54 return p.Palette
55 }
56
57 // IndexAlphaAt returns the palette index and Alpha component of the given
58 // coords.
59 func (p *PalettedAlpha) IndexAlphaAt(x, y int) lcolor.IndexedAlpha {
60 if !(image.Point{x, y}.In(p.Rect)) {
61 return lcolor.IndexedAlpha{}
62 }
63
64 return p.Pix[p.PixOffset(x, y)]
65 }
66
67 // Opaque returns true if the image is completely opaque.
68 func (p *PalettedAlpha) Opaque() bool {
69 for _, c := range p.Pix {
70 if c.A != 255 {
71 return true
72 }
73 }
74
75 return false
76 }
77
78 // PixOffset returns the index of the Pix array corresponding to the given
79 // coords.
80 func (p *PalettedAlpha) PixOffset(x, y int) int {
81 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
82 }
83
84 // Set converts the given colour to the closest in the palette and sets it at
85 // the given coords.
86 func (p *PalettedAlpha) Set(x, y int, c color.Color) {
87 if !(image.Point{x, y}.In(p.Rect)) {
88 return
89 }
90
91 _, _, _, a := c.RGBA()
92 p.Pix[p.PixOffset(x, y)] = lcolor.IndexedAlpha{
93 I: uint8(p.Palette.Index(c)),
94 A: uint8(a >> 8),
95 }
96 }
97
98 // SetIndexAlpha directly set the index and alpha channels to the given coords.
99 func (p *PalettedAlpha) SetIndexAlpha(x, y int, ia lcolor.IndexedAlpha) {
100 if !(image.Point{x, y}.In(p.Rect)) {
101 return
102 }
103
104 p.Pix[p.PixOffset(x, y)] = ia
105 }
106
107 // SubImage returns the Image viewable through the given bounds.
108 func (p *PalettedAlpha) SubImage(r image.Rectangle) image.Image {
109 r = r.Intersect(p.Rect)
110
111 if r.Empty() {
112 return &PalettedAlpha{}
113 }
114
115 return &PalettedAlpha{
116 Pix: p.Pix[p.PixOffset(r.Min.X, r.Min.Y):],
117 Stride: p.Stride,
118 Rect: r,
119 Palette: p.Palette,
120 }
121 }
122