scanner.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. package imaging
  2. import (
  3. "image"
  4. "image/color"
  5. )
  6. type scanner struct {
  7. image image.Image
  8. w, h int
  9. palette []color.NRGBA
  10. }
  11. func newScanner(img image.Image) *scanner {
  12. s := &scanner{
  13. image: img,
  14. w: img.Bounds().Dx(),
  15. h: img.Bounds().Dy(),
  16. }
  17. if img, ok := img.(*image.Paletted); ok {
  18. s.palette = make([]color.NRGBA, len(img.Palette))
  19. for i := 0; i < len(img.Palette); i++ {
  20. s.palette[i] = color.NRGBAModel.Convert(img.Palette[i]).(color.NRGBA)
  21. }
  22. }
  23. return s
  24. }
  25. // scan scans the given rectangular region of the image into dst.
  26. func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) {
  27. switch img := s.image.(type) {
  28. case *image.NRGBA:
  29. size := (x2 - x1) * 4
  30. j := 0
  31. i := y1*img.Stride + x1*4
  32. for y := y1; y < y2; y++ {
  33. copy(dst[j:j+size], img.Pix[i:i+size])
  34. j += size
  35. i += img.Stride
  36. }
  37. case *image.NRGBA64:
  38. j := 0
  39. for y := y1; y < y2; y++ {
  40. i := y*img.Stride + x1*8
  41. for x := x1; x < x2; x++ {
  42. dst[j+0] = img.Pix[i+0]
  43. dst[j+1] = img.Pix[i+2]
  44. dst[j+2] = img.Pix[i+4]
  45. dst[j+3] = img.Pix[i+6]
  46. j += 4
  47. i += 8
  48. }
  49. }
  50. case *image.RGBA:
  51. j := 0
  52. for y := y1; y < y2; y++ {
  53. i := y*img.Stride + x1*4
  54. for x := x1; x < x2; x++ {
  55. a := img.Pix[i+3]
  56. switch a {
  57. case 0:
  58. dst[j+0] = 0
  59. dst[j+1] = 0
  60. dst[j+2] = 0
  61. case 0xff:
  62. dst[j+0] = img.Pix[i+0]
  63. dst[j+1] = img.Pix[i+1]
  64. dst[j+2] = img.Pix[i+2]
  65. default:
  66. r16 := uint16(img.Pix[i+0])
  67. g16 := uint16(img.Pix[i+1])
  68. b16 := uint16(img.Pix[i+2])
  69. a16 := uint16(a)
  70. dst[j+0] = uint8(r16 * 0xff / a16)
  71. dst[j+1] = uint8(g16 * 0xff / a16)
  72. dst[j+2] = uint8(b16 * 0xff / a16)
  73. }
  74. dst[j+3] = a
  75. j += 4
  76. i += 4
  77. }
  78. }
  79. case *image.RGBA64:
  80. j := 0
  81. for y := y1; y < y2; y++ {
  82. i := y*img.Stride + x1*8
  83. for x := x1; x < x2; x++ {
  84. a := img.Pix[i+6]
  85. switch a {
  86. case 0:
  87. dst[j+0] = 0
  88. dst[j+1] = 0
  89. dst[j+2] = 0
  90. case 0xff:
  91. dst[j+0] = img.Pix[i+0]
  92. dst[j+1] = img.Pix[i+2]
  93. dst[j+2] = img.Pix[i+4]
  94. default:
  95. r32 := uint32(img.Pix[i+0])<<8 | uint32(img.Pix[i+1])
  96. g32 := uint32(img.Pix[i+2])<<8 | uint32(img.Pix[i+3])
  97. b32 := uint32(img.Pix[i+4])<<8 | uint32(img.Pix[i+5])
  98. a32 := uint32(img.Pix[i+6])<<8 | uint32(img.Pix[i+7])
  99. dst[j+0] = uint8((r32 * 0xffff / a32) >> 8)
  100. dst[j+1] = uint8((g32 * 0xffff / a32) >> 8)
  101. dst[j+2] = uint8((b32 * 0xffff / a32) >> 8)
  102. }
  103. dst[j+3] = a
  104. j += 4
  105. i += 8
  106. }
  107. }
  108. case *image.Gray:
  109. j := 0
  110. for y := y1; y < y2; y++ {
  111. i := y*img.Stride + x1
  112. for x := x1; x < x2; x++ {
  113. c := img.Pix[i]
  114. dst[j+0] = c
  115. dst[j+1] = c
  116. dst[j+2] = c
  117. dst[j+3] = 0xff
  118. j += 4
  119. i++
  120. }
  121. }
  122. case *image.Gray16:
  123. j := 0
  124. for y := y1; y < y2; y++ {
  125. i := y*img.Stride + x1*2
  126. for x := x1; x < x2; x++ {
  127. c := img.Pix[i]
  128. dst[j+0] = c
  129. dst[j+1] = c
  130. dst[j+2] = c
  131. dst[j+3] = 0xff
  132. j += 4
  133. i += 2
  134. }
  135. }
  136. case *image.YCbCr:
  137. j := 0
  138. x1 += img.Rect.Min.X
  139. x2 += img.Rect.Min.X
  140. y1 += img.Rect.Min.Y
  141. y2 += img.Rect.Min.Y
  142. for y := y1; y < y2; y++ {
  143. iy := (y-img.Rect.Min.Y)*img.YStride + (x1 - img.Rect.Min.X)
  144. for x := x1; x < x2; x++ {
  145. var ic int
  146. switch img.SubsampleRatio {
  147. case image.YCbCrSubsampleRatio444:
  148. ic = (y-img.Rect.Min.Y)*img.CStride + (x - img.Rect.Min.X)
  149. case image.YCbCrSubsampleRatio422:
  150. ic = (y-img.Rect.Min.Y)*img.CStride + (x/2 - img.Rect.Min.X/2)
  151. case image.YCbCrSubsampleRatio420:
  152. ic = (y/2-img.Rect.Min.Y/2)*img.CStride + (x/2 - img.Rect.Min.X/2)
  153. case image.YCbCrSubsampleRatio440:
  154. ic = (y/2-img.Rect.Min.Y/2)*img.CStride + (x - img.Rect.Min.X)
  155. default:
  156. ic = img.COffset(x, y)
  157. }
  158. yy := int(img.Y[iy])
  159. cb := int(img.Cb[ic]) - 128
  160. cr := int(img.Cr[ic]) - 128
  161. r := (yy<<16 + 91881*cr + 1<<15) >> 16
  162. if r > 0xff {
  163. r = 0xff
  164. } else if r < 0 {
  165. r = 0
  166. }
  167. g := (yy<<16 - 22554*cb - 46802*cr + 1<<15) >> 16
  168. if g > 0xff {
  169. g = 0xff
  170. } else if g < 0 {
  171. g = 0
  172. }
  173. b := (yy<<16 + 116130*cb + 1<<15) >> 16
  174. if b > 0xff {
  175. b = 0xff
  176. } else if b < 0 {
  177. b = 0
  178. }
  179. dst[j+0] = uint8(r)
  180. dst[j+1] = uint8(g)
  181. dst[j+2] = uint8(b)
  182. dst[j+3] = 0xff
  183. iy++
  184. j += 4
  185. }
  186. }
  187. case *image.Paletted:
  188. j := 0
  189. for y := y1; y < y2; y++ {
  190. i := y*img.Stride + x1
  191. for x := x1; x < x2; x++ {
  192. c := s.palette[img.Pix[i]]
  193. dst[j+0] = c.R
  194. dst[j+1] = c.G
  195. dst[j+2] = c.B
  196. dst[j+3] = c.A
  197. j += 4
  198. i++
  199. }
  200. }
  201. default:
  202. j := 0
  203. b := s.image.Bounds()
  204. x1 += b.Min.X
  205. x2 += b.Min.X
  206. y1 += b.Min.Y
  207. y2 += b.Min.Y
  208. for y := y1; y < y2; y++ {
  209. for x := x1; x < x2; x++ {
  210. r16, g16, b16, a16 := s.image.At(x, y).RGBA()
  211. switch a16 {
  212. case 0xffff:
  213. dst[j+0] = uint8(r16 >> 8)
  214. dst[j+1] = uint8(g16 >> 8)
  215. dst[j+2] = uint8(b16 >> 8)
  216. dst[j+3] = 0xff
  217. case 0:
  218. dst[j+0] = 0
  219. dst[j+1] = 0
  220. dst[j+2] = 0
  221. dst[j+3] = 0
  222. default:
  223. dst[j+0] = uint8(((r16 * 0xffff) / a16) >> 8)
  224. dst[j+1] = uint8(((g16 * 0xffff) / a16) >> 8)
  225. dst[j+2] = uint8(((b16 * 0xffff) / a16) >> 8)
  226. dst[j+3] = uint8(a16 >> 8)
  227. }
  228. j += 4
  229. }
  230. }
  231. }
  232. }