]> Cypherpunks repositories - gostls13.git/commitdiff
image: add PalettedImage interface, and make image/png recognize it.
authorJaroslavas Počepko <jp@webmaster.ms>
Tue, 30 Aug 2011 22:27:00 +0000 (08:27 +1000)
committerNigel Tao <nigeltao@golang.org>
Tue, 30 Aug 2011 22:27:00 +0000 (08:27 +1000)
R=golang-dev, rsc, bradfitz, nigeltao
CC=golang-dev
https://golang.org/cl/4956046

src/pkg/image/image.go
src/pkg/image/png/writer.go

index 11def94354ad9570d435f7793388b8454332d9a9..a01cda864e0789a4fb9b2dbe7e53c4db846be50d 100644 (file)
@@ -24,6 +24,17 @@ type Image interface {
        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
@@ -741,6 +752,9 @@ func (p PalettedColorModel) Index(c Color) int {
                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
                }
        }
index 55ca97e0628ed98dd2da24be53cd4c5665b6f800..f9556a0f906dda77027374eba17dc6b21b6b1cd8 100644 (file)
@@ -336,9 +336,16 @@ func writeImage(w io.Writer, m image.Image, cb int) os.Error {
                                }
                        }
                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++ {
@@ -432,7 +439,12 @@ func Encode(w io.Writer, m image.Image) os.Error {
        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 {
@@ -459,8 +471,8 @@ func Encode(w io.Writer, m image.Image) os.Error {
        _, 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()