package blend

import (
	"image"
	"testing"

	"github.com/anthonynsimon/bild/util"
)

func TestNormal(t *testing.T) {
	cases := []struct {
		value0   image.Image
		value1   image.Image
		expected *image.RGBA
	}{
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
					0x40, 0x40, 0x40, 0xFF, 0x00, 0x00, 0x00, 0xFF,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0xFF,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0xFF,
					0x60, 0x60, 0x60, 0xFF, 0x00, 0x00, 0x00, 0xFF,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
					0x40, 0x40, 0x40, 0xFF, 0x00, 0x00, 0x00, 0xFF,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0x00, 0x80, 0x80, 0x80, 0x00,
					0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
					0x40, 0x40, 0x40, 0xFF, 0x00, 0x00, 0x00, 0xFF,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0xFF, 0xFF, 0xFF, 0xFF,
					0x40, 0x40, 0x40, 0xFF, 0x00, 0x00, 0x00, 0xFF,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80, 0xFF,
					0x80, 0x80, 0x80, 0xFF, 0x80, 0x80, 0x80, 0xFF,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xBF, 0xBF, 0xBF, 0xFF, 0x80, 0x80, 0x80, 0xFF,
					0x80, 0x80, 0x80, 0xFF, 0x80, 0x80, 0x80, 0xFF,
				},
			},
		},
	}

	for _, c := range cases {
		actual := Normal(c.value0, c.value1)
		if !util.RGBAImageEqual(actual, c.expected) {
			t.Errorf("%s: expected %#v, actual: %#v", "Normal", c.expected, actual)
		}
	}
}

func TestAdd(t *testing.T) {
	cases := []struct {
		value0   image.Image
		value1   image.Image
		expected *image.RGBA
	}{
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xff,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x40, 0x40, 0x40, 0x80, 0x40, 0x40, 0x40, 0x80, 0x40, 0x40, 0x40, 0x80, 0x40, 0x40, 0x40, 0x80,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80,
					0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xff, 0xff, 0xff, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0x60, 0x60, 0x60, 0xa0, 0x40, 0x40, 0x40, 0x80,
				},
			},
		},
	}

	for _, c := range cases {
		actual := Add(c.value0, c.value1)
		if !util.RGBAImageEqual(actual, c.expected) {
			t.Errorf("%s: expected %#v, actual: %#v", "Add", c.expected, actual)
		}
	}
}

func TestMultiply(t *testing.T) {
	cases := []struct {
		value0   image.Image
		value1   image.Image
		expected *image.RGBA
	}{
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x60, 0x60, 0x60, 0xff, 0x60, 0x60, 0x60, 0xff, 0x60, 0x60, 0x60, 0xff, 0x60, 0x60, 0x60, 0xff,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
					0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x80,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80,
					0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xbf, 0xbf, 0xbf, 0xff, 0x60, 0x60, 0x60, 0xff, 0x18, 0x18, 0x18, 0xa0, 0x0, 0x0, 0x0, 0x80,
				},
			},
		},
	}

	for _, c := range cases {
		actual := Multiply(c.value0, c.value1)
		if !util.RGBAImageEqual(actual, c.expected) {
			t.Errorf("%s: expected %#v, actual: %#v", "Multiply", c.expected, actual)
		}
	}
}

func TestOverlay(t *testing.T) {
	cases := []struct {
		value0   image.Image
		value1   image.Image
		expected *image.RGBA
	}{
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x1c, 0x1c, 0x1c, 0x40, 0x1c, 0x1c, 0x1c, 0x40, 0x1c, 0x1c, 0x1c, 0x40, 0x1c, 0x1c, 0x1c, 0x40,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80,
					0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0xff, 0x20, 0x20, 0x20, 0xa0, 0x0, 0x0, 0x0, 0x80,
				},
			},
		},
	}

	for _, c := range cases {
		actual := Overlay(c.value0, c.value1)
		if !util.RGBAImageEqual(actual, c.expected) {
			t.Errorf("%s: expected %#v, actual: %#v", "Overlay", c.expected, actual)
		}
	}
}

func TestSoftLight(t *testing.T) {
	cases := []struct {
		value0   image.Image
		value1   image.Image
		expected *image.RGBA
	}{
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x1d, 0x1d, 0x1d, 0x40, 0x1d, 0x1d, 0x1d, 0x40, 0x1d, 0x1d, 0x1d, 0x40, 0x1d, 0x1d, 0x1d, 0x40,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80,
					0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0xff, 0x20, 0x20, 0x20, 0xa0, 0x0, 0x0, 0x0, 0x80,
				},
			},
		},
	}

	for _, c := range cases {
		actual := SoftLight(c.value0, c.value1)
		if !util.RGBAImageEqual(actual, c.expected) {
			t.Errorf("%s: expected %#v, actual: %#v", "Softlight", c.expected, actual)
		}
	}
}

func TestScreen(t *testing.T) {
	cases := []struct {
		value0   image.Image
		value1   image.Image
		expected *image.RGBA
	}{
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x9f, 0x9f, 0x9f, 0xff, 0x9f, 0x9f, 0x9f, 0xff, 0x9f, 0x9f, 0x9f, 0xff, 0x9f, 0x9f, 0x9f, 0xff,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x23, 0x23, 0x23, 0x40, 0x23, 0x23, 0x23, 0x40, 0x23, 0x23, 0x23, 0x40, 0x23, 0x23, 0x23, 0x40,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80,
					0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xff, 0xff, 0xff, 0xff, 0x9f, 0x9f, 0x9f, 0xff, 0x58, 0x58, 0x58, 0xa0, 0x40, 0x40, 0x40, 0x80,
				},
			},
		},
	}

	for _, c := range cases {
		actual := Screen(c.value0, c.value1)
		if !util.RGBAImageEqual(actual, c.expected) {
			t.Errorf("%s: expected %#v, actual: %#v", "Screen", c.expected, actual)
		}
	}
}

func TestDifference(t *testing.T) {
	cases := []struct {
		value0   image.Image
		value1   image.Image
		expected *image.RGBA
	}{
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x3f, 0x3f, 0x3f, 0xff, 0x3f, 0x3f, 0x3f, 0xff, 0x3f, 0x3f, 0x3f, 0xff, 0x3f, 0x3f, 0x3f, 0xff,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x1b, 0x1b, 0x1b, 0x40, 0x1b, 0x1b, 0x1b, 0x40, 0x1b, 0x1b, 0x1b, 0x40, 0x1b, 0x1b, 0x1b, 0x40,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80,
					0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xbe, 0xbe, 0xbe, 0xff, 0x3f, 0x3f, 0x3f, 0xff, 0x40, 0x40, 0x40, 0xa0, 0x40, 0x40, 0x40, 0x80,
				},
			},
		},
	}

	for _, c := range cases {
		actual := Difference(c.value0, c.value1)
		if !util.RGBAImageEqual(actual, c.expected) {
			t.Errorf("%s: expected %#v, actual: %#v", "Difference", c.expected, actual)
		}
	}
}

func TestDivide(t *testing.T) {
	cases := []struct {
		value0   image.Image
		value1   image.Image
		expected *image.RGBA
	}{
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xff,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x3b, 0x3b, 0x3b, 0x40, 0x3b, 0x3b, 0x3b, 0x40, 0x3b, 0x3b, 0x3b, 0x40, 0x3b, 0x3b, 0x3b, 0x40,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80,
					0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xff, 0xff, 0xff, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0x2f, 0x2f, 0x2f, 0xa0, 0x0, 0x0, 0x0, 0x80,
				},
			},
		},
	}

	for _, c := range cases {
		actual := Divide(c.value0, c.value1)
		if !util.RGBAImageEqual(actual, c.expected) {
			t.Errorf("%s: expected %#v, actual: %#v", "Divide", c.expected, actual)
		}
	}
}

func TestColorBurn(t *testing.T) {
	cases := []struct {
		value0   image.Image
		value1   image.Image
		expected *image.RGBA
	}{
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x40, 0x40, 0x40, 0xff, 0x40, 0x40, 0x40, 0xff, 0x40, 0x40, 0x40, 0xff, 0x40, 0x40, 0x40, 0xff,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x1b, 0x1b, 0x1b, 0x40, 0x1b, 0x1b, 0x1b, 0x40, 0x1b, 0x1b, 0x1b, 0x40, 0x1b, 0x1b, 0x1b, 0x40,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80,
					0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xff, 0xff, 0xff, 0xff, 0x40, 0x40, 0x40, 0xff, 0xf, 0xf, 0xf, 0xa0, 0x0, 0x0, 0x0, 0x80,
				},
			},
		},
	}

	for _, c := range cases {
		actual := ColorBurn(c.value0, c.value1)
		if !util.RGBAImageEqual(actual, c.expected) {
			t.Errorf("%s: expected %#v, actual: %#v", "ColorBurn", c.expected, actual)
		}
	}
}

func TestExclusion(t *testing.T) {
	cases := []struct {
		value0   image.Image
		value1   image.Image
		expected *image.RGBA
	}{
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x7f, 0x7f, 0x7f, 0xff, 0x7f, 0x7f, 0x7f, 0xff, 0x7f, 0x7f, 0x7f, 0xff, 0x7f, 0x7f, 0x7f, 0xff,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x23, 0x23, 0x23, 0x40, 0x23, 0x23, 0x23, 0x40, 0x23, 0x23, 0x23, 0x40, 0x23, 0x23, 0x23, 0x40,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80,
					0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xbe, 0xbe, 0xbe, 0xff, 0x7f, 0x7f, 0x7f, 0xff, 0x50, 0x50, 0x50, 0xa0, 0x40, 0x40, 0x40, 0x80,
				},
			},
		},
	}

	for _, c := range cases {
		actual := Exclusion(c.value0, c.value1)
		if !util.RGBAImageEqual(actual, c.expected) {
			t.Errorf("%s: expected %#v, actual: %#v", "Exclusion", c.expected, actual)
		}
	}
}

func TestColorDodge(t *testing.T) {
	cases := []struct {
		value0   image.Image
		value1   image.Image
		expected *image.RGBA
	}{
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xff,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x40, 0x20, 0x20, 0x20, 0x40, 0x20, 0x20, 0x20, 0x40, 0x20, 0x20, 0x20, 0x40,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80,
					0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xff, 0xff, 0xff, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0x30, 0x30, 0x30, 0xa0, 0x0, 0x0, 0x0, 0x80,
				},
			},
		},
	}

	for _, c := range cases {
		actual := ColorDodge(c.value0, c.value1)
		if !util.RGBAImageEqual(actual, c.expected) {
			t.Errorf("%s: expected %#v, actual: %#v", "ColorDodge", c.expected, actual)
		}
	}
}

func TestLinearBurn(t *testing.T) {
	cases := []struct {
		value0   image.Image
		value1   image.Image
		expected *image.RGBA
	}{
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x40, 0x40, 0x40, 0xff, 0x40, 0x40, 0x40, 0xff, 0x40, 0x40, 0x40, 0xff, 0x40, 0x40, 0x40, 0xff,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x1b, 0x1b, 0x1b, 0x40, 0x1b, 0x1b, 0x1b, 0x40, 0x1b, 0x1b, 0x1b, 0x40, 0x1b, 0x1b, 0x1b, 0x40,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80,
					0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xbf, 0xbf, 0xbf, 0xff, 0x40, 0x40, 0x40, 0xff, 0xf, 0xf, 0xf, 0xa0, 0x0, 0x0, 0x0, 0x80,
				},
			},
		},
	}

	for _, c := range cases {
		actual := LinearBurn(c.value0, c.value1)
		if !util.RGBAImageEqual(actual, c.expected) {
			t.Errorf("%s: expected %#v, actual: %#v", "LinearBurn", c.expected, actual)
		}
	}
}

func TestLinearLight(t *testing.T) {
	cases := []struct {
		value0   image.Image
		value1   image.Image
		expected *image.RGBA
	}{
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0xbf, 0xbf, 0xbf, 0xff,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x1b, 0x1b, 0x1b, 0x40, 0x1b, 0x1b, 0x1b, 0x40, 0x1b, 0x1b, 0x1b, 0x40, 0x1b, 0x1b, 0x1b, 0x40,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80,
					0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xff, 0xff, 0xff, 0xff, 0xbf, 0xbf, 0xbf, 0xff, 0x60, 0x60, 0x60, 0xa0, 0x40, 0x40, 0x40, 0x80,
				},
			},
		},
	}

	for _, c := range cases {
		actual := LinearLight(c.value0, c.value1)
		if !util.RGBAImageEqual(actual, c.expected) {
			t.Errorf("%s: expected %#v, actual: %#v", "LinearLight", c.expected, actual)
		}
	}
}

func TestSubtract(t *testing.T) {
	cases := []struct {
		value0   image.Image
		value1   image.Image
		expected *image.RGBA
	}{
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x3f, 0x3f, 0x3f, 0xff, 0x3f, 0x3f, 0x3f, 0xff,
					0x3f, 0x3f, 0x3f, 0xff, 0x3f, 0x3f, 0x3f, 0xff,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x1b, 0x1b, 0x1b, 0x40, 0x1b, 0x1b, 0x1b, 0x40,
					0x1b, 0x1b, 0x1b, 0x40, 0x1b, 0x1b, 0x1b, 0x40,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0xFF,
					0x20, 0x20, 0x20, 0xFF, 0x00, 0x00, 0x00, 0xFF,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0xFF, 0x80, 0x80, 0x80, 0xFF,
					0x80, 0x80, 0x80, 0xFF, 0x80, 0x80, 0x80, 0xFF,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0xff,
					0x60, 0x60, 0x60, 0xff, 0x80, 0x80, 0x80, 0xff,
				},
			},
		},
	}

	for _, c := range cases {
		actual := Subtract(c.value0, c.value1)
		if !util.RGBAImageEqual(actual, c.expected) {
			t.Errorf("%s: expected %#v, actual: %#v", "Subtract", c.expected, actual)
		}
	}
}

func TestOpacity(t *testing.T) {
	cases := []struct {
		value0   image.Image
		value1   image.Image
		expected *image.RGBA
		percent  float64
	}{
		{
			percent: 1.0,
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x73, 0x73, 0x73, 0xa0, 0x73, 0x73, 0x73, 0xa0,
					0x73, 0x73, 0x73, 0xa0, 0x73, 0x73, 0x73, 0xa0,
				},
			},
		},
		{
			percent: 0.0,
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0xa0, 0x20, 0x20, 0x20, 0xa0,
					0x20, 0x20, 0x20, 0xa0, 0x20, 0x20, 0x20, 0xa0,
				},
			},
		},
		{
			percent: 0.5,
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80,
					0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xdf, 0xdf, 0xdf, 0xff, 0x80, 0x80, 0x80, 0xff,
					0x38, 0x38, 0x38, 0xa0, 0x20, 0x20, 0x20, 0x80,
				},
			},
		},
	}

	for _, c := range cases {
		actual := Opacity(c.value0, c.value1, c.percent)
		if !util.RGBAImageEqual(actual, c.expected) {
			t.Errorf("%s: expected %#v, actual: %#v", "Opacity", c.expected, actual)
		}
	}
}

func TestDarken(t *testing.T) {
	cases := []struct {
		value0   image.Image
		value1   image.Image
		expected *image.RGBA
	}{
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x73, 0x73, 0x73, 0xa0, 0x73, 0x73, 0x73, 0xa0,
					0x73, 0x73, 0x73, 0xa0, 0x73, 0x73, 0x73, 0xa0,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0xa0, 0x20, 0x20, 0x20, 0xa0,
					0x20, 0x20, 0x20, 0xa0, 0x20, 0x20, 0x20, 0xa0,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80,
					0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xbf, 0xbf, 0xbf, 0xff, 0x80, 0x80, 0x80, 0xff,
					0x20, 0x20, 0x20, 0xa0, 0x0, 0x0, 0x0, 0x80,
				},
			},
		},
	}

	for _, c := range cases {
		actual := Darken(c.value0, c.value1)
		if !util.RGBAImageEqual(actual, c.expected) {
			t.Errorf("%s: expected %#v, actual: %#v", "Darken", c.expected, actual)
		}
	}
}

func TestLighten(t *testing.T) {
	cases := []struct {
		value0   image.Image
		value1   image.Image
		expected *image.RGBA
	}{
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0xa0, 0x80, 0x80, 0x80, 0xa0,
					0x80, 0x80, 0x80, 0xa0, 0x80, 0x80, 0x80, 0xa0,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
					0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x50, 0x50, 0x50, 0xa0, 0x50, 0x50, 0x50, 0xa0,
					0x50, 0x50, 0x50, 0xa0, 0x50, 0x50, 0x50, 0xa0,
				},
			},
		},
		{
			value0: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80,
					0x20, 0x20, 0x20, 0x20, 0x00, 0x80, 0x00, 0x00,
				},
			},
			value1: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
					0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x20, 0x80,
				},
			},
			expected: &image.RGBA{
				Rect:   image.Rect(0, 0, 2, 2),
				Stride: 8,
				Pix: []uint8{
					0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0xff,
					0x50, 0x50, 0x50, 0xa0, 0x0, 0x80, 0x10, 0x80,
				},
			},
		},
	}

	for _, c := range cases {
		actual := Lighten(c.value0, c.value1)
		if !util.RGBAImageEqual(actual, c.expected) {
			t.Errorf("%s: expected %#v, actual: %#v", "Lighten", c.expected, actual)
		}
	}
}
