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

     1  package gift
     2  
     3  import (
     4  	"image"
     5  	"testing"
     6  )
     7  
     8  func TestConvolution(t *testing.T) {
     9  
    10  	testData := []struct {
    11  		desc                  string
    12  		kernel                []float32
    13  		normalize, alpha, abs bool
    14  		delta                 float32
    15  		srcb, dstb            image.Rectangle
    16  		srcPix, dstPix        []uint8
    17  	}{
    18  		{
    19  			"convolution (0x0, false, false, false, 0)",
    20  			[]float32{},
    21  			false, false, false, 0,
    22  			image.Rect(-1, -1, 2, 2),
    23  			image.Rect(0, 0, 3, 3),
    24  			[]uint8{
    25  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x60, 0x80,
    26  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    27  				0x80, 0x60, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    28  			},
    29  			[]uint8{
    30  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x60, 0x80,
    31  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    32  				0x80, 0x60, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    33  			},
    34  		},
    35  		{
    36  			"convolution (3x3, false, false, false, 0)",
    37  			[]float32{
    38  				0, 0, 1,
    39  				0, 0, 0,
    40  				1, 0, 0,
    41  			},
    42  			false, false, false, 0,
    43  			image.Rect(-1, -1, 2, 2),
    44  			image.Rect(0, 0, 3, 3),
    45  			[]uint8{
    46  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x60, 0x80,
    47  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    48  				0x80, 0x60, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    49  			},
    50  			[]uint8{
    51  				0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x60, 0x00, 0x20, 0x40, 0x60, 0x80,
    52  				0x80, 0x60, 0x40, 0x00, 0xA0, 0xA0, 0xA0, 0x00, 0x20, 0x40, 0x60, 0x00,
    53  				0x80, 0x60, 0x40, 0x20, 0x80, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
    54  			},
    55  		},
    56  		{
    57  			"convolution (3x3, true, false, false, 0)",
    58  			[]float32{
    59  				0, 0, 1,
    60  				0, 0, 0,
    61  				1, 0, 0,
    62  			},
    63  			true, false, false, 0,
    64  			image.Rect(-1, -1, 2, 2),
    65  			image.Rect(0, 0, 3, 3),
    66  			[]uint8{
    67  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x60, 0x80,
    68  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    69  				0x80, 0x60, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    70  			},
    71  			[]uint8{
    72  				0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0x00, 0x10, 0x20, 0x30, 0x80,
    73  				0x40, 0x30, 0x20, 0x00, 0x50, 0x50, 0x50, 0x00, 0x10, 0x20, 0x30, 0x00,
    74  				0x40, 0x30, 0x20, 0x20, 0x40, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
    75  			},
    76  		},
    77  		{
    78  			"convolution (3x3, false, true, false, 0)",
    79  			[]float32{
    80  				0, 0, 1,
    81  				0, 0, 0,
    82  				1, 0, 0,
    83  			},
    84  			false, true, false, 0,
    85  			image.Rect(-1, -1, 2, 2),
    86  			image.Rect(0, 0, 3, 3),
    87  			[]uint8{
    88  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x60, 0x80,
    89  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    90  				0x80, 0x60, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    91  			},
    92  			[]uint8{
    93  				0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x60, 0x80, 0x20, 0x40, 0x60, 0x80,
    94  				0x80, 0x60, 0x40, 0x20, 0xA0, 0xA0, 0xA0, 0xA0, 0x20, 0x40, 0x60, 0x80,
    95  				0x80, 0x60, 0x40, 0x20, 0x80, 0x60, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00,
    96  			},
    97  		},
    98  		{
    99  			"convolution (3x3, true, true, true, 0)",
   100  			[]float32{
   101  				0, 0, 0,
   102  				-0.5, 0, 0.5,
   103  				0, 0, 0,
   104  			},
   105  			true, true, true, 0,
   106  			image.Rect(-1, -1, 2, 2),
   107  			image.Rect(0, 0, 3, 3),
   108  			[]uint8{
   109  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x60, 0x80,
   110  				0x80, 0x60, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x60, 0x80,
   111  				0x80, 0x60, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   112  			},
   113  			[]uint8{
   114  				0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x60, 0x80, 0x20, 0x40, 0x60, 0x80,
   115  				0x80, 0x60, 0x40, 0x20, 0x60, 0x20, 0x20, 0x60, 0x20, 0x40, 0x60, 0x80,
   116  				0x80, 0x60, 0x40, 0x20, 0x80, 0x60, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00,
   117  			},
   118  		},
   119  		{
   120  			"convolution (3x3, false, true, false, 3 / 255.0)",
   121  			[]float32{
   122  				0, 0, 1,
   123  				0, 0, 0,
   124  				1, 0, 0,
   125  			},
   126  			false, true, false, 3 / 255.0,
   127  			image.Rect(-1, -1, 2, 2),
   128  			image.Rect(0, 0, 3, 3),
   129  			[]uint8{
   130  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x60, 0x80,
   131  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   132  				0x80, 0x60, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   133  			},
   134  			[]uint8{
   135  				0x03, 0x03, 0x03, 0x03, 0x23, 0x43, 0x63, 0x83, 0x23, 0x43, 0x63, 0x83,
   136  				0x83, 0x63, 0x43, 0x23, 0xA3, 0xA3, 0xA3, 0xA3, 0x23, 0x43, 0x63, 0x83,
   137  				0x83, 0x63, 0x43, 0x23, 0x83, 0x63, 0x43, 0x23, 0x03, 0x03, 0x03, 0x03,
   138  			},
   139  		},
   140  		{
   141  			"convolution (3x3, false, false, true, 0)",
   142  			[]float32{
   143  				0, 0, -0.5,
   144  				0, 0, 0,
   145  				0, 0, 0,
   146  			},
   147  			false, false, true, 0.0,
   148  			image.Rect(-1, -1, 2, 2),
   149  			image.Rect(0, 0, 3, 3),
   150  			[]uint8{
   151  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x60, 0x80,
   152  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   153  				0x80, 0x60, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   154  			},
   155  			[]uint8{
   156  				0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0x00, 0x10, 0x20, 0x30, 0x80,
   157  				0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0x00, 0x10, 0x20, 0x30, 0x00,
   158  				0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   159  			},
   160  		},
   161  		{
   162  			"convolution (7x7, false, true, false, 0)",
   163  			[]float32{
   164  				0, 0, 0, 0, 0, 0, 1,
   165  				0, 0, 0, 0, 0, 0, 0,
   166  				0, 0, 0, 0, 0, 0, 0,
   167  				0, 0, 0, 0, 0, 0, 0,
   168  				0, 0, 0, 0, 0, 0, 0,
   169  				0, 0, 0, 0, 0, 0, 0,
   170  				1, 0, 0, 0, 0, 0, 0,
   171  			},
   172  			false, true, false, 0,
   173  			image.Rect(-1, -1, 2, 2),
   174  			image.Rect(0, 0, 3, 3),
   175  			[]uint8{
   176  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x60, 0x80,
   177  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   178  				0x80, 0x60, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   179  			},
   180  			[]uint8{
   181  				0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
   182  				0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
   183  				0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
   184  			},
   185  		},
   186  	}
   187  
   188  	for _, d := range testData {
   189  		for _, parallel := range []bool{true, false} {
   190  			src := image.NewNRGBA(d.srcb)
   191  			src.Pix = d.srcPix
   192  
   193  			f := Convolution(d.kernel, d.normalize, d.alpha, d.abs, d.delta)
   194  			dst := image.NewNRGBA(f.Bounds(src.Bounds()))
   195  			f.Draw(dst, src, &Options{Parallelization: parallel})
   196  
   197  			if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) {
   198  				t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix)
   199  			}
   200  		}
   201  	}
   202  
   203  	testKernelSizes := []struct {
   204  		klen, size int
   205  	}{
   206  		{0, 0},
   207  		{1, 1}, {3, 1}, {8, 1},
   208  		{9, 3}, {16, 3}, {24, 3},
   209  		{25, 5}, {40, 5}, {48, 5},
   210  	}
   211  
   212  	for _, d := range testKernelSizes {
   213  		tmp := make([]float32, d.klen)
   214  		sz, _ := prepareConvolutionWeights(tmp, true)
   215  		if sz != d.size {
   216  			t.Errorf("unexpected kernel size: %d %d", d.klen, sz)
   217  		}
   218  	}
   219  
   220  	// check no panics
   221  	Convolution([]float32{}, true, true, true, 1).Draw(image.NewGray(image.Rect(0, 0, 0, 0)), image.NewGray(image.Rect(0, 0, 0, 0)), nil)
   222  	convolve1dh(image.NewGray(image.Rect(0, 0, 1, 1)), image.NewGray(image.Rect(0, 0, 1, 1)), []float32{}, nil)
   223  	convolve1dv(image.NewGray(image.Rect(0, 0, 1, 1)), image.NewGray(image.Rect(0, 0, 1, 1)), []float32{}, nil)
   224  	convolve1dh(image.NewGray(image.Rect(0, 0, 0, 0)), image.NewGray(image.Rect(0, 0, 0, 0)), []float32{}, nil)
   225  	convolve1dv(image.NewGray(image.Rect(0, 0, 0, 0)), image.NewGray(image.Rect(0, 0, 0, 0)), []float32{}, nil)
   226  	convolveLine([]pixel{}, []pixel{}, []uweight{})
   227  	prepareConvolutionWeights1d([]float32{0, 0})
   228  	prepareConvolutionWeights1d([]float32{})
   229  }
   230  
   231  func TestGaussianBlur(t *testing.T) {
   232  
   233  	testData := []struct {
   234  		desc           string
   235  		sigma          float32
   236  		srcb, dstb     image.Rectangle
   237  		srcPix, dstPix []uint8
   238  	}{
   239  		{
   240  			"blur (0.0)",
   241  			0.0,
   242  			image.Rect(-1, -1, 4, 2),
   243  			image.Rect(0, 0, 5, 3),
   244  			[]uint8{
   245  				0x00, 0x00, 0x00, 0x00, 0x00,
   246  				0x00, 0xC0, 0x00, 0xC0, 0x00,
   247  				0x00, 0x00, 0x00, 0x00, 0x00,
   248  			},
   249  			[]uint8{
   250  				0x00, 0x00, 0x00, 0x00, 0x00,
   251  				0x00, 0xC0, 0x00, 0xC0, 0x00,
   252  				0x00, 0x00, 0x00, 0x00, 0x00,
   253  			},
   254  		},
   255  		{
   256  			"blur (0.3)",
   257  			0.3,
   258  			image.Rect(-1, -1, 4, 2),
   259  			image.Rect(0, 0, 5, 3),
   260  			[]uint8{
   261  				0x00, 0x00, 0x00, 0x00, 0x00,
   262  				0x00, 0xC0, 0x00, 0xC0, 0x00,
   263  				0x00, 0x00, 0x00, 0x00, 0x00,
   264  			},
   265  			[]uint8{
   266  				0x00, 0x01, 0x00, 0x01, 0x00,
   267  				0x01, 0xBD, 0x01, 0xBD, 0x01,
   268  				0x00, 0x01, 0x00, 0x01, 0x00,
   269  			},
   270  		},
   271  		{
   272  			"blur (1.0)",
   273  			1.0,
   274  			image.Rect(-1, -1, 4, 2),
   275  			image.Rect(0, 0, 5, 3),
   276  			[]uint8{
   277  				0x00, 0x00, 0x00, 0x00, 0x00,
   278  				0x00, 0xC0, 0x00, 0xC0, 0x00,
   279  				0x00, 0x00, 0x00, 0x00, 0x00,
   280  			},
   281  			[]uint8{
   282  				0x0B, 0x15, 0x16, 0x15, 0x0B,
   283  				0x13, 0x23, 0x25, 0x23, 0x13,
   284  				0x0B, 0x15, 0x16, 0x15, 0x0B,
   285  			},
   286  		},
   287  		{
   288  			"blur (3.0)",
   289  			3.0,
   290  			image.Rect(-1, -1, 4, 2),
   291  			image.Rect(0, 0, 5, 3),
   292  			[]uint8{
   293  				0x00, 0x00, 0x00, 0x00, 0x00,
   294  				0x00, 0xC0, 0x00, 0xC0, 0x00,
   295  				0x00, 0x00, 0x00, 0x00, 0x00,
   296  			},
   297  			[]uint8{
   298  				0x05, 0x06, 0x06, 0x06, 0x05,
   299  				0x05, 0x06, 0x06, 0x06, 0x05,
   300  				0x05, 0x06, 0x06, 0x06, 0x05,
   301  			},
   302  		},
   303  	}
   304  
   305  	for _, d := range testData {
   306  		src := image.NewGray(d.srcb)
   307  		src.Pix = d.srcPix
   308  
   309  		f := GaussianBlur(d.sigma)
   310  		dst := image.NewGray(f.Bounds(src.Bounds()))
   311  		f.Draw(dst, src, nil)
   312  
   313  		if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) {
   314  			t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix)
   315  		}
   316  	}
   317  
   318  	// check no panics
   319  	GaussianBlur(0.5).Draw(image.NewGray(image.Rect(0, 0, 0, 0)), image.NewGray(image.Rect(0, 0, 0, 0)), nil)
   320  }
   321  
   322  func TestUnsharpMask(t *testing.T) {
   323  
   324  	testData := []struct {
   325  		desc                    string
   326  		sigma, amount, thresold float32
   327  		srcb, dstb              image.Rectangle
   328  		srcPix, dstPix          []uint8
   329  	}{
   330  		{
   331  			"unsharp mask (0.3, 1.0, 0.0)",
   332  			0.3, 1.0, 0.0,
   333  			image.Rect(-1, -1, 4, 2),
   334  			image.Rect(0, 0, 5, 3),
   335  			[]uint8{
   336  				0x00, 0x40, 0x00, 0x40, 0x00,
   337  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   338  				0x00, 0x80, 0x00, 0x80, 0x00,
   339  			},
   340  			[]uint8{
   341  				0x00, 0x40, 0x00, 0x40, 0x00,
   342  				0x60, 0xB1, 0xA1, 0xB1, 0x60,
   343  				0x00, 0x81, 0x00, 0x81, 0x00,
   344  			},
   345  		},
   346  		{
   347  			"unsharp mask (1.0, 1.0, 0.0)",
   348  			1.0, 1.0, 0.0,
   349  			image.Rect(-1, -1, 4, 2),
   350  			image.Rect(0, 0, 5, 3),
   351  			[]uint8{
   352  				0x00, 0x40, 0x00, 0x40, 0x00,
   353  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   354  				0x00, 0x80, 0x00, 0x80, 0x00,
   355  			},
   356  			[]uint8{
   357  				0x00, 0x45, 0x00, 0x45, 0x00,
   358  				0x82, 0xFF, 0xE4, 0xFF, 0x82,
   359  				0x00, 0xB2, 0x00, 0xB2, 0x00,
   360  			},
   361  		},
   362  		{
   363  			"unsharp mask (1.0, 0.5, 0.0)",
   364  			1.0, 0.5, 0.0,
   365  			image.Rect(-1, -1, 4, 2),
   366  			image.Rect(0, 0, 5, 3),
   367  			[]uint8{
   368  				0x00, 0x40, 0x00, 0x40, 0x00,
   369  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   370  				0x00, 0x80, 0x00, 0x80, 0x00,
   371  			},
   372  			[]uint8{
   373  				0x00, 0x42, 0x00, 0x42, 0x00,
   374  				0x71, 0xDD, 0xC2, 0xDD, 0x71,
   375  				0x00, 0x99, 0x00, 0x99, 0x00,
   376  			},
   377  		},
   378  		{
   379  			"unsharp mask (1.0, 1.0, 0.05)",
   380  			1.0, 1.0, 0.05,
   381  			image.Rect(-1, -1, 4, 2),
   382  			image.Rect(0, 0, 5, 3),
   383  			[]uint8{
   384  				0x00, 0x40, 0x00, 0x40, 0x00,
   385  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   386  				0x00, 0x80, 0x00, 0x80, 0x00,
   387  			},
   388  			[]uint8{
   389  				0x00, 0x40, 0x00, 0x40, 0x00,
   390  				0x82, 0xFF, 0xE4, 0xFF, 0x82,
   391  				0x00, 0xB2, 0x00, 0xB2, 0x00,
   392  			},
   393  		},
   394  	}
   395  
   396  	for _, d := range testData {
   397  		src := image.NewGray(d.srcb)
   398  		src.Pix = d.srcPix
   399  
   400  		f := UnsharpMask(d.sigma, d.amount, d.thresold)
   401  		dst := image.NewGray(f.Bounds(src.Bounds()))
   402  		f.Draw(dst, src, nil)
   403  
   404  		if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) {
   405  			t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix)
   406  		}
   407  	}
   408  
   409  	// check no panics
   410  	UnsharpMask(0.5, 1.0, 0.0).Draw(image.NewGray(image.Rect(0, 0, 0, 0)), image.NewGray(image.Rect(0, 0, 0, 0)), nil)
   411  }
   412  
   413  func TestMean(t *testing.T) {
   414  
   415  	testData := []struct {
   416  		desc           string
   417  		ksize          int
   418  		disk           bool
   419  		srcb, dstb     image.Rectangle
   420  		srcPix, dstPix []uint8
   421  	}{
   422  		{
   423  			"mean (0x0 false)",
   424  			0, false,
   425  			image.Rect(-1, -1, 4, 2),
   426  			image.Rect(0, 0, 5, 3),
   427  			[]uint8{
   428  				0x00, 0x40, 0x00, 0x40, 0x00,
   429  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   430  				0x00, 0x80, 0x00, 0x80, 0x00,
   431  			},
   432  			[]uint8{
   433  				0x00, 0x40, 0x00, 0x40, 0x00,
   434  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   435  				0x00, 0x80, 0x00, 0x80, 0x00,
   436  			},
   437  		},
   438  		{
   439  			"mean (1x1 false)",
   440  			1, false,
   441  			image.Rect(-1, -1, 4, 2),
   442  			image.Rect(0, 0, 5, 3),
   443  			[]uint8{
   444  				0x00, 0x40, 0x00, 0x40, 0x00,
   445  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   446  				0x00, 0x80, 0x00, 0x80, 0x00,
   447  			},
   448  			[]uint8{
   449  				0x00, 0x40, 0x00, 0x40, 0x00,
   450  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   451  				0x00, 0x80, 0x00, 0x80, 0x00,
   452  			},
   453  		},
   454  		{
   455  			"mean (2x2 true)",
   456  			2, true,
   457  			image.Rect(-1, -1, 4, 2),
   458  			image.Rect(0, 0, 5, 3),
   459  			[]uint8{
   460  				0x00, 0x40, 0x00, 0x40, 0x00,
   461  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   462  				0x00, 0x80, 0x00, 0x80, 0x00,
   463  			},
   464  			[]uint8{
   465  				0x00, 0x40, 0x00, 0x40, 0x00,
   466  				0x60, 0xB0, 0xA0, 0xB0, 0x60,
   467  				0x00, 0x80, 0x00, 0x80, 0x00,
   468  			},
   469  		},
   470  		{
   471  			"mean (3x3 false)",
   472  			3, false,
   473  			image.Rect(-1, -1, 4, 2),
   474  			image.Rect(0, 0, 5, 3),
   475  			[]uint8{
   476  				0x10, 0x40, 0x00, 0x40, 0x10,
   477  				0x20, 0x50, 0x00, 0x50, 0x20,
   478  				0x30, 0x60, 0x00, 0x60, 0x30,
   479  			},
   480  			[]uint8{
   481  				0x25, 0x1E, 0x2E, 0x1E, 0x25,
   482  				0x30, 0x25, 0x35, 0x25, 0x30,
   483  				0x3B, 0x2C, 0x3C, 0x2C, 0x3B,
   484  			},
   485  		},
   486  		{
   487  			"mean (3x3 true)",
   488  			3, true,
   489  			image.Rect(-1, -1, 4, 2),
   490  			image.Rect(0, 0, 5, 3),
   491  			[]uint8{
   492  				0x10, 0x40, 0x00, 0x40, 0x10,
   493  				0x20, 0x50, 0x00, 0x50, 0x20,
   494  				0x30, 0x60, 0x00, 0x60, 0x30,
   495  			},
   496  			[]uint8{
   497  				0x1D, 0x2D, 0x1A, 0x2D, 0x1D,
   498  				0x2A, 0x36, 0x20, 0x36, 0x2A,
   499  				0x36, 0x40, 0x26, 0x40, 0x36,
   500  			},
   501  		},
   502  	}
   503  
   504  	for _, d := range testData {
   505  		src := image.NewGray(d.srcb)
   506  		src.Pix = d.srcPix
   507  
   508  		f := Mean(d.ksize, d.disk)
   509  		dst := image.NewGray(f.Bounds(src.Bounds()))
   510  		f.Draw(dst, src, nil)
   511  
   512  		if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) {
   513  			t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix)
   514  		}
   515  	}
   516  
   517  	// check no panics
   518  	Mean(5, false).Draw(image.NewGray(image.Rect(0, 0, 0, 0)), image.NewGray(image.Rect(0, 0, 0, 0)), nil)
   519  }
   520  
   521  func TestSobel(t *testing.T) {
   522  	testData := []struct {
   523  		desc           string
   524  		srcb, dstb     image.Rectangle
   525  		srcPix, dstPix []uint8
   526  	}{
   527  
   528  		{
   529  			"sobel 0x0",
   530  			image.Rect(0, 0, 0, 0),
   531  			image.Rect(0, 0, 0, 0),
   532  			[]uint8{},
   533  			[]uint8{},
   534  		},
   535  		{
   536  			"sobel 6x6",
   537  			image.Rect(-1, -1, 5, 5),
   538  			image.Rect(0, 0, 6, 6),
   539  			[]uint8{
   540  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   541  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   542  				0x00, 0x00, 0x99, 0x99, 0x99, 0x99,
   543  				0x00, 0x00, 0x99, 0x99, 0x99, 0x99,
   544  				0x00, 0x00, 0x99, 0x99, 0x99, 0x99,
   545  				0x00, 0x00, 0x99, 0x99, 0x99, 0x99,
   546  			},
   547  			[]uint8{
   548  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   549  				0x00, 0xd8, 0xff, 0xff, 0xff, 0xff,
   550  				0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
   551  				0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
   552  				0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
   553  				0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
   554  			},
   555  		},
   556  	}
   557  
   558  	for _, d := range testData {
   559  		src := image.NewGray(d.srcb)
   560  		src.Pix = d.srcPix
   561  
   562  		f := Sobel()
   563  		dst := image.NewGray(f.Bounds(src.Bounds()))
   564  		f.Draw(dst, src, nil)
   565  
   566  		if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) {
   567  			t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix)
   568  		}
   569  	}
   570  }