draw.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Package draw provides image composition functions.
  5. //
  6. // See "The Go image/draw package" for an introduction to this package:
  7. // http://golang.org/doc/articles/image_draw.html
  8. package draw
  9. import (
  10. "image"
  11. "image/color"
  12. )
  13. // m is the maximum color value returned by image.Color.RGBA.
  14. const m = 1<<16 - 1
  15. // Image is an image.Image with a Set method to change a single pixel.
  16. type Image interface {
  17. image.Image
  18. Set(x, y int, c color.Color)
  19. }
  20. // Quantizer produces a palette for an image.
  21. type Quantizer interface {
  22. // Quantize appends up to cap(p) - len(p) colors to p and returns the
  23. // updated palette suitable for converting m to a paletted image.
  24. Quantize(p color.Palette, m image.Image) color.Palette
  25. }
  26. // Op is a Porter-Duff compositing operator.
  27. type Op int
  28. const (
  29. // Over specifies ``(src in mask) over dst''.
  30. Over Op = iota
  31. // Src specifies ``src in mask''.
  32. Src
  33. )
  34. // Draw implements the Drawer interface by calling the Draw function with this
  35. // Op.
  36. func (op Op) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
  37. DrawMask(dst, r, src, sp, nil, image.Point{}, op)
  38. }
  39. // Drawer contains the Draw method.
  40. type Drawer interface {
  41. // Draw aligns r.Min in dst with sp in src and then replaces the
  42. // rectangle r in dst with the result of drawing src on dst.
  43. Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point)
  44. }
  45. // FloydSteinberg is a Drawer that is the Src Op with Floyd-Steinberg error
  46. // diffusion.
  47. var FloydSteinberg Drawer = floydSteinberg{}
  48. type floydSteinberg struct{}
  49. func (floydSteinberg) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
  50. clip(dst, &r, src, &sp, nil, nil)
  51. if r.Empty() {
  52. return
  53. }
  54. drawPaletted(dst, r, src, sp, true)
  55. }
  56. // clip clips r against each image's bounds (after translating into the
  57. // destination image's co-ordinate space) and shifts the points sp and mp by
  58. // the same amount as the change in r.Min.
  59. func clip(dst Image, r *image.Rectangle, src image.Image, sp *image.Point, mask image.Image, mp *image.Point) {
  60. orig := r.Min
  61. *r = r.Intersect(dst.Bounds())
  62. *r = r.Intersect(src.Bounds().Add(orig.Sub(*sp)))
  63. if mask != nil {
  64. *r = r.Intersect(mask.Bounds().Add(orig.Sub(*mp)))
  65. }
  66. dx := r.Min.X - orig.X
  67. dy := r.Min.Y - orig.Y
  68. if dx == 0 && dy == 0 {
  69. return
  70. }
  71. (*sp).X += dx
  72. (*sp).Y += dy
  73. (*mp).X += dx
  74. (*mp).Y += dy
  75. }
  76. func processBackward(dst Image, r image.Rectangle, src image.Image, sp image.Point) bool {
  77. return image.Image(dst) == src &&
  78. r.Overlaps(r.Add(sp.Sub(r.Min))) &&
  79. (sp.Y < r.Min.Y || (sp.Y == r.Min.Y && sp.X < r.Min.X))
  80. }
  81. // Draw calls DrawMask with a nil mask.
  82. func Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op) {
  83. DrawMask(dst, r, src, sp, nil, image.Point{}, op)
  84. }
  85. // DrawMask aligns r.Min in dst with sp in src and mp in mask and then replaces the rectangle r
  86. // in dst with the result of a Porter-Duff composition. A nil mask is treated as opaque.
  87. func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) {
  88. clip(dst, &r, src, &sp, mask, &mp)
  89. if r.Empty() {
  90. return
  91. }
  92. // Fast paths for special cases. If none of them apply, then we fall back to a general but slow implementation.
  93. switch dst0 := dst.(type) {
  94. case *image.RGBA:
  95. if op == Over {
  96. if mask == nil {
  97. switch src0 := src.(type) {
  98. case *image.Uniform:
  99. drawFillOver(dst0, r, src0)
  100. return
  101. case *image.RGBA:
  102. drawCopyOver(dst0, r, src0, sp)
  103. return
  104. case *image.NRGBA:
  105. drawNRGBAOver(dst0, r, src0, sp)
  106. return
  107. case *image.YCbCr:
  108. if drawYCbCr(dst0, r, src0, sp) {
  109. return
  110. }
  111. }
  112. } else if mask0, ok := mask.(*image.Alpha); ok {
  113. switch src0 := src.(type) {
  114. case *image.Uniform:
  115. drawGlyphOver(dst0, r, src0, mask0, mp)
  116. return
  117. }
  118. }
  119. } else {
  120. if mask == nil {
  121. switch src0 := src.(type) {
  122. case *image.Uniform:
  123. drawFillSrc(dst0, r, src0)
  124. return
  125. case *image.RGBA:
  126. drawCopySrc(dst0, r, src0, sp)
  127. return
  128. case *image.NRGBA:
  129. drawNRGBASrc(dst0, r, src0, sp)
  130. return
  131. case *image.YCbCr:
  132. if drawYCbCr(dst0, r, src0, sp) {
  133. return
  134. }
  135. }
  136. }
  137. }
  138. drawRGBA(dst0, r, src, sp, mask, mp, op)
  139. return
  140. case *image.Paletted:
  141. if op == Src && mask == nil && !processBackward(dst, r, src, sp) {
  142. drawPaletted(dst0, r, src, sp, false)
  143. }
  144. }
  145. x0, x1, dx := r.Min.X, r.Max.X, 1
  146. y0, y1, dy := r.Min.Y, r.Max.Y, 1
  147. if processBackward(dst, r, src, sp) {
  148. x0, x1, dx = x1-1, x0-1, -1
  149. y0, y1, dy = y1-1, y0-1, -1
  150. }
  151. var out color.RGBA64
  152. sy := sp.Y + y0 - r.Min.Y
  153. my := mp.Y + y0 - r.Min.Y
  154. for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
  155. sx := sp.X + x0 - r.Min.X
  156. mx := mp.X + x0 - r.Min.X
  157. for x := x0; x != x1; x, sx, mx = x+dx, sx+dx, mx+dx {
  158. ma := uint32(m)
  159. if mask != nil {
  160. _, _, _, ma = mask.At(mx, my).RGBA()
  161. }
  162. switch {
  163. case ma == 0:
  164. if op == Over {
  165. // No-op.
  166. } else {
  167. dst.Set(x, y, color.Transparent)
  168. }
  169. case ma == m && op == Src:
  170. dst.Set(x, y, src.At(sx, sy))
  171. default:
  172. sr, sg, sb, sa := src.At(sx, sy).RGBA()
  173. if op == Over {
  174. dr, dg, db, da := dst.At(x, y).RGBA()
  175. a := m - (sa * ma / m)
  176. out.R = uint16((dr*a + sr*ma) / m)
  177. out.G = uint16((dg*a + sg*ma) / m)
  178. out.B = uint16((db*a + sb*ma) / m)
  179. out.A = uint16((da*a + sa*ma) / m)
  180. } else {
  181. out.R = uint16(sr * ma / m)
  182. out.G = uint16(sg * ma / m)
  183. out.B = uint16(sb * ma / m)
  184. out.A = uint16(sa * ma / m)
  185. }
  186. // The third argument is &out instead of out (and out is
  187. // declared outside of the inner loop) to avoid the implicit
  188. // conversion to color.Color here allocating memory in the
  189. // inner loop if sizeof(color.RGBA64) > sizeof(uintptr).
  190. dst.Set(x, y, &out)
  191. }
  192. }
  193. }
  194. }
  195. func drawFillOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform) {
  196. sr, sg, sb, sa := src.RGBA()
  197. // The 0x101 is here for the same reason as in drawRGBA.
  198. a := (m - sa) * 0x101
  199. i0 := dst.PixOffset(r.Min.X, r.Min.Y)
  200. i1 := i0 + r.Dx()*4
  201. for y := r.Min.Y; y != r.Max.Y; y++ {
  202. for i := i0; i < i1; i += 4 {
  203. dr := uint32(dst.Pix[i+0])
  204. dg := uint32(dst.Pix[i+1])
  205. db := uint32(dst.Pix[i+2])
  206. da := uint32(dst.Pix[i+3])
  207. dst.Pix[i+0] = uint8((dr*a/m + sr) >> 8)
  208. dst.Pix[i+1] = uint8((dg*a/m + sg) >> 8)
  209. dst.Pix[i+2] = uint8((db*a/m + sb) >> 8)
  210. dst.Pix[i+3] = uint8((da*a/m + sa) >> 8)
  211. }
  212. i0 += dst.Stride
  213. i1 += dst.Stride
  214. }
  215. }
  216. func drawFillSrc(dst *image.RGBA, r image.Rectangle, src *image.Uniform) {
  217. sr, sg, sb, sa := src.RGBA()
  218. // The built-in copy function is faster than a straightforward for loop to fill the destination with
  219. // the color, but copy requires a slice source. We therefore use a for loop to fill the first row, and
  220. // then use the first row as the slice source for the remaining rows.
  221. i0 := dst.PixOffset(r.Min.X, r.Min.Y)
  222. i1 := i0 + r.Dx()*4
  223. for i := i0; i < i1; i += 4 {
  224. dst.Pix[i+0] = uint8(sr >> 8)
  225. dst.Pix[i+1] = uint8(sg >> 8)
  226. dst.Pix[i+2] = uint8(sb >> 8)
  227. dst.Pix[i+3] = uint8(sa >> 8)
  228. }
  229. firstRow := dst.Pix[i0:i1]
  230. for y := r.Min.Y + 1; y < r.Max.Y; y++ {
  231. i0 += dst.Stride
  232. i1 += dst.Stride
  233. copy(dst.Pix[i0:i1], firstRow)
  234. }
  235. }
  236. func drawCopyOver(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.Point) {
  237. dx, dy := r.Dx(), r.Dy()
  238. d0 := dst.PixOffset(r.Min.X, r.Min.Y)
  239. s0 := src.PixOffset(sp.X, sp.Y)
  240. var (
  241. ddelta, sdelta int
  242. i0, i1, idelta int
  243. )
  244. if r.Min.Y < sp.Y || r.Min.Y == sp.Y && r.Min.X <= sp.X {
  245. ddelta = dst.Stride
  246. sdelta = src.Stride
  247. i0, i1, idelta = 0, dx*4, +4
  248. } else {
  249. // If the source start point is higher than the destination start point, or equal height but to the left,
  250. // then we compose the rows in right-to-left, bottom-up order instead of left-to-right, top-down.
  251. d0 += (dy - 1) * dst.Stride
  252. s0 += (dy - 1) * src.Stride
  253. ddelta = -dst.Stride
  254. sdelta = -src.Stride
  255. i0, i1, idelta = (dx-1)*4, -4, -4
  256. }
  257. for ; dy > 0; dy-- {
  258. dpix := dst.Pix[d0:]
  259. spix := src.Pix[s0:]
  260. for i := i0; i != i1; i += idelta {
  261. sr := uint32(spix[i+0]) * 0x101
  262. sg := uint32(spix[i+1]) * 0x101
  263. sb := uint32(spix[i+2]) * 0x101
  264. sa := uint32(spix[i+3]) * 0x101
  265. dr := uint32(dpix[i+0])
  266. dg := uint32(dpix[i+1])
  267. db := uint32(dpix[i+2])
  268. da := uint32(dpix[i+3])
  269. // The 0x101 is here for the same reason as in drawRGBA.
  270. a := (m - sa) * 0x101
  271. dpix[i+0] = uint8((dr*a/m + sr) >> 8)
  272. dpix[i+1] = uint8((dg*a/m + sg) >> 8)
  273. dpix[i+2] = uint8((db*a/m + sb) >> 8)
  274. dpix[i+3] = uint8((da*a/m + sa) >> 8)
  275. }
  276. d0 += ddelta
  277. s0 += sdelta
  278. }
  279. }
  280. func drawCopySrc(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.Point) {
  281. n, dy := 4*r.Dx(), r.Dy()
  282. d0 := dst.PixOffset(r.Min.X, r.Min.Y)
  283. s0 := src.PixOffset(sp.X, sp.Y)
  284. var ddelta, sdelta int
  285. if r.Min.Y <= sp.Y {
  286. ddelta = dst.Stride
  287. sdelta = src.Stride
  288. } else {
  289. // If the source start point is higher than the destination start point, then we compose the rows
  290. // in bottom-up order instead of top-down. Unlike the drawCopyOver function, we don't have to
  291. // check the x co-ordinates because the built-in copy function can handle overlapping slices.
  292. d0 += (dy - 1) * dst.Stride
  293. s0 += (dy - 1) * src.Stride
  294. ddelta = -dst.Stride
  295. sdelta = -src.Stride
  296. }
  297. for ; dy > 0; dy-- {
  298. copy(dst.Pix[d0:d0+n], src.Pix[s0:s0+n])
  299. d0 += ddelta
  300. s0 += sdelta
  301. }
  302. }
  303. func drawNRGBAOver(dst *image.RGBA, r image.Rectangle, src *image.NRGBA, sp image.Point) {
  304. i0 := (r.Min.X - dst.Rect.Min.X) * 4
  305. i1 := (r.Max.X - dst.Rect.Min.X) * 4
  306. si0 := (sp.X - src.Rect.Min.X) * 4
  307. yMax := r.Max.Y - dst.Rect.Min.Y
  308. y := r.Min.Y - dst.Rect.Min.Y
  309. sy := sp.Y - src.Rect.Min.Y
  310. for ; y != yMax; y, sy = y+1, sy+1 {
  311. dpix := dst.Pix[y*dst.Stride:]
  312. spix := src.Pix[sy*src.Stride:]
  313. for i, si := i0, si0; i < i1; i, si = i+4, si+4 {
  314. // Convert from non-premultiplied color to pre-multiplied color.
  315. sa := uint32(spix[si+3]) * 0x101
  316. sr := uint32(spix[si+0]) * sa / 0xff
  317. sg := uint32(spix[si+1]) * sa / 0xff
  318. sb := uint32(spix[si+2]) * sa / 0xff
  319. dr := uint32(dpix[i+0])
  320. dg := uint32(dpix[i+1])
  321. db := uint32(dpix[i+2])
  322. da := uint32(dpix[i+3])
  323. // The 0x101 is here for the same reason as in drawRGBA.
  324. a := (m - sa) * 0x101
  325. dpix[i+0] = uint8((dr*a/m + sr) >> 8)
  326. dpix[i+1] = uint8((dg*a/m + sg) >> 8)
  327. dpix[i+2] = uint8((db*a/m + sb) >> 8)
  328. dpix[i+3] = uint8((da*a/m + sa) >> 8)
  329. }
  330. }
  331. }
  332. func drawNRGBASrc(dst *image.RGBA, r image.Rectangle, src *image.NRGBA, sp image.Point) {
  333. i0 := (r.Min.X - dst.Rect.Min.X) * 4
  334. i1 := (r.Max.X - dst.Rect.Min.X) * 4
  335. si0 := (sp.X - src.Rect.Min.X) * 4
  336. yMax := r.Max.Y - dst.Rect.Min.Y
  337. y := r.Min.Y - dst.Rect.Min.Y
  338. sy := sp.Y - src.Rect.Min.Y
  339. for ; y != yMax; y, sy = y+1, sy+1 {
  340. dpix := dst.Pix[y*dst.Stride:]
  341. spix := src.Pix[sy*src.Stride:]
  342. for i, si := i0, si0; i < i1; i, si = i+4, si+4 {
  343. // Convert from non-premultiplied color to pre-multiplied color.
  344. sa := uint32(spix[si+3]) * 0x101
  345. sr := uint32(spix[si+0]) * sa / 0xff
  346. sg := uint32(spix[si+1]) * sa / 0xff
  347. sb := uint32(spix[si+2]) * sa / 0xff
  348. dpix[i+0] = uint8(sr >> 8)
  349. dpix[i+1] = uint8(sg >> 8)
  350. dpix[i+2] = uint8(sb >> 8)
  351. dpix[i+3] = uint8(sa >> 8)
  352. }
  353. }
  354. }
  355. func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Point) (ok bool) {
  356. // An image.YCbCr is always fully opaque, and so if the mask is implicitly nil
  357. // (i.e. fully opaque) then the op is effectively always Src.
  358. x0 := (r.Min.X - dst.Rect.Min.X) * 4
  359. x1 := (r.Max.X - dst.Rect.Min.X) * 4
  360. y0 := r.Min.Y - dst.Rect.Min.Y
  361. y1 := r.Max.Y - dst.Rect.Min.Y
  362. switch src.SubsampleRatio {
  363. case image.YCbCrSubsampleRatio444:
  364. for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
  365. dpix := dst.Pix[y*dst.Stride:]
  366. yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
  367. ci := (sy-src.Rect.Min.Y)*src.CStride + (sp.X - src.Rect.Min.X)
  368. for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 {
  369. rr, gg, bb := color.YCbCrToRGB(src.Y[yi], src.Cb[ci], src.Cr[ci])
  370. dpix[x+0] = rr
  371. dpix[x+1] = gg
  372. dpix[x+2] = bb
  373. dpix[x+3] = 255
  374. }
  375. }
  376. case image.YCbCrSubsampleRatio422:
  377. for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
  378. dpix := dst.Pix[y*dst.Stride:]
  379. yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
  380. ciBase := (sy-src.Rect.Min.Y)*src.CStride - src.Rect.Min.X/2
  381. for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 {
  382. ci := ciBase + sx/2
  383. rr, gg, bb := color.YCbCrToRGB(src.Y[yi], src.Cb[ci], src.Cr[ci])
  384. dpix[x+0] = rr
  385. dpix[x+1] = gg
  386. dpix[x+2] = bb
  387. dpix[x+3] = 255
  388. }
  389. }
  390. case image.YCbCrSubsampleRatio420:
  391. for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
  392. dpix := dst.Pix[y*dst.Stride:]
  393. yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
  394. ciBase := (sy/2-src.Rect.Min.Y/2)*src.CStride - src.Rect.Min.X/2
  395. for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 {
  396. ci := ciBase + sx/2
  397. rr, gg, bb := color.YCbCrToRGB(src.Y[yi], src.Cb[ci], src.Cr[ci])
  398. dpix[x+0] = rr
  399. dpix[x+1] = gg
  400. dpix[x+2] = bb
  401. dpix[x+3] = 255
  402. }
  403. }
  404. case image.YCbCrSubsampleRatio440:
  405. for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
  406. dpix := dst.Pix[y*dst.Stride:]
  407. yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
  408. ci := (sy/2-src.Rect.Min.Y/2)*src.CStride + (sp.X - src.Rect.Min.X)
  409. for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 {
  410. rr, gg, bb := color.YCbCrToRGB(src.Y[yi], src.Cb[ci], src.Cr[ci])
  411. dpix[x+0] = rr
  412. dpix[x+1] = gg
  413. dpix[x+2] = bb
  414. dpix[x+3] = 255
  415. }
  416. }
  417. default:
  418. return false
  419. }
  420. return true
  421. }
  422. func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask *image.Alpha, mp image.Point) {
  423. i0 := dst.PixOffset(r.Min.X, r.Min.Y)
  424. i1 := i0 + r.Dx()*4
  425. mi0 := mask.PixOffset(mp.X, mp.Y)
  426. sr, sg, sb, sa := src.RGBA()
  427. for y, my := r.Min.Y, mp.Y; y != r.Max.Y; y, my = y+1, my+1 {
  428. for i, mi := i0, mi0; i < i1; i, mi = i+4, mi+1 {
  429. ma := uint32(mask.Pix[mi])
  430. if ma == 0 {
  431. continue
  432. }
  433. ma |= ma << 8
  434. dr := uint32(dst.Pix[i+0])
  435. dg := uint32(dst.Pix[i+1])
  436. db := uint32(dst.Pix[i+2])
  437. da := uint32(dst.Pix[i+3])
  438. // The 0x101 is here for the same reason as in drawRGBA.
  439. a := (m - (sa * ma / m)) * 0x101
  440. dst.Pix[i+0] = uint8((dr*a + sr*ma) / m >> 8)
  441. dst.Pix[i+1] = uint8((dg*a + sg*ma) / m >> 8)
  442. dst.Pix[i+2] = uint8((db*a + sb*ma) / m >> 8)
  443. dst.Pix[i+3] = uint8((da*a + sa*ma) / m >> 8)
  444. }
  445. i0 += dst.Stride
  446. i1 += dst.Stride
  447. mi0 += mask.Stride
  448. }
  449. }
  450. func drawRGBA(dst *image.RGBA, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) {
  451. x0, x1, dx := r.Min.X, r.Max.X, 1
  452. y0, y1, dy := r.Min.Y, r.Max.Y, 1
  453. if image.Image(dst) == src && r.Overlaps(r.Add(sp.Sub(r.Min))) {
  454. if sp.Y < r.Min.Y || sp.Y == r.Min.Y && sp.X < r.Min.X {
  455. x0, x1, dx = x1-1, x0-1, -1
  456. y0, y1, dy = y1-1, y0-1, -1
  457. }
  458. }
  459. sy := sp.Y + y0 - r.Min.Y
  460. my := mp.Y + y0 - r.Min.Y
  461. sx0 := sp.X + x0 - r.Min.X
  462. mx0 := mp.X + x0 - r.Min.X
  463. sx1 := sx0 + (x1 - x0)
  464. i0 := dst.PixOffset(x0, y0)
  465. di := dx * 4
  466. for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
  467. for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx {
  468. ma := uint32(m)
  469. if mask != nil {
  470. _, _, _, ma = mask.At(mx, my).RGBA()
  471. }
  472. sr, sg, sb, sa := src.At(sx, sy).RGBA()
  473. if op == Over {
  474. dr := uint32(dst.Pix[i+0])
  475. dg := uint32(dst.Pix[i+1])
  476. db := uint32(dst.Pix[i+2])
  477. da := uint32(dst.Pix[i+3])
  478. // dr, dg, db and da are all 8-bit color at the moment, ranging in [0,255].
  479. // We work in 16-bit color, and so would normally do:
  480. // dr |= dr << 8
  481. // and similarly for dg, db and da, but instead we multiply a
  482. // (which is a 16-bit color, ranging in [0,65535]) by 0x101.
  483. // This yields the same result, but is fewer arithmetic operations.
  484. a := (m - (sa * ma / m)) * 0x101
  485. dst.Pix[i+0] = uint8((dr*a + sr*ma) / m >> 8)
  486. dst.Pix[i+1] = uint8((dg*a + sg*ma) / m >> 8)
  487. dst.Pix[i+2] = uint8((db*a + sb*ma) / m >> 8)
  488. dst.Pix[i+3] = uint8((da*a + sa*ma) / m >> 8)
  489. } else {
  490. dst.Pix[i+0] = uint8(sr * ma / m >> 8)
  491. dst.Pix[i+1] = uint8(sg * ma / m >> 8)
  492. dst.Pix[i+2] = uint8(sb * ma / m >> 8)
  493. dst.Pix[i+3] = uint8(sa * ma / m >> 8)
  494. }
  495. }
  496. i0 += dy * dst.Stride
  497. }
  498. }
  499. // clamp clamps i to the interval [0, 0xffff].
  500. func clamp(i int32) int32 {
  501. if i < 0 {
  502. return 0
  503. }
  504. if i > 0xffff {
  505. return 0xffff
  506. }
  507. return i
  508. }
  509. func drawPaletted(dst Image, r image.Rectangle, src image.Image, sp image.Point, floydSteinberg bool) {
  510. // TODO(nigeltao): handle the case where the dst and src overlap.
  511. // Does it even make sense to try and do Floyd-Steinberg whilst
  512. // walking the image backward (right-to-left bottom-to-top)?
  513. // If dst is an *image.Paletted, we have a fast path for dst.Set and
  514. // dst.At. The dst.Set equivalent is a batch version of the algorithm
  515. // used by color.Palette's Index method in image/color/color.go, plus
  516. // optional Floyd-Steinberg error diffusion.
  517. palette, pix, stride := [][3]int32(nil), []byte(nil), 0
  518. if p, ok := dst.(*image.Paletted); ok {
  519. palette = make([][3]int32, len(p.Palette))
  520. for i, col := range p.Palette {
  521. r, g, b, _ := col.RGBA()
  522. palette[i][0] = int32(r)
  523. palette[i][1] = int32(g)
  524. palette[i][2] = int32(b)
  525. }
  526. pix, stride = p.Pix[p.PixOffset(r.Min.X, r.Min.Y):], p.Stride
  527. }
  528. // quantErrorCurr and quantErrorNext are the Floyd-Steinberg quantization
  529. // errors that have been propagated to the pixels in the current and next
  530. // rows. The +2 simplifies calculation near the edges.
  531. var quantErrorCurr, quantErrorNext [][3]int32
  532. if floydSteinberg {
  533. quantErrorCurr = make([][3]int32, r.Dx()+2)
  534. quantErrorNext = make([][3]int32, r.Dx()+2)
  535. }
  536. // Loop over each source pixel.
  537. out := color.RGBA64{A: 0xffff}
  538. for y := 0; y != r.Dy(); y++ {
  539. for x := 0; x != r.Dx(); x++ {
  540. // er, eg and eb are the pixel's R,G,B values plus the
  541. // optional Floyd-Steinberg error.
  542. sr, sg, sb, _ := src.At(sp.X+x, sp.Y+y).RGBA()
  543. er, eg, eb := int32(sr), int32(sg), int32(sb)
  544. if floydSteinberg {
  545. er = clamp(er + quantErrorCurr[x+1][0]/16)
  546. eg = clamp(eg + quantErrorCurr[x+1][1]/16)
  547. eb = clamp(eb + quantErrorCurr[x+1][2]/16)
  548. }
  549. if palette != nil {
  550. // Find the closest palette color in Euclidean R,G,B space: the
  551. // one that minimizes sum-squared-difference. We shift by 1 bit
  552. // to avoid potential uint32 overflow in sum-squared-difference.
  553. // TODO(nigeltao): consider smarter algorithms.
  554. bestIndex, bestSSD := 0, uint32(1<<32-1)
  555. for index, p := range palette {
  556. delta := (er - p[0]) >> 1
  557. ssd := uint32(delta * delta)
  558. delta = (eg - p[1]) >> 1
  559. ssd += uint32(delta * delta)
  560. delta = (eb - p[2]) >> 1
  561. ssd += uint32(delta * delta)
  562. if ssd < bestSSD {
  563. bestIndex, bestSSD = index, ssd
  564. if ssd == 0 {
  565. break
  566. }
  567. }
  568. }
  569. pix[y*stride+x] = byte(bestIndex)
  570. if !floydSteinberg {
  571. continue
  572. }
  573. er -= int32(palette[bestIndex][0])
  574. eg -= int32(palette[bestIndex][1])
  575. eb -= int32(palette[bestIndex][2])
  576. } else {
  577. out.R = uint16(er)
  578. out.G = uint16(eg)
  579. out.B = uint16(eb)
  580. // The third argument is &out instead of out (and out is
  581. // declared outside of the inner loop) to avoid the implicit
  582. // conversion to color.Color here allocating memory in the
  583. // inner loop if sizeof(color.RGBA64) > sizeof(uintptr).
  584. dst.Set(r.Min.X+x, r.Min.Y+y, &out)
  585. if !floydSteinberg {
  586. continue
  587. }
  588. sr, sg, sb, _ = dst.At(r.Min.X+x, r.Min.Y+y).RGBA()
  589. er -= int32(sr)
  590. eg -= int32(sg)
  591. eb -= int32(sb)
  592. }
  593. // Propagate the Floyd-Steinberg quantization error.
  594. quantErrorNext[x+0][0] += er * 3
  595. quantErrorNext[x+0][1] += eg * 3
  596. quantErrorNext[x+0][2] += eb * 3
  597. quantErrorNext[x+1][0] += er * 5
  598. quantErrorNext[x+1][1] += eg * 5
  599. quantErrorNext[x+1][2] += eb * 5
  600. quantErrorNext[x+2][0] += er * 1
  601. quantErrorNext[x+2][1] += eg * 1
  602. quantErrorNext[x+2][2] += eb * 1
  603. quantErrorCurr[x+2][0] += er * 7
  604. quantErrorCurr[x+2][1] += eg * 7
  605. quantErrorCurr[x+2][2] += eb * 7
  606. }
  607. // Recycle the quantization error buffers.
  608. if floydSteinberg {
  609. quantErrorCurr, quantErrorNext = quantErrorNext, quantErrorCurr
  610. for i := range quantErrorNext {
  611. quantErrorNext[i] = [3]int32{}
  612. }
  613. }
  614. }
  615. }