1
0

adjust_test.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  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 TestAdjustSaturation(t *testing.T) {
  94. testCases := []struct {
  95. name string
  96. src image.Image
  97. p float64
  98. want *image.NRGBA
  99. }{
  100. {
  101. "AdjustSaturation 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. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  117. 0x0f, 0x22, 0x35, 0xff, 0x35, 0x22, 0x0f, 0xff, 0xaf, 0x2c, 0xc2, 0xff,
  118. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  119. },
  120. },
  121. },
  122. {
  123. "AdjustSaturation 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. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  139. 0x00, 0x22, 0x44, 0xff, 0x44, 0x22, 0x00, 0xff, 0xd0, 0x00, 0xee, 0xff,
  140. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  141. },
  142. },
  143. },
  144. {
  145. "AdjustSaturation 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. 0xc2, 0x0a, 0x0a, 0x01, 0x0a, 0xc2, 0x0a, 0x02, 0x0a, 0x0a, 0xc2, 0x03,
  161. 0x13, 0x22, 0x31, 0xff, 0x31, 0x22, 0x13, 0xff, 0xa5, 0x3a, 0xb4, 0xff,
  162. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  163. },
  164. },
  165. },
  166. {
  167. "AdjustSaturation 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. 0x66, 0x66, 0x66, 0x01, 0x66, 0x66, 0x66, 0x02, 0x66, 0x66, 0x66, 0x03,
  183. 0x22, 0x22, 0x22, 0xff, 0x22, 0x22, 0x22, 0xff, 0x77, 0x77, 0x77, 0xff,
  184. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  185. },
  186. },
  187. },
  188. {
  189. "AdjustSaturation 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 := AdjustSaturation(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 TestAdjustSaturationGolden(t *testing.T) {
  221. for name, p := range map[string]float64{
  222. "out_saturation_m30.png": -30,
  223. "out_saturation_p30.png": 30,
  224. } {
  225. got := AdjustSaturation(testdataFlowersSmallPNG, p)
  226. want, err := Open("testdata/" + name)
  227. if err != nil {
  228. t.Fatalf("failed to open image: %v", err)
  229. }
  230. if !compareNRGBAGolden(got, toNRGBA(want)) {
  231. t.Errorf("resulting image differs from golden: %s", name)
  232. }
  233. }
  234. }
  235. func BenchmarkAdjustSaturation(b *testing.B) {
  236. b.ReportAllocs()
  237. for i := 0; i < b.N; i++ {
  238. AdjustSaturation(testdataBranchesJPG, 10)
  239. }
  240. }
  241. func TestAdjustContrast(t *testing.T) {
  242. testCases := []struct {
  243. name string
  244. src image.Image
  245. p float64
  246. want *image.NRGBA
  247. }{
  248. {
  249. "AdjustContrast 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. 0xd5, 0x00, 0x00, 0x01, 0x00, 0xd5, 0x00, 0x02, 0x00, 0x00, 0xd5, 0x03,
  265. 0x05, 0x18, 0x2b, 0xff, 0x2b, 0x18, 0x05, 0xff, 0xaf, 0x2b, 0xc2, 0xff,
  266. 0x00, 0x00, 0x00, 0xff, 0x2b, 0x2b, 0x2b, 0xff, 0xff, 0xff, 0xff, 0xff,
  267. },
  268. },
  269. },
  270. {
  271. "AdjustContrast 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, 0x00, 0x00, 0x01, 0x00, 0xff, 0x00, 0x02, 0x00, 0x00, 0xff, 0x03,
  287. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff,
  288. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
  289. },
  290. },
  291. },
  292. {
  293. "AdjustContrast 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. 0xc4, 0x0d, 0x0d, 0x01, 0x0d, 0xc4, 0x0d, 0x02, 0x0d, 0x0d, 0xc4, 0x03,
  309. 0x1c, 0x2b, 0x3b, 0xff, 0x3b, 0x2b, 0x1c, 0xff, 0xa6, 0x3b, 0xb5, 0xff,
  310. 0x0d, 0x0d, 0x0d, 0xff, 0x3b, 0x3b, 0x3b, 0xff, 0xf2, 0xf2, 0xf2, 0xff,
  311. },
  312. },
  313. },
  314. {
  315. "AdjustContrast 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. 0x80, 0x80, 0x80, 0x01, 0x80, 0x80, 0x80, 0x02, 0x80, 0x80, 0x80, 0x03,
  331. 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff,
  332. 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff,
  333. },
  334. },
  335. },
  336. {
  337. "AdjustContrast 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 := AdjustContrast(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 TestAdjustContrastGolden(t *testing.T) {
  369. for name, p := range map[string]float64{
  370. "out_contrast_m15.png": -15,
  371. "out_contrast_p15.png": 15,
  372. } {
  373. got := AdjustContrast(testdataFlowersSmallPNG, p)
  374. want, err := Open("testdata/" + name)
  375. if err != nil {
  376. t.Fatalf("failed to open image: %v", err)
  377. }
  378. if !compareNRGBAGolden(got, toNRGBA(want)) {
  379. t.Fatalf("resulting image differs from golden: %s", name)
  380. }
  381. }
  382. }
  383. func BenchmarkAdjustContrast(b *testing.B) {
  384. b.ReportAllocs()
  385. for i := 0; i < b.N; i++ {
  386. AdjustContrast(testdataBranchesJPG, 10)
  387. }
  388. }
  389. func TestAdjustBrightness(t *testing.T) {
  390. testCases := []struct {
  391. name string
  392. src image.Image
  393. p float64
  394. want *image.NRGBA
  395. }{
  396. {
  397. "AdjustBrightness 3x3 10",
  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. 10,
  408. &image.NRGBA{
  409. Rect: image.Rect(0, 0, 3, 3),
  410. Stride: 3 * 4,
  411. Pix: []uint8{
  412. 0xe6, 0x1a, 0x1a, 0x01, 0x1a, 0xe6, 0x1a, 0x02, 0x1a, 0x1a, 0xe6, 0x03,
  413. 0x2b, 0x3c, 0x4d, 0xff, 0x4d, 0x3c, 0x2b, 0xff, 0xc4, 0x4d, 0xd5, 0xff,
  414. 0x1a, 0x1a, 0x1a, 0xff, 0x4d, 0x4d, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff,
  415. },
  416. },
  417. },
  418. {
  419. "AdjustBrightness 3x3 100",
  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. 100,
  430. &image.NRGBA{
  431. Rect: image.Rect(0, 0, 3, 3),
  432. Stride: 3 * 4,
  433. Pix: []uint8{
  434. 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x02, 0xff, 0xff, 0xff, 0x03,
  435. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  436. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  437. },
  438. },
  439. },
  440. {
  441. "AdjustBrightness 3x3 -10",
  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. -10,
  452. &image.NRGBA{
  453. Rect: image.Rect(0, 0, 3, 3),
  454. Stride: 3 * 4,
  455. Pix: []uint8{
  456. 0xb3, 0x00, 0x00, 0x01, 0x00, 0xb3, 0x00, 0x02, 0x00, 0x00, 0xb3, 0x03,
  457. 0x00, 0x09, 0x1a, 0xff, 0x1a, 0x09, 0x00, 0xff, 0x91, 0x1a, 0xa2, 0xff,
  458. 0x00, 0x00, 0x00, 0xff, 0x1a, 0x1a, 0x1a, 0xff, 0xe6, 0xe6, 0xe6, 0xff,
  459. },
  460. },
  461. },
  462. {
  463. "AdjustBrightness 3x3 -100",
  464. &image.NRGBA{
  465. Rect: image.Rect(-1, -1, 2, 2),
  466. Stride: 3 * 4,
  467. Pix: []uint8{
  468. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  469. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  470. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  471. },
  472. },
  473. -100,
  474. &image.NRGBA{
  475. Rect: image.Rect(0, 0, 3, 3),
  476. Stride: 3 * 4,
  477. Pix: []uint8{
  478. 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03,
  479. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
  480. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
  481. },
  482. },
  483. },
  484. {
  485. "AdjustBrightness 3x3 0",
  486. &image.NRGBA{
  487. Rect: image.Rect(-1, -1, 2, 2),
  488. Stride: 3 * 4,
  489. Pix: []uint8{
  490. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  491. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  492. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  493. },
  494. },
  495. 0,
  496. &image.NRGBA{
  497. Rect: image.Rect(0, 0, 3, 3),
  498. Stride: 3 * 4,
  499. Pix: []uint8{
  500. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  501. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  502. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  503. },
  504. },
  505. },
  506. }
  507. for _, tc := range testCases {
  508. t.Run(tc.name, func(t *testing.T) {
  509. got := AdjustBrightness(tc.src, tc.p)
  510. if !compareNRGBA(got, tc.want, 0) {
  511. t.Fatalf("got result %#v want %#v", got, tc.want)
  512. }
  513. })
  514. }
  515. }
  516. func TestAdjustBrightnessGolden(t *testing.T) {
  517. for name, p := range map[string]float64{
  518. "out_brightness_m10.png": -10,
  519. "out_brightness_p10.png": 10,
  520. } {
  521. got := AdjustBrightness(testdataFlowersSmallPNG, p)
  522. want, err := Open("testdata/" + name)
  523. if err != nil {
  524. t.Fatalf("failed to open image: %v", err)
  525. }
  526. if !compareNRGBAGolden(got, toNRGBA(want)) {
  527. t.Fatalf("resulting image differs from golden: %s", name)
  528. }
  529. }
  530. }
  531. func BenchmarkAdjustBrightness(b *testing.B) {
  532. b.ReportAllocs()
  533. for i := 0; i < b.N; i++ {
  534. AdjustBrightness(testdataBranchesJPG, 10)
  535. }
  536. }
  537. func TestAdjustGamma(t *testing.T) {
  538. testCases := []struct {
  539. name string
  540. src image.Image
  541. p float64
  542. want *image.NRGBA
  543. }{
  544. {
  545. "AdjustGamma 3x3 0.75",
  546. &image.NRGBA{
  547. Rect: image.Rect(-1, -1, 2, 2),
  548. Stride: 3 * 4,
  549. Pix: []uint8{
  550. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  551. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  552. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  553. },
  554. },
  555. 0.75,
  556. &image.NRGBA{
  557. Rect: image.Rect(0, 0, 3, 3),
  558. Stride: 3 * 4,
  559. Pix: []uint8{
  560. 0xbd, 0x00, 0x00, 0x01, 0x00, 0xbd, 0x00, 0x02, 0x00, 0x00, 0xbd, 0x03,
  561. 0x07, 0x11, 0x1e, 0xff, 0x1e, 0x11, 0x07, 0xff, 0x95, 0x1e, 0xa9, 0xff,
  562. 0x00, 0x00, 0x00, 0xff, 0x1e, 0x1e, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff,
  563. },
  564. },
  565. },
  566. {
  567. "AdjustGamma 3x3 1.5",
  568. &image.NRGBA{
  569. Rect: image.Rect(-1, -1, 2, 2),
  570. Stride: 3 * 4,
  571. Pix: []uint8{
  572. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  573. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  574. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  575. },
  576. },
  577. 1.5,
  578. &image.NRGBA{
  579. Rect: image.Rect(0, 0, 3, 3),
  580. Stride: 3 * 4,
  581. Pix: []uint8{
  582. 0xdc, 0x00, 0x00, 0x01, 0x00, 0xdc, 0x00, 0x02, 0x00, 0x00, 0xdc, 0x03,
  583. 0x2a, 0x43, 0x57, 0xff, 0x57, 0x43, 0x2a, 0xff, 0xc3, 0x57, 0xcf, 0xff,
  584. 0x00, 0x00, 0x00, 0xff, 0x57, 0x57, 0x57, 0xff, 0xff, 0xff, 0xff, 0xff,
  585. },
  586. },
  587. },
  588. {
  589. "AdjustGamma 3x3 1.0",
  590. &image.NRGBA{
  591. Rect: image.Rect(-1, -1, 2, 2),
  592. Stride: 3 * 4,
  593. Pix: []uint8{
  594. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  595. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  596. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  597. },
  598. },
  599. 1.0,
  600. &image.NRGBA{
  601. Rect: image.Rect(0, 0, 3, 3),
  602. Stride: 3 * 4,
  603. Pix: []uint8{
  604. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  605. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  606. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  607. },
  608. },
  609. },
  610. }
  611. for _, tc := range testCases {
  612. t.Run(tc.name, func(t *testing.T) {
  613. got := AdjustGamma(tc.src, tc.p)
  614. if !compareNRGBA(got, tc.want, 0) {
  615. t.Fatalf("got result %#v want %#v", got, tc.want)
  616. }
  617. })
  618. }
  619. }
  620. func TestAdjustGammaGolden(t *testing.T) {
  621. for name, g := range map[string]float64{
  622. "out_gamma_0.75.png": 0.75,
  623. "out_gamma_1.25.png": 1.25,
  624. } {
  625. got := AdjustGamma(testdataFlowersSmallPNG, g)
  626. want, err := Open("testdata/" + name)
  627. if err != nil {
  628. t.Fatalf("failed to open image: %v", err)
  629. }
  630. if !compareNRGBAGolden(got, toNRGBA(want)) {
  631. t.Fatalf("resulting image differs from golden: %s", name)
  632. }
  633. }
  634. }
  635. func BenchmarkAdjustGamma(b *testing.B) {
  636. b.ReportAllocs()
  637. for i := 0; i < b.N; i++ {
  638. AdjustGamma(testdataBranchesJPG, 1.5)
  639. }
  640. }
  641. func TestAdjustSigmoid(t *testing.T) {
  642. testCases := []struct {
  643. name string
  644. src image.Image
  645. m float64
  646. p float64
  647. want *image.NRGBA
  648. }{
  649. {
  650. "AdjustSigmoid 3x3 0.5 3.0",
  651. &image.NRGBA{
  652. Rect: image.Rect(-1, -1, 2, 2),
  653. Stride: 3 * 4,
  654. Pix: []uint8{
  655. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  656. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  657. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  658. },
  659. },
  660. 0.5,
  661. 3.0,
  662. &image.NRGBA{
  663. Rect: image.Rect(0, 0, 3, 3),
  664. Stride: 3 * 4,
  665. Pix: []uint8{
  666. 0xd4, 0x00, 0x00, 0x01, 0x00, 0xd4, 0x00, 0x02, 0x00, 0x00, 0xd4, 0x03,
  667. 0x0d, 0x1b, 0x2b, 0xff, 0x2b, 0x1b, 0x0d, 0xff, 0xb1, 0x2b, 0xc3, 0xff,
  668. 0x00, 0x00, 0x00, 0xff, 0x2b, 0x2b, 0x2b, 0xff, 0xff, 0xff, 0xff, 0xff,
  669. },
  670. },
  671. },
  672. {
  673. "AdjustSigmoid 3x3 0.5 -3.0",
  674. &image.NRGBA{
  675. Rect: image.Rect(-1, -1, 2, 2),
  676. Stride: 3 * 4,
  677. Pix: []uint8{
  678. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  679. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  680. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  681. },
  682. },
  683. 0.5,
  684. -3.0,
  685. &image.NRGBA{
  686. Rect: image.Rect(0, 0, 3, 3),
  687. Stride: 3 * 4,
  688. Pix: []uint8{
  689. 0xc4, 0x00, 0x00, 0x01, 0x00, 0xc4, 0x00, 0x02, 0x00, 0x00, 0xc4, 0x03,
  690. 0x16, 0x2a, 0x3b, 0xff, 0x3b, 0x2a, 0x16, 0xff, 0xa4, 0x3b, 0xb3, 0xff,
  691. 0x00, 0x00, 0x00, 0xff, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xff,
  692. },
  693. },
  694. },
  695. {
  696. "AdjustSigmoid 3x3 0.5 0.0",
  697. &image.NRGBA{
  698. Rect: image.Rect(-1, -1, 2, 2),
  699. Stride: 3 * 4,
  700. Pix: []uint8{
  701. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  702. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  703. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  704. },
  705. },
  706. 0.5,
  707. 0.0,
  708. &image.NRGBA{
  709. Rect: image.Rect(0, 0, 3, 3),
  710. Stride: 3 * 4,
  711. Pix: []uint8{
  712. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  713. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  714. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  715. },
  716. },
  717. },
  718. }
  719. for _, tc := range testCases {
  720. t.Run(tc.name, func(t *testing.T) {
  721. got := AdjustSigmoid(tc.src, tc.m, tc.p)
  722. if !compareNRGBA(got, tc.want, 0) {
  723. t.Fatalf("got result %#v want %#v", got, tc.want)
  724. }
  725. })
  726. }
  727. }
  728. func BenchmarkAdjustSigmoid(b *testing.B) {
  729. b.ReportAllocs()
  730. for i := 0; i < b.N; i++ {
  731. AdjustSigmoid(testdataBranchesJPG, 0.5, 3.0)
  732. }
  733. }
  734. func TestAdjustFunc(t *testing.T) {
  735. testCases := []struct {
  736. name string
  737. src image.Image
  738. fn func(c color.NRGBA) color.NRGBA
  739. want *image.NRGBA
  740. }{
  741. {
  742. "invert",
  743. &image.NRGBA{
  744. Rect: image.Rect(-1, -1, 2, 2),
  745. Stride: 3 * 4,
  746. Pix: []uint8{
  747. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  748. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  749. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  750. },
  751. },
  752. func(c color.NRGBA) color.NRGBA {
  753. return color.NRGBA{255 - c.R, 255 - c.G, 255 - c.B, c.A}
  754. },
  755. &image.NRGBA{
  756. Rect: image.Rect(0, 0, 3, 3),
  757. Stride: 3 * 4,
  758. Pix: []uint8{
  759. 0x33, 0xff, 0xff, 0x01, 0xff, 0x33, 0xff, 0x02, 0xff, 0xff, 0x33, 0x03,
  760. 0xee, 0xdd, 0xcc, 0xff, 0xcc, 0xdd, 0xee, 0xff, 0x55, 0xcc, 0x44, 0xff,
  761. 0xff, 0xff, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0x00, 0x00, 0x00, 0xff,
  762. },
  763. },
  764. },
  765. {
  766. "threshold",
  767. &image.NRGBA{
  768. Rect: image.Rect(-1, -1, 2, 2),
  769. Stride: 3 * 4,
  770. Pix: []uint8{
  771. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  772. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  773. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  774. },
  775. },
  776. func(c color.NRGBA) color.NRGBA {
  777. y := 0.299*float64(c.R) + 0.587*float64(c.G) + 0.114*float64(c.B)
  778. if y > 0x55 {
  779. return color.NRGBA{0xff, 0xff, 0xff, c.A}
  780. }
  781. return color.NRGBA{0x00, 0x00, 0x00, c.A}
  782. },
  783. &image.NRGBA{
  784. Rect: image.Rect(0, 0, 3, 3),
  785. Stride: 3 * 4,
  786. Pix: []uint8{
  787. 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, 0x03,
  788. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
  789. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
  790. },
  791. },
  792. },
  793. }
  794. for _, tc := range testCases {
  795. t.Run(tc.name, func(t *testing.T) {
  796. got := AdjustFunc(tc.src, tc.fn)
  797. if !compareNRGBA(got, tc.want, 0) {
  798. t.Fatalf("got result %#v want %#v", got, tc.want)
  799. }
  800. })
  801. }
  802. }
  803. func BenchmarkAdjustFunc(b *testing.B) {
  804. b.ReportAllocs()
  805. for i := 0; i < b.N; i++ {
  806. AdjustFunc(testdataBranchesJPG, func(c color.NRGBA) color.NRGBA {
  807. return color.NRGBA{c.B, c.G, c.R, c.A}
  808. })
  809. }
  810. }