From: Nigel Tao Date: Tue, 5 May 2015 07:39:09 +0000 (+1000) Subject: image/gif: allow encoding a single-frame image whose top-left corner X-Git-Tag: go1.5beta1~732 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=8ae44af2bb94963c626b2ec637fc580fdc7d7934;p=gostls13.git image/gif: allow encoding a single-frame image whose top-left corner isn't (0, 0). Also fix a s/b.Min.X/b.Max.X/ typo in bounds checking. Fixes #10676 Change-Id: Ie5ff7ec20ca30367a8e65d32061959a2d8e089e9 Reviewed-on: https://go-review.googlesource.com/9712 Reviewed-by: Rob Pike --- diff --git a/src/image/gif/writer.go b/src/image/gif/writer.go index e14d034602..dd317901d4 100644 --- a/src/image/gif/writer.go +++ b/src/image/gif/writer.go @@ -190,7 +190,7 @@ func (e *encoder) writeImageBlock(pm *image.Paletted, delay int, disposal byte) } b := pm.Bounds() - if b.Dx() >= 1<<16 || b.Dy() >= 1<<16 || b.Min.X < 0 || b.Min.X >= 1<<16 || b.Min.Y < 0 || b.Min.Y >= 1<<16 { + if b.Min.X < 0 || b.Max.X >= 1<<16 || b.Min.Y < 0 || b.Max.Y >= 1<<16 { e.err = errors.New("gif: image block is too large to encode") return } @@ -365,6 +365,15 @@ func Encode(w io.Writer, m image.Image, o *Options) error { opts.Drawer.Draw(pm, b, m, image.ZP) } + // When calling Encode instead of EncodeAll, the single-frame image is + // translated such that its top-left corner is (0, 0), so that the single + // frame completely fills the overall GIF's bounds. + if pm.Rect.Min != (image.Point{}) { + dup := *pm + dup.Rect = dup.Rect.Sub(dup.Rect.Min) + pm = &dup + } + return EncodeAll(w, &GIF{ Image: []*image.Paletted{pm}, Delay: []int{0}, diff --git a/src/image/gif/writer_test.go b/src/image/gif/writer_test.go index d33976e415..db61a5c3c2 100644 --- a/src/image/gif/writer_test.go +++ b/src/image/gif/writer_test.go @@ -297,7 +297,7 @@ func TestEncodeZeroGIF(t *testing.T) { } } -func TestEncodeFrameOutOfBounds(t *testing.T) { +func TestEncodeAllFramesOutOfBounds(t *testing.T) { images := []*image.Paletted{ image.NewPaletted(image.Rect(0, 0, 5, 5), palette.Plan9), image.NewPaletted(image.Rect(2, 2, 8, 8), palette.Plan9), @@ -326,6 +326,32 @@ func TestEncodeFrameOutOfBounds(t *testing.T) { } } +func TestEncodeNonZeroMinPoint(t *testing.T) { + points := []image.Point{ + image.Point{-8, -9}, + image.Point{-4, -4}, + image.Point{-3, +3}, + image.Point{+0, +0}, + image.Point{+2, +2}, + } + for _, p := range points { + src := image.NewPaletted(image.Rectangle{Min: p, Max: p.Add(image.Point{6, 6})}, palette.Plan9) + var buf bytes.Buffer + if err := Encode(&buf, src, nil); err != nil { + t.Errorf("p=%v: Encode: %v", p, err) + continue + } + m, err := Decode(&buf) + if err != nil { + t.Errorf("p=%v: Decode: %v", p, err) + continue + } + if got, want := m.Bounds(), image.Rect(0, 0, 6, 6); got != want { + t.Errorf("p=%v: got %v, want %v", p, got, want) + } + } +} + func TestEncodeImplicitConfigSize(t *testing.T) { // For backwards compatibility for Go 1.4 and earlier code, the Config // field is optional, and if zero, the width and height is implied by the