adjust_test.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. package imaging
  2. import (
  3. "image"
  4. "image/color"
  5. "testing"
  6. )
  7. func TestGrayscale(t *testing.T) {
  8. testCases := []struct {
  9. name string
  10. src image.Image
  11. want *image.NRGBA
  12. }{
  13. {
  14. "Grayscale 3x3",
  15. &image.NRGBA{
  16. Rect: image.Rect(-1, -1, 2, 2),
  17. Stride: 3 * 4,
  18. Pix: []uint8{
  19. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  20. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  21. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  22. },
  23. },
  24. &image.NRGBA{
  25. Rect: image.Rect(0, 0, 3, 3),
  26. Stride: 3 * 4,
  27. Pix: []uint8{
  28. 0x3d, 0x3d, 0x3d, 0x01, 0x78, 0x78, 0x78, 0x02, 0x17, 0x17, 0x17, 0x03,
  29. 0x1f, 0x1f, 0x1f, 0xff, 0x25, 0x25, 0x25, 0xff, 0x66, 0x66, 0x66, 0xff,
  30. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  31. },
  32. },
  33. },
  34. }
  35. for _, tc := range testCases {
  36. t.Run(tc.name, func(t *testing.T) {
  37. got := Grayscale(tc.src)
  38. if !compareNRGBA(got, tc.want, 0) {
  39. t.Fatalf("got result %#v want %#v", got, tc.want)
  40. }
  41. })
  42. }
  43. }
  44. func BenchmarkGrayscale(b *testing.B) {
  45. b.ReportAllocs()
  46. for i := 0; i < b.N; i++ {
  47. Grayscale(testdataBranchesJPG)
  48. }
  49. }
  50. func TestInvert(t *testing.T) {
  51. testCases := []struct {
  52. name string
  53. src image.Image
  54. want *image.NRGBA
  55. }{
  56. {
  57. "Invert 3x3",
  58. &image.NRGBA{
  59. Rect: image.Rect(-1, -1, 2, 2),
  60. Stride: 3 * 4,
  61. Pix: []uint8{
  62. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  63. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  64. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  65. },
  66. },
  67. &image.NRGBA{
  68. Rect: image.Rect(0, 0, 3, 3),
  69. Stride: 3 * 4,
  70. Pix: []uint8{
  71. 0x33, 0xff, 0xff, 0x01, 0xff, 0x33, 0xff, 0x02, 0xff, 0xff, 0x33, 0x03,
  72. 0xee, 0xdd, 0xcc, 0xff, 0xcc, 0xdd, 0xee, 0xff, 0x55, 0xcc, 0x44, 0xff,
  73. 0xff, 0xff, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0x00, 0x00, 0x00, 0xff,
  74. },
  75. },
  76. },
  77. }
  78. for _, tc := range testCases {
  79. t.Run(tc.name, func(t *testing.T) {
  80. got := Invert(tc.src)
  81. if !compareNRGBA(got, tc.want, 0) {
  82. t.Fatalf("got result %#v want %#v", got, tc.want)
  83. }
  84. })
  85. }
  86. }
  87. func BenchmarkInvert(b *testing.B) {
  88. b.ReportAllocs()
  89. for i := 0; i < b.N; i++ {
  90. Invert(testdataBranchesJPG)
  91. }
  92. }
  93. func TestAdjustContrast(t *testing.T) {
  94. testCases := []struct {
  95. name string
  96. src image.Image
  97. p float64
  98. want *image.NRGBA
  99. }{
  100. {
  101. "AdjustContrast 3x3 10",
  102. &image.NRGBA{
  103. Rect: image.Rect(-1, -1, 2, 2),
  104. Stride: 3 * 4,
  105. Pix: []uint8{
  106. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  107. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  108. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  109. },
  110. },
  111. 10,
  112. &image.NRGBA{
  113. Rect: image.Rect(0, 0, 3, 3),
  114. Stride: 3 * 4,
  115. Pix: []uint8{
  116. 0xd5, 0x00, 0x00, 0x01, 0x00, 0xd5, 0x00, 0x02, 0x00, 0x00, 0xd5, 0x03,
  117. 0x05, 0x18, 0x2b, 0xff, 0x2b, 0x18, 0x05, 0xff, 0xaf, 0x2b, 0xc2, 0xff,
  118. 0x00, 0x00, 0x00, 0xff, 0x2b, 0x2b, 0x2b, 0xff, 0xff, 0xff, 0xff, 0xff,
  119. },
  120. },
  121. },
  122. {
  123. "AdjustContrast 3x3 100",
  124. &image.NRGBA{
  125. Rect: image.Rect(-1, -1, 2, 2),
  126. Stride: 3 * 4,
  127. Pix: []uint8{
  128. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  129. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  130. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  131. },
  132. },
  133. 100,
  134. &image.NRGBA{
  135. Rect: image.Rect(0, 0, 3, 3),
  136. Stride: 3 * 4,
  137. Pix: []uint8{
  138. 0xff, 0x00, 0x00, 0x01, 0x00, 0xff, 0x00, 0x02, 0x00, 0x00, 0xff, 0x03,
  139. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff,
  140. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
  141. },
  142. },
  143. },
  144. {
  145. "AdjustContrast 3x3 -10",
  146. &image.NRGBA{
  147. Rect: image.Rect(-1, -1, 2, 2),
  148. Stride: 3 * 4,
  149. Pix: []uint8{
  150. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  151. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  152. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  153. },
  154. },
  155. -10,
  156. &image.NRGBA{
  157. Rect: image.Rect(0, 0, 3, 3),
  158. Stride: 3 * 4,
  159. Pix: []uint8{
  160. 0xc4, 0x0d, 0x0d, 0x01, 0x0d, 0xc4, 0x0d, 0x02, 0x0d, 0x0d, 0xc4, 0x03,
  161. 0x1c, 0x2b, 0x3b, 0xff, 0x3b, 0x2b, 0x1c, 0xff, 0xa6, 0x3b, 0xb5, 0xff,
  162. 0x0d, 0x0d, 0x0d, 0xff, 0x3b, 0x3b, 0x3b, 0xff, 0xf2, 0xf2, 0xf2, 0xff,
  163. },
  164. },
  165. },
  166. {
  167. "AdjustContrast 3x3 -100",
  168. &image.NRGBA{
  169. Rect: image.Rect(-1, -1, 2, 2),
  170. Stride: 3 * 4,
  171. Pix: []uint8{
  172. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  173. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  174. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  175. },
  176. },
  177. -100,
  178. &image.NRGBA{
  179. Rect: image.Rect(0, 0, 3, 3),
  180. Stride: 3 * 4,
  181. Pix: []uint8{
  182. 0x80, 0x80, 0x80, 0x01, 0x80, 0x80, 0x80, 0x02, 0x80, 0x80, 0x80, 0x03,
  183. 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff,
  184. 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff,
  185. },
  186. },
  187. },
  188. {
  189. "AdjustContrast 3x3 0",
  190. &image.NRGBA{
  191. Rect: image.Rect(-1, -1, 2, 2),
  192. Stride: 3 * 4,
  193. Pix: []uint8{
  194. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  195. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  196. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  197. },
  198. },
  199. 0,
  200. &image.NRGBA{
  201. Rect: image.Rect(0, 0, 3, 3),
  202. Stride: 3 * 4,
  203. Pix: []uint8{
  204. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  205. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  206. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  207. },
  208. },
  209. },
  210. }
  211. for _, tc := range testCases {
  212. t.Run(tc.name, func(t *testing.T) {
  213. got := AdjustContrast(tc.src, tc.p)
  214. if !compareNRGBA(got, tc.want, 0) {
  215. t.Fatalf("got result %#v want %#v", got, tc.want)
  216. }
  217. })
  218. }
  219. }
  220. func TestAdjustContrastGolden(t *testing.T) {
  221. for name, p := range map[string]float64{
  222. "out_contrast_m15.png": -15,
  223. "out_contrast_p15.png": 15,
  224. } {
  225. got := AdjustContrast(testdataFlowersSmallPNG, p)
  226. want, err := Open("testdata/" + name)
  227. if err != nil {
  228. t.Fatalf("failed to open image: %v", err)
  229. }
  230. if !compareNRGBA(got, toNRGBA(want), 0) {
  231. t.Fatalf("resulting image differs from golden: %s", name)
  232. }
  233. }
  234. }
  235. func BenchmarkAdjustContrast(b *testing.B) {
  236. b.ReportAllocs()
  237. for i := 0; i < b.N; i++ {
  238. AdjustContrast(testdataBranchesJPG, 10)
  239. }
  240. }
  241. func TestAdjustBrightness(t *testing.T) {
  242. testCases := []struct {
  243. name string
  244. src image.Image
  245. p float64
  246. want *image.NRGBA
  247. }{
  248. {
  249. "AdjustBrightness 3x3 10",
  250. &image.NRGBA{
  251. Rect: image.Rect(-1, -1, 2, 2),
  252. Stride: 3 * 4,
  253. Pix: []uint8{
  254. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  255. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  256. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  257. },
  258. },
  259. 10,
  260. &image.NRGBA{
  261. Rect: image.Rect(0, 0, 3, 3),
  262. Stride: 3 * 4,
  263. Pix: []uint8{
  264. 0xe6, 0x1a, 0x1a, 0x01, 0x1a, 0xe6, 0x1a, 0x02, 0x1a, 0x1a, 0xe6, 0x03,
  265. 0x2b, 0x3c, 0x4d, 0xff, 0x4d, 0x3c, 0x2b, 0xff, 0xc4, 0x4d, 0xd5, 0xff,
  266. 0x1a, 0x1a, 0x1a, 0xff, 0x4d, 0x4d, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff,
  267. },
  268. },
  269. },
  270. {
  271. "AdjustBrightness 3x3 100",
  272. &image.NRGBA{
  273. Rect: image.Rect(-1, -1, 2, 2),
  274. Stride: 3 * 4,
  275. Pix: []uint8{
  276. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  277. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  278. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  279. },
  280. },
  281. 100,
  282. &image.NRGBA{
  283. Rect: image.Rect(0, 0, 3, 3),
  284. Stride: 3 * 4,
  285. Pix: []uint8{
  286. 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x02, 0xff, 0xff, 0xff, 0x03,
  287. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  288. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  289. },
  290. },
  291. },
  292. {
  293. "AdjustBrightness 3x3 -10",
  294. &image.NRGBA{
  295. Rect: image.Rect(-1, -1, 2, 2),
  296. Stride: 3 * 4,
  297. Pix: []uint8{
  298. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  299. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  300. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  301. },
  302. },
  303. -10,
  304. &image.NRGBA{
  305. Rect: image.Rect(0, 0, 3, 3),
  306. Stride: 3 * 4,
  307. Pix: []uint8{
  308. 0xb3, 0x00, 0x00, 0x01, 0x00, 0xb3, 0x00, 0x02, 0x00, 0x00, 0xb3, 0x03,
  309. 0x00, 0x09, 0x1a, 0xff, 0x1a, 0x09, 0x00, 0xff, 0x91, 0x1a, 0xa2, 0xff,
  310. 0x00, 0x00, 0x00, 0xff, 0x1a, 0x1a, 0x1a, 0xff, 0xe6, 0xe6, 0xe6, 0xff,
  311. },
  312. },
  313. },
  314. {
  315. "AdjustBrightness 3x3 -100",
  316. &image.NRGBA{
  317. Rect: image.Rect(-1, -1, 2, 2),
  318. Stride: 3 * 4,
  319. Pix: []uint8{
  320. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  321. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  322. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  323. },
  324. },
  325. -100,
  326. &image.NRGBA{
  327. Rect: image.Rect(0, 0, 3, 3),
  328. Stride: 3 * 4,
  329. Pix: []uint8{
  330. 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03,
  331. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
  332. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
  333. },
  334. },
  335. },
  336. {
  337. "AdjustBrightness 3x3 0",
  338. &image.NRGBA{
  339. Rect: image.Rect(-1, -1, 2, 2),
  340. Stride: 3 * 4,
  341. Pix: []uint8{
  342. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  343. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  344. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  345. },
  346. },
  347. 0,
  348. &image.NRGBA{
  349. Rect: image.Rect(0, 0, 3, 3),
  350. Stride: 3 * 4,
  351. Pix: []uint8{
  352. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  353. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  354. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  355. },
  356. },
  357. },
  358. }
  359. for _, tc := range testCases {
  360. t.Run(tc.name, func(t *testing.T) {
  361. got := AdjustBrightness(tc.src, tc.p)
  362. if !compareNRGBA(got, tc.want, 0) {
  363. t.Fatalf("got result %#v want %#v", got, tc.want)
  364. }
  365. })
  366. }
  367. }
  368. func TestAdjustBrightnessGolden(t *testing.T) {
  369. for name, p := range map[string]float64{
  370. "out_brightness_m10.png": -10,
  371. "out_brightness_p10.png": 10,
  372. } {
  373. got := AdjustBrightness(testdataFlowersSmallPNG, p)
  374. want, err := Open("testdata/" + name)
  375. if err != nil {
  376. t.Fatalf("failed to open image: %v", err)
  377. }
  378. if !compareNRGBA(got, toNRGBA(want), 0) {
  379. t.Fatalf("resulting image differs from golden: %s", name)
  380. }
  381. }
  382. }
  383. func BenchmarkAdjustBrightness(b *testing.B) {
  384. b.ReportAllocs()
  385. for i := 0; i < b.N; i++ {
  386. AdjustBrightness(testdataBranchesJPG, 10)
  387. }
  388. }
  389. func TestAdjustGamma(t *testing.T) {
  390. testCases := []struct {
  391. name string
  392. src image.Image
  393. p float64
  394. want *image.NRGBA
  395. }{
  396. {
  397. "AdjustGamma 3x3 0.75",
  398. &image.NRGBA{
  399. Rect: image.Rect(-1, -1, 2, 2),
  400. Stride: 3 * 4,
  401. Pix: []uint8{
  402. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  403. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  404. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  405. },
  406. },
  407. 0.75,
  408. &image.NRGBA{
  409. Rect: image.Rect(0, 0, 3, 3),
  410. Stride: 3 * 4,
  411. Pix: []uint8{
  412. 0xbd, 0x00, 0x00, 0x01, 0x00, 0xbd, 0x00, 0x02, 0x00, 0x00, 0xbd, 0x03,
  413. 0x07, 0x11, 0x1e, 0xff, 0x1e, 0x11, 0x07, 0xff, 0x95, 0x1e, 0xa9, 0xff,
  414. 0x00, 0x00, 0x00, 0xff, 0x1e, 0x1e, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff,
  415. },
  416. },
  417. },
  418. {
  419. "AdjustGamma 3x3 1.5",
  420. &image.NRGBA{
  421. Rect: image.Rect(-1, -1, 2, 2),
  422. Stride: 3 * 4,
  423. Pix: []uint8{
  424. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  425. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  426. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  427. },
  428. },
  429. 1.5,
  430. &image.NRGBA{
  431. Rect: image.Rect(0, 0, 3, 3),
  432. Stride: 3 * 4,
  433. Pix: []uint8{
  434. 0xdc, 0x00, 0x00, 0x01, 0x00, 0xdc, 0x00, 0x02, 0x00, 0x00, 0xdc, 0x03,
  435. 0x2a, 0x43, 0x57, 0xff, 0x57, 0x43, 0x2a, 0xff, 0xc3, 0x57, 0xcf, 0xff,
  436. 0x00, 0x00, 0x00, 0xff, 0x57, 0x57, 0x57, 0xff, 0xff, 0xff, 0xff, 0xff,
  437. },
  438. },
  439. },
  440. {
  441. "AdjustGamma 3x3 1.0",
  442. &image.NRGBA{
  443. Rect: image.Rect(-1, -1, 2, 2),
  444. Stride: 3 * 4,
  445. Pix: []uint8{
  446. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  447. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  448. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  449. },
  450. },
  451. 1.0,
  452. &image.NRGBA{
  453. Rect: image.Rect(0, 0, 3, 3),
  454. Stride: 3 * 4,
  455. Pix: []uint8{
  456. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  457. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  458. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  459. },
  460. },
  461. },
  462. }
  463. for _, tc := range testCases {
  464. t.Run(tc.name, func(t *testing.T) {
  465. got := AdjustGamma(tc.src, tc.p)
  466. if !compareNRGBA(got, tc.want, 0) {
  467. t.Fatalf("got result %#v want %#v", got, tc.want)
  468. }
  469. })
  470. }
  471. }
  472. func TestAdjustGammaGolden(t *testing.T) {
  473. for name, g := range map[string]float64{
  474. "out_gamma_0.75.png": 0.75,
  475. "out_gamma_1.25.png": 1.25,
  476. } {
  477. got := AdjustGamma(testdataFlowersSmallPNG, g)
  478. want, err := Open("testdata/" + name)
  479. if err != nil {
  480. t.Fatalf("failed to open image: %v", err)
  481. }
  482. if !compareNRGBA(got, toNRGBA(want), 0) {
  483. t.Fatalf("resulting image differs from golden: %s", name)
  484. }
  485. }
  486. }
  487. func BenchmarkAdjustGamma(b *testing.B) {
  488. b.ReportAllocs()
  489. for i := 0; i < b.N; i++ {
  490. AdjustGamma(testdataBranchesJPG, 1.5)
  491. }
  492. }
  493. func TestAdjustSigmoid(t *testing.T) {
  494. testCases := []struct {
  495. name string
  496. src image.Image
  497. m float64
  498. p float64
  499. want *image.NRGBA
  500. }{
  501. {
  502. "AdjustSigmoid 3x3 0.5 3.0",
  503. &image.NRGBA{
  504. Rect: image.Rect(-1, -1, 2, 2),
  505. Stride: 3 * 4,
  506. Pix: []uint8{
  507. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  508. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  509. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  510. },
  511. },
  512. 0.5,
  513. 3.0,
  514. &image.NRGBA{
  515. Rect: image.Rect(0, 0, 3, 3),
  516. Stride: 3 * 4,
  517. Pix: []uint8{
  518. 0xd4, 0x00, 0x00, 0x01, 0x00, 0xd4, 0x00, 0x02, 0x00, 0x00, 0xd4, 0x03,
  519. 0x0d, 0x1b, 0x2b, 0xff, 0x2b, 0x1b, 0x0d, 0xff, 0xb1, 0x2b, 0xc3, 0xff,
  520. 0x00, 0x00, 0x00, 0xff, 0x2b, 0x2b, 0x2b, 0xff, 0xff, 0xff, 0xff, 0xff,
  521. },
  522. },
  523. },
  524. {
  525. "AdjustSigmoid 3x3 0.5 -3.0",
  526. &image.NRGBA{
  527. Rect: image.Rect(-1, -1, 2, 2),
  528. Stride: 3 * 4,
  529. Pix: []uint8{
  530. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  531. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  532. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  533. },
  534. },
  535. 0.5,
  536. -3.0,
  537. &image.NRGBA{
  538. Rect: image.Rect(0, 0, 3, 3),
  539. Stride: 3 * 4,
  540. Pix: []uint8{
  541. 0xc4, 0x00, 0x00, 0x01, 0x00, 0xc4, 0x00, 0x02, 0x00, 0x00, 0xc4, 0x03,
  542. 0x16, 0x2a, 0x3b, 0xff, 0x3b, 0x2a, 0x16, 0xff, 0xa4, 0x3b, 0xb3, 0xff,
  543. 0x00, 0x00, 0x00, 0xff, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xff,
  544. },
  545. },
  546. },
  547. {
  548. "AdjustSigmoid 3x3 0.5 0.0",
  549. &image.NRGBA{
  550. Rect: image.Rect(-1, -1, 2, 2),
  551. Stride: 3 * 4,
  552. Pix: []uint8{
  553. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  554. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  555. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  556. },
  557. },
  558. 0.5,
  559. 0.0,
  560. &image.NRGBA{
  561. Rect: image.Rect(0, 0, 3, 3),
  562. Stride: 3 * 4,
  563. Pix: []uint8{
  564. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  565. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  566. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  567. },
  568. },
  569. },
  570. }
  571. for _, tc := range testCases {
  572. t.Run(tc.name, func(t *testing.T) {
  573. got := AdjustSigmoid(tc.src, tc.m, tc.p)
  574. if !compareNRGBA(got, tc.want, 0) {
  575. t.Fatalf("got result %#v want %#v", got, tc.want)
  576. }
  577. })
  578. }
  579. }
  580. func BenchmarkAdjustSigmoid(b *testing.B) {
  581. b.ReportAllocs()
  582. for i := 0; i < b.N; i++ {
  583. AdjustSigmoid(testdataBranchesJPG, 0.5, 3.0)
  584. }
  585. }
  586. func TestAdjustFunc(t *testing.T) {
  587. testCases := []struct {
  588. name string
  589. src image.Image
  590. fn func(c color.NRGBA) color.NRGBA
  591. want *image.NRGBA
  592. }{
  593. {
  594. "invert",
  595. &image.NRGBA{
  596. Rect: image.Rect(-1, -1, 2, 2),
  597. Stride: 3 * 4,
  598. Pix: []uint8{
  599. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  600. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  601. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  602. },
  603. },
  604. func(c color.NRGBA) color.NRGBA {
  605. return color.NRGBA{255 - c.R, 255 - c.G, 255 - c.B, c.A}
  606. },
  607. &image.NRGBA{
  608. Rect: image.Rect(0, 0, 3, 3),
  609. Stride: 3 * 4,
  610. Pix: []uint8{
  611. 0x33, 0xff, 0xff, 0x01, 0xff, 0x33, 0xff, 0x02, 0xff, 0xff, 0x33, 0x03,
  612. 0xee, 0xdd, 0xcc, 0xff, 0xcc, 0xdd, 0xee, 0xff, 0x55, 0xcc, 0x44, 0xff,
  613. 0xff, 0xff, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0x00, 0x00, 0x00, 0xff,
  614. },
  615. },
  616. },
  617. {
  618. "threshold",
  619. &image.NRGBA{
  620. Rect: image.Rect(-1, -1, 2, 2),
  621. Stride: 3 * 4,
  622. Pix: []uint8{
  623. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  624. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  625. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  626. },
  627. },
  628. func(c color.NRGBA) color.NRGBA {
  629. y := 0.299*float64(c.R) + 0.587*float64(c.G) + 0.114*float64(c.B)
  630. if y > 0x55 {
  631. return color.NRGBA{0xff, 0xff, 0xff, c.A}
  632. }
  633. return color.NRGBA{0x00, 0x00, 0x00, c.A}
  634. },
  635. &image.NRGBA{
  636. Rect: image.Rect(0, 0, 3, 3),
  637. Stride: 3 * 4,
  638. Pix: []uint8{
  639. 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, 0x03,
  640. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
  641. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
  642. },
  643. },
  644. },
  645. }
  646. for _, tc := range testCases {
  647. t.Run(tc.name, func(t *testing.T) {
  648. got := AdjustFunc(tc.src, tc.fn)
  649. if !compareNRGBA(got, tc.want, 0) {
  650. t.Fatalf("got result %#v want %#v", got, tc.want)
  651. }
  652. })
  653. }
  654. }