limage - xcf/compressed.go
1 package xcf
2
3 import (
4 "image"
5 "image/color"
6 "io"
7
8 "vimagination.zapto.org/byteio"
9 "vimagination.zapto.org/limage/lcolor"
10 "vimagination.zapto.org/memio"
11 )
12
13 type compressedImage struct {
14 tiles [][][]byte
15 width int
16 tile int
17 decompressed [64 * 64 * 4]byte
18 }
19
20 func (c *compressedImage) decompressTile(x, y int) int {
21 tile := (y/64)*((c.width+63)/64) + (x / 64)
22 if tile != c.tile {
23 var (
24 n int
25 data memio.Buffer
26 )
27 r := rle{Reader: &byteio.StickyBigEndianReader{Reader: &data}}
28 for n, data = range c.tiles[tile] {
29 r.Read(c.decompressed[64*64*n : 64*64*(n+1)])
30 if r.Reader.Err == io.EOF {
31 r.Reader.Err = nil
32 }
33 }
34 c.tile = tile
35 }
36 if x < c.width & ^63 {
37 return 64*(y%64) + (x % 64)
38 }
39 return (c.width&63)*(y%64) + (x % 64)
40 }
41
42 // CompressedRGB is an image.Image for which the data remains in a compressed
43 // form until read.
44 type CompressedRGB struct {
45 compressedImage
46 Rect image.Rectangle
47 }
48
49 // ColorModel returns the RGB Color Model
50 func (CompressedRGB) ColorModel() color.Model { return lcolor.RGBModel }
51
52 // Bounds returns a Rect containg the boundary data for the image
53 func (c *CompressedRGB) Bounds() image.Rectangle { return c.Rect }
54
55 // At returns colour at the specified coords
56 func (c *CompressedRGB) At(x, y int) color.Color { return c.RGBAt(x, y) }
57
58 // RGBAt returns RGB colour at the specified coords
59 func (c *CompressedRGB) RGBAt(x, y int) lcolor.RGB {
60 if !(image.Point{x, y}).In(c.Rect) {
61 return lcolor.RGB{}
62 }
63 p := c.decompressTile(x, y)
64 return lcolor.RGB{
65 R: c.decompressed[p],
66 G: c.decompressed[p+64*64],
67 B: c.decompressed[p+64*64*2],
68 }
69 }
70
71 // CompressedNRGB is an image.Image for which the data remains in a compressed
72 // form until read.
73 type CompressedNRGBA struct {
74 compressedImage
75 Rect image.Rectangle
76 }
77
78 // ColorModel returns the NRGBA Color Model
79 func (CompressedNRGBA) ColorModel() color.Model { return color.NRGBAModel }
80
81 // Bounds returns a Rect containg the boundary data for the image
82 func (c *CompressedNRGBA) Bounds() image.Rectangle { return c.Rect }
83
84 // At returns colour at the specified coords
85 func (c *CompressedNRGBA) At(x, y int) color.Color { return c.NRGBAAt(x, y) }
86
87 // NRGBAAt returns NRGBA colour at the specified coords
88 func (c *CompressedNRGBA) NRGBAAt(x, y int) color.NRGBA {
89 if !(image.Point{x, y}).In(c.Rect) {
90 return color.NRGBA{}
91 }
92 p := c.decompressTile(x, y)
93 return color.NRGBA{
94 c.decompressed[p],
95 c.decompressed[p+64*64],
96 c.decompressed[p+64*64*2],
97 c.decompressed[p+64*64*3],
98 }
99 }
100
101 // CompressedGray is an image.Image for which the data remains in a compressed
102 // form until read.
103 type CompressedGray struct {
104 compressedImage
105 Rect image.Rectangle
106 }
107
108 // ColorModel returns the Gray Color Model
109 func (CompressedGray) ColorModel() color.Model { return color.GrayModel }
110
111 // Bounds returns a Rect containg the boundary data for the image
112 func (c *CompressedGray) Bounds() image.Rectangle { return c.Rect }
113
114 // At returns colour at the specified coords
115 func (c *CompressedGray) At(x, y int) color.Color { return c.GrayAt(x, y) }
116
117 // GrayAt returns Gray colour at the specified coords
118 func (c *CompressedGray) GrayAt(x, y int) color.Gray {
119 if !(image.Point{x, y}).In(c.Rect) {
120 return color.Gray{}
121 }
122 p := c.decompressTile(x, y)
123 return color.Gray{
124 c.decompressed[p],
125 }
126 }
127
128 // CompressedGrayAlpha is an image.Image for which the data remains in a
129 // compressed form until read.
130 type CompressedGrayAlpha struct {
131 compressedImage
132 Rect image.Rectangle
133 }
134
135 // ColorModel returns the Gray Alpha Color Model
136 func (CompressedGrayAlpha) ColorModel() color.Model { return lcolor.GrayAlphaModel }
137
138 // Bounds returns a Rect containg the boundary data for the image
139 func (c *CompressedGrayAlpha) Bounds() image.Rectangle { return c.Rect }
140
141 // At returns colour at the specified coords
142 func (c *CompressedGrayAlpha) At(x, y int) color.Color { return c.GrayAlphaAt(x, y) }
143
144 // GrayAlphaAt returns Gray+Alpha colour at the specified coords
145 func (c *CompressedGrayAlpha) GrayAlphaAt(x, y int) lcolor.GrayAlpha {
146 if !(image.Point{x, y}).In(c.Rect) {
147 return lcolor.GrayAlpha{}
148 }
149 p := c.decompressTile(x, y)
150 return lcolor.GrayAlpha{
151 Y: c.decompressed[p],
152 A: c.decompressed[p+64*64],
153 }
154 }
155
156 // CompressedPaletted is an image.Image for which the data remains in a
157 // compressed form until read.
158 type CompressedPaletted struct {
159 compressedImage
160 Rect image.Rectangle
161 Palette color.Palette
162 }
163
164 // ColorModel returns the Pallette of the image
165 func (c *CompressedPaletted) ColorModel() color.Model { return c.Palette }
166
167 // Bounds returns a Rect containg the boundary data for the image
168 func (c *CompressedPaletted) Bounds() image.Rectangle { return c.Rect }
169
170 // At returns colour at the specified coords
171 func (c *CompressedPaletted) At(x, y int) color.Color {
172 if c.Palette == nil {
173 return nil
174 }
175 if !(image.Point{x, y}).In(c.Rect) {
176 return color.Gray{}
177 }
178 p := c.decompressTile(x, y)
179 i := c.decompressed[p]
180 r, g, b, _ := c.Palette[i].RGBA()
181 return color.NRGBA{
182 R: uint8(r >> 8),
183 G: uint8(g >> 8),
184 B: uint8(b >> 8),
185 A: 255,
186 }
187 }
188
189 // CompressedPalettedAlpha is an image.Image for which the data remains in a
190 // compressed form until read.
191 type CompressedPalettedAlpha struct {
192 compressedImage
193 Rect image.Rectangle
194 Palette lcolor.AlphaPalette
195 }
196
197 // ColorModel returns the Pallette of the image
198 func (c *CompressedPalettedAlpha) ColorModel() color.Model { return c.Palette }
199
200 // Bounds returns a Rect containg the boundary data for the image
201 func (c *CompressedPalettedAlpha) Bounds() image.Rectangle { return c.Rect }
202
203 // At returns colour at the specified coords
204 func (c *CompressedPalettedAlpha) At(x, y int) color.Color {
205 if c.Palette == nil {
206 return nil
207 }
208 if !(image.Point{x, y}).In(c.Rect) {
209 return color.Gray{}
210 }
211 p := c.decompressTile(x, y)
212 r, g, b, _ := c.Palette[c.decompressed[p]].RGBA()
213 return color.NRGBA{
214 R: uint8(r >> 8),
215 G: uint8(g >> 8),
216 B: uint8(b >> 8),
217 A: c.decompressed[64*64+p],
218 }
219 }
220