123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- package imaging
- import (
- "image"
- "math"
- "runtime"
- "testing"
- )
- var (
- testdataBranchesJPG = mustOpen("testdata/branches.jpg")
- testdataBranchesPNG = mustOpen("testdata/branches.png")
- testdataFlowersSmallPNG = mustOpen("testdata/flowers_small.png")
- )
- func mustOpen(filename string) image.Image {
- img, err := Open(filename)
- if err != nil {
- panic(err)
- }
- return img
- }
- func TestParallel(t *testing.T) {
- for _, n := range []int{0, 1, 10, 100, 1000} {
- for _, p := range []int{1, 2, 4, 8, 16, 100} {
- if !testParallelN(n, p) {
- t.Fatalf("test [parallel %d %d] failed", n, p)
- }
- }
- }
- }
- func testParallelN(n, procs int) bool {
- data := make([]bool, n)
- before := runtime.GOMAXPROCS(0)
- runtime.GOMAXPROCS(procs)
- parallel(0, n, func(is <-chan int) {
- for i := range is {
- data[i] = true
- }
- })
- runtime.GOMAXPROCS(before)
- for i := 0; i < n; i++ {
- if !data[i] {
- return false
- }
- }
- return true
- }
- func TestClamp(t *testing.T) {
- testCases := []struct {
- f float64
- u uint8
- }{
- {0, 0},
- {255, 255},
- {128, 128},
- {0.49, 0},
- {0.50, 1},
- {254.9, 255},
- {254.0, 254},
- {256, 255},
- {2500, 255},
- {-10, 0},
- {127.6, 128},
- }
- for _, tc := range testCases {
- if clamp(tc.f) != tc.u {
- t.Fatalf("test [clamp %v %v] failed: %v", tc.f, tc.u, clamp(tc.f))
- }
- }
- }
- func TestReverse(t *testing.T) {
- testCases := []struct {
- pix []uint8
- want []uint8
- }{
- {
- pix: []uint8{},
- want: []uint8{},
- },
- {
- pix: []uint8{1, 2, 3, 4},
- want: []uint8{1, 2, 3, 4},
- },
- {
- pix: []uint8{1, 2, 3, 4, 5, 6, 7, 8},
- want: []uint8{5, 6, 7, 8, 1, 2, 3, 4},
- },
- {
- pix: []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
- want: []uint8{9, 10, 11, 12, 5, 6, 7, 8, 1, 2, 3, 4},
- },
- }
- for _, tc := range testCases {
- t.Run("", func(t *testing.T) {
- reverse(tc.pix)
- if !compareBytes(tc.pix, tc.want, 0) {
- t.Fatalf("got pix %v want %v", tc.pix, tc.want)
- }
- })
- }
- }
- func compareNRGBA(img1, img2 *image.NRGBA, delta int) bool {
- if !img1.Rect.Eq(img2.Rect) {
- return false
- }
- return compareBytes(img1.Pix, img2.Pix, delta)
- }
- func compareBytes(a, b []uint8, delta int) bool {
- if len(a) != len(b) {
- return false
- }
- for i := 0; i < len(a); i++ {
- if absint(int(a[i])-int(b[i])) > delta {
- return false
- }
- }
- return true
- }
- // compareNRGBAGolden is a special version of compareNRGBA used in golden tests.
- // All the golden images are generated on amd64 architecture. Due to differences
- // in floating-point rounding on different architectures, we need to add some
- // level of tolerance when comparing images on architectures other than amd64.
- // See https://golang.org/ref/spec#Floating_point_operators for information on
- // fused multiply and add (FMA) instruction.
- func compareNRGBAGolden(img1, img2 *image.NRGBA) bool {
- delta := 0
- if runtime.GOARCH != "amd64" {
- delta = 1
- }
- return compareNRGBA(img1, img2, delta)
- }
- func compareFloat64(a, b, delta float64) bool {
- return math.Abs(a-b) <= delta
- }
- var rgbHSLTestCases = []struct {
- r, g, b uint8
- h, s, l float64
- }{
- {
- r: 255,
- g: 0,
- b: 0,
- h: 0.000,
- s: 1.000,
- l: 0.500,
- },
- {
- r: 191,
- g: 191,
- b: 0,
- h: 0.167,
- s: 1.000,
- l: 0.375,
- },
- {
- r: 0,
- g: 128,
- b: 0,
- h: 0.333,
- s: 1.000,
- l: 0.251,
- },
- {
- r: 128,
- g: 255,
- b: 255,
- h: 0.500,
- s: 1.000,
- l: 0.751,
- },
- {
- r: 128,
- g: 128,
- b: 255,
- h: 0.667,
- s: 1.000,
- l: 0.751,
- },
- {
- r: 191,
- g: 64,
- b: 191,
- h: 0.833,
- s: 0.498,
- l: 0.500,
- },
- {
- r: 160,
- g: 164,
- b: 36,
- h: 0.172,
- s: 0.640,
- l: 0.392,
- },
- {
- r: 65,
- g: 27,
- b: 234,
- h: 0.697,
- s: 0.831,
- l: 0.512,
- },
- {
- r: 30,
- g: 172,
- b: 65,
- h: 0.374,
- s: 0.703,
- l: 0.396,
- },
- {
- r: 240,
- g: 200,
- b: 14,
- h: 0.137,
- s: 0.890,
- l: 0.498,
- },
- {
- r: 180,
- g: 48,
- b: 229,
- h: 0.788,
- s: 0.777,
- l: 0.543,
- },
- {
- r: 237,
- g: 119,
- b: 81,
- h: 0.040,
- s: 0.813,
- l: 0.624,
- },
- {
- r: 254,
- g: 248,
- b: 136,
- h: 0.158,
- s: 0.983,
- l: 0.765,
- },
- {
- r: 25,
- g: 203,
- b: 151,
- h: 0.451,
- s: 0.781,
- l: 0.447,
- },
- {
- r: 54,
- g: 38,
- b: 152,
- h: 0.690,
- s: 0.600,
- l: 0.373,
- },
- {
- r: 126,
- g: 126,
- b: 184,
- h: 0.667,
- s: 0.290,
- l: 0.608,
- },
- }
- func TestRGBToHSL(t *testing.T) {
- for _, tc := range rgbHSLTestCases {
- t.Run("", func(t *testing.T) {
- h, s, l := rgbToHSL(tc.r, tc.g, tc.b)
- if !compareFloat64(h, tc.h, 0.001) || !compareFloat64(s, tc.s, 0.001) || !compareFloat64(l, tc.l, 0.001) {
- t.Fatalf("(%d, %d, %d): got (%.3f, %.3f, %.3f) want (%.3f, %.3f, %.3f)", tc.r, tc.g, tc.b, h, s, l, tc.h, tc.s, tc.l)
- }
- })
- }
- }
- func TestHSLToRGB(t *testing.T) {
- for _, tc := range rgbHSLTestCases {
- t.Run("", func(t *testing.T) {
- r, g, b := hslToRGB(tc.h, tc.s, tc.l)
- if r != tc.r || g != tc.g || b != tc.b {
- t.Fatalf("(%.3f, %.3f, %.3f): got (%d, %d, %d) want (%d, %d, %d)", tc.h, tc.s, tc.l, r, g, b, tc.r, tc.g, tc.b)
- }
- })
- }
- }
|