1
0

tools_test.go 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124
  1. package imaging
  2. import (
  3. "bytes"
  4. "image"
  5. "image/color"
  6. "testing"
  7. )
  8. func TestNew(t *testing.T) {
  9. testCases := []struct {
  10. name string
  11. w, h int
  12. c color.Color
  13. dstBounds image.Rectangle
  14. dstPix []uint8
  15. }{
  16. {
  17. "New 1x1 transparent",
  18. 1, 1,
  19. color.Transparent,
  20. image.Rect(0, 0, 1, 1),
  21. []uint8{0x00, 0x00, 0x00, 0x00},
  22. },
  23. {
  24. "New 1x2 red",
  25. 1, 2,
  26. color.RGBA{255, 0, 0, 255},
  27. image.Rect(0, 0, 1, 2),
  28. []uint8{0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff},
  29. },
  30. {
  31. "New 2x1 white",
  32. 2, 1,
  33. color.White,
  34. image.Rect(0, 0, 2, 1),
  35. []uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
  36. },
  37. {
  38. "New 3x3 with alpha",
  39. 3, 3,
  40. color.NRGBA{0x01, 0x23, 0x45, 0x67},
  41. image.Rect(0, 0, 3, 3),
  42. []uint8{
  43. 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67,
  44. 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67,
  45. 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67,
  46. },
  47. },
  48. {
  49. "New 0x0 white",
  50. 0, 0,
  51. color.White,
  52. image.Rect(0, 0, 0, 0),
  53. nil,
  54. },
  55. {
  56. "New 800x600 custom",
  57. 800, 600,
  58. color.NRGBA{1, 2, 3, 4},
  59. image.Rect(0, 0, 800, 600),
  60. bytes.Repeat([]byte{1, 2, 3, 4}, 800*600),
  61. },
  62. }
  63. for _, tc := range testCases {
  64. t.Run(tc.name, func(t *testing.T) {
  65. got := New(tc.w, tc.h, tc.c)
  66. want := image.NewNRGBA(tc.dstBounds)
  67. want.Pix = tc.dstPix
  68. if !compareNRGBA(got, want, 0) {
  69. t.Fatalf("got result %#v want %#v", got, want)
  70. }
  71. })
  72. }
  73. }
  74. func BenchmarkNew(b *testing.B) {
  75. b.ReportAllocs()
  76. for i := 0; i < b.N; i++ {
  77. New(1024, 1024, color.White)
  78. }
  79. }
  80. func TestClone(t *testing.T) {
  81. testCases := []struct {
  82. name string
  83. src image.Image
  84. want *image.NRGBA
  85. }{
  86. {
  87. "Clone NRGBA",
  88. &image.NRGBA{
  89. Rect: image.Rect(-1, -1, 0, 1),
  90. Stride: 1 * 4,
  91. Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  92. },
  93. &image.NRGBA{
  94. Rect: image.Rect(0, 0, 1, 2),
  95. Stride: 1 * 4,
  96. Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  97. },
  98. },
  99. {
  100. "Clone NRGBA64",
  101. &image.NRGBA64{
  102. Rect: image.Rect(-1, -1, 0, 1),
  103. Stride: 1 * 8,
  104. Pix: []uint8{
  105. 0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33,
  106. 0xcc, 0xcc, 0xdd, 0xdd, 0xee, 0xee, 0xff, 0xff,
  107. },
  108. },
  109. &image.NRGBA{
  110. Rect: image.Rect(0, 0, 1, 2),
  111. Stride: 1 * 4,
  112. Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  113. },
  114. },
  115. {
  116. "Clone RGBA",
  117. &image.RGBA{
  118. Rect: image.Rect(-1, -1, 0, 2),
  119. Stride: 1 * 4,
  120. Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  121. },
  122. &image.NRGBA{
  123. Rect: image.Rect(0, 0, 1, 3),
  124. Stride: 1 * 4,
  125. Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  126. },
  127. },
  128. {
  129. "Clone RGBA64",
  130. &image.RGBA64{
  131. Rect: image.Rect(-1, -1, 0, 2),
  132. Stride: 1 * 8,
  133. Pix: []uint8{
  134. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  135. 0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33,
  136. 0xcc, 0xcc, 0xdd, 0xdd, 0xee, 0xee, 0xff, 0xff,
  137. },
  138. },
  139. &image.NRGBA{
  140. Rect: image.Rect(0, 0, 1, 3),
  141. Stride: 1 * 4,
  142. Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 0x33, 0xcc, 0xdd, 0xee, 0xff},
  143. },
  144. },
  145. {
  146. "Clone Gray",
  147. &image.Gray{
  148. Rect: image.Rect(-1, -1, 0, 1),
  149. Stride: 1 * 1,
  150. Pix: []uint8{0x11, 0xee},
  151. },
  152. &image.NRGBA{
  153. Rect: image.Rect(0, 0, 1, 2),
  154. Stride: 1 * 4,
  155. Pix: []uint8{0x11, 0x11, 0x11, 0xff, 0xee, 0xee, 0xee, 0xff},
  156. },
  157. },
  158. {
  159. "Clone Gray16",
  160. &image.Gray16{
  161. Rect: image.Rect(-1, -1, 0, 1),
  162. Stride: 1 * 2,
  163. Pix: []uint8{0x11, 0x11, 0xee, 0xee},
  164. },
  165. &image.NRGBA{
  166. Rect: image.Rect(0, 0, 1, 2),
  167. Stride: 1 * 4,
  168. Pix: []uint8{0x11, 0x11, 0x11, 0xff, 0xee, 0xee, 0xee, 0xff},
  169. },
  170. },
  171. {
  172. "Clone Alpha",
  173. &image.Alpha{
  174. Rect: image.Rect(-1, -1, 0, 1),
  175. Stride: 1 * 1,
  176. Pix: []uint8{0x11, 0xee},
  177. },
  178. &image.NRGBA{
  179. Rect: image.Rect(0, 0, 1, 2),
  180. Stride: 1 * 4,
  181. Pix: []uint8{0xff, 0xff, 0xff, 0x11, 0xff, 0xff, 0xff, 0xee},
  182. },
  183. },
  184. {
  185. "Clone YCbCr",
  186. &image.YCbCr{
  187. Rect: image.Rect(-1, -1, 5, 0),
  188. SubsampleRatio: image.YCbCrSubsampleRatio444,
  189. YStride: 6,
  190. CStride: 6,
  191. Y: []uint8{0x00, 0xff, 0x7f, 0x26, 0x4b, 0x0e},
  192. Cb: []uint8{0x80, 0x80, 0x80, 0x6b, 0x56, 0xc0},
  193. Cr: []uint8{0x80, 0x80, 0x80, 0xc0, 0x4b, 0x76},
  194. },
  195. &image.NRGBA{
  196. Rect: image.Rect(0, 0, 6, 1),
  197. Stride: 6 * 4,
  198. Pix: []uint8{
  199. 0x00, 0x00, 0x00, 0xff,
  200. 0xff, 0xff, 0xff, 0xff,
  201. 0x7f, 0x7f, 0x7f, 0xff,
  202. 0x7f, 0x00, 0x00, 0xff,
  203. 0x00, 0x7f, 0x00, 0xff,
  204. 0x00, 0x00, 0x7f, 0xff,
  205. },
  206. },
  207. },
  208. {
  209. "Clone YCbCr 444",
  210. &image.YCbCr{
  211. Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
  212. Cb: []uint8{0x55, 0xd4, 0xff, 0x8e, 0x2c, 0x01, 0x6b, 0xaa, 0xc0, 0x95, 0x56, 0x40, 0x80, 0x80, 0x80, 0x80},
  213. Cr: []uint8{0xff, 0xeb, 0x6b, 0x36, 0x15, 0x95, 0xc0, 0xb5, 0x76, 0x41, 0x4b, 0x8c, 0x80, 0x80, 0x80, 0x80},
  214. YStride: 4,
  215. CStride: 4,
  216. SubsampleRatio: image.YCbCrSubsampleRatio444,
  217. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  218. },
  219. &image.NRGBA{
  220. Pix: []uint8{0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x49, 0xe1, 0xca, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0x0, 0xff, 0x7f, 0x0, 0x0, 0xff, 0x7f, 0x0, 0x7f, 0xff, 0x0, 0x0, 0x7f, 0xff, 0x0, 0x7f, 0x7f, 0xff, 0x0, 0x7f, 0x0, 0xff, 0x82, 0x7f, 0x0, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff},
  221. Stride: 16,
  222. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  223. },
  224. },
  225. {
  226. "Clone YCbCr 440",
  227. &image.YCbCr{
  228. Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
  229. Cb: []uint8{0x2c, 0x01, 0x6b, 0xaa, 0x80, 0x80, 0x80, 0x80},
  230. Cr: []uint8{0x15, 0x95, 0xc0, 0xb5, 0x80, 0x80, 0x80, 0x80},
  231. YStride: 4,
  232. CStride: 4,
  233. SubsampleRatio: image.YCbCrSubsampleRatio440,
  234. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  235. },
  236. &image.NRGBA{
  237. Pix: []uint8{0x0, 0xb5, 0x0, 0xff, 0x86, 0x86, 0x0, 0xff, 0x77, 0x0, 0x0, 0xff, 0xfb, 0x7d, 0xfb, 0xff, 0x0, 0xff, 0x1, 0xff, 0xff, 0xff, 0x1, 0xff, 0x80, 0x0, 0x1, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0xe, 0xe, 0xe, 0xff, 0x59, 0x59, 0x59, 0xff, 0x4b, 0x4b, 0x4b, 0xff, 0x71, 0x71, 0x71, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff},
  238. Stride: 16,
  239. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  240. },
  241. },
  242. {
  243. "Clone YCbCr 422",
  244. &image.YCbCr{
  245. Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
  246. Cb: []uint8{0xd4, 0x8e, 0x01, 0xaa, 0x95, 0x40, 0x80, 0x80},
  247. Cr: []uint8{0xeb, 0x36, 0x95, 0xb5, 0x41, 0x8c, 0x80, 0x80},
  248. YStride: 4,
  249. CStride: 2,
  250. SubsampleRatio: image.YCbCrSubsampleRatio422,
  251. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  252. },
  253. &image.NRGBA{
  254. Pix: []uint8{0xe2, 0x0, 0xe1, 0xff, 0xff, 0x0, 0xfe, 0xff, 0x0, 0x4d, 0x36, 0xff, 0x49, 0xe1, 0xca, 0xff, 0xb3, 0xb3, 0x0, 0xff, 0xff, 0xff, 0x1, 0xff, 0x70, 0x0, 0x70, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0x0, 0x34, 0x33, 0xff, 0x1, 0x7f, 0x7e, 0xff, 0x5c, 0x58, 0x0, 0xff, 0x82, 0x7e, 0x0, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff},
  255. Stride: 16,
  256. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  257. },
  258. },
  259. {
  260. "Clone YCbCr 420",
  261. &image.YCbCr{
  262. Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff},
  263. Cb: []uint8{0x01, 0xaa, 0x80, 0x80},
  264. Cr: []uint8{0x95, 0xb5, 0x80, 0x80},
  265. YStride: 4, CStride: 2,
  266. SubsampleRatio: image.YCbCrSubsampleRatio420,
  267. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  268. },
  269. &image.NRGBA{
  270. Pix: []uint8{0x69, 0x69, 0x0, 0xff, 0x86, 0x86, 0x0, 0xff, 0x67, 0x0, 0x67, 0xff, 0xfb, 0x7d, 0xfb, 0xff, 0xb3, 0xb3, 0x0, 0xff, 0xff, 0xff, 0x1, 0xff, 0x70, 0x0, 0x70, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0xe, 0xe, 0xe, 0xff, 0x59, 0x59, 0x59, 0xff, 0x4b, 0x4b, 0x4b, 0xff, 0x71, 0x71, 0x71, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff},
  271. Stride: 16,
  272. Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}},
  273. },
  274. },
  275. {
  276. "Clone Paletted",
  277. &image.Paletted{
  278. Rect: image.Rect(-1, -1, 5, 0),
  279. Stride: 6 * 1,
  280. Palette: color.Palette{
  281. color.NRGBA{R: 0x00, G: 0x00, B: 0x00, A: 0xff},
  282. color.NRGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff},
  283. color.NRGBA{R: 0x7f, G: 0x7f, B: 0x7f, A: 0xff},
  284. color.NRGBA{R: 0x7f, G: 0x00, B: 0x00, A: 0xff},
  285. color.NRGBA{R: 0x00, G: 0x7f, B: 0x00, A: 0xff},
  286. color.NRGBA{R: 0x00, G: 0x00, B: 0x7f, A: 0xff},
  287. },
  288. Pix: []uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5},
  289. },
  290. &image.NRGBA{
  291. Rect: image.Rect(0, 0, 6, 1),
  292. Stride: 6 * 4,
  293. Pix: []uint8{
  294. 0x00, 0x00, 0x00, 0xff,
  295. 0xff, 0xff, 0xff, 0xff,
  296. 0x7f, 0x7f, 0x7f, 0xff,
  297. 0x7f, 0x00, 0x00, 0xff,
  298. 0x00, 0x7f, 0x00, 0xff,
  299. 0x00, 0x00, 0x7f, 0xff,
  300. },
  301. },
  302. },
  303. }
  304. for _, tc := range testCases {
  305. t.Run(tc.name, func(t *testing.T) {
  306. got := Clone(tc.src)
  307. delta := 0
  308. if _, ok := tc.src.(*image.YCbCr); ok {
  309. delta = 1
  310. }
  311. if !compareNRGBA(got, tc.want, delta) {
  312. t.Fatalf("got result %#v want %#v", got, tc.want)
  313. }
  314. })
  315. }
  316. }
  317. func TestCrop(t *testing.T) {
  318. testCases := []struct {
  319. name string
  320. src image.Image
  321. r image.Rectangle
  322. want *image.NRGBA
  323. }{
  324. {
  325. "Crop 2x3 2x1",
  326. &image.NRGBA{
  327. Rect: image.Rect(-1, -1, 1, 2),
  328. Stride: 2 * 4,
  329. Pix: []uint8{
  330. 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff,
  331. 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  332. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
  333. },
  334. },
  335. image.Rect(-1, 0, 1, 1),
  336. &image.NRGBA{
  337. Rect: image.Rect(0, 0, 2, 1),
  338. Stride: 2 * 4,
  339. Pix: []uint8{
  340. 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  341. },
  342. },
  343. },
  344. }
  345. for _, tc := range testCases {
  346. t.Run(tc.name, func(t *testing.T) {
  347. got := Crop(tc.src, tc.r)
  348. if !compareNRGBA(got, tc.want, 0) {
  349. t.Fatalf("got result %#v want %#v", got, tc.want)
  350. }
  351. })
  352. }
  353. }
  354. func BenchmarkCrop(b *testing.B) {
  355. b.ReportAllocs()
  356. for i := 0; i < b.N; i++ {
  357. Crop(testdataBranchesJPG, image.Rect(100, 100, 300, 300))
  358. }
  359. }
  360. func TestCropCenter(t *testing.T) {
  361. testCases := []struct {
  362. name string
  363. src image.Image
  364. w, h int
  365. want *image.NRGBA
  366. }{
  367. {
  368. "CropCenter 2x3 2x1",
  369. &image.NRGBA{
  370. Rect: image.Rect(-1, -1, 1, 2),
  371. Stride: 2 * 4,
  372. Pix: []uint8{
  373. 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff,
  374. 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  375. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
  376. },
  377. },
  378. 2, 1,
  379. &image.NRGBA{
  380. Rect: image.Rect(0, 0, 2, 1),
  381. Stride: 2 * 4,
  382. Pix: []uint8{
  383. 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  384. },
  385. },
  386. },
  387. {
  388. "CropCenter 2x3 0x1",
  389. &image.NRGBA{
  390. Rect: image.Rect(-1, -1, 1, 2),
  391. Stride: 2 * 4,
  392. Pix: []uint8{
  393. 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff,
  394. 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  395. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
  396. },
  397. },
  398. 0, 1,
  399. &image.NRGBA{
  400. Rect: image.Rect(0, 0, 0, 0),
  401. Stride: 0,
  402. Pix: []uint8{},
  403. },
  404. },
  405. {
  406. "CropCenter 2x3 5x5",
  407. &image.NRGBA{
  408. Rect: image.Rect(-1, -1, 1, 2),
  409. Stride: 2 * 4,
  410. Pix: []uint8{
  411. 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff,
  412. 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  413. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
  414. },
  415. },
  416. 5, 5,
  417. &image.NRGBA{
  418. Rect: image.Rect(0, 0, 2, 3),
  419. Stride: 2 * 4,
  420. Pix: []uint8{
  421. 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff,
  422. 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  423. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
  424. },
  425. },
  426. },
  427. }
  428. for _, tc := range testCases {
  429. t.Run(tc.name, func(t *testing.T) {
  430. got := CropCenter(tc.src, tc.w, tc.h)
  431. if !compareNRGBA(got, tc.want, 0) {
  432. t.Fatalf("got result %#v want %#v", got, tc.want)
  433. }
  434. })
  435. }
  436. }
  437. func TestCropAnchor(t *testing.T) {
  438. testCases := []struct {
  439. name string
  440. src image.Image
  441. w, h int
  442. anchor Anchor
  443. want *image.NRGBA
  444. }{
  445. {
  446. "CropAnchor 4x4 2x2 TopLeft",
  447. &image.NRGBA{
  448. Rect: image.Rect(-1, -1, 3, 3),
  449. Stride: 4 * 4,
  450. Pix: []uint8{
  451. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  452. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  453. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  454. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  455. },
  456. },
  457. 2, 2,
  458. TopLeft,
  459. &image.NRGBA{
  460. Rect: image.Rect(0, 0, 2, 2),
  461. Stride: 2 * 4,
  462. Pix: []uint8{
  463. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  464. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  465. },
  466. },
  467. },
  468. {
  469. "CropAnchor 4x4 2x2 Top",
  470. &image.NRGBA{
  471. Rect: image.Rect(-1, -1, 3, 3),
  472. Stride: 4 * 4,
  473. Pix: []uint8{
  474. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  475. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  476. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  477. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  478. },
  479. },
  480. 2, 2,
  481. Top,
  482. &image.NRGBA{
  483. Rect: image.Rect(0, 0, 2, 2),
  484. Stride: 2 * 4,
  485. Pix: []uint8{
  486. 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
  487. 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
  488. },
  489. },
  490. },
  491. {
  492. "CropAnchor 4x4 2x2 TopRight",
  493. &image.NRGBA{
  494. Rect: image.Rect(-1, -1, 3, 3),
  495. Stride: 4 * 4,
  496. Pix: []uint8{
  497. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  498. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  499. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  500. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  501. },
  502. },
  503. 2, 2,
  504. TopRight,
  505. &image.NRGBA{
  506. Rect: image.Rect(0, 0, 2, 2),
  507. Stride: 2 * 4,
  508. Pix: []uint8{
  509. 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  510. 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  511. },
  512. },
  513. },
  514. {
  515. "CropAnchor 4x4 2x2 Left",
  516. &image.NRGBA{
  517. Rect: image.Rect(-1, -1, 3, 3),
  518. Stride: 4 * 4,
  519. Pix: []uint8{
  520. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  521. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  522. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  523. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  524. },
  525. },
  526. 2, 2,
  527. Left,
  528. &image.NRGBA{
  529. Rect: image.Rect(0, 0, 2, 2),
  530. Stride: 2 * 4,
  531. Pix: []uint8{
  532. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  533. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
  534. },
  535. },
  536. },
  537. {
  538. "CropAnchor 4x4 2x2 Center",
  539. &image.NRGBA{
  540. Rect: image.Rect(-1, -1, 3, 3),
  541. Stride: 4 * 4,
  542. Pix: []uint8{
  543. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  544. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  545. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  546. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  547. },
  548. },
  549. 2, 2,
  550. Center,
  551. &image.NRGBA{
  552. Rect: image.Rect(0, 0, 2, 2),
  553. Stride: 2 * 4,
  554. Pix: []uint8{
  555. 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
  556. 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
  557. },
  558. },
  559. },
  560. {
  561. "CropAnchor 4x4 2x2 Right",
  562. &image.NRGBA{
  563. Rect: image.Rect(-1, -1, 3, 3),
  564. Stride: 4 * 4,
  565. Pix: []uint8{
  566. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  567. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  568. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  569. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  570. },
  571. },
  572. 2, 2,
  573. Right,
  574. &image.NRGBA{
  575. Rect: image.Rect(0, 0, 2, 2),
  576. Stride: 2 * 4,
  577. Pix: []uint8{
  578. 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  579. 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  580. },
  581. },
  582. },
  583. {
  584. "CropAnchor 4x4 2x2 BottomLeft",
  585. &image.NRGBA{
  586. Rect: image.Rect(-1, -1, 3, 3),
  587. Stride: 4 * 4,
  588. Pix: []uint8{
  589. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  590. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  591. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  592. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  593. },
  594. },
  595. 2, 2,
  596. BottomLeft,
  597. &image.NRGBA{
  598. Rect: image.Rect(0, 0, 2, 2),
  599. Stride: 2 * 4,
  600. Pix: []uint8{
  601. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
  602. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
  603. },
  604. },
  605. },
  606. {
  607. "CropAnchor 4x4 2x2 Bottom",
  608. &image.NRGBA{
  609. Rect: image.Rect(-1, -1, 3, 3),
  610. Stride: 4 * 4,
  611. Pix: []uint8{
  612. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  613. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  614. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  615. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  616. },
  617. },
  618. 2, 2,
  619. Bottom,
  620. &image.NRGBA{
  621. Rect: image.Rect(0, 0, 2, 2),
  622. Stride: 2 * 4,
  623. Pix: []uint8{
  624. 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
  625. 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
  626. },
  627. },
  628. },
  629. {
  630. "CropAnchor 4x4 2x2 BottomRight",
  631. &image.NRGBA{
  632. Rect: image.Rect(-1, -1, 3, 3),
  633. Stride: 4 * 4,
  634. Pix: []uint8{
  635. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  636. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  637. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  638. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  639. },
  640. },
  641. 2, 2,
  642. BottomRight,
  643. &image.NRGBA{
  644. Rect: image.Rect(0, 0, 2, 2),
  645. Stride: 2 * 4,
  646. Pix: []uint8{
  647. 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  648. 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  649. },
  650. },
  651. },
  652. {
  653. "CropAnchor 4x4 0x0 BottomRight",
  654. &image.NRGBA{
  655. Rect: image.Rect(-1, -1, 3, 3),
  656. Stride: 4 * 4,
  657. Pix: []uint8{
  658. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  659. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  660. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  661. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  662. },
  663. },
  664. 0, 0,
  665. BottomRight,
  666. &image.NRGBA{
  667. Rect: image.Rect(0, 0, 0, 0),
  668. Stride: 0,
  669. Pix: []uint8{},
  670. },
  671. },
  672. {
  673. "CropAnchor 4x4 100x100 BottomRight",
  674. &image.NRGBA{
  675. Rect: image.Rect(-1, -1, 3, 3),
  676. Stride: 4 * 4,
  677. Pix: []uint8{
  678. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  679. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  680. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  681. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  682. },
  683. },
  684. 100, 100,
  685. BottomRight,
  686. &image.NRGBA{
  687. Rect: image.Rect(0, 0, 4, 4),
  688. Stride: 4 * 4,
  689. Pix: []uint8{
  690. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  691. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  692. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  693. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  694. },
  695. },
  696. },
  697. {
  698. "CropAnchor 4x4 1x100 BottomRight",
  699. &image.NRGBA{
  700. Rect: image.Rect(-1, -1, 3, 3),
  701. Stride: 4 * 4,
  702. Pix: []uint8{
  703. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  704. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  705. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  706. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  707. },
  708. },
  709. 1, 100,
  710. BottomRight,
  711. &image.NRGBA{
  712. Rect: image.Rect(0, 0, 1, 4),
  713. Stride: 1 * 4,
  714. Pix: []uint8{
  715. 0x0c, 0x0d, 0x0e, 0x0f,
  716. 0x1c, 0x1d, 0x1e, 0x1f,
  717. 0x2c, 0x2d, 0x2e, 0x2f,
  718. 0x3c, 0x3d, 0x3e, 0x3f,
  719. },
  720. },
  721. },
  722. {
  723. "CropAnchor 4x4 0x100 BottomRight",
  724. &image.NRGBA{
  725. Rect: image.Rect(-1, -1, 3, 3),
  726. Stride: 4 * 4,
  727. Pix: []uint8{
  728. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  729. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  730. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  731. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  732. },
  733. },
  734. 0, 100,
  735. BottomRight,
  736. &image.NRGBA{
  737. Rect: image.Rect(0, 0, 0, 0),
  738. Stride: 0,
  739. Pix: []uint8{},
  740. },
  741. },
  742. }
  743. for _, tc := range testCases {
  744. t.Run(tc.name, func(t *testing.T) {
  745. got := CropAnchor(tc.src, tc.w, tc.h, tc.anchor)
  746. if !compareNRGBA(got, tc.want, 0) {
  747. t.Fatalf("got result %#v want %#v", got, tc.want)
  748. }
  749. })
  750. }
  751. }
  752. func TestPaste(t *testing.T) {
  753. testCases := []struct {
  754. name string
  755. src1 image.Image
  756. src2 image.Image
  757. p image.Point
  758. want *image.NRGBA
  759. }{
  760. {
  761. "Paste 2x3 2x1",
  762. &image.NRGBA{
  763. Rect: image.Rect(-1, -1, 1, 2),
  764. Stride: 2 * 4,
  765. Pix: []uint8{
  766. 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff,
  767. 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  768. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
  769. },
  770. },
  771. &image.NRGBA{
  772. Rect: image.Rect(1, 1, 3, 2),
  773. Stride: 2 * 4,
  774. Pix: []uint8{
  775. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
  776. },
  777. },
  778. image.Pt(-1, 0),
  779. &image.NRGBA{
  780. Rect: image.Rect(0, 0, 2, 3),
  781. Stride: 2 * 4,
  782. Pix: []uint8{
  783. 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff,
  784. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
  785. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
  786. },
  787. },
  788. },
  789. {
  790. "Paste 3x4 4x3 bottom right intersection",
  791. &image.NRGBA{
  792. Rect: image.Rect(-1, -1, 2, 3),
  793. Stride: 3 * 4,
  794. Pix: []uint8{
  795. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
  796. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
  797. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
  798. 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
  799. },
  800. },
  801. &image.NRGBA{
  802. Rect: image.Rect(1, 1, 5, 4),
  803. Stride: 4 * 4,
  804. Pix: []uint8{
  805. 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
  806. 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
  807. 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
  808. },
  809. },
  810. image.Pt(0, 1),
  811. &image.NRGBA{
  812. Rect: image.Rect(0, 0, 3, 4),
  813. Stride: 3 * 4,
  814. Pix: []uint8{
  815. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
  816. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
  817. 0x30, 0x31, 0x32, 0x33, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
  818. 0x40, 0x41, 0x42, 0x43, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
  819. },
  820. },
  821. },
  822. {
  823. "Paste 3x4 4x3 top left intersection",
  824. &image.NRGBA{
  825. Rect: image.Rect(-1, -1, 2, 3),
  826. Stride: 3 * 4,
  827. Pix: []uint8{
  828. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
  829. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
  830. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
  831. 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
  832. },
  833. },
  834. &image.NRGBA{
  835. Rect: image.Rect(1, 1, 5, 4),
  836. Stride: 4 * 4,
  837. Pix: []uint8{
  838. 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
  839. 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
  840. 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
  841. },
  842. },
  843. image.Pt(-3, -2),
  844. &image.NRGBA{
  845. Rect: image.Rect(0, 0, 3, 4),
  846. Stride: 3 * 4,
  847. Pix: []uint8{
  848. 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0x18, 0x19, 0x1a, 0x1b,
  849. 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0x28, 0x29, 0x2a, 0x2b,
  850. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
  851. 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
  852. },
  853. },
  854. },
  855. {
  856. "Paste 3x4 4x3 no intersection",
  857. &image.NRGBA{
  858. Rect: image.Rect(-1, -1, 2, 3),
  859. Stride: 3 * 4,
  860. Pix: []uint8{
  861. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
  862. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
  863. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
  864. 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
  865. },
  866. },
  867. &image.NRGBA{
  868. Rect: image.Rect(1, 1, 5, 4),
  869. Stride: 4 * 4,
  870. Pix: []uint8{
  871. 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
  872. 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
  873. 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
  874. },
  875. },
  876. image.Pt(-20, 20),
  877. &image.NRGBA{
  878. Rect: image.Rect(0, 0, 3, 4),
  879. Stride: 3 * 4,
  880. Pix: []uint8{
  881. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
  882. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
  883. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
  884. 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
  885. },
  886. },
  887. },
  888. }
  889. for _, tc := range testCases {
  890. t.Run(tc.name, func(t *testing.T) {
  891. got := Paste(tc.src1, tc.src2, tc.p)
  892. if !compareNRGBA(got, tc.want, 0) {
  893. t.Fatalf("got result %#v want %#v", got, tc.want)
  894. }
  895. })
  896. }
  897. }
  898. func BenchmarkPaste(b *testing.B) {
  899. b.ReportAllocs()
  900. for i := 0; i < b.N; i++ {
  901. Paste(testdataBranchesJPG, testdataFlowersSmallPNG, image.Pt(100, 100))
  902. }
  903. }
  904. func TestPasteCenter(t *testing.T) {
  905. testCases := []struct {
  906. name string
  907. src1 image.Image
  908. src2 image.Image
  909. want *image.NRGBA
  910. }{
  911. {
  912. "PasteCenter 2x3 2x1",
  913. &image.NRGBA{
  914. Rect: image.Rect(-1, -1, 1, 2),
  915. Stride: 2 * 4,
  916. Pix: []uint8{
  917. 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff,
  918. 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
  919. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
  920. },
  921. },
  922. &image.NRGBA{
  923. Rect: image.Rect(1, 1, 3, 2),
  924. Stride: 2 * 4,
  925. Pix: []uint8{
  926. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
  927. },
  928. },
  929. &image.NRGBA{
  930. Rect: image.Rect(0, 0, 2, 3),
  931. Stride: 2 * 4,
  932. Pix: []uint8{
  933. 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff,
  934. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
  935. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
  936. },
  937. },
  938. },
  939. }
  940. for _, tc := range testCases {
  941. t.Run(tc.name, func(t *testing.T) {
  942. got := PasteCenter(tc.src1, tc.src2)
  943. if !compareNRGBA(got, tc.want, 0) {
  944. t.Fatalf("got result %#v want %#v", got, tc.want)
  945. }
  946. })
  947. }
  948. }
  949. func TestOverlay(t *testing.T) {
  950. testCases := []struct {
  951. name string
  952. src1 image.Image
  953. src2 image.Image
  954. p image.Point
  955. a float64
  956. want *image.NRGBA
  957. }{
  958. {
  959. "Overlay 2x3 2x1 1.0",
  960. &image.NRGBA{
  961. Rect: image.Rect(-1, -1, 1, 2),
  962. Stride: 2 * 4,
  963. Pix: []uint8{
  964. 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff,
  965. 0x60, 0x00, 0x90, 0xff, 0xff, 0x00, 0x99, 0x7f,
  966. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
  967. },
  968. },
  969. &image.NRGBA{
  970. Rect: image.Rect(1, 1, 3, 2),
  971. Stride: 2 * 4,
  972. Pix: []uint8{
  973. 0x20, 0x40, 0x80, 0x7f, 0xaa, 0xbb, 0xcc, 0xff,
  974. },
  975. },
  976. image.Pt(-1, 0),
  977. 1.0,
  978. &image.NRGBA{
  979. Rect: image.Rect(0, 0, 2, 3),
  980. Stride: 2 * 4,
  981. Pix: []uint8{
  982. 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff,
  983. 0x40, 0x1f, 0x88, 0xff, 0xaa, 0xbb, 0xcc, 0xff,
  984. 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
  985. },
  986. },
  987. },
  988. {
  989. "Overlay 2x2 2x2 0.5",
  990. &image.NRGBA{
  991. Rect: image.Rect(-1, -1, 1, 1),
  992. Stride: 2 * 4,
  993. Pix: []uint8{
  994. 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  995. 0x00, 0x00, 0xff, 0xff, 0x20, 0x20, 0x20, 0x00,
  996. },
  997. },
  998. &image.NRGBA{
  999. Rect: image.Rect(-1, -1, 1, 1),
  1000. Stride: 2 * 4,
  1001. Pix: []uint8{
  1002. 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  1003. 0xff, 0xff, 0x00, 0xff, 0x20, 0x20, 0x20, 0xff,
  1004. },
  1005. },
  1006. image.Pt(-1, -1),
  1007. 0.5,
  1008. &image.NRGBA{
  1009. Rect: image.Rect(0, 0, 2, 2),
  1010. Stride: 2 * 4,
  1011. Pix: []uint8{
  1012. 0xff, 0x7f, 0x7f, 0xff, 0x00, 0xff, 0x00, 0xff,
  1013. 0x7f, 0x7f, 0x7f, 0xff, 0x20, 0x20, 0x20, 0x7f,
  1014. },
  1015. },
  1016. },
  1017. {
  1018. "Overlay 2x2 2x2 0.5 no intersection",
  1019. &image.NRGBA{
  1020. Rect: image.Rect(-1, -1, 1, 1),
  1021. Stride: 2 * 4,
  1022. Pix: []uint8{
  1023. 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1024. 0x00, 0x00, 0xff, 0xff, 0x20, 0x20, 0x20, 0x00,
  1025. },
  1026. },
  1027. &image.NRGBA{
  1028. Rect: image.Rect(-1, -1, 1, 1),
  1029. Stride: 2 * 4,
  1030. Pix: []uint8{
  1031. 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  1032. 0xff, 0xff, 0x00, 0xff, 0x20, 0x20, 0x20, 0xff,
  1033. },
  1034. },
  1035. image.Pt(-10, 10),
  1036. 0.5,
  1037. &image.NRGBA{
  1038. Rect: image.Rect(0, 0, 2, 2),
  1039. Stride: 2 * 4,
  1040. Pix: []uint8{
  1041. 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
  1042. 0x00, 0x00, 0xff, 0xff, 0x20, 0x20, 0x20, 0x00,
  1043. },
  1044. },
  1045. },
  1046. }
  1047. for _, tc := range testCases {
  1048. t.Run(tc.name, func(t *testing.T) {
  1049. got := Overlay(tc.src1, tc.src2, tc.p, tc.a)
  1050. if !compareNRGBA(got, tc.want, 0) {
  1051. t.Fatalf("got result %#v want %#v", got, tc.want)
  1052. }
  1053. })
  1054. }
  1055. }
  1056. func BenchmarkOverlay(b *testing.B) {
  1057. b.ReportAllocs()
  1058. for i := 0; i < b.N; i++ {
  1059. Overlay(testdataBranchesJPG, testdataFlowersSmallPNG, image.Pt(100, 100), 0.5)
  1060. }
  1061. }
  1062. func TestOverlayCenter(t *testing.T) {
  1063. testCases := []struct {
  1064. name string
  1065. src1 image.Image
  1066. src2 image.Image
  1067. a float64
  1068. want *image.NRGBA
  1069. }{
  1070. {
  1071. "OverlayCenter 2x3 2x1",
  1072. &image.NRGBA{
  1073. Rect: image.Rect(-1, -1, 1, 2),
  1074. Stride: 2 * 4,
  1075. Pix: []uint8{
  1076. 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0xff,
  1077. 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0xff,
  1078. 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0xff,
  1079. },
  1080. },
  1081. &image.NRGBA{
  1082. Rect: image.Rect(1, 1, 3, 2),
  1083. Stride: 2 * 4,
  1084. Pix: []uint8{
  1085. 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
  1086. },
  1087. },
  1088. 0.5,
  1089. &image.NRGBA{
  1090. Rect: image.Rect(0, 0, 2, 3),
  1091. Stride: 2 * 4,
  1092. Pix: []uint8{
  1093. 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0xff,
  1094. 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff,
  1095. 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0xff,
  1096. },
  1097. },
  1098. },
  1099. }
  1100. for _, tc := range testCases {
  1101. t.Run(tc.name, func(t *testing.T) {
  1102. got := OverlayCenter(tc.src1, tc.src2, 0.5)
  1103. if !compareNRGBA(got, tc.want, 0) {
  1104. t.Fatalf("got result %#v want %#v", got, tc.want)
  1105. }
  1106. })
  1107. }
  1108. }