aboutsummaryrefslogtreecommitdiff
path: root/src/image
diff options
context:
space:
mode:
authorkawakami <kawakami.ozone@gmail.com>2019-05-16 03:11:44 +0900
committerBenny Siegert <bsiegert@gmail.com>2019-05-22 20:41:27 +0000
commit983986f23d81eae6ee202bd31383d04e73187536 (patch)
treee97b18c39102f28325171efe149e4f7245dc4a00 /src/image
parent94a9dad8fdcd7adf2036482391f715ea3ab35cd9 (diff)
downloadgo-983986f23d81eae6ee202bd31383d04e73187536.tar.gz
go-983986f23d81eae6ee202bd31383d04e73187536.zip
image/gif: fix transparency loss when encoding a wrapped *image.Paletted
This keeps transparency of a wrapped image.Image even after it is encoded. Fixes #30995 Change-Id: I1f7ac98b1741f83ed740f6eda6c36b7e9b16e5af Reviewed-on: https://go-review.googlesource.com/c/go/+/177377 Reviewed-by: Hayato Kawakami <kawakami.ozone@gmail.com> Reviewed-by: Benny Siegert <bsiegert@gmail.com> Run-TryBot: Benny Siegert <bsiegert@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/image')
-rw-r--r--src/image/gif/writer.go14
-rw-r--r--src/image/gif/writer_test.go81
-rw-r--r--src/image/testdata/triangle-001.gifbin0 -> 1476 bytes
3 files changed, 90 insertions, 5 deletions
diff --git a/src/image/gif/writer.go b/src/image/gif/writer.go
index 5819df0dd0..7220446de5 100644
--- a/src/image/gif/writer.go
+++ b/src/image/gif/writer.go
@@ -433,8 +433,18 @@ func Encode(w io.Writer, m image.Image, o *Options) error {
opts.Drawer = draw.FloydSteinberg
}
- pm, ok := m.(*image.Paletted)
- if !ok || len(pm.Palette) > opts.NumColors {
+ pm, _ := m.(*image.Paletted)
+ if pm == nil {
+ if cp, ok := m.ColorModel().(color.Palette); ok {
+ pm = image.NewPaletted(b, cp)
+ for y := b.Min.Y; y < b.Max.Y; y++ {
+ for x := b.Min.X; x < b.Max.X; x++ {
+ pm.Set(x, y, cp.Convert(m.At(x, y)))
+ }
+ }
+ }
+ }
+ if pm == nil || len(pm.Palette) > opts.NumColors {
// Set pm to be a palettedized copy of m, including its bounds, which
// might not start at (0, 0).
//
diff --git a/src/image/gif/writer_test.go b/src/image/gif/writer_test.go
index 91275bb907..0bc24d1bee 100644
--- a/src/image/gif/writer_test.go
+++ b/src/image/gif/writer_test.go
@@ -48,11 +48,17 @@ func delta(u0, u1 uint32) int64 {
// have the same bounds.
func averageDelta(m0, m1 image.Image) int64 {
b := m0.Bounds()
+ return averageDeltaBound(m0, m1, b, b)
+}
+
+// averageDeltaBounds returns the average delta in RGB space. The average delta is
+// calulated in the specified bounds.
+func averageDeltaBound(m0, m1 image.Image, b0, b1 image.Rectangle) int64 {
var sum, n int64
- for y := b.Min.Y; y < b.Max.Y; y++ {
- for x := b.Min.X; x < b.Max.X; x++ {
+ for y := b0.Min.Y; y < b0.Max.Y; y++ {
+ for x := b0.Min.X; x < b0.Max.X; x++ {
c0 := m0.At(x, y)
- c1 := m1.At(x, y)
+ c1 := m1.At(x-b0.Min.X+b1.Min.X, y-b0.Min.Y+b1.Min.Y)
r0, g0, b0, _ := c0.RGBA()
r1, g1, b1, _ := c1.RGBA()
sum += delta(r0, r1)
@@ -581,6 +587,75 @@ func TestEncodeCroppedSubImages(t *testing.T) {
}
}
+type offsetImage struct {
+ image.Image
+ Rect image.Rectangle
+}
+
+func (i offsetImage) Bounds() image.Rectangle {
+ return i.Rect
+}
+
+func TestEncodeWrappedImage(t *testing.T) {
+ m0, err := readImg("../testdata/video-001.gif")
+ if err != nil {
+ t.Fatalf("readImg: %v", err)
+ }
+
+ // Case 1: Enocde a wrapped image.Image
+ buf := new(bytes.Buffer)
+ w0 := offsetImage{m0, m0.Bounds()}
+ err = Encode(buf, w0, nil)
+ if err != nil {
+ t.Fatalf("Encode: %v", err)
+ }
+ w1, err := Decode(buf)
+ if err != nil {
+ t.Fatalf("Dencode: %v", err)
+ }
+ avgDelta := averageDelta(m0, w1)
+ if avgDelta > 0 {
+ t.Fatalf("Wrapped: average delta is too high. expected: 0, got %d", avgDelta)
+ }
+
+ // Case 2: Enocde a wrapped image.Image with offset
+ b0 := image.Rectangle{
+ Min: image.Point{
+ X: 128,
+ Y: 64,
+ },
+ Max: image.Point{
+ X: 256,
+ Y: 128,
+ },
+ }
+ w0 = offsetImage{m0, b0}
+ buf = new(bytes.Buffer)
+ err = Encode(buf, w0, nil)
+ if err != nil {
+ t.Fatalf("Encode: %v", err)
+ }
+ w1, err = Decode(buf)
+ if err != nil {
+ t.Fatalf("Dencode: %v", err)
+ }
+
+ b1 := image.Rectangle{
+ Min: image.Point{
+ X: 0,
+ Y: 0,
+ },
+ Max: image.Point{
+ X: 128,
+ Y: 64,
+ },
+ }
+ avgDelta = averageDeltaBound(m0, w1, b0, b1)
+ if avgDelta > 0 {
+ t.Fatalf("Wrapped and offset: average delta is too high. expected: 0, got %d", avgDelta)
+ }
+}
+
func BenchmarkEncode(b *testing.B) {
bo := image.Rect(0, 0, 640, 480)
rnd := rand.New(rand.NewSource(123))
diff --git a/src/image/testdata/triangle-001.gif b/src/image/testdata/triangle-001.gif
new file mode 100644
index 0000000000..f3d45bbfa4
--- /dev/null
+++ b/src/image/testdata/triangle-001.gif
Binary files differ