1
0

resize_test.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. package imaging
  2. import (
  3. "fmt"
  4. "image"
  5. "testing"
  6. )
  7. func TestResize(t *testing.T) {
  8. testCases := []struct {
  9. name string
  10. src image.Image
  11. w, h int
  12. f ResampleFilter
  13. want *image.NRGBA
  14. }{
  15. {
  16. "Resize 2x2 1x1 box",
  17. &image.NRGBA{
  18. Rect: image.Rect(-1, -1, 1, 1),
  19. Stride: 2 * 4,
  20. Pix: []uint8{
  21. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
  22. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
  23. },
  24. },
  25. 1, 1,
  26. Box,
  27. &image.NRGBA{
  28. Rect: image.Rect(0, 0, 1, 1),
  29. Stride: 1 * 4,
  30. Pix: []uint8{0x55, 0x55, 0x55, 0xc0},
  31. },
  32. },
  33. {
  34. "Resize 2x2 1x2 box",
  35. &image.NRGBA{
  36. Rect: image.Rect(-1, -1, 1, 1),
  37. Stride: 2 * 4,
  38. Pix: []uint8{
  39. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
  40. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
  41. },
  42. },
  43. 1, 2,
  44. Box,
  45. &image.NRGBA{
  46. Rect: image.Rect(0, 0, 1, 2),
  47. Stride: 1 * 4,
  48. Pix: []uint8{
  49. 0xff, 0x00, 0x00, 0x80,
  50. 0x00, 0x80, 0x80, 0xff,
  51. },
  52. },
  53. },
  54. {
  55. "Resize 2x2 2x1 box",
  56. &image.NRGBA{
  57. Rect: image.Rect(-1, -1, 1, 1),
  58. Stride: 2 * 4,
  59. Pix: []uint8{
  60. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
  61. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
  62. },
  63. },
  64. 2, 1,
  65. Box,
  66. &image.NRGBA{
  67. Rect: image.Rect(0, 0, 2, 1),
  68. Stride: 2 * 4,
  69. Pix: []uint8{
  70. 0x00, 0xff, 0x00, 0x80, 0x80, 0x00, 0x80, 0xff,
  71. },
  72. },
  73. },
  74. {
  75. "Resize 2x2 2x2 box",
  76. &image.NRGBA{
  77. Rect: image.Rect(-1, -1, 1, 1),
  78. Stride: 2 * 4,
  79. Pix: []uint8{
  80. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
  81. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
  82. },
  83. },
  84. 2, 2,
  85. Box,
  86. &image.NRGBA{
  87. Rect: image.Rect(0, 0, 2, 2),
  88. Stride: 2 * 4,
  89. Pix: []uint8{
  90. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
  91. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
  92. },
  93. },
  94. },
  95. {
  96. "Resize 3x1 1x1 nearest",
  97. &image.NRGBA{
  98. Rect: image.Rect(-1, -1, 2, 0),
  99. Stride: 3 * 4,
  100. Pix: []uint8{
  101. 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
  102. },
  103. },
  104. 1, 1,
  105. NearestNeighbor,
  106. &image.NRGBA{
  107. Rect: image.Rect(0, 0, 1, 1),
  108. Stride: 1 * 4,
  109. Pix: []uint8{0x00, 0xff, 0x00, 0xff},
  110. },
  111. },
  112. {
  113. "Resize 2x2 0x4 box",
  114. &image.NRGBA{
  115. Rect: image.Rect(-1, -1, 1, 1),
  116. Stride: 2 * 4,
  117. Pix: []uint8{
  118. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
  119. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
  120. },
  121. },
  122. 0, 4,
  123. Box,
  124. &image.NRGBA{
  125. Rect: image.Rect(0, 0, 4, 4),
  126. Stride: 4 * 4,
  127. Pix: []uint8{
  128. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
  129. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
  130. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
  131. 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
  132. },
  133. },
  134. },
  135. {
  136. "Resize 2x2 4x0 linear",
  137. &image.NRGBA{
  138. Rect: image.Rect(-1, -1, 1, 1),
  139. Stride: 2 * 4,
  140. Pix: []uint8{
  141. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
  142. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
  143. },
  144. },
  145. 4, 0,
  146. Linear,
  147. &image.NRGBA{
  148. Rect: image.Rect(0, 0, 4, 4),
  149. Stride: 4 * 4,
  150. Pix: []uint8{
  151. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x40, 0xff, 0x00, 0x00, 0xbf, 0xff, 0x00, 0x00, 0xff,
  152. 0x00, 0xff, 0x00, 0x40, 0x6e, 0x6d, 0x25, 0x70, 0xb0, 0x14, 0x3b, 0xcf, 0xbf, 0x00, 0x40, 0xff,
  153. 0x00, 0xff, 0x00, 0xbf, 0x14, 0xb0, 0x3b, 0xcf, 0x33, 0x33, 0x99, 0xef, 0x40, 0x00, 0xbf, 0xff,
  154. 0x00, 0xff, 0x00, 0xff, 0x00, 0xbf, 0x40, 0xff, 0x00, 0x40, 0xbf, 0xff, 0x00, 0x00, 0xff, 0xff,
  155. },
  156. },
  157. },
  158. {
  159. "Resize 0x0 1x1 box",
  160. &image.NRGBA{
  161. Rect: image.Rect(-1, -1, -1, -1),
  162. Stride: 0,
  163. Pix: []uint8{},
  164. },
  165. 1, 1,
  166. Box,
  167. &image.NRGBA{},
  168. },
  169. {
  170. "Resize 2x2 0x0 box",
  171. &image.NRGBA{
  172. Rect: image.Rect(-1, -1, 1, 1),
  173. Stride: 2 * 4,
  174. Pix: []uint8{
  175. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
  176. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
  177. },
  178. },
  179. 0, 0,
  180. Box,
  181. &image.NRGBA{},
  182. },
  183. {
  184. "Resize 2x2 -1x0 box",
  185. &image.NRGBA{
  186. Rect: image.Rect(-1, -1, 1, 1),
  187. Stride: 2 * 4,
  188. Pix: []uint8{
  189. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
  190. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
  191. },
  192. },
  193. -1, 0,
  194. Box,
  195. &image.NRGBA{},
  196. },
  197. }
  198. for _, tc := range testCases {
  199. t.Run(tc.name, func(t *testing.T) {
  200. got := Resize(tc.src, tc.w, tc.h, tc.f)
  201. if !compareNRGBA(got, tc.want, 0) {
  202. t.Fatalf("got result %#v want %#v", got, tc.want)
  203. }
  204. })
  205. }
  206. }
  207. func TestResampleFilters(t *testing.T) {
  208. for _, filter := range []ResampleFilter{
  209. NearestNeighbor,
  210. Box,
  211. Linear,
  212. Hermite,
  213. MitchellNetravali,
  214. CatmullRom,
  215. BSpline,
  216. Gaussian,
  217. Lanczos,
  218. Hann,
  219. Hamming,
  220. Blackman,
  221. Bartlett,
  222. Welch,
  223. Cosine,
  224. } {
  225. t.Run("", func(t *testing.T) {
  226. src := image.NewNRGBA(image.Rect(-1, -1, 2, 3))
  227. got := Resize(src, 5, 6, filter)
  228. want := image.NewNRGBA(image.Rect(0, 0, 5, 6))
  229. if !compareNRGBA(got, want, 0) {
  230. t.Fatalf("got result %#v want %#v", got, want)
  231. }
  232. if filter.Kernel != nil {
  233. if x := filter.Kernel(filter.Support + 0.0001); x != 0 {
  234. t.Fatalf("got kernel value %f want 0", x)
  235. }
  236. }
  237. })
  238. }
  239. }
  240. func TestResizeGolden(t *testing.T) {
  241. for name, filter := range map[string]ResampleFilter{
  242. "out_resize_nearest.png": NearestNeighbor,
  243. "out_resize_linear.png": Linear,
  244. "out_resize_catrom.png": CatmullRom,
  245. "out_resize_lanczos.png": Lanczos,
  246. } {
  247. got := Resize(testdataBranchesPNG, 150, 0, filter)
  248. want, err := Open("testdata/" + name)
  249. if err != nil {
  250. t.Fatalf("failed to open image: %v", err)
  251. }
  252. if !compareNRGBA(got, toNRGBA(want), 0) {
  253. t.Fatalf("resulting image differs from golden: %s", name)
  254. }
  255. }
  256. }
  257. func TestFit(t *testing.T) {
  258. testCases := []struct {
  259. name string
  260. src image.Image
  261. w, h int
  262. f ResampleFilter
  263. want *image.NRGBA
  264. }{
  265. {
  266. "Fit 2x2 1x10 box",
  267. &image.NRGBA{
  268. Rect: image.Rect(-1, -1, 1, 1),
  269. Stride: 2 * 4,
  270. Pix: []uint8{
  271. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
  272. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
  273. },
  274. },
  275. 1, 10,
  276. Box,
  277. &image.NRGBA{
  278. Rect: image.Rect(0, 0, 1, 1),
  279. Stride: 1 * 4,
  280. Pix: []uint8{0x55, 0x55, 0x55, 0xc0},
  281. },
  282. },
  283. {
  284. "Fit 2x2 10x1 box",
  285. &image.NRGBA{
  286. Rect: image.Rect(-1, -1, 1, 1),
  287. Stride: 2 * 4,
  288. Pix: []uint8{
  289. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
  290. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
  291. },
  292. },
  293. 10, 1,
  294. Box,
  295. &image.NRGBA{
  296. Rect: image.Rect(0, 0, 1, 1),
  297. Stride: 1 * 4,
  298. Pix: []uint8{0x55, 0x55, 0x55, 0xc0},
  299. },
  300. },
  301. {
  302. "Fit 2x2 10x10 box",
  303. &image.NRGBA{
  304. Rect: image.Rect(-1, -1, 1, 1),
  305. Stride: 2 * 4,
  306. Pix: []uint8{
  307. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
  308. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
  309. },
  310. },
  311. 10, 10,
  312. Box,
  313. &image.NRGBA{
  314. Rect: image.Rect(0, 0, 2, 2),
  315. Stride: 2 * 4,
  316. Pix: []uint8{
  317. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
  318. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
  319. },
  320. },
  321. },
  322. {
  323. "Fit 0x0 1x1 box",
  324. &image.NRGBA{
  325. Rect: image.Rect(-1, -1, -1, -1),
  326. Stride: 0,
  327. Pix: []uint8{},
  328. },
  329. 1, 1,
  330. Box,
  331. &image.NRGBA{},
  332. },
  333. {
  334. "Fit 2x2 0x0 box",
  335. &image.NRGBA{
  336. Rect: image.Rect(-1, -1, 1, 1),
  337. Stride: 2 * 4,
  338. Pix: []uint8{
  339. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
  340. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
  341. },
  342. },
  343. 0, 0,
  344. Box,
  345. &image.NRGBA{},
  346. },
  347. {
  348. "Fit 2x2 -1x0 box",
  349. &image.NRGBA{
  350. Rect: image.Rect(-1, -1, 1, 1),
  351. Stride: 2 * 4,
  352. Pix: []uint8{
  353. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
  354. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
  355. },
  356. },
  357. -1, 0,
  358. Box,
  359. &image.NRGBA{},
  360. },
  361. }
  362. for _, tc := range testCases {
  363. t.Run(tc.name, func(t *testing.T) {
  364. got := Fit(tc.src, tc.w, tc.h, tc.f)
  365. if !compareNRGBA(got, tc.want, 0) {
  366. t.Fatalf("got result %#v want %#v", got, tc.want)
  367. }
  368. })
  369. }
  370. }
  371. func TestFill(t *testing.T) {
  372. testCases := []struct {
  373. name string
  374. src image.Image
  375. w, h int
  376. a Anchor
  377. f ResampleFilter
  378. want *image.NRGBA
  379. }{
  380. {
  381. "Fill 4x4 2x2 Center Nearest",
  382. &image.NRGBA{
  383. Rect: image.Rect(-1, -1, 3, 3),
  384. Stride: 4 * 4,
  385. Pix: []uint8{
  386. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  387. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  388. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  389. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  390. },
  391. },
  392. 2, 2,
  393. Center,
  394. NearestNeighbor,
  395. &image.NRGBA{
  396. Rect: image.Rect(0, 0, 2, 2),
  397. Stride: 2 * 4,
  398. Pix: []uint8{
  399. 0x14, 0x15, 0x16, 0x17, 0x1c, 0x1d, 0x1e, 0x1f,
  400. 0x34, 0x35, 0x36, 0x37, 0x3c, 0x3d, 0x3e, 0x3f,
  401. },
  402. },
  403. },
  404. {
  405. "Fill 4x4 1x4 TopLeft Nearest",
  406. &image.NRGBA{
  407. Rect: image.Rect(-1, -1, 3, 3),
  408. Stride: 4 * 4,
  409. Pix: []uint8{
  410. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  411. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  412. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  413. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  414. },
  415. },
  416. 1, 4,
  417. TopLeft,
  418. NearestNeighbor,
  419. &image.NRGBA{
  420. Rect: image.Rect(0, 0, 1, 4),
  421. Stride: 1 * 4,
  422. Pix: []uint8{
  423. 0x00, 0x01, 0x02, 0x03,
  424. 0x10, 0x11, 0x12, 0x13,
  425. 0x20, 0x21, 0x22, 0x23,
  426. 0x30, 0x31, 0x32, 0x33,
  427. },
  428. },
  429. },
  430. {
  431. "Fill 4x4 8x2 Bottom Nearest",
  432. &image.NRGBA{
  433. Rect: image.Rect(-1, -1, 3, 3),
  434. Stride: 4 * 4,
  435. Pix: []uint8{
  436. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  437. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  438. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  439. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  440. },
  441. },
  442. 8, 2,
  443. Bottom,
  444. NearestNeighbor,
  445. &image.NRGBA{
  446. Rect: image.Rect(0, 0, 8, 2),
  447. Stride: 8 * 4,
  448. Pix: []uint8{
  449. 0x30, 0x31, 0x32, 0x33, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x3c, 0x3d, 0x3e, 0x3f,
  450. 0x30, 0x31, 0x32, 0x33, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x3c, 0x3d, 0x3e, 0x3f,
  451. },
  452. },
  453. },
  454. {
  455. "Fill 4x4 2x8 Top Nearest",
  456. &image.NRGBA{
  457. Rect: image.Rect(-1, -1, 3, 3),
  458. Stride: 4 * 4,
  459. Pix: []uint8{
  460. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  461. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  462. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  463. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  464. },
  465. },
  466. 2, 8,
  467. Top,
  468. NearestNeighbor,
  469. &image.NRGBA{
  470. Rect: image.Rect(0, 0, 2, 8),
  471. Stride: 2 * 4,
  472. Pix: []uint8{
  473. 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
  474. 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
  475. 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
  476. 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
  477. 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
  478. 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
  479. 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
  480. 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
  481. },
  482. },
  483. },
  484. {
  485. "Fill 4x4 4x4 TopRight Box",
  486. &image.NRGBA{
  487. Rect: image.Rect(-1, -1, 3, 3),
  488. Stride: 4 * 4,
  489. Pix: []uint8{
  490. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  491. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  492. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  493. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  494. },
  495. },
  496. 4, 4,
  497. TopRight,
  498. Box,
  499. &image.NRGBA{
  500. Rect: image.Rect(0, 0, 4, 4),
  501. Stride: 4 * 4,
  502. Pix: []uint8{
  503. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  504. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  505. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  506. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  507. },
  508. },
  509. },
  510. {
  511. "Fill 4x4 0x4 Left Box",
  512. &image.NRGBA{
  513. Rect: image.Rect(-1, -1, 3, 3),
  514. Stride: 4 * 4,
  515. Pix: []uint8{
  516. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  517. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  518. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  519. 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  520. },
  521. },
  522. 0, 4,
  523. Left,
  524. Box,
  525. &image.NRGBA{},
  526. },
  527. {
  528. "Fill 0x0 4x4 Right Box",
  529. &image.NRGBA{},
  530. 4, 4,
  531. Right,
  532. Box,
  533. &image.NRGBA{},
  534. },
  535. }
  536. for _, tc := range testCases {
  537. t.Run(tc.name, func(t *testing.T) {
  538. got := Fill(tc.src, tc.w, tc.h, tc.a, tc.f)
  539. if !compareNRGBA(got, tc.want, 0) {
  540. t.Fatalf("got result %#v want %#v", got, tc.want)
  541. }
  542. })
  543. }
  544. }
  545. func TestThumbnail(t *testing.T) {
  546. testCases := []struct {
  547. name string
  548. src image.Image
  549. w, h int
  550. f ResampleFilter
  551. want *image.NRGBA
  552. }{
  553. {
  554. "Thumbnail 6x2 1x1 box",
  555. &image.NRGBA{
  556. Rect: image.Rect(-1, -1, 5, 1),
  557. Stride: 6 * 4,
  558. Pix: []uint8{
  559. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  560. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  561. },
  562. },
  563. 1, 1,
  564. Box,
  565. &image.NRGBA{
  566. Rect: image.Rect(0, 0, 1, 1),
  567. Stride: 1 * 4,
  568. Pix: []uint8{0x55, 0x55, 0x55, 0xc0},
  569. },
  570. },
  571. {
  572. "Thumbnail 2x6 1x1 box",
  573. &image.NRGBA{
  574. Rect: image.Rect(-1, -1, 1, 5),
  575. Stride: 2 * 4,
  576. Pix: []uint8{
  577. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  578. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  579. 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
  580. 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
  581. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  582. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  583. },
  584. },
  585. 1, 1,
  586. Box,
  587. &image.NRGBA{
  588. Rect: image.Rect(0, 0, 1, 1),
  589. Stride: 1 * 4,
  590. Pix: []uint8{0x55, 0x55, 0x55, 0xc0},
  591. },
  592. },
  593. {
  594. "Thumbnail 1x3 2x2 box",
  595. &image.NRGBA{
  596. Rect: image.Rect(-1, -1, 0, 2),
  597. Stride: 1 * 4,
  598. Pix: []uint8{
  599. 0x00, 0x00, 0x00, 0x00,
  600. 0xff, 0x00, 0x00, 0xff,
  601. 0xff, 0xff, 0xff, 0xff,
  602. },
  603. },
  604. 2, 2,
  605. Box,
  606. &image.NRGBA{
  607. Rect: image.Rect(0, 0, 2, 2),
  608. Stride: 2 * 4,
  609. Pix: []uint8{
  610. 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
  611. 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
  612. },
  613. },
  614. },
  615. }
  616. for _, tc := range testCases {
  617. t.Run(tc.name, func(t *testing.T) {
  618. got := Thumbnail(tc.src, tc.w, tc.h, tc.f)
  619. if !compareNRGBA(got, tc.want, 0) {
  620. t.Fatalf("got result %#v want %#v", got, tc.want)
  621. }
  622. })
  623. }
  624. }
  625. func BenchmarkResize(b *testing.B) {
  626. for _, dir := range []string{"Down", "Up"} {
  627. for _, filter := range []string{"NearestNeighbor", "Linear", "CatmullRom", "Lanczos"} {
  628. for _, format := range []string{"JPEG", "PNG"} {
  629. var size int
  630. switch dir {
  631. case "Down":
  632. size = 100
  633. case "Up":
  634. size = 1000
  635. }
  636. var f ResampleFilter
  637. switch filter {
  638. case "NearestNeighbor":
  639. f = NearestNeighbor
  640. case "Linear":
  641. f = Linear
  642. case "CatmullRom":
  643. f = CatmullRom
  644. case "Lanczos":
  645. f = Lanczos
  646. }
  647. var img image.Image
  648. switch format {
  649. case "JPEG":
  650. img = testdataBranchesJPG
  651. case "PNG":
  652. img = testdataBranchesPNG
  653. }
  654. b.Run(fmt.Sprintf("%s %s %s", dir, filter, format), func(b *testing.B) {
  655. b.ReportAllocs()
  656. for i := 0; i < b.N; i++ {
  657. Resize(img, size, size, f)
  658. }
  659. })
  660. }
  661. }
  662. }
  663. }