resize_test.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. package resize
  2. import (
  3. "image"
  4. "image/color"
  5. "runtime"
  6. "testing"
  7. )
  8. var img = image.NewGray16(image.Rect(0, 0, 3, 3))
  9. func init() {
  10. runtime.GOMAXPROCS(runtime.NumCPU())
  11. img.Set(1, 1, color.White)
  12. }
  13. func Test_Param1(t *testing.T) {
  14. m := Resize(0, 0, img, NearestNeighbor)
  15. if m.Bounds() != img.Bounds() {
  16. t.Fail()
  17. }
  18. }
  19. func Test_Param2(t *testing.T) {
  20. m := Resize(100, 0, img, NearestNeighbor)
  21. if m.Bounds() != image.Rect(0, 0, 100, 100) {
  22. t.Fail()
  23. }
  24. }
  25. func Test_ZeroImg(t *testing.T) {
  26. zeroImg := image.NewGray16(image.Rect(0, 0, 0, 0))
  27. m := Resize(0, 0, zeroImg, NearestNeighbor)
  28. if m.Bounds() != zeroImg.Bounds() {
  29. t.Fail()
  30. }
  31. }
  32. func Test_HalfZeroImg(t *testing.T) {
  33. zeroImg := image.NewGray16(image.Rect(0, 0, 0, 100))
  34. m := Resize(0, 1, zeroImg, NearestNeighbor)
  35. if m.Bounds() != zeroImg.Bounds() {
  36. t.Fail()
  37. }
  38. m = Resize(1, 0, zeroImg, NearestNeighbor)
  39. if m.Bounds() != zeroImg.Bounds() {
  40. t.Fail()
  41. }
  42. }
  43. func Test_CorrectResize(t *testing.T) {
  44. zeroImg := image.NewGray16(image.Rect(0, 0, 256, 256))
  45. m := Resize(60, 0, zeroImg, NearestNeighbor)
  46. if m.Bounds() != image.Rect(0, 0, 60, 60) {
  47. t.Fail()
  48. }
  49. }
  50. func Test_SameColorWithRGBA(t *testing.T) {
  51. img := image.NewRGBA(image.Rect(0, 0, 20, 20))
  52. for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
  53. for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
  54. img.SetRGBA(x, y, color.RGBA{0x80, 0x80, 0x80, 0xFF})
  55. }
  56. }
  57. out := Resize(10, 10, img, Lanczos3)
  58. for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ {
  59. for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ {
  60. color := out.At(x, y).(color.RGBA)
  61. if color.R != 0x80 || color.G != 0x80 || color.B != 0x80 || color.A != 0xFF {
  62. t.Errorf("%+v", color)
  63. }
  64. }
  65. }
  66. }
  67. func Test_SameColorWithNRGBA(t *testing.T) {
  68. img := image.NewNRGBA(image.Rect(0, 0, 20, 20))
  69. for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
  70. for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
  71. img.SetNRGBA(x, y, color.NRGBA{0x80, 0x80, 0x80, 0xFF})
  72. }
  73. }
  74. out := Resize(10, 10, img, Lanczos3)
  75. for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ {
  76. for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ {
  77. color := out.At(x, y).(color.RGBA)
  78. if color.R != 0x80 || color.G != 0x80 || color.B != 0x80 || color.A != 0xFF {
  79. t.Errorf("%+v", color)
  80. }
  81. }
  82. }
  83. }
  84. func Test_SameColorWithRGBA64(t *testing.T) {
  85. img := image.NewRGBA64(image.Rect(0, 0, 20, 20))
  86. for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
  87. for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
  88. img.SetRGBA64(x, y, color.RGBA64{0x8000, 0x8000, 0x8000, 0xFFFF})
  89. }
  90. }
  91. out := Resize(10, 10, img, Lanczos3)
  92. for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ {
  93. for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ {
  94. color := out.At(x, y).(color.RGBA64)
  95. if color.R != 0x8000 || color.G != 0x8000 || color.B != 0x8000 || color.A != 0xFFFF {
  96. t.Errorf("%+v", color)
  97. }
  98. }
  99. }
  100. }
  101. func Test_SameColorWithNRGBA64(t *testing.T) {
  102. img := image.NewNRGBA64(image.Rect(0, 0, 20, 20))
  103. for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
  104. for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
  105. img.SetNRGBA64(x, y, color.NRGBA64{0x8000, 0x8000, 0x8000, 0xFFFF})
  106. }
  107. }
  108. out := Resize(10, 10, img, Lanczos3)
  109. for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ {
  110. for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ {
  111. color := out.At(x, y).(color.RGBA64)
  112. if color.R != 0x8000 || color.G != 0x8000 || color.B != 0x8000 || color.A != 0xFFFF {
  113. t.Errorf("%+v", color)
  114. }
  115. }
  116. }
  117. }
  118. func Test_SameColorWithGray(t *testing.T) {
  119. img := image.NewGray(image.Rect(0, 0, 20, 20))
  120. for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
  121. for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
  122. img.SetGray(x, y, color.Gray{0x80})
  123. }
  124. }
  125. out := Resize(10, 10, img, Lanczos3)
  126. for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ {
  127. for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ {
  128. color := out.At(x, y).(color.Gray)
  129. if color.Y != 0x80 {
  130. t.Errorf("%+v", color)
  131. }
  132. }
  133. }
  134. }
  135. func Test_SameColorWithGray16(t *testing.T) {
  136. img := image.NewGray16(image.Rect(0, 0, 20, 20))
  137. for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
  138. for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
  139. img.SetGray16(x, y, color.Gray16{0x8000})
  140. }
  141. }
  142. out := Resize(10, 10, img, Lanczos3)
  143. for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ {
  144. for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ {
  145. color := out.At(x, y).(color.Gray16)
  146. if color.Y != 0x8000 {
  147. t.Errorf("%+v", color)
  148. }
  149. }
  150. }
  151. }
  152. func Test_Bounds(t *testing.T) {
  153. img := image.NewRGBA(image.Rect(20, 10, 200, 99))
  154. out := Resize(80, 80, img, Lanczos2)
  155. out.At(0, 0)
  156. }
  157. func Test_SameSizeReturnsOriginal(t *testing.T) {
  158. img := image.NewRGBA(image.Rect(0, 0, 10, 10))
  159. out := Resize(0, 0, img, Lanczos2)
  160. if img != out {
  161. t.Fail()
  162. }
  163. out = Resize(10, 10, img, Lanczos2)
  164. if img != out {
  165. t.Fail()
  166. }
  167. }
  168. func Test_PixelCoordinates(t *testing.T) {
  169. checkers := image.NewGray(image.Rect(0, 0, 4, 4))
  170. checkers.Pix = []uint8{
  171. 255, 0, 255, 0,
  172. 0, 255, 0, 255,
  173. 255, 0, 255, 0,
  174. 0, 255, 0, 255,
  175. }
  176. resized := Resize(12, 12, checkers, NearestNeighbor).(*image.Gray)
  177. if resized.Pix[0] != 255 || resized.Pix[1] != 255 || resized.Pix[2] != 255 {
  178. t.Fail()
  179. }
  180. if resized.Pix[3] != 0 || resized.Pix[4] != 0 || resized.Pix[5] != 0 {
  181. t.Fail()
  182. }
  183. }
  184. func Test_ResizeWithPremultipliedAlpha(t *testing.T) {
  185. img := image.NewRGBA(image.Rect(0, 0, 1, 4))
  186. for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
  187. // 0x80 = 0.5 * 0xFF.
  188. img.SetRGBA(0, y, color.RGBA{0x80, 0x80, 0x80, 0x80})
  189. }
  190. out := Resize(1, 2, img, MitchellNetravali)
  191. outputColor := out.At(0, 0).(color.RGBA)
  192. if outputColor.R != 0x80 {
  193. t.Fail()
  194. }
  195. }
  196. func Test_ResizeWithTranslucentColor(t *testing.T) {
  197. img := image.NewNRGBA(image.Rect(0, 0, 1, 2))
  198. // Set the pixel colors to an "invisible green" and white.
  199. // After resizing, the green shouldn't be visible.
  200. img.SetNRGBA(0, 0, color.NRGBA{0x00, 0xFF, 0x00, 0x00})
  201. img.SetNRGBA(0, 1, color.NRGBA{0x00, 0x00, 0x00, 0xFF})
  202. out := Resize(1, 1, img, Bilinear)
  203. _, g, _, _ := out.At(0, 0).RGBA()
  204. if g != 0x00 {
  205. t.Errorf("%+v", g)
  206. }
  207. }
  208. const (
  209. // Use a small image size for benchmarks. We don't want memory performance
  210. // to affect the benchmark results.
  211. benchMaxX = 250
  212. benchMaxY = 250
  213. // Resize values near the original size require increase the amount of time
  214. // resize spends converting the image.
  215. benchWidth = 200
  216. benchHeight = 200
  217. )
  218. func benchRGBA(b *testing.B, interp InterpolationFunction) {
  219. m := image.NewRGBA(image.Rect(0, 0, benchMaxX, benchMaxY))
  220. // Initialize m's pixels to create a non-uniform image.
  221. for y := m.Rect.Min.Y; y < m.Rect.Max.Y; y++ {
  222. for x := m.Rect.Min.X; x < m.Rect.Max.X; x++ {
  223. i := m.PixOffset(x, y)
  224. m.Pix[i+0] = uint8(y + 4*x)
  225. m.Pix[i+1] = uint8(y + 4*x)
  226. m.Pix[i+2] = uint8(y + 4*x)
  227. m.Pix[i+3] = uint8(4*y + x)
  228. }
  229. }
  230. var out image.Image
  231. b.ResetTimer()
  232. for i := 0; i < b.N; i++ {
  233. out = Resize(benchWidth, benchHeight, m, interp)
  234. }
  235. out.At(0, 0)
  236. }
  237. // The names of some interpolation functions are truncated so that the columns
  238. // of 'go test -bench' line up.
  239. func Benchmark_Nearest_RGBA(b *testing.B) {
  240. benchRGBA(b, NearestNeighbor)
  241. }
  242. func Benchmark_Bilinear_RGBA(b *testing.B) {
  243. benchRGBA(b, Bilinear)
  244. }
  245. func Benchmark_Bicubic_RGBA(b *testing.B) {
  246. benchRGBA(b, Bicubic)
  247. }
  248. func Benchmark_Mitchell_RGBA(b *testing.B) {
  249. benchRGBA(b, MitchellNetravali)
  250. }
  251. func Benchmark_Lanczos2_RGBA(b *testing.B) {
  252. benchRGBA(b, Lanczos2)
  253. }
  254. func Benchmark_Lanczos3_RGBA(b *testing.B) {
  255. benchRGBA(b, Lanczos3)
  256. }
  257. func benchYCbCr(b *testing.B, interp InterpolationFunction) {
  258. m := image.NewYCbCr(image.Rect(0, 0, benchMaxX, benchMaxY), image.YCbCrSubsampleRatio422)
  259. // Initialize m's pixels to create a non-uniform image.
  260. for y := m.Rect.Min.Y; y < m.Rect.Max.Y; y++ {
  261. for x := m.Rect.Min.X; x < m.Rect.Max.X; x++ {
  262. yi := m.YOffset(x, y)
  263. ci := m.COffset(x, y)
  264. m.Y[yi] = uint8(16*y + x)
  265. m.Cb[ci] = uint8(y + 16*x)
  266. m.Cr[ci] = uint8(y + 16*x)
  267. }
  268. }
  269. var out image.Image
  270. b.ResetTimer()
  271. for i := 0; i < b.N; i++ {
  272. out = Resize(benchWidth, benchHeight, m, interp)
  273. }
  274. out.At(0, 0)
  275. }
  276. func Benchmark_Nearest_YCC(b *testing.B) {
  277. benchYCbCr(b, NearestNeighbor)
  278. }
  279. func Benchmark_Bilinear_YCC(b *testing.B) {
  280. benchYCbCr(b, Bilinear)
  281. }
  282. func Benchmark_Bicubic_YCC(b *testing.B) {
  283. benchYCbCr(b, Bicubic)
  284. }
  285. func Benchmark_Mitchell_YCC(b *testing.B) {
  286. benchYCbCr(b, MitchellNetravali)
  287. }
  288. func Benchmark_Lanczos2_YCC(b *testing.B) {
  289. benchYCbCr(b, Lanczos2)
  290. }
  291. func Benchmark_Lanczos3_YCC(b *testing.B) {
  292. benchYCbCr(b, Lanczos3)
  293. }