1
0

scanner_test.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. package imaging
  2. import (
  3. "fmt"
  4. "image"
  5. "image/color"
  6. "image/color/palette"
  7. "image/draw"
  8. "testing"
  9. )
  10. func TestScanner(t *testing.T) {
  11. rect := image.Rect(-1, -1, 15, 15)
  12. colors := palette.Plan9
  13. testCases := []struct {
  14. name string
  15. img image.Image
  16. }{
  17. {
  18. name: "NRGBA",
  19. img: makeNRGBAImage(rect, colors),
  20. },
  21. {
  22. name: "NRGBA64",
  23. img: makeNRGBA64Image(rect, colors),
  24. },
  25. {
  26. name: "RGBA",
  27. img: makeRGBAImage(rect, colors),
  28. },
  29. {
  30. name: "RGBA64",
  31. img: makeRGBA64Image(rect, colors),
  32. },
  33. {
  34. name: "Gray",
  35. img: makeGrayImage(rect, colors),
  36. },
  37. {
  38. name: "Gray16",
  39. img: makeGray16Image(rect, colors),
  40. },
  41. {
  42. name: "YCbCr-444",
  43. img: makeYCbCrImage(rect, colors, image.YCbCrSubsampleRatio444),
  44. },
  45. {
  46. name: "YCbCr-422",
  47. img: makeYCbCrImage(rect, colors, image.YCbCrSubsampleRatio422),
  48. },
  49. {
  50. name: "YCbCr-420",
  51. img: makeYCbCrImage(rect, colors, image.YCbCrSubsampleRatio420),
  52. },
  53. {
  54. name: "YCbCr-440",
  55. img: makeYCbCrImage(rect, colors, image.YCbCrSubsampleRatio440),
  56. },
  57. {
  58. name: "YCbCr-410",
  59. img: makeYCbCrImage(rect, colors, image.YCbCrSubsampleRatio410),
  60. },
  61. {
  62. name: "YCbCr-411",
  63. img: makeYCbCrImage(rect, colors, image.YCbCrSubsampleRatio411),
  64. },
  65. {
  66. name: "Paletted",
  67. img: makePalettedImage(rect, colors),
  68. },
  69. {
  70. name: "Alpha",
  71. img: makeAlphaImage(rect, colors),
  72. },
  73. {
  74. name: "Alpha16",
  75. img: makeAlpha16Image(rect, colors),
  76. },
  77. {
  78. name: "Generic",
  79. img: makeGenericImage(rect, colors),
  80. },
  81. }
  82. for _, tc := range testCases {
  83. t.Run(tc.name, func(t *testing.T) {
  84. r := tc.img.Bounds()
  85. s := newScanner(tc.img)
  86. for y := r.Min.Y; y < r.Max.Y; y++ {
  87. buf := make([]byte, r.Dx()*4)
  88. s.scan(0, y-r.Min.Y, r.Dx(), y+1-r.Min.Y, buf)
  89. wantBuf := readRow(tc.img, y)
  90. if !compareBytes(buf, wantBuf, 1) {
  91. fmt.Println(tc.img)
  92. t.Fatalf("scan horizontal line (y=%d): got %v want %v", y, buf, wantBuf)
  93. }
  94. }
  95. for x := r.Min.X; x < r.Max.X; x++ {
  96. buf := make([]byte, r.Dy()*4)
  97. s.scan(x-r.Min.X, 0, x+1-r.Min.X, r.Dy(), buf)
  98. wantBuf := readColumn(tc.img, x)
  99. if !compareBytes(buf, wantBuf, 1) {
  100. t.Fatalf("scan vertical line (x=%d): got %v want %v", x, buf, wantBuf)
  101. }
  102. }
  103. })
  104. }
  105. }
  106. func makeYCbCrImage(rect image.Rectangle, colors []color.Color, sr image.YCbCrSubsampleRatio) *image.YCbCr {
  107. img := image.NewYCbCr(rect, sr)
  108. j := 0
  109. for y := rect.Min.Y; y < rect.Max.Y; y++ {
  110. for x := rect.Min.X; x < rect.Max.X; x++ {
  111. iy := img.YOffset(x, y)
  112. ic := img.COffset(x, y)
  113. c := color.NRGBAModel.Convert(colors[j]).(color.NRGBA)
  114. img.Y[iy], img.Cb[ic], img.Cr[ic] = color.RGBToYCbCr(c.R, c.G, c.B)
  115. j++
  116. }
  117. }
  118. return img
  119. }
  120. func makeNRGBAImage(rect image.Rectangle, colors []color.Color) *image.NRGBA {
  121. img := image.NewNRGBA(rect)
  122. fillDrawImage(img, colors)
  123. return img
  124. }
  125. func makeNRGBA64Image(rect image.Rectangle, colors []color.Color) *image.NRGBA64 {
  126. img := image.NewNRGBA64(rect)
  127. fillDrawImage(img, colors)
  128. return img
  129. }
  130. func makeRGBAImage(rect image.Rectangle, colors []color.Color) *image.RGBA {
  131. img := image.NewRGBA(rect)
  132. fillDrawImage(img, colors)
  133. return img
  134. }
  135. func makeRGBA64Image(rect image.Rectangle, colors []color.Color) *image.RGBA64 {
  136. img := image.NewRGBA64(rect)
  137. fillDrawImage(img, colors)
  138. return img
  139. }
  140. func makeGrayImage(rect image.Rectangle, colors []color.Color) *image.Gray {
  141. img := image.NewGray(rect)
  142. fillDrawImage(img, colors)
  143. return img
  144. }
  145. func makeGray16Image(rect image.Rectangle, colors []color.Color) *image.Gray16 {
  146. img := image.NewGray16(rect)
  147. fillDrawImage(img, colors)
  148. return img
  149. }
  150. func makePalettedImage(rect image.Rectangle, colors []color.Color) *image.Paletted {
  151. img := image.NewPaletted(rect, colors)
  152. fillDrawImage(img, colors)
  153. return img
  154. }
  155. func makeAlphaImage(rect image.Rectangle, colors []color.Color) *image.Alpha {
  156. img := image.NewAlpha(rect)
  157. fillDrawImage(img, colors)
  158. return img
  159. }
  160. func makeAlpha16Image(rect image.Rectangle, colors []color.Color) *image.Alpha16 {
  161. img := image.NewAlpha16(rect)
  162. fillDrawImage(img, colors)
  163. return img
  164. }
  165. func makeGenericImage(rect image.Rectangle, colors []color.Color) image.Image {
  166. img := image.NewRGBA(rect)
  167. fillDrawImage(img, colors)
  168. type genericImage struct{ *image.RGBA }
  169. return &genericImage{img}
  170. }
  171. func fillDrawImage(img draw.Image, colors []color.Color) {
  172. colorsNRGBA := make([]color.NRGBA, len(colors))
  173. for i, c := range colors {
  174. nrgba := color.NRGBAModel.Convert(c).(color.NRGBA)
  175. nrgba.A = uint8(i % 256)
  176. colorsNRGBA[i] = nrgba
  177. }
  178. rect := img.Bounds()
  179. i := 0
  180. for y := rect.Min.Y; y < rect.Max.Y; y++ {
  181. for x := rect.Min.X; x < rect.Max.X; x++ {
  182. img.Set(x, y, colorsNRGBA[i])
  183. i++
  184. }
  185. }
  186. }
  187. func readRow(img image.Image, y int) []uint8 {
  188. row := make([]byte, img.Bounds().Dx()*4)
  189. i := 0
  190. for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
  191. c := color.NRGBAModel.Convert(img.At(x, y)).(color.NRGBA)
  192. row[i+0] = c.R
  193. row[i+1] = c.G
  194. row[i+2] = c.B
  195. row[i+3] = c.A
  196. i += 4
  197. }
  198. return row
  199. }
  200. func readColumn(img image.Image, x int) []uint8 {
  201. column := make([]byte, img.Bounds().Dy()*4)
  202. i := 0
  203. for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
  204. c := color.NRGBAModel.Convert(img.At(x, y)).(color.NRGBA)
  205. column[i+0] = c.R
  206. column[i+1] = c.G
  207. column[i+2] = c.B
  208. column[i+3] = c.A
  209. i += 4
  210. }
  211. return column
  212. }