utils_test.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. package imaging
  2. import (
  3. "image"
  4. "math"
  5. "runtime"
  6. "sync/atomic"
  7. "testing"
  8. )
  9. var (
  10. testdataBranchesJPG = mustOpen("testdata/branches.jpg")
  11. testdataBranchesPNG = mustOpen("testdata/branches.png")
  12. testdataFlowersSmallPNG = mustOpen("testdata/flowers_small.png")
  13. )
  14. func mustOpen(filename string) image.Image {
  15. img, err := Open(filename)
  16. if err != nil {
  17. panic(err)
  18. }
  19. return img
  20. }
  21. func TestParallel(t *testing.T) {
  22. for _, n := range []int{0, 1, 10, 100, 1000} {
  23. for _, p := range []int{1, 2, 4, 8, 16, 100} {
  24. if !testParallelN(n, p) {
  25. t.Fatalf("test [parallel %d %d] failed", n, p)
  26. }
  27. }
  28. }
  29. }
  30. func testParallelN(n, procs int) bool {
  31. data := make([]bool, n)
  32. before := runtime.GOMAXPROCS(0)
  33. runtime.GOMAXPROCS(procs)
  34. parallel(0, n, func(is <-chan int) {
  35. for i := range is {
  36. data[i] = true
  37. }
  38. })
  39. runtime.GOMAXPROCS(before)
  40. for i := 0; i < n; i++ {
  41. if !data[i] {
  42. return false
  43. }
  44. }
  45. return true
  46. }
  47. func TestParallelMaxProcs(t *testing.T) {
  48. for _, n := range []int{0, 1, 10, 100, 1000} {
  49. for _, p := range []int{1, 2, 4, 8, 16, 100} {
  50. if !testParallelMaxProcsN(n, p) {
  51. t.Fatalf("test [parallel max procs %d %d] failed", n, p)
  52. }
  53. }
  54. }
  55. }
  56. func testParallelMaxProcsN(n, procs int) bool {
  57. data := make([]bool, n)
  58. SetMaxProcs(procs)
  59. parallel(0, n, func(is <-chan int) {
  60. for i := range is {
  61. data[i] = true
  62. }
  63. })
  64. SetMaxProcs(0)
  65. for i := 0; i < n; i++ {
  66. if !data[i] {
  67. return false
  68. }
  69. }
  70. return true
  71. }
  72. func TestSetMaxProcs(t *testing.T) {
  73. for _, p := range []int{-1, 0, 10} {
  74. SetMaxProcs(p)
  75. if int(atomic.LoadInt64(&maxProcs)) != p {
  76. t.Fatalf("test [set max procs %d] failed", p)
  77. }
  78. }
  79. SetMaxProcs(0)
  80. }
  81. func TestClamp(t *testing.T) {
  82. testCases := []struct {
  83. f float64
  84. u uint8
  85. }{
  86. {0, 0},
  87. {255, 255},
  88. {128, 128},
  89. {0.49, 0},
  90. {0.50, 1},
  91. {254.9, 255},
  92. {254.0, 254},
  93. {256, 255},
  94. {2500, 255},
  95. {-10, 0},
  96. {127.6, 128},
  97. }
  98. for _, tc := range testCases {
  99. if clamp(tc.f) != tc.u {
  100. t.Fatalf("test [clamp %v %v] failed: %v", tc.f, tc.u, clamp(tc.f))
  101. }
  102. }
  103. }
  104. func TestReverse(t *testing.T) {
  105. testCases := []struct {
  106. pix []uint8
  107. want []uint8
  108. }{
  109. {
  110. pix: []uint8{},
  111. want: []uint8{},
  112. },
  113. {
  114. pix: []uint8{1, 2, 3, 4},
  115. want: []uint8{1, 2, 3, 4},
  116. },
  117. {
  118. pix: []uint8{1, 2, 3, 4, 5, 6, 7, 8},
  119. want: []uint8{5, 6, 7, 8, 1, 2, 3, 4},
  120. },
  121. {
  122. pix: []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
  123. want: []uint8{9, 10, 11, 12, 5, 6, 7, 8, 1, 2, 3, 4},
  124. },
  125. }
  126. for _, tc := range testCases {
  127. t.Run("", func(t *testing.T) {
  128. reverse(tc.pix)
  129. if !compareBytes(tc.pix, tc.want, 0) {
  130. t.Fatalf("got pix %v want %v", tc.pix, tc.want)
  131. }
  132. })
  133. }
  134. }
  135. func compareNRGBA(img1, img2 *image.NRGBA, delta int) bool {
  136. if !img1.Rect.Eq(img2.Rect) {
  137. return false
  138. }
  139. return compareBytes(img1.Pix, img2.Pix, delta)
  140. }
  141. func compareBytes(a, b []uint8, delta int) bool {
  142. if len(a) != len(b) {
  143. return false
  144. }
  145. for i := 0; i < len(a); i++ {
  146. if absint(int(a[i])-int(b[i])) > delta {
  147. return false
  148. }
  149. }
  150. return true
  151. }
  152. // compareNRGBAGolden is a special version of compareNRGBA used in golden tests.
  153. // All the golden images are generated on amd64 architecture. Due to differences
  154. // in floating-point rounding on different architectures, we need to add some
  155. // level of tolerance when comparing images on architectures other than amd64.
  156. // See https://golang.org/ref/spec#Floating_point_operators for information on
  157. // fused multiply and add (FMA) instruction.
  158. func compareNRGBAGolden(img1, img2 *image.NRGBA) bool {
  159. delta := 0
  160. if runtime.GOARCH != "amd64" {
  161. delta = 1
  162. }
  163. return compareNRGBA(img1, img2, delta)
  164. }
  165. func compareFloat64(a, b, delta float64) bool {
  166. return math.Abs(a-b) <= delta
  167. }
  168. var rgbHSLTestCases = []struct {
  169. r, g, b uint8
  170. h, s, l float64
  171. }{
  172. {
  173. r: 255,
  174. g: 0,
  175. b: 0,
  176. h: 0.000,
  177. s: 1.000,
  178. l: 0.500,
  179. },
  180. {
  181. r: 191,
  182. g: 191,
  183. b: 0,
  184. h: 0.167,
  185. s: 1.000,
  186. l: 0.375,
  187. },
  188. {
  189. r: 0,
  190. g: 128,
  191. b: 0,
  192. h: 0.333,
  193. s: 1.000,
  194. l: 0.251,
  195. },
  196. {
  197. r: 128,
  198. g: 255,
  199. b: 255,
  200. h: 0.500,
  201. s: 1.000,
  202. l: 0.751,
  203. },
  204. {
  205. r: 128,
  206. g: 128,
  207. b: 255,
  208. h: 0.667,
  209. s: 1.000,
  210. l: 0.751,
  211. },
  212. {
  213. r: 191,
  214. g: 64,
  215. b: 191,
  216. h: 0.833,
  217. s: 0.498,
  218. l: 0.500,
  219. },
  220. {
  221. r: 160,
  222. g: 164,
  223. b: 36,
  224. h: 0.172,
  225. s: 0.640,
  226. l: 0.392,
  227. },
  228. {
  229. r: 65,
  230. g: 27,
  231. b: 234,
  232. h: 0.697,
  233. s: 0.831,
  234. l: 0.512,
  235. },
  236. {
  237. r: 30,
  238. g: 172,
  239. b: 65,
  240. h: 0.374,
  241. s: 0.703,
  242. l: 0.396,
  243. },
  244. {
  245. r: 240,
  246. g: 200,
  247. b: 14,
  248. h: 0.137,
  249. s: 0.890,
  250. l: 0.498,
  251. },
  252. {
  253. r: 180,
  254. g: 48,
  255. b: 229,
  256. h: 0.788,
  257. s: 0.777,
  258. l: 0.543,
  259. },
  260. {
  261. r: 237,
  262. g: 119,
  263. b: 81,
  264. h: 0.040,
  265. s: 0.813,
  266. l: 0.624,
  267. },
  268. {
  269. r: 254,
  270. g: 248,
  271. b: 136,
  272. h: 0.158,
  273. s: 0.983,
  274. l: 0.765,
  275. },
  276. {
  277. r: 25,
  278. g: 203,
  279. b: 151,
  280. h: 0.451,
  281. s: 0.781,
  282. l: 0.447,
  283. },
  284. {
  285. r: 54,
  286. g: 38,
  287. b: 152,
  288. h: 0.690,
  289. s: 0.600,
  290. l: 0.373,
  291. },
  292. {
  293. r: 126,
  294. g: 126,
  295. b: 184,
  296. h: 0.667,
  297. s: 0.290,
  298. l: 0.608,
  299. },
  300. }
  301. func TestRGBToHSL(t *testing.T) {
  302. for _, tc := range rgbHSLTestCases {
  303. t.Run("", func(t *testing.T) {
  304. h, s, l := rgbToHSL(tc.r, tc.g, tc.b)
  305. if !compareFloat64(h, tc.h, 0.001) || !compareFloat64(s, tc.s, 0.001) || !compareFloat64(l, tc.l, 0.001) {
  306. 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)
  307. }
  308. })
  309. }
  310. }
  311. func TestHSLToRGB(t *testing.T) {
  312. for _, tc := range rgbHSLTestCases {
  313. t.Run("", func(t *testing.T) {
  314. r, g, b := hslToRGB(tc.h, tc.s, tc.l)
  315. if r != tc.r || g != tc.g || b != tc.b {
  316. 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)
  317. }
  318. })
  319. }
  320. }