At(x, y int) Color
}
+// PalettedImage is an image whose colors may come from a limited palette.
+// If m is a PalettedImage and m.ColorModel() returns a PalettedColorModel p,
+// then m.At(x, y) should be equivalent to p[m.ColorIndexAt(x, y)]. If m's
+// color model is not a PalettedColorModel, then ColorIndexAt's behavior is
+// undefined.
+type PalettedImage interface {
+ // ColorIndexAt returns the palette index of the pixel at (x, y).
+ ColorIndexAt(x, y int) uint8
+ Image
+}
+
// RGBA is an in-memory image of RGBAColor values.
type RGBA struct {
// Pix holds the image's pixels, in R, G, B, A order. The pixel at
dr, dg, db := diff(cr, vr), diff(cg, vg), diff(cb, vb)
ssd := (dr * dr) + (dg * dg) + (db * db)
if ssd < bestSSD {
+ if ssd == 0 {
+ return i
+ }
ret, bestSSD = i, ssd
}
}
}
}
case cbP8:
- paletted := m.(*image.Paletted)
- offset := (y - b.Min.Y) * paletted.Stride
- copy(cr[0][1:], paletted.Pix[offset:offset+b.Dx()])
+ if p, _ := m.(*image.Paletted); p != nil {
+ offset := (y - b.Min.Y) * p.Stride
+ copy(cr[0][1:], p.Pix[offset:offset+b.Dx()])
+ } else {
+ pi := m.(image.PalettedImage)
+ for x := b.Min.X; x < b.Max.X; x++ {
+ cr[0][i] = pi.ColorIndexAt(x, y)
+ i += 1
+ }
+ }
case cbTCA8:
// Convert from image.Image (which is alpha-premultiplied) to PNG's non-alpha-premultiplied.
for x := b.Min.X; x < b.Max.X; x++ {
var e encoder
e.w = w
e.m = m
- pal, _ := m.(*image.Paletted)
+
+ var pal image.PalettedColorModel
+ // cbP8 encoding needs PalettedImage's ColorIndexAt method.
+ if _, ok := m.(image.PalettedImage); ok {
+ pal, _ = m.ColorModel().(image.PalettedColorModel)
+ }
if pal != nil {
e.cb = cbP8
} else {
_, e.err = io.WriteString(w, pngHeader)
e.writeIHDR()
if pal != nil {
- e.writePLTE(pal.Palette)
- e.maybeWritetRNS(pal.Palette)
+ e.writePLTE(pal)
+ e.maybeWritetRNS(pal)
}
e.writeIDATs()
e.writeIEND()