adjust_test.go 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118
  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 TestAdjustHue(t *testing.T) {
  242. testCases := []struct {
  243. name string
  244. src image.Image
  245. p float64
  246. want *image.NRGBA
  247. }{
  248. {
  249. "AdjustHue 3x3 -540",
  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. -540,
  260. &image.NRGBA{
  261. Rect: image.Rect(0, 0, 3, 3),
  262. Stride: 3 * 4,
  263. Pix: []uint8{
  264. 0x00, 0xcc, 0xcc, 0x01, 0xcc, 0x00, 0xcc, 0x02, 0xcc, 0xcc, 0x00, 0x03,
  265. 0x33, 0x22, 0x11, 0xff, 0x11, 0x22, 0x33, 0xff, 0x44, 0xbb, 0x33, 0xff,
  266. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  267. },
  268. },
  269. },
  270. {
  271. "AdjustHue 3x3 -360",
  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. -360,
  282. &image.NRGBA{
  283. Rect: image.Rect(0, 0, 3, 3),
  284. Stride: 3 * 4,
  285. Pix: []uint8{
  286. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  287. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  288. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  289. },
  290. },
  291. },
  292. {
  293. "AdjustHue 3x3 -350",
  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. -350,
  304. &image.NRGBA{
  305. Rect: image.Rect(0, 0, 3, 3),
  306. Stride: 3 * 4,
  307. Pix: []uint8{
  308. 0xcc, 0x22, 0x00, 0x01, 0x00, 0xcc, 0x22, 0x02, 0x22, 0x00, 0xcc, 0x03,
  309. 0x11, 0x1c, 0x33, 0xff, 0x33, 0x28, 0x11, 0xff, 0xbb, 0x33, 0xb5, 0xff,
  310. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  311. },
  312. },
  313. },
  314. {
  315. "AdjustHue 3x3 -180",
  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. -180,
  326. &image.NRGBA{
  327. Rect: image.Rect(0, 0, 3, 3),
  328. Stride: 3 * 4,
  329. Pix: []uint8{
  330. 0x00, 0xcc, 0xcc, 0x01, 0xcc, 0x00, 0xcc, 0x02, 0xcc, 0xcc, 0x00, 0x03,
  331. 0x33, 0x22, 0x11, 0xff, 0x11, 0x22, 0x33, 0xff, 0x44, 0xbb, 0x33, 0xff,
  332. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  333. },
  334. },
  335. },
  336. {
  337. "AdjustHue 3x3 -10",
  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. -10,
  348. &image.NRGBA{
  349. Rect: image.Rect(0, 0, 3, 3),
  350. Stride: 3 * 4,
  351. Pix: []uint8{
  352. 0xcc, 0x00, 0x22, 0x01, 0x22, 0xcc, 0x00, 0x02, 0x00, 0x22, 0xcc, 0x03,
  353. 0x11, 0x28, 0x33, 0xff, 0x33, 0x1c, 0x11, 0xff, 0x93, 0x33, 0xbb, 0xff,
  354. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  355. },
  356. },
  357. },
  358. {
  359. "AdjustHue 3x3 0",
  360. &image.NRGBA{
  361. Rect: image.Rect(-1, -1, 2, 2),
  362. Stride: 3 * 4,
  363. Pix: []uint8{
  364. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  365. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  366. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  367. },
  368. },
  369. 0,
  370. &image.NRGBA{
  371. Rect: image.Rect(0, 0, 3, 3),
  372. Stride: 3 * 4,
  373. Pix: []uint8{
  374. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  375. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  376. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  377. },
  378. },
  379. },
  380. {
  381. "AdjustHue 3x3 10",
  382. &image.NRGBA{
  383. Rect: image.Rect(-1, -1, 2, 2),
  384. Stride: 3 * 4,
  385. Pix: []uint8{
  386. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  387. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  388. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  389. },
  390. },
  391. 10,
  392. &image.NRGBA{
  393. Rect: image.Rect(0, 0, 3, 3),
  394. Stride: 3 * 4,
  395. Pix: []uint8{
  396. 0xcc, 0x22, 0x00, 0x01, 0x00, 0xcc, 0x22, 0x02, 0x22, 0x00, 0xcc, 0x03,
  397. 0x11, 0x1c, 0x33, 0xff, 0x33, 0x28, 0x11, 0xff, 0xbb, 0x33, 0xb5, 0xff,
  398. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  399. },
  400. },
  401. },
  402. {
  403. "AdjustHue 3x3 180",
  404. &image.NRGBA{
  405. Rect: image.Rect(-1, -1, 2, 2),
  406. Stride: 3 * 4,
  407. Pix: []uint8{
  408. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  409. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  410. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  411. },
  412. },
  413. 180,
  414. &image.NRGBA{
  415. Rect: image.Rect(0, 0, 3, 3),
  416. Stride: 3 * 4,
  417. Pix: []uint8{
  418. 0x00, 0xcc, 0xcc, 0x01, 0xcc, 0x00, 0xcc, 0x02, 0xcc, 0xcc, 0x00, 0x03,
  419. 0x33, 0x22, 0x11, 0xff, 0x11, 0x22, 0x33, 0xff, 0x44, 0xbb, 0x33, 0xff,
  420. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  421. },
  422. },
  423. },
  424. {
  425. "AdjustHue 3x3 350",
  426. &image.NRGBA{
  427. Rect: image.Rect(-1, -1, 2, 2),
  428. Stride: 3 * 4,
  429. Pix: []uint8{
  430. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  431. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  432. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  433. },
  434. },
  435. 350,
  436. &image.NRGBA{
  437. Rect: image.Rect(0, 0, 3, 3),
  438. Stride: 3 * 4,
  439. Pix: []uint8{
  440. 0xcc, 0x00, 0x22, 0x01, 0x22, 0xcc, 0x00, 0x02, 0x00, 0x22, 0xcc, 0x03,
  441. 0x11, 0x28, 0x33, 0xff, 0x33, 0x1c, 0x11, 0xff, 0x93, 0x33, 0xbb, 0xff,
  442. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  443. },
  444. },
  445. },
  446. {
  447. "AdjustHue 3x3 360",
  448. &image.NRGBA{
  449. Rect: image.Rect(-1, -1, 2, 2),
  450. Stride: 3 * 4,
  451. Pix: []uint8{
  452. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  453. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  454. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  455. },
  456. },
  457. 360,
  458. &image.NRGBA{
  459. Rect: image.Rect(0, 0, 3, 3),
  460. Stride: 3 * 4,
  461. Pix: []uint8{
  462. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  463. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  464. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  465. },
  466. },
  467. },
  468. {
  469. "AdjustHue 3x3 540",
  470. &image.NRGBA{
  471. Rect: image.Rect(-1, -1, 2, 2),
  472. Stride: 3 * 4,
  473. Pix: []uint8{
  474. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  475. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  476. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  477. },
  478. },
  479. 540,
  480. &image.NRGBA{
  481. Rect: image.Rect(0, 0, 3, 3),
  482. Stride: 3 * 4,
  483. Pix: []uint8{
  484. 0x00, 0xcc, 0xcc, 0x01, 0xcc, 0x00, 0xcc, 0x02, 0xcc, 0xcc, 0x00, 0x03,
  485. 0x33, 0x22, 0x11, 0xff, 0x11, 0x22, 0x33, 0xff, 0x44, 0xbb, 0x33, 0xff,
  486. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  487. },
  488. },
  489. },
  490. }
  491. for _, tc := range testCases {
  492. t.Run(tc.name, func(t *testing.T) {
  493. got := AdjustHue(tc.src, tc.p)
  494. if !compareNRGBA(got, tc.want, 0) {
  495. t.Fatalf("got result %#v want %#v", got, tc.want)
  496. }
  497. })
  498. }
  499. }
  500. func TestAdjustHueGolden(t *testing.T) {
  501. for name, p := range map[string]float64{
  502. "out_hue_m480.png": -480,
  503. "out_hue_m120.png": -120,
  504. "out_hue_m60.png": -60,
  505. "out_hue_p60.png": 60,
  506. "out_hue_p120.png": 120,
  507. "out_hue_p480.png": 480,
  508. } {
  509. got := AdjustHue(testdataFlowersSmallPNG, p)
  510. want, err := Open("testdata/" + name)
  511. if err != nil {
  512. t.Fatalf("failed to open image: %v", err)
  513. }
  514. if !compareNRGBAGolden(got, toNRGBA(want)) {
  515. t.Errorf("resulting image differs from golden: %s", name)
  516. }
  517. }
  518. }
  519. func BenchmarkAdjustHue(b *testing.B) {
  520. b.ReportAllocs()
  521. for i := 0; i < b.N; i++ {
  522. AdjustHue(testdataBranchesJPG, 10)
  523. }
  524. }
  525. func TestAdjustContrast(t *testing.T) {
  526. testCases := []struct {
  527. name string
  528. src image.Image
  529. p float64
  530. want *image.NRGBA
  531. }{
  532. {
  533. "AdjustContrast 3x3 10",
  534. &image.NRGBA{
  535. Rect: image.Rect(-1, -1, 2, 2),
  536. Stride: 3 * 4,
  537. Pix: []uint8{
  538. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  539. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  540. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  541. },
  542. },
  543. 10,
  544. &image.NRGBA{
  545. Rect: image.Rect(0, 0, 3, 3),
  546. Stride: 3 * 4,
  547. Pix: []uint8{
  548. 0xd5, 0x00, 0x00, 0x01, 0x00, 0xd5, 0x00, 0x02, 0x00, 0x00, 0xd5, 0x03,
  549. 0x05, 0x18, 0x2b, 0xff, 0x2b, 0x18, 0x05, 0xff, 0xaf, 0x2b, 0xc2, 0xff,
  550. 0x00, 0x00, 0x00, 0xff, 0x2b, 0x2b, 0x2b, 0xff, 0xff, 0xff, 0xff, 0xff,
  551. },
  552. },
  553. },
  554. {
  555. "AdjustContrast 3x3 100",
  556. &image.NRGBA{
  557. Rect: image.Rect(-1, -1, 2, 2),
  558. Stride: 3 * 4,
  559. Pix: []uint8{
  560. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  561. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  562. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  563. },
  564. },
  565. 100,
  566. &image.NRGBA{
  567. Rect: image.Rect(0, 0, 3, 3),
  568. Stride: 3 * 4,
  569. Pix: []uint8{
  570. 0xff, 0x00, 0x00, 0x01, 0x00, 0xff, 0x00, 0x02, 0x00, 0x00, 0xff, 0x03,
  571. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff,
  572. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
  573. },
  574. },
  575. },
  576. {
  577. "AdjustContrast 3x3 -10",
  578. &image.NRGBA{
  579. Rect: image.Rect(-1, -1, 2, 2),
  580. Stride: 3 * 4,
  581. Pix: []uint8{
  582. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  583. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  584. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  585. },
  586. },
  587. -10,
  588. &image.NRGBA{
  589. Rect: image.Rect(0, 0, 3, 3),
  590. Stride: 3 * 4,
  591. Pix: []uint8{
  592. 0xc4, 0x0d, 0x0d, 0x01, 0x0d, 0xc4, 0x0d, 0x02, 0x0d, 0x0d, 0xc4, 0x03,
  593. 0x1c, 0x2b, 0x3b, 0xff, 0x3b, 0x2b, 0x1c, 0xff, 0xa6, 0x3b, 0xb5, 0xff,
  594. 0x0d, 0x0d, 0x0d, 0xff, 0x3b, 0x3b, 0x3b, 0xff, 0xf2, 0xf2, 0xf2, 0xff,
  595. },
  596. },
  597. },
  598. {
  599. "AdjustContrast 3x3 -100",
  600. &image.NRGBA{
  601. Rect: image.Rect(-1, -1, 2, 2),
  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. -100,
  610. &image.NRGBA{
  611. Rect: image.Rect(0, 0, 3, 3),
  612. Stride: 3 * 4,
  613. Pix: []uint8{
  614. 0x80, 0x80, 0x80, 0x01, 0x80, 0x80, 0x80, 0x02, 0x80, 0x80, 0x80, 0x03,
  615. 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff,
  616. 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff,
  617. },
  618. },
  619. },
  620. {
  621. "AdjustContrast 3x3 0",
  622. &image.NRGBA{
  623. Rect: image.Rect(-1, -1, 2, 2),
  624. Stride: 3 * 4,
  625. Pix: []uint8{
  626. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  627. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  628. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  629. },
  630. },
  631. 0,
  632. &image.NRGBA{
  633. Rect: image.Rect(0, 0, 3, 3),
  634. Stride: 3 * 4,
  635. Pix: []uint8{
  636. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  637. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  638. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  639. },
  640. },
  641. },
  642. }
  643. for _, tc := range testCases {
  644. t.Run(tc.name, func(t *testing.T) {
  645. got := AdjustContrast(tc.src, tc.p)
  646. if !compareNRGBA(got, tc.want, 0) {
  647. t.Fatalf("got result %#v want %#v", got, tc.want)
  648. }
  649. })
  650. }
  651. }
  652. func TestAdjustContrastGolden(t *testing.T) {
  653. for name, p := range map[string]float64{
  654. "out_contrast_m15.png": -15,
  655. "out_contrast_p15.png": 15,
  656. } {
  657. got := AdjustContrast(testdataFlowersSmallPNG, p)
  658. want, err := Open("testdata/" + name)
  659. if err != nil {
  660. t.Fatalf("failed to open image: %v", err)
  661. }
  662. if !compareNRGBAGolden(got, toNRGBA(want)) {
  663. t.Fatalf("resulting image differs from golden: %s", name)
  664. }
  665. }
  666. }
  667. func BenchmarkAdjustContrast(b *testing.B) {
  668. b.ReportAllocs()
  669. for i := 0; i < b.N; i++ {
  670. AdjustContrast(testdataBranchesJPG, 10)
  671. }
  672. }
  673. func TestAdjustBrightness(t *testing.T) {
  674. testCases := []struct {
  675. name string
  676. src image.Image
  677. p float64
  678. want *image.NRGBA
  679. }{
  680. {
  681. "AdjustBrightness 3x3 10",
  682. &image.NRGBA{
  683. Rect: image.Rect(-1, -1, 2, 2),
  684. Stride: 3 * 4,
  685. Pix: []uint8{
  686. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  687. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  688. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  689. },
  690. },
  691. 10,
  692. &image.NRGBA{
  693. Rect: image.Rect(0, 0, 3, 3),
  694. Stride: 3 * 4,
  695. Pix: []uint8{
  696. 0xe6, 0x1a, 0x1a, 0x01, 0x1a, 0xe6, 0x1a, 0x02, 0x1a, 0x1a, 0xe6, 0x03,
  697. 0x2b, 0x3c, 0x4d, 0xff, 0x4d, 0x3c, 0x2b, 0xff, 0xc4, 0x4d, 0xd5, 0xff,
  698. 0x1a, 0x1a, 0x1a, 0xff, 0x4d, 0x4d, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff,
  699. },
  700. },
  701. },
  702. {
  703. "AdjustBrightness 3x3 100",
  704. &image.NRGBA{
  705. Rect: image.Rect(-1, -1, 2, 2),
  706. Stride: 3 * 4,
  707. Pix: []uint8{
  708. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  709. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  710. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  711. },
  712. },
  713. 100,
  714. &image.NRGBA{
  715. Rect: image.Rect(0, 0, 3, 3),
  716. Stride: 3 * 4,
  717. Pix: []uint8{
  718. 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x02, 0xff, 0xff, 0xff, 0x03,
  719. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  720. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  721. },
  722. },
  723. },
  724. {
  725. "AdjustBrightness 3x3 -10",
  726. &image.NRGBA{
  727. Rect: image.Rect(-1, -1, 2, 2),
  728. Stride: 3 * 4,
  729. Pix: []uint8{
  730. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  731. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  732. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  733. },
  734. },
  735. -10,
  736. &image.NRGBA{
  737. Rect: image.Rect(0, 0, 3, 3),
  738. Stride: 3 * 4,
  739. Pix: []uint8{
  740. 0xb3, 0x00, 0x00, 0x01, 0x00, 0xb3, 0x00, 0x02, 0x00, 0x00, 0xb3, 0x03,
  741. 0x00, 0x09, 0x1a, 0xff, 0x1a, 0x09, 0x00, 0xff, 0x91, 0x1a, 0xa2, 0xff,
  742. 0x00, 0x00, 0x00, 0xff, 0x1a, 0x1a, 0x1a, 0xff, 0xe6, 0xe6, 0xe6, 0xff,
  743. },
  744. },
  745. },
  746. {
  747. "AdjustBrightness 3x3 -100",
  748. &image.NRGBA{
  749. Rect: image.Rect(-1, -1, 2, 2),
  750. Stride: 3 * 4,
  751. Pix: []uint8{
  752. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  753. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  754. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  755. },
  756. },
  757. -100,
  758. &image.NRGBA{
  759. Rect: image.Rect(0, 0, 3, 3),
  760. Stride: 3 * 4,
  761. Pix: []uint8{
  762. 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03,
  763. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
  764. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
  765. },
  766. },
  767. },
  768. {
  769. "AdjustBrightness 3x3 0",
  770. &image.NRGBA{
  771. Rect: image.Rect(-1, -1, 2, 2),
  772. Stride: 3 * 4,
  773. Pix: []uint8{
  774. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  775. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  776. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  777. },
  778. },
  779. 0,
  780. &image.NRGBA{
  781. Rect: image.Rect(0, 0, 3, 3),
  782. Stride: 3 * 4,
  783. Pix: []uint8{
  784. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  785. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  786. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  787. },
  788. },
  789. },
  790. }
  791. for _, tc := range testCases {
  792. t.Run(tc.name, func(t *testing.T) {
  793. got := AdjustBrightness(tc.src, tc.p)
  794. if !compareNRGBA(got, tc.want, 0) {
  795. t.Fatalf("got result %#v want %#v", got, tc.want)
  796. }
  797. })
  798. }
  799. }
  800. func TestAdjustBrightnessGolden(t *testing.T) {
  801. for name, p := range map[string]float64{
  802. "out_brightness_m10.png": -10,
  803. "out_brightness_p10.png": 10,
  804. } {
  805. got := AdjustBrightness(testdataFlowersSmallPNG, p)
  806. want, err := Open("testdata/" + name)
  807. if err != nil {
  808. t.Fatalf("failed to open image: %v", err)
  809. }
  810. if !compareNRGBAGolden(got, toNRGBA(want)) {
  811. t.Fatalf("resulting image differs from golden: %s", name)
  812. }
  813. }
  814. }
  815. func BenchmarkAdjustBrightness(b *testing.B) {
  816. b.ReportAllocs()
  817. for i := 0; i < b.N; i++ {
  818. AdjustBrightness(testdataBranchesJPG, 10)
  819. }
  820. }
  821. func TestAdjustGamma(t *testing.T) {
  822. testCases := []struct {
  823. name string
  824. src image.Image
  825. p float64
  826. want *image.NRGBA
  827. }{
  828. {
  829. "AdjustGamma 3x3 0.75",
  830. &image.NRGBA{
  831. Rect: image.Rect(-1, -1, 2, 2),
  832. Stride: 3 * 4,
  833. Pix: []uint8{
  834. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  835. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  836. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  837. },
  838. },
  839. 0.75,
  840. &image.NRGBA{
  841. Rect: image.Rect(0, 0, 3, 3),
  842. Stride: 3 * 4,
  843. Pix: []uint8{
  844. 0xbd, 0x00, 0x00, 0x01, 0x00, 0xbd, 0x00, 0x02, 0x00, 0x00, 0xbd, 0x03,
  845. 0x07, 0x11, 0x1e, 0xff, 0x1e, 0x11, 0x07, 0xff, 0x95, 0x1e, 0xa9, 0xff,
  846. 0x00, 0x00, 0x00, 0xff, 0x1e, 0x1e, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff,
  847. },
  848. },
  849. },
  850. {
  851. "AdjustGamma 3x3 1.5",
  852. &image.NRGBA{
  853. Rect: image.Rect(-1, -1, 2, 2),
  854. Stride: 3 * 4,
  855. Pix: []uint8{
  856. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  857. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  858. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  859. },
  860. },
  861. 1.5,
  862. &image.NRGBA{
  863. Rect: image.Rect(0, 0, 3, 3),
  864. Stride: 3 * 4,
  865. Pix: []uint8{
  866. 0xdc, 0x00, 0x00, 0x01, 0x00, 0xdc, 0x00, 0x02, 0x00, 0x00, 0xdc, 0x03,
  867. 0x2a, 0x43, 0x57, 0xff, 0x57, 0x43, 0x2a, 0xff, 0xc3, 0x57, 0xcf, 0xff,
  868. 0x00, 0x00, 0x00, 0xff, 0x57, 0x57, 0x57, 0xff, 0xff, 0xff, 0xff, 0xff,
  869. },
  870. },
  871. },
  872. {
  873. "AdjustGamma 3x3 1.0",
  874. &image.NRGBA{
  875. Rect: image.Rect(-1, -1, 2, 2),
  876. Stride: 3 * 4,
  877. Pix: []uint8{
  878. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  879. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  880. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  881. },
  882. },
  883. 1.0,
  884. &image.NRGBA{
  885. Rect: image.Rect(0, 0, 3, 3),
  886. Stride: 3 * 4,
  887. Pix: []uint8{
  888. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  889. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  890. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  891. },
  892. },
  893. },
  894. }
  895. for _, tc := range testCases {
  896. t.Run(tc.name, func(t *testing.T) {
  897. got := AdjustGamma(tc.src, tc.p)
  898. if !compareNRGBA(got, tc.want, 0) {
  899. t.Fatalf("got result %#v want %#v", got, tc.want)
  900. }
  901. })
  902. }
  903. }
  904. func TestAdjustGammaGolden(t *testing.T) {
  905. for name, g := range map[string]float64{
  906. "out_gamma_0.75.png": 0.75,
  907. "out_gamma_1.25.png": 1.25,
  908. } {
  909. got := AdjustGamma(testdataFlowersSmallPNG, g)
  910. want, err := Open("testdata/" + name)
  911. if err != nil {
  912. t.Fatalf("failed to open image: %v", err)
  913. }
  914. if !compareNRGBAGolden(got, toNRGBA(want)) {
  915. t.Fatalf("resulting image differs from golden: %s", name)
  916. }
  917. }
  918. }
  919. func BenchmarkAdjustGamma(b *testing.B) {
  920. b.ReportAllocs()
  921. for i := 0; i < b.N; i++ {
  922. AdjustGamma(testdataBranchesJPG, 1.5)
  923. }
  924. }
  925. func TestAdjustSigmoid(t *testing.T) {
  926. testCases := []struct {
  927. name string
  928. src image.Image
  929. m float64
  930. p float64
  931. want *image.NRGBA
  932. }{
  933. {
  934. "AdjustSigmoid 3x3 0.5 3.0",
  935. &image.NRGBA{
  936. Rect: image.Rect(-1, -1, 2, 2),
  937. Stride: 3 * 4,
  938. Pix: []uint8{
  939. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  940. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  941. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  942. },
  943. },
  944. 0.5,
  945. 3.0,
  946. &image.NRGBA{
  947. Rect: image.Rect(0, 0, 3, 3),
  948. Stride: 3 * 4,
  949. Pix: []uint8{
  950. 0xd4, 0x00, 0x00, 0x01, 0x00, 0xd4, 0x00, 0x02, 0x00, 0x00, 0xd4, 0x03,
  951. 0x0d, 0x1b, 0x2b, 0xff, 0x2b, 0x1b, 0x0d, 0xff, 0xb1, 0x2b, 0xc3, 0xff,
  952. 0x00, 0x00, 0x00, 0xff, 0x2b, 0x2b, 0x2b, 0xff, 0xff, 0xff, 0xff, 0xff,
  953. },
  954. },
  955. },
  956. {
  957. "AdjustSigmoid 3x3 0.5 -3.0",
  958. &image.NRGBA{
  959. Rect: image.Rect(-1, -1, 2, 2),
  960. Stride: 3 * 4,
  961. Pix: []uint8{
  962. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  963. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  964. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  965. },
  966. },
  967. 0.5,
  968. -3.0,
  969. &image.NRGBA{
  970. Rect: image.Rect(0, 0, 3, 3),
  971. Stride: 3 * 4,
  972. Pix: []uint8{
  973. 0xc4, 0x00, 0x00, 0x01, 0x00, 0xc4, 0x00, 0x02, 0x00, 0x00, 0xc4, 0x03,
  974. 0x16, 0x2a, 0x3b, 0xff, 0x3b, 0x2a, 0x16, 0xff, 0xa4, 0x3b, 0xb3, 0xff,
  975. 0x00, 0x00, 0x00, 0xff, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xff,
  976. },
  977. },
  978. },
  979. {
  980. "AdjustSigmoid 3x3 0.5 0.0",
  981. &image.NRGBA{
  982. Rect: image.Rect(-1, -1, 2, 2),
  983. Stride: 3 * 4,
  984. Pix: []uint8{
  985. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  986. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  987. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  988. },
  989. },
  990. 0.5,
  991. 0.0,
  992. &image.NRGBA{
  993. Rect: image.Rect(0, 0, 3, 3),
  994. Stride: 3 * 4,
  995. Pix: []uint8{
  996. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  997. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  998. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  999. },
  1000. },
  1001. },
  1002. }
  1003. for _, tc := range testCases {
  1004. t.Run(tc.name, func(t *testing.T) {
  1005. got := AdjustSigmoid(tc.src, tc.m, tc.p)
  1006. if !compareNRGBA(got, tc.want, 0) {
  1007. t.Fatalf("got result %#v want %#v", got, tc.want)
  1008. }
  1009. })
  1010. }
  1011. }
  1012. func BenchmarkAdjustSigmoid(b *testing.B) {
  1013. b.ReportAllocs()
  1014. for i := 0; i < b.N; i++ {
  1015. AdjustSigmoid(testdataBranchesJPG, 0.5, 3.0)
  1016. }
  1017. }
  1018. func TestAdjustFunc(t *testing.T) {
  1019. testCases := []struct {
  1020. name string
  1021. src image.Image
  1022. fn func(c color.NRGBA) color.NRGBA
  1023. want *image.NRGBA
  1024. }{
  1025. {
  1026. "invert",
  1027. &image.NRGBA{
  1028. Rect: image.Rect(-1, -1, 2, 2),
  1029. Stride: 3 * 4,
  1030. Pix: []uint8{
  1031. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  1032. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  1033. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  1034. },
  1035. },
  1036. func(c color.NRGBA) color.NRGBA {
  1037. return color.NRGBA{255 - c.R, 255 - c.G, 255 - c.B, c.A}
  1038. },
  1039. &image.NRGBA{
  1040. Rect: image.Rect(0, 0, 3, 3),
  1041. Stride: 3 * 4,
  1042. Pix: []uint8{
  1043. 0x33, 0xff, 0xff, 0x01, 0xff, 0x33, 0xff, 0x02, 0xff, 0xff, 0x33, 0x03,
  1044. 0xee, 0xdd, 0xcc, 0xff, 0xcc, 0xdd, 0xee, 0xff, 0x55, 0xcc, 0x44, 0xff,
  1045. 0xff, 0xff, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0x00, 0x00, 0x00, 0xff,
  1046. },
  1047. },
  1048. },
  1049. {
  1050. "threshold",
  1051. &image.NRGBA{
  1052. Rect: image.Rect(-1, -1, 2, 2),
  1053. Stride: 3 * 4,
  1054. Pix: []uint8{
  1055. 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03,
  1056. 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff,
  1057. 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
  1058. },
  1059. },
  1060. func(c color.NRGBA) color.NRGBA {
  1061. y := 0.299*float64(c.R) + 0.587*float64(c.G) + 0.114*float64(c.B)
  1062. if y > 0x55 {
  1063. return color.NRGBA{0xff, 0xff, 0xff, c.A}
  1064. }
  1065. return color.NRGBA{0x00, 0x00, 0x00, c.A}
  1066. },
  1067. &image.NRGBA{
  1068. Rect: image.Rect(0, 0, 3, 3),
  1069. Stride: 3 * 4,
  1070. Pix: []uint8{
  1071. 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, 0x03,
  1072. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
  1073. 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
  1074. },
  1075. },
  1076. },
  1077. }
  1078. for _, tc := range testCases {
  1079. t.Run(tc.name, func(t *testing.T) {
  1080. got := AdjustFunc(tc.src, tc.fn)
  1081. if !compareNRGBA(got, tc.want, 0) {
  1082. t.Fatalf("got result %#v want %#v", got, tc.want)
  1083. }
  1084. })
  1085. }
  1086. }
  1087. func BenchmarkAdjustFunc(b *testing.B) {
  1088. b.ReportAllocs()
  1089. for i := 0; i < b.N; i++ {
  1090. AdjustFunc(testdataBranchesJPG, func(c color.NRGBA) color.NRGBA {
  1091. return color.NRGBA{c.B, c.G, c.R, c.A}
  1092. })
  1093. }
  1094. }