github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/image/gif/writer_test.go (about)

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package gif
     6  
     7  import (
     8  	"bytes"
     9  	"image"
    10  	"image/color"
    11  	_ "image/png"
    12  	"io/ioutil"
    13  	"math/rand"
    14  	"os"
    15  	"testing"
    16  )
    17  
    18  func readImg(filename string) (image.Image, error) {
    19  	f, err := os.Open(filename)
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  	defer f.Close()
    24  	m, _, err := image.Decode(f)
    25  	return m, err
    26  }
    27  
    28  func readGIF(filename string) (*GIF, error) {
    29  	f, err := os.Open(filename)
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  	defer f.Close()
    34  	return DecodeAll(f)
    35  }
    36  
    37  func delta(u0, u1 uint32) int64 {
    38  	d := int64(u0) - int64(u1)
    39  	if d < 0 {
    40  		return -d
    41  	}
    42  	return d
    43  }
    44  
    45  // averageDelta returns the average delta in RGB space. The two images must
    46  // have the same bounds.
    47  func averageDelta(m0, m1 image.Image) int64 {
    48  	b := m0.Bounds()
    49  	var sum, n int64
    50  	for y := b.Min.Y; y < b.Max.Y; y++ {
    51  		for x := b.Min.X; x < b.Max.X; x++ {
    52  			c0 := m0.At(x, y)
    53  			c1 := m1.At(x, y)
    54  			r0, g0, b0, _ := c0.RGBA()
    55  			r1, g1, b1, _ := c1.RGBA()
    56  			sum += delta(r0, r1)
    57  			sum += delta(g0, g1)
    58  			sum += delta(b0, b1)
    59  			n += 3
    60  		}
    61  	}
    62  	return sum / n
    63  }
    64  
    65  var testCase = []struct {
    66  	filename  string
    67  	tolerance int64
    68  }{
    69  	{"../testdata/video-001.png", 1 << 12},
    70  	{"../testdata/video-001.gif", 0},
    71  	{"../testdata/video-001.interlaced.gif", 0},
    72  }
    73  
    74  func TestWriter(t *testing.T) {
    75  	for _, tc := range testCase {
    76  		m0, err := readImg(tc.filename)
    77  		if err != nil {
    78  			t.Error(tc.filename, err)
    79  			continue
    80  		}
    81  		var buf bytes.Buffer
    82  		err = Encode(&buf, m0, nil)
    83  		if err != nil {
    84  			t.Error(tc.filename, err)
    85  			continue
    86  		}
    87  		m1, err := Decode(&buf)
    88  		if err != nil {
    89  			t.Error(tc.filename, err)
    90  			continue
    91  		}
    92  		if m0.Bounds() != m1.Bounds() {
    93  			t.Errorf("%s, bounds differ: %v and %v", tc.filename, m0.Bounds(), m1.Bounds())
    94  			continue
    95  		}
    96  		// Compare the average delta to the tolerance level.
    97  		avgDelta := averageDelta(m0, m1)
    98  		if avgDelta > tc.tolerance {
    99  			t.Errorf("%s: average delta is too high. expected: %d, got %d", tc.filename, tc.tolerance, avgDelta)
   100  			continue
   101  		}
   102  	}
   103  }
   104  
   105  var frames = []string{
   106  	"../testdata/video-001.gif",
   107  	"../testdata/video-005.gray.gif",
   108  }
   109  
   110  func TestEncodeAll(t *testing.T) {
   111  	g0 := &GIF{
   112  		Image:     make([]*image.Paletted, len(frames)),
   113  		Delay:     make([]int, len(frames)),
   114  		LoopCount: 5,
   115  	}
   116  	for i, f := range frames {
   117  		m, err := readGIF(f)
   118  		if err != nil {
   119  			t.Error(f, err)
   120  		}
   121  		g0.Image[i] = m.Image[0]
   122  	}
   123  	var buf bytes.Buffer
   124  	if err := EncodeAll(&buf, g0); err != nil {
   125  		t.Fatal("EncodeAll:", err)
   126  	}
   127  	g1, err := DecodeAll(&buf)
   128  	if err != nil {
   129  		t.Fatal("DecodeAll:", err)
   130  	}
   131  	if g0.LoopCount != g1.LoopCount {
   132  		t.Errorf("loop counts differ: %d and %d", g0.LoopCount, g1.LoopCount)
   133  	}
   134  	for i := range g0.Image {
   135  		m0, m1 := g0.Image[i], g1.Image[i]
   136  		if m0.Bounds() != m1.Bounds() {
   137  			t.Errorf("%s, bounds differ: %v and %v", frames[i], m0.Bounds(), m1.Bounds())
   138  		}
   139  		d0, d1 := g0.Delay[i], g1.Delay[i]
   140  		if d0 != d1 {
   141  			t.Errorf("%s: delay values differ: %d and %d", frames[i], d0, d1)
   142  		}
   143  	}
   144  
   145  	g1.Delay = make([]int, 1)
   146  	if err := EncodeAll(ioutil.Discard, g1); err == nil {
   147  		t.Error("expected error from mismatched delay and image slice lengths")
   148  	}
   149  	if err := EncodeAll(ioutil.Discard, &GIF{}); err == nil {
   150  		t.Error("expected error from providing empty gif")
   151  	}
   152  }
   153  
   154  func BenchmarkEncode(b *testing.B) {
   155  	b.StopTimer()
   156  
   157  	bo := image.Rect(0, 0, 640, 480)
   158  	rnd := rand.New(rand.NewSource(123))
   159  
   160  	// Restrict to a 256-color paletted image to avoid quantization path.
   161  	palette := make(color.Palette, 256)
   162  	for i := range palette {
   163  		palette[i] = color.RGBA{
   164  			uint8(rnd.Intn(256)),
   165  			uint8(rnd.Intn(256)),
   166  			uint8(rnd.Intn(256)),
   167  			255,
   168  		}
   169  	}
   170  	img := image.NewPaletted(image.Rect(0, 0, 640, 480), palette)
   171  	for y := bo.Min.Y; y < bo.Max.Y; y++ {
   172  		for x := bo.Min.X; x < bo.Max.X; x++ {
   173  			img.Set(x, y, palette[rnd.Intn(256)])
   174  		}
   175  	}
   176  
   177  	b.SetBytes(640 * 480 * 4)
   178  	b.StartTimer()
   179  	for i := 0; i < b.N; i++ {
   180  		Encode(ioutil.Discard, img, nil)
   181  	}
   182  }
   183  
   184  func BenchmarkQuantizedEncode(b *testing.B) {
   185  	b.StopTimer()
   186  	img := image.NewRGBA(image.Rect(0, 0, 640, 480))
   187  	bo := img.Bounds()
   188  	rnd := rand.New(rand.NewSource(123))
   189  	for y := bo.Min.Y; y < bo.Max.Y; y++ {
   190  		for x := bo.Min.X; x < bo.Max.X; x++ {
   191  			img.SetRGBA(x, y, color.RGBA{
   192  				uint8(rnd.Intn(256)),
   193  				uint8(rnd.Intn(256)),
   194  				uint8(rnd.Intn(256)),
   195  				255,
   196  			})
   197  		}
   198  	}
   199  	b.SetBytes(640 * 480 * 4)
   200  	b.StartTimer()
   201  	for i := 0; i < b.N; i++ {
   202  		Encode(ioutil.Discard, img, nil)
   203  	}
   204  }