mirror of
https://github.com/golang/go
synced 2024-11-27 02:31:18 -07:00
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>
This commit is contained in:
parent
94a9dad8fd
commit
983986f23d
@ -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).
|
||||
//
|
||||
|
@ -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))
|
||||
|
BIN
src/image/testdata/triangle-001.gif
vendored
Normal file
BIN
src/image/testdata/triangle-001.gif
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
Loading…
Reference in New Issue
Block a user