github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/gift/colors_test.go (about)

     1  package gift
     2  
     3  import (
     4  	"image"
     5  	"image/color"
     6  	"image/draw"
     7  	"math"
     8  	"testing"
     9  )
    10  
    11  func TestLut(t *testing.T) {
    12  	fn := func(v float32) float32 {
    13  		return v
    14  	}
    15  	for _, size := range []int{10, 100, 1000} {
    16  		lut := prepareLut(size, fn)
    17  		l := len(lut)
    18  		if l != size {
    19  			t.Errorf("LUT bad size: expected %v got %v", size, l)
    20  		}
    21  		if lut[0] != 0 {
    22  			t.Errorf("LUT bad start value: expected 0 got %v", lut[0])
    23  		}
    24  		if lut[l-1] != 1 {
    25  			t.Errorf("LUT bad end value: expected 1 got %v", lut[l-1])
    26  		}
    27  	}
    28  	lut := prepareLut(10000, fn)
    29  	for _, u := range []float32{0.0, 0.0001, 0.5555, 0.9999, 1.0} {
    30  		v := getFromLut(lut, u)
    31  		if math.Abs(float64(v-u)) > 0.0001 {
    32  			t.Errorf("LUT bad value: expected %v got %v", u, v)
    33  		}
    34  	}
    35  }
    36  
    37  func TestInvert(t *testing.T) {
    38  	src := image.NewGray(image.Rect(0, 0, 256, 1))
    39  	for i := 0; i <= 255; i++ {
    40  		src.Pix[i] = uint8(i)
    41  	}
    42  	g := New(Invert())
    43  	dst := image.NewGray(g.Bounds(src.Bounds()))
    44  	g.Draw(dst, src)
    45  
    46  	for i := 0; i <= 255; i++ {
    47  		if dst.Pix[i] != 255-src.Pix[i] {
    48  			t.Errorf("InvertColors: index %d: expected %d got %d", i, 255-src.Pix[i], dst.Pix[i])
    49  		}
    50  	}
    51  }
    52  
    53  func TestColorspaceSRGBToLinear(t *testing.T) {
    54  	vals := []float32{
    55  		0.00000,
    56  		0.01002,
    57  		0.03310,
    58  		0.07324,
    59  		0.13287,
    60  		0.21404,
    61  		0.31855,
    62  		0.44799,
    63  		0.60383,
    64  		0.78741,
    65  		1.00000,
    66  	}
    67  
    68  	imgs := []draw.Image{
    69  		image.NewGray(image.Rect(0, 0, 11, 11)),
    70  		image.NewGray(image.Rect(0, 0, 111, 111)),
    71  		image.NewGray16(image.Rect(0, 0, 11, 11)),
    72  		image.NewGray16(image.Rect(0, 0, 1111, 1111)),
    73  	}
    74  	for _, img := range imgs {
    75  		for i := 0; i <= 10; i++ {
    76  			img.Set(i, 0, color.Gray{uint8(255 * float32(i) / 10.0)})
    77  		}
    78  		img2 := image.NewGray(img.Bounds())
    79  		New(ColorspaceSRGBToLinear()).Draw(img2, img)
    80  		if !img2.Bounds().Size().Eq(img.Bounds().Size()) {
    81  			t.Errorf("ColorspaceSRGBToLinear bad result size: expected %v got %v", img.Bounds().Size(), img2.Bounds().Size())
    82  		}
    83  		for i := 0; i <= 10; i++ {
    84  			expected := uint8(vals[i]*255.0 + 0.5)
    85  			c := img2.At(i, 0).(color.Gray)
    86  			if math.Abs(float64(c.Y)-float64(expected)) > 1 {
    87  				t.Errorf("ColorspaceSRGBToLinear bad color value at index %v expected %v got %v", i, expected, c.Y)
    88  			}
    89  		}
    90  	}
    91  }
    92  
    93  func TestColorspaceLinearToSRGB(t *testing.T) {
    94  	vals := []float32{
    95  		0.00000,
    96  		0.34919,
    97  		0.48453,
    98  		0.58383,
    99  		0.66519,
   100  		0.73536,
   101  		0.79774,
   102  		0.85431,
   103  		0.90633,
   104  		0.95469,
   105  		1.00000,
   106  	}
   107  
   108  	imgs := []draw.Image{
   109  		image.NewGray(image.Rect(0, 0, 11, 11)),
   110  		image.NewGray(image.Rect(0, 0, 111, 111)),
   111  		image.NewGray16(image.Rect(0, 0, 11, 11)),
   112  		image.NewGray16(image.Rect(0, 0, 1111, 1111)),
   113  	}
   114  	for _, img := range imgs {
   115  		for i := 0; i <= 10; i++ {
   116  			img.Set(i, 0, color.Gray{uint8(255 * float32(i) / 10.0)})
   117  		}
   118  		img2 := image.NewGray(img.Bounds())
   119  		New(ColorspaceLinearToSRGB()).Draw(img2, img)
   120  		if !img2.Bounds().Size().Eq(img.Bounds().Size()) {
   121  			t.Errorf("ColorspaceLinearRGBToSRGB bad result size: expected %v got %v", img.Bounds().Size(), img2.Bounds().Size())
   122  		}
   123  		for i := 0; i <= 10; i++ {
   124  			expected := uint8(vals[i]*255.0 + 0.5)
   125  			c := img2.At(i, 0).(color.Gray)
   126  			if math.Abs(float64(c.Y)-float64(expected)) > 1 {
   127  				t.Errorf("ColorspaceLinearRGBToSRGB bad color value at index %v expected %v got %v", i, expected, c.Y)
   128  			}
   129  		}
   130  	}
   131  
   132  }
   133  
   134  func TestAdjustGamma(t *testing.T) {
   135  	src := image.NewGray(image.Rect(0, 0, 256, 1))
   136  	dst := image.NewGray(image.Rect(0, 0, 256, 1))
   137  	for i := 0; i <= 255; i++ {
   138  		src.Pix[i] = uint8(i)
   139  	}
   140  	ag := Gamma(2.0)
   141  	ag.Draw(dst, src, nil)
   142  
   143  	for i := 100; i <= 150; i++ {
   144  		if dst.Pix[i] <= src.Pix[i] {
   145  			t.Errorf("Gamma unexpected color")
   146  		}
   147  	}
   148  
   149  	ag = Gamma(0.5)
   150  	ag.Draw(dst, src, nil)
   151  
   152  	for i := 100; i <= 150; i++ {
   153  		if dst.Pix[i] >= src.Pix[i] {
   154  			t.Errorf("Gamma unexpected color")
   155  		}
   156  	}
   157  
   158  	ag = Gamma(1.0)
   159  	ag.Draw(dst, src, nil)
   160  
   161  	for i := 100; i <= 150; i++ {
   162  		if dst.Pix[i] != src.Pix[i] {
   163  			t.Errorf("Gamma unexpected color")
   164  		}
   165  	}
   166  }
   167  
   168  func TestContrast(t *testing.T) {
   169  	testData := []struct {
   170  		desc           string
   171  		p              float32
   172  		srcb, dstb     image.Rectangle
   173  		srcPix, dstPix []uint8
   174  	}{
   175  		{
   176  			"contrast (0)",
   177  			0,
   178  			image.Rect(-1, -1, 4, 2),
   179  			image.Rect(0, 0, 5, 3),
   180  			[]uint8{
   181  				0x00, 0x40, 0x00, 0x40, 0x00,
   182  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   183  				0x00, 0x80, 0x00, 0x80, 0x00,
   184  			},
   185  			[]uint8{
   186  				0x00, 0x40, 0x00, 0x40, 0x00,
   187  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   188  				0x00, 0x80, 0x00, 0x80, 0x00,
   189  			},
   190  		},
   191  		{
   192  			"contrast (30)",
   193  			30,
   194  			image.Rect(-1, -1, 4, 2),
   195  			image.Rect(0, 0, 5, 3),
   196  			[]uint8{
   197  				0x00, 0x40, 0x00, 0x40, 0x00,
   198  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   199  				0x00, 0x80, 0x00, 0x80, 0x00,
   200  			},
   201  			[]uint8{
   202  				0x00, 0x25, 0x00, 0x25, 0x00,
   203  				0x53, 0xC5, 0xAE, 0xC5, 0x53,
   204  				0x00, 0x80, 0x00, 0x80, 0x00,
   205  			},
   206  		},
   207  		{
   208  			"contrast (-30)",
   209  			-30,
   210  			image.Rect(-1, -1, 4, 2),
   211  			image.Rect(0, 0, 5, 3),
   212  			[]uint8{
   213  				0x00, 0x40, 0x00, 0x40, 0x00,
   214  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   215  				0x00, 0x80, 0x00, 0x80, 0x00,
   216  			},
   217  			[]uint8{
   218  				0x26, 0x53, 0x26, 0x53, 0x26,
   219  				0x69, 0xA1, 0x96, 0xA1, 0x69,
   220  				0x26, 0x80, 0x26, 0x80, 0x26,
   221  			},
   222  		},
   223  		{
   224  			"contrast (100)",
   225  			100,
   226  			image.Rect(-1, -1, 4, 2),
   227  			image.Rect(0, 0, 5, 3),
   228  			[]uint8{
   229  				0x00, 0x40, 0x00, 0x40, 0x00,
   230  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   231  				0x00, 0x80, 0x00, 0x80, 0x00,
   232  			},
   233  			[]uint8{
   234  				0x00, 0x00, 0x00, 0x00, 0x00,
   235  				0x00, 0xFF, 0xFF, 0xFF, 0x00,
   236  				0x00, 0xFF, 0x00, 0xFF, 0x00,
   237  			},
   238  		},
   239  		{
   240  			"contrast (200)",
   241  			200,
   242  			image.Rect(-1, -1, 4, 2),
   243  			image.Rect(0, 0, 5, 3),
   244  			[]uint8{
   245  				0x00, 0x40, 0x00, 0x40, 0x00,
   246  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   247  				0x00, 0x80, 0x00, 0x80, 0x00,
   248  			},
   249  			[]uint8{
   250  				0x00, 0x00, 0x00, 0x00, 0x00,
   251  				0x00, 0xFF, 0xFF, 0xFF, 0x00,
   252  				0x00, 0xFF, 0x00, 0xFF, 0x00,
   253  			},
   254  		},
   255  		{
   256  			"contrast (-100)",
   257  			-100,
   258  			image.Rect(-1, -1, 4, 2),
   259  			image.Rect(0, 0, 5, 3),
   260  			[]uint8{
   261  				0x00, 0x40, 0x00, 0x40, 0x00,
   262  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   263  				0x00, 0x80, 0x00, 0x80, 0x00,
   264  			},
   265  			[]uint8{
   266  				0x80, 0x80, 0x80, 0x80, 0x80,
   267  				0x80, 0x80, 0x80, 0x80, 0x80,
   268  				0x80, 0x80, 0x80, 0x80, 0x80,
   269  			},
   270  		},
   271  		{
   272  			"contrast (-200)",
   273  			-200,
   274  			image.Rect(-1, -1, 4, 2),
   275  			image.Rect(0, 0, 5, 3),
   276  			[]uint8{
   277  				0x00, 0x40, 0x00, 0x40, 0x00,
   278  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   279  				0x00, 0x80, 0x00, 0x80, 0x00,
   280  			},
   281  			[]uint8{
   282  				0x80, 0x80, 0x80, 0x80, 0x80,
   283  				0x80, 0x80, 0x80, 0x80, 0x80,
   284  				0x80, 0x80, 0x80, 0x80, 0x80,
   285  			},
   286  		},
   287  	}
   288  
   289  	for _, d := range testData {
   290  		src := image.NewGray(d.srcb)
   291  		src.Pix = d.srcPix
   292  
   293  		f := Contrast(d.p)
   294  		dst := image.NewGray(f.Bounds(src.Bounds()))
   295  		f.Draw(dst, src, nil)
   296  
   297  		if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) {
   298  			t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix)
   299  		}
   300  	}
   301  }
   302  
   303  func TestBrightness(t *testing.T) {
   304  	testData := []struct {
   305  		desc           string
   306  		p              float32
   307  		srcb, dstb     image.Rectangle
   308  		srcPix, dstPix []uint8
   309  	}{
   310  		{
   311  			"brightness (0)",
   312  			0,
   313  			image.Rect(-1, -1, 4, 2),
   314  			image.Rect(0, 0, 5, 3),
   315  			[]uint8{
   316  				0x00, 0x40, 0x00, 0x40, 0x00,
   317  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   318  				0x00, 0x80, 0x00, 0x80, 0x00,
   319  			},
   320  			[]uint8{
   321  				0x00, 0x40, 0x00, 0x40, 0x00,
   322  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   323  				0x00, 0x80, 0x00, 0x80, 0x00,
   324  			},
   325  		},
   326  		{
   327  			"brightness (30)",
   328  			30,
   329  			image.Rect(-1, -1, 4, 2),
   330  			image.Rect(0, 0, 5, 3),
   331  			[]uint8{
   332  				0x00, 0x40, 0x00, 0x40, 0x00,
   333  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   334  				0x00, 0x80, 0x00, 0x80, 0x00,
   335  			},
   336  			[]uint8{
   337  				0x4D, 0x8D, 0x4D, 0x8D, 0x4D,
   338  				0xAD, 0xFD, 0xED, 0xFD, 0xAD,
   339  				0x4D, 0xCD, 0x4D, 0xCD, 0x4D,
   340  			},
   341  		},
   342  		{
   343  			"brightness (-30)",
   344  			-30,
   345  			image.Rect(-1, -1, 4, 2),
   346  			image.Rect(0, 0, 5, 3),
   347  			[]uint8{
   348  				0x00, 0x40, 0x00, 0x40, 0x00,
   349  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   350  				0x00, 0x80, 0x00, 0x80, 0x00,
   351  			},
   352  			[]uint8{
   353  				0x00, 0x00, 0x00, 0x00, 0x00,
   354  				0x14, 0x64, 0x53, 0x64, 0x14,
   355  				0x00, 0x34, 0x00, 0x34, 0x00,
   356  			},
   357  		},
   358  
   359  		{
   360  			"brightness (100)",
   361  			100,
   362  			image.Rect(-1, -1, 4, 2),
   363  			image.Rect(0, 0, 5, 3),
   364  			[]uint8{
   365  				0x00, 0x40, 0x00, 0x40, 0x00,
   366  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   367  				0x00, 0x80, 0x00, 0x80, 0x00,
   368  			},
   369  			[]uint8{
   370  				0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   371  				0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   372  				0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   373  			},
   374  		},
   375  		{
   376  			"brightness (200)",
   377  			200,
   378  			image.Rect(-1, -1, 4, 2),
   379  			image.Rect(0, 0, 5, 3),
   380  			[]uint8{
   381  				0x00, 0x40, 0x00, 0x40, 0x00,
   382  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   383  				0x00, 0x80, 0x00, 0x80, 0x00,
   384  			},
   385  			[]uint8{
   386  				0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   387  				0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   388  				0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   389  			},
   390  		},
   391  		{
   392  			"brightness (-100)",
   393  			-100,
   394  			image.Rect(-1, -1, 4, 2),
   395  			image.Rect(0, 0, 5, 3),
   396  			[]uint8{
   397  				0x00, 0x40, 0x00, 0x40, 0x00,
   398  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   399  				0x00, 0x80, 0x00, 0x80, 0x00,
   400  			},
   401  			[]uint8{
   402  				0x00, 0x00, 0x00, 0x00, 0x00,
   403  				0x00, 0x00, 0x00, 0x00, 0x00,
   404  				0x00, 0x00, 0x00, 0x00, 0x00,
   405  			},
   406  		},
   407  		{
   408  			"brightness (-200)",
   409  			-200,
   410  			image.Rect(-1, -1, 4, 2),
   411  			image.Rect(0, 0, 5, 3),
   412  			[]uint8{
   413  				0x00, 0x40, 0x00, 0x40, 0x00,
   414  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   415  				0x00, 0x80, 0x00, 0x80, 0x00,
   416  			},
   417  			[]uint8{
   418  				0x00, 0x00, 0x00, 0x00, 0x00,
   419  				0x00, 0x00, 0x00, 0x00, 0x00,
   420  				0x00, 0x00, 0x00, 0x00, 0x00,
   421  			},
   422  		},
   423  	}
   424  
   425  	for _, d := range testData {
   426  		src := image.NewGray(d.srcb)
   427  		src.Pix = d.srcPix
   428  
   429  		f := Brightness(d.p)
   430  		dst := image.NewGray(f.Bounds(src.Bounds()))
   431  		f.Draw(dst, src, nil)
   432  
   433  		if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) {
   434  			t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix)
   435  		}
   436  	}
   437  }
   438  
   439  func TestSigmoid(t *testing.T) {
   440  	testData := []struct {
   441  		desc             string
   442  		midpoint, factor float32
   443  		srcb, dstb       image.Rectangle
   444  		srcPix, dstPix   []uint8
   445  	}{
   446  		{
   447  			"sigmoid (0.5, 0)",
   448  			0.5, 0,
   449  			image.Rect(-1, -1, 4, 2),
   450  			image.Rect(0, 0, 5, 3),
   451  			[]uint8{
   452  				0x00, 0x40, 0x00, 0x40, 0x00,
   453  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   454  				0x00, 0x80, 0x00, 0x80, 0x00,
   455  			},
   456  			[]uint8{
   457  				0x00, 0x40, 0x00, 0x40, 0x00,
   458  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   459  				0x00, 0x80, 0x00, 0x80, 0x00,
   460  			},
   461  		},
   462  		{
   463  			"sigmoid (0.5, 3)",
   464  			0.5, 3,
   465  			image.Rect(-1, -1, 4, 2),
   466  			image.Rect(0, 0, 5, 3),
   467  			[]uint8{
   468  				0x00, 0x40, 0x00, 0x40, 0x00,
   469  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   470  				0x00, 0x80, 0x00, 0x80, 0x00,
   471  			},
   472  			[]uint8{
   473  				0x00, 0x38, 0x00, 0x38, 0x00,
   474  				0x5B, 0xB7, 0xA5, 0xB7, 0x5B,
   475  				0x00, 0x80, 0x00, 0x80, 0x00,
   476  			},
   477  		},
   478  		{
   479  			"sigmoid (0.5, -3)",
   480  			0.5, -3,
   481  			image.Rect(-1, -1, 4, 2),
   482  			image.Rect(0, 0, 5, 3),
   483  			[]uint8{
   484  				0x00, 0x40, 0x00, 0x40, 0x00,
   485  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   486  				0x00, 0x80, 0x00, 0x80, 0x00,
   487  			},
   488  			[]uint8{
   489  				0x00, 0x48, 0x00, 0x48, 0x00,
   490  				0x65, 0xA9, 0x9B, 0xA9, 0x65,
   491  				0x00, 0x80, 0x00, 0x80, 0x00,
   492  			},
   493  		},
   494  	}
   495  
   496  	for _, d := range testData {
   497  		src := image.NewGray(d.srcb)
   498  		src.Pix = d.srcPix
   499  
   500  		f := Sigmoid(d.midpoint, d.factor)
   501  		dst := image.NewGray(f.Bounds(src.Bounds()))
   502  		f.Draw(dst, src, nil)
   503  
   504  		if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) {
   505  			t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix)
   506  		}
   507  	}
   508  }
   509  
   510  func TestGrayscale(t *testing.T) {
   511  	testData := []struct {
   512  		desc           string
   513  		srcb, dstb     image.Rectangle
   514  		srcPix, dstPix []uint8
   515  	}{
   516  
   517  		{
   518  			"grayscale 0x0",
   519  			image.Rect(0, 0, 0, 0),
   520  			image.Rect(0, 0, 0, 0),
   521  			[]uint8{},
   522  			[]uint8{},
   523  		},
   524  		{
   525  			"grayscale 2x3",
   526  			image.Rect(-1, -1, 1, 2),
   527  			image.Rect(0, 0, 2, 3),
   528  			[]uint8{
   529  				0x00, 0x10, 0x20, 0x30, 0xFF, 0x00, 0x88, 0xFF,
   530  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   531  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   532  			},
   533  			[]uint8{
   534  				0x0D, 0x0D, 0x0D, 0x30, 0x5C, 0x5C, 0x5C, 0xFF,
   535  				0xE3, 0xE3, 0xE3, 0xC0, 0x56, 0x56, 0x56, 0x00,
   536  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   537  			},
   538  		},
   539  	}
   540  
   541  	for _, d := range testData {
   542  		src := image.NewNRGBA(d.srcb)
   543  		src.Pix = d.srcPix
   544  
   545  		f := Grayscale()
   546  		dst := image.NewNRGBA(f.Bounds(src.Bounds()))
   547  		f.Draw(dst, src, nil)
   548  
   549  		if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) {
   550  			t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix)
   551  		}
   552  	}
   553  }
   554  
   555  func TestSepia(t *testing.T) {
   556  	testData := []struct {
   557  		desc           string
   558  		p              float32
   559  		srcb, dstb     image.Rectangle
   560  		srcPix, dstPix []uint8
   561  	}{
   562  
   563  		{
   564  			"sepia 100 0x0",
   565  			100,
   566  			image.Rect(0, 0, 0, 0),
   567  			image.Rect(0, 0, 0, 0),
   568  			[]uint8{},
   569  			[]uint8{},
   570  		},
   571  		{
   572  			"sepia 0 2x3",
   573  			0,
   574  			image.Rect(-1, -1, 1, 2),
   575  			image.Rect(0, 0, 2, 3),
   576  			[]uint8{
   577  				0x00, 0x10, 0x20, 0x30, 0xFF, 0x00, 0x88, 0xFF,
   578  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   579  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   580  			},
   581  			[]uint8{
   582  				0x00, 0x10, 0x20, 0x30, 0xFF, 0x00, 0x88, 0xFF,
   583  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   584  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   585  			},
   586  		},
   587  		{
   588  			"sepia 100 2x3",
   589  			100,
   590  			image.Rect(-1, -1, 1, 2),
   591  			image.Rect(0, 0, 2, 3),
   592  			[]uint8{
   593  				0x00, 0x10, 0x20, 0x30, 0xFF, 0x00, 0x88, 0xFF,
   594  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   595  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   596  			},
   597  			[]uint8{
   598  				0x12, 0x10, 0x0D, 0x30, 0x7E, 0x70, 0x57, 0xFF,
   599  				0xFF, 0xFF, 0xD4, 0xC0, 0x78, 0x6B, 0x54, 0x00,
   600  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xEF, 0xFF,
   601  			},
   602  		},
   603  	}
   604  
   605  	for _, d := range testData {
   606  		src := image.NewNRGBA(d.srcb)
   607  		src.Pix = d.srcPix
   608  
   609  		f := Sepia(d.p)
   610  		dst := image.NewNRGBA(f.Bounds(src.Bounds()))
   611  		f.Draw(dst, src, nil)
   612  
   613  		if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) {
   614  			t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix)
   615  		}
   616  	}
   617  }
   618  
   619  func TestNormalizeHue(t *testing.T) {
   620  	testData := []struct {
   621  		h0, h1 float32
   622  	}{
   623  		{0, 0},
   624  		{0.1, 0.1},
   625  		{0.5, 0.5},
   626  		{0.9, 0.9},
   627  		{1.1, 0.1},
   628  		{3.0, 0.0},
   629  		{5.7, 0.7},
   630  		{-0.1, 0.9},
   631  		{-0.5, 0.5},
   632  		{-0.9, 0.1},
   633  		{-3.0, 0.0},
   634  		{-5.7, 0.3},
   635  	}
   636  
   637  	for _, d := range testData {
   638  		h := normalizeHue(d.h0)
   639  		if absf32(h-d.h1) > 0.00001 {
   640  			t.Errorf("normalizeHue(%#v) failed: %#v expected: %#v", d.h0, h, d.h1)
   641  		}
   642  	}
   643  
   644  }
   645  
   646  func TestHue(t *testing.T) {
   647  	testData := []struct {
   648  		desc           string
   649  		p              float32
   650  		srcb, dstb     image.Rectangle
   651  		srcPix, dstPix []uint8
   652  	}{
   653  
   654  		{
   655  			"hue 0 0x0",
   656  			0,
   657  			image.Rect(0, 0, 0, 0),
   658  			image.Rect(0, 0, 0, 0),
   659  			[]uint8{},
   660  			[]uint8{},
   661  		},
   662  		{
   663  			"hue 0",
   664  			0,
   665  			image.Rect(-1, -1, 1, 3),
   666  			image.Rect(0, 0, 2, 4),
   667  			[]uint8{
   668  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   669  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   670  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   671  				0xEE, 0x50, 0xA0, 0x77, 0xFD, 0xFE, 0xFD, 0xFD,
   672  			},
   673  			[]uint8{
   674  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   675  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   676  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   677  				0xEE, 0x50, 0xA0, 0x77, 0xFD, 0xFE, 0xFD, 0xFD,
   678  			},
   679  		},
   680  		{
   681  			"hue -720", // same as 0
   682  			-720,
   683  			image.Rect(-1, -1, 1, 3),
   684  			image.Rect(0, 0, 2, 4),
   685  			[]uint8{
   686  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   687  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   688  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   689  				0xEE, 0x50, 0xA0, 0x77, 0xFD, 0xFE, 0xFD, 0xFD,
   690  			},
   691  			[]uint8{
   692  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   693  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   694  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   695  				0xEE, 0x50, 0xA0, 0x77, 0xFD, 0xFE, 0xFD, 0xFD,
   696  			},
   697  		},
   698  		{
   699  			"hue -90",
   700  			-90,
   701  			image.Rect(-1, -1, 1, 3),
   702  			image.Rect(0, 0, 2, 4),
   703  			[]uint8{
   704  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   705  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   706  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   707  				0xEE, 0x50, 0xA0, 0x77, 0xFD, 0xFE, 0xFD, 0xFD,
   708  			},
   709  			[]uint8{
   710  				0x00, 0x20, 0x00, 0x30, 0x99, 0x33, 0x99, 0xFF,
   711  				0xF0, 0xD0, 0xF0, 0xC0, 0x11, 0xBB, 0x11, 0x00,
   712  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   713  				0x50, 0x51, 0xEE, 0x77, 0xFE, 0xFE, 0xFD, 0xFD,
   714  			},
   715  		},
   716  		{
   717  			"hue 630", // same as -90
   718  			630,
   719  			image.Rect(-1, -1, 1, 3),
   720  			image.Rect(0, 0, 2, 4),
   721  			[]uint8{
   722  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   723  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   724  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   725  				0xEE, 0x50, 0xA0, 0x77, 0xFD, 0xFE, 0xFD, 0xFD,
   726  			},
   727  			[]uint8{
   728  				0x00, 0x20, 0x00, 0x30, 0x99, 0x33, 0x99, 0xFF,
   729  				0xF0, 0xD0, 0xF0, 0xC0, 0x11, 0xBB, 0x11, 0x00,
   730  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   731  				0x50, 0x51, 0xEE, 0x77, 0xFE, 0xFE, 0xFD, 0xFD,
   732  			},
   733  		},
   734  		{
   735  			"hue 90",
   736  			90,
   737  			image.Rect(-1, -1, 1, 3),
   738  			image.Rect(0, 0, 2, 4),
   739  			[]uint8{
   740  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   741  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   742  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   743  				0xEE, 0x50, 0xA0, 0x77, 0xFD, 0xFE, 0xFD, 0xFD,
   744  			},
   745  			[]uint8{
   746  				0x20, 0x00, 0x20, 0x30, 0x33, 0x99, 0x33, 0xFF,
   747  				0xD0, 0xF0, 0xD0, 0xC0, 0xBB, 0x11, 0xBB, 0x00,
   748  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   749  				0xEE, 0xED, 0x50, 0x77, 0xFD, 0xFE, 0xFE, 0xFD,
   750  			},
   751  		},
   752  		{
   753  			"hue 3690", // same as 90
   754  			3690,
   755  			image.Rect(-1, -1, 1, 3),
   756  			image.Rect(0, 0, 2, 4),
   757  			[]uint8{
   758  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   759  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   760  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   761  				0xEE, 0x50, 0xA0, 0x77, 0xFD, 0xFE, 0xFD, 0xFD,
   762  			},
   763  			[]uint8{
   764  				0x20, 0x00, 0x20, 0x30, 0x33, 0x99, 0x33, 0xFF,
   765  				0xD0, 0xF0, 0xD0, 0xC0, 0xBB, 0x11, 0xBB, 0x00,
   766  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   767  				0xEE, 0xED, 0x50, 0x77, 0xFD, 0xFE, 0xFE, 0xFD,
   768  			},
   769  		},
   770  	}
   771  
   772  	for _, d := range testData {
   773  		src := image.NewNRGBA(d.srcb)
   774  		src.Pix = d.srcPix
   775  
   776  		f := Hue(d.p)
   777  		dst := image.NewNRGBA(f.Bounds(src.Bounds()))
   778  		f.Draw(dst, src, nil)
   779  
   780  		if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) {
   781  			t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix)
   782  		}
   783  	}
   784  }
   785  
   786  func TestSaturation(t *testing.T) {
   787  	testData := []struct {
   788  		desc           string
   789  		p              float32
   790  		srcb, dstb     image.Rectangle
   791  		srcPix, dstPix []uint8
   792  	}{
   793  
   794  		{
   795  			"saturation 0 0x0",
   796  			0,
   797  			image.Rect(0, 0, 0, 0),
   798  			image.Rect(0, 0, 0, 0),
   799  			[]uint8{},
   800  			[]uint8{},
   801  		},
   802  		{
   803  			"saturation 0",
   804  			0,
   805  			image.Rect(-1, -1, 1, 3),
   806  			image.Rect(0, 0, 2, 4),
   807  			[]uint8{
   808  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   809  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   810  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   811  				0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD,
   812  			},
   813  			[]uint8{
   814  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   815  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   816  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   817  				0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD,
   818  			},
   819  		},
   820  		{
   821  			"saturation -50",
   822  			-50,
   823  			image.Rect(-1, -1, 1, 3),
   824  			image.Rect(0, 0, 2, 4),
   825  			[]uint8{
   826  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   827  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   828  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   829  				0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD,
   830  			},
   831  			[]uint8{
   832  				0x08, 0x10, 0x18, 0x30, 0x80, 0x66, 0x4D, 0xFF,
   833  				0xE8, 0xE0, 0xD8, 0xC0, 0x3B, 0x66, 0x91, 0x00,
   834  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   835  				0xBC, 0x74, 0x9C, 0x77, 0xF2, 0xFA, 0xF2, 0xFD,
   836  			},
   837  		},
   838  		{
   839  			"saturation 100",
   840  			100,
   841  			image.Rect(-1, -1, 1, 3),
   842  			image.Rect(0, 0, 2, 4),
   843  			[]uint8{
   844  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   845  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   846  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   847  				0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD,
   848  			},
   849  			[]uint8{
   850  				0x00, 0x10, 0x20, 0x30, 0xCC, 0x66, 0x00, 0xFF,
   851  				0xFF, 0xE0, 0xC1, 0xC0, 0x00, 0x66, 0xCC, 0x00,
   852  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   853  				0xFF, 0x31, 0xA3, 0x77, 0xED, 0xFF, 0xED, 0xFD,
   854  			},
   855  		},
   856  	}
   857  
   858  	for _, d := range testData {
   859  		src := image.NewNRGBA(d.srcb)
   860  		src.Pix = d.srcPix
   861  
   862  		f := Saturation(d.p)
   863  		dst := image.NewNRGBA(f.Bounds(src.Bounds()))
   864  		f.Draw(dst, src, nil)
   865  
   866  		if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) {
   867  			t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix)
   868  		}
   869  	}
   870  }
   871  
   872  func TestColorize(t *testing.T) {
   873  	testData := []struct {
   874  		desc           string
   875  		h, s, p        float32
   876  		srcb, dstb     image.Rectangle
   877  		srcPix, dstPix []uint8
   878  	}{
   879  
   880  		{
   881  			"colorize 0, 0, 0, 0x0",
   882  			0, 0, 0,
   883  			image.Rect(0, 0, 0, 0),
   884  			image.Rect(0, 0, 0, 0),
   885  			[]uint8{},
   886  			[]uint8{},
   887  		},
   888  		{
   889  			"colorize 0, 100, 0",
   890  			0, 100, 0,
   891  			image.Rect(-1, -1, 1, 3),
   892  			image.Rect(0, 0, 2, 4),
   893  			[]uint8{
   894  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   895  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   896  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   897  				0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD,
   898  			},
   899  			[]uint8{
   900  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   901  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   902  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   903  				0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD,
   904  			},
   905  		},
   906  
   907  		{
   908  			"colorize 0, 100, 100",
   909  			0, 100, 100,
   910  			image.Rect(-1, -1, 1, 3),
   911  			image.Rect(0, 0, 2, 4),
   912  			[]uint8{
   913  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   914  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   915  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   916  				0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD,
   917  			},
   918  			[]uint8{
   919  				0x20, 0x00, 0x00, 0x30, 0xCC, 0x00, 0x00, 0xFF,
   920  				0xFF, 0xC1, 0xC1, 0xC0, 0xCC, 0x00, 0x00, 0x00,
   921  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   922  				0xFF, 0x31, 0x31, 0x77, 0xFF, 0xED, 0xED, 0xFD,
   923  			},
   924  		},
   925  	}
   926  
   927  	for _, d := range testData {
   928  		src := image.NewNRGBA(d.srcb)
   929  		src.Pix = d.srcPix
   930  
   931  		f := Colorize(d.h, d.s, d.p)
   932  		dst := image.NewNRGBA(f.Bounds(src.Bounds()))
   933  		f.Draw(dst, src, nil)
   934  
   935  		if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) {
   936  			t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix)
   937  		}
   938  	}
   939  }
   940  
   941  func TestColorBalance(t *testing.T) {
   942  	testData := []struct {
   943  		desc           string
   944  		r, g, b        float32
   945  		srcb, dstb     image.Rectangle
   946  		srcPix, dstPix []uint8
   947  	}{
   948  
   949  		{
   950  			"color balance 0, 0, 0, 0x0",
   951  			0, 0, 0,
   952  			image.Rect(0, 0, 0, 0),
   953  			image.Rect(0, 0, 0, 0),
   954  			[]uint8{},
   955  			[]uint8{},
   956  		},
   957  		{
   958  			"color balance 0, 0, 0",
   959  			0, 0, 0,
   960  			image.Rect(-1, -1, 1, 3),
   961  			image.Rect(0, 0, 2, 4),
   962  			[]uint8{
   963  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   964  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   965  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   966  				0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD,
   967  			},
   968  			[]uint8{
   969  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   970  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   971  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   972  				0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD,
   973  			},
   974  		},
   975  
   976  		{
   977  			"color balance 10, -20, 200",
   978  			10, -20, 200,
   979  			image.Rect(-1, -1, 1, 3),
   980  			image.Rect(0, 0, 2, 4),
   981  			[]uint8{
   982  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
   983  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
   984  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
   985  				0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD,
   986  			},
   987  			[]uint8{
   988  				0x00, 0x0D, 0x60, 0x30, 0xA8, 0x52, 0x99, 0xFF,
   989  				0xFF, 0xB3, 0xFF, 0xC0, 0x13, 0x52, 0xFF, 0x00,
   990  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xCC, 0xFF, 0xFF,
   991  				0xF6, 0x40, 0xFF, 0x77, 0xFF, 0xCB, 0xFF, 0xFD,
   992  			},
   993  		},
   994  	}
   995  
   996  	for _, d := range testData {
   997  		src := image.NewNRGBA(d.srcb)
   998  		src.Pix = d.srcPix
   999  
  1000  		f := ColorBalance(d.r, d.g, d.b)
  1001  		dst := image.NewNRGBA(f.Bounds(src.Bounds()))
  1002  		f.Draw(dst, src, nil)
  1003  
  1004  		if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) {
  1005  			t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix)
  1006  		}
  1007  	}
  1008  }
  1009  
  1010  func TestColorFunc(t *testing.T) {
  1011  	testData := []struct {
  1012  		desc           string
  1013  		fn             func(r0, g0, b0, a0 float32) (r, g, b, a float32)
  1014  		srcb, dstb     image.Rectangle
  1015  		srcPix, dstPix []uint8
  1016  	}{
  1017  
  1018  		{
  1019  			"color func 0x0",
  1020  			func(r0, g0, b0, a0 float32) (r, g, b, a float32) {
  1021  				return r0, g0, b0, a0
  1022  			},
  1023  			image.Rect(0, 0, 0, 0),
  1024  			image.Rect(0, 0, 0, 0),
  1025  			[]uint8{},
  1026  			[]uint8{},
  1027  		},
  1028  		{
  1029  			"color func swap channels",
  1030  			func(r0, g0, b0, a0 float32) (r, g, b, a float32) {
  1031  				return a0, b0, g0, r0
  1032  			},
  1033  			image.Rect(-1, -1, 1, 3),
  1034  			image.Rect(0, 0, 2, 4),
  1035  			[]uint8{
  1036  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
  1037  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
  1038  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
  1039  				0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD,
  1040  			},
  1041  			[]uint8{
  1042  				0x30, 0x20, 0x10, 0x00, 0xFF, 0x33, 0x66, 0x99,
  1043  				0xC0, 0xD0, 0xE0, 0xF0, 0x00, 0xBB, 0x66, 0x11,
  1044  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
  1045  				0x77, 0xA0, 0x50, 0xE0, 0xFD, 0xEE, 0xFE, 0xEE,
  1046  			},
  1047  		},
  1048  
  1049  		{
  1050  			"color func invert all",
  1051  			func(r0, g0, b0, a0 float32) (r, g, b, a float32) {
  1052  				return 1 - r0, 1 - g0, 1 - b0, 1 - a0
  1053  			},
  1054  			image.Rect(-1, -1, 1, 3),
  1055  			image.Rect(0, 0, 2, 4),
  1056  			[]uint8{
  1057  				0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF,
  1058  				0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00,
  1059  				0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
  1060  				0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD,
  1061  			},
  1062  			[]uint8{
  1063  				0xFF, 0xEF, 0xDF, 0xCF, 0x66, 0x99, 0xCC, 0x00,
  1064  				0x0F, 0x1F, 0x2F, 0x3F, 0xEE, 0x99, 0x44, 0xFF,
  1065  				0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
  1066  				0x1F, 0xAF, 0x5F, 0x88, 0x11, 0x01, 0x11, 0x02,
  1067  			},
  1068  		},
  1069  	}
  1070  
  1071  	for _, d := range testData {
  1072  		src := image.NewNRGBA(d.srcb)
  1073  		src.Pix = d.srcPix
  1074  
  1075  		f := ColorFunc(d.fn)
  1076  		dst := image.NewNRGBA(f.Bounds(src.Bounds()))
  1077  		f.Draw(dst, src, nil)
  1078  
  1079  		if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) {
  1080  			t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix)
  1081  		}
  1082  	}
  1083  }