affine.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // Copyright 2011 The Graphics-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 graphics
  5. import (
  6. "code.google.com/p/graphics-go/graphics/interp"
  7. "errors"
  8. "image"
  9. "image/draw"
  10. "math"
  11. )
  12. // I is the identity Affine transform matrix.
  13. var I = Affine{
  14. 1, 0, 0,
  15. 0, 1, 0,
  16. 0, 0, 1,
  17. }
  18. // Affine is a 3x3 2D affine transform matrix.
  19. // M(i,j) is Affine[i*3+j].
  20. type Affine [9]float64
  21. // Mul returns the multiplication of two affine transform matrices.
  22. func (a Affine) Mul(b Affine) Affine {
  23. return Affine{
  24. a[0]*b[0] + a[1]*b[3] + a[2]*b[6],
  25. a[0]*b[1] + a[1]*b[4] + a[2]*b[7],
  26. a[0]*b[2] + a[1]*b[5] + a[2]*b[8],
  27. a[3]*b[0] + a[4]*b[3] + a[5]*b[6],
  28. a[3]*b[1] + a[4]*b[4] + a[5]*b[7],
  29. a[3]*b[2] + a[4]*b[5] + a[5]*b[8],
  30. a[6]*b[0] + a[7]*b[3] + a[8]*b[6],
  31. a[6]*b[1] + a[7]*b[4] + a[8]*b[7],
  32. a[6]*b[2] + a[7]*b[5] + a[8]*b[8],
  33. }
  34. }
  35. func (a Affine) transformRGBA(dst *image.RGBA, src *image.RGBA, i interp.RGBA) error {
  36. srcb := src.Bounds()
  37. b := dst.Bounds()
  38. for y := b.Min.Y; y < b.Max.Y; y++ {
  39. for x := b.Min.X; x < b.Max.X; x++ {
  40. sx, sy := a.pt(x, y)
  41. if inBounds(srcb, sx, sy) {
  42. c := i.RGBA(src, sx, sy)
  43. off := (y-dst.Rect.Min.Y)*dst.Stride + (x-dst.Rect.Min.X)*4
  44. dst.Pix[off+0] = c.R
  45. dst.Pix[off+1] = c.G
  46. dst.Pix[off+2] = c.B
  47. dst.Pix[off+3] = c.A
  48. }
  49. }
  50. }
  51. return nil
  52. }
  53. // Transform applies the affine transform to src and produces dst.
  54. func (a Affine) Transform(dst draw.Image, src image.Image, i interp.Interp) error {
  55. if dst == nil {
  56. return errors.New("graphics: dst is nil")
  57. }
  58. if src == nil {
  59. return errors.New("graphics: src is nil")
  60. }
  61. // RGBA fast path.
  62. dstRGBA, dstOk := dst.(*image.RGBA)
  63. srcRGBA, srcOk := src.(*image.RGBA)
  64. interpRGBA, interpOk := i.(interp.RGBA)
  65. if dstOk && srcOk && interpOk {
  66. return a.transformRGBA(dstRGBA, srcRGBA, interpRGBA)
  67. }
  68. srcb := src.Bounds()
  69. b := dst.Bounds()
  70. for y := b.Min.Y; y < b.Max.Y; y++ {
  71. for x := b.Min.X; x < b.Max.X; x++ {
  72. sx, sy := a.pt(x, y)
  73. if inBounds(srcb, sx, sy) {
  74. dst.Set(x, y, i.Interp(src, sx, sy))
  75. }
  76. }
  77. }
  78. return nil
  79. }
  80. func inBounds(b image.Rectangle, x, y float64) bool {
  81. if x < float64(b.Min.X) || x >= float64(b.Max.X) {
  82. return false
  83. }
  84. if y < float64(b.Min.Y) || y >= float64(b.Max.Y) {
  85. return false
  86. }
  87. return true
  88. }
  89. func (a Affine) pt(x0, y0 int) (x1, y1 float64) {
  90. fx := float64(x0) + 0.5
  91. fy := float64(y0) + 0.5
  92. x1 = fx*a[0] + fy*a[1] + a[2]
  93. y1 = fx*a[3] + fy*a[4] + a[5]
  94. return x1, y1
  95. }
  96. // TransformCenter applies the affine transform to src and produces dst.
  97. // Equivalent to
  98. // a.CenterFit(dst, src).Transform(dst, src, i).
  99. func (a Affine) TransformCenter(dst draw.Image, src image.Image, i interp.Interp) error {
  100. if dst == nil {
  101. return errors.New("graphics: dst is nil")
  102. }
  103. if src == nil {
  104. return errors.New("graphics: src is nil")
  105. }
  106. return a.CenterFit(dst.Bounds(), src.Bounds()).Transform(dst, src, i)
  107. }
  108. // Scale produces a scaling transform of factors x and y.
  109. func (a Affine) Scale(x, y float64) Affine {
  110. return a.Mul(Affine{
  111. 1 / x, 0, 0,
  112. 0, 1 / y, 0,
  113. 0, 0, 1,
  114. })
  115. }
  116. // Rotate produces a clockwise rotation transform of angle, in radians.
  117. func (a Affine) Rotate(angle float64) Affine {
  118. s, c := math.Sincos(angle)
  119. return a.Mul(Affine{
  120. +c, +s, +0,
  121. -s, +c, +0,
  122. +0, +0, +1,
  123. })
  124. }
  125. // Shear produces a shear transform by the slopes x and y.
  126. func (a Affine) Shear(x, y float64) Affine {
  127. d := 1 - x*y
  128. return a.Mul(Affine{
  129. +1 / d, -x / d, 0,
  130. -y / d, +1 / d, 0,
  131. 0, 0, 1,
  132. })
  133. }
  134. // Translate produces a translation transform with pixel distances x and y.
  135. func (a Affine) Translate(x, y float64) Affine {
  136. return a.Mul(Affine{
  137. 1, 0, -x,
  138. 0, 1, -y,
  139. 0, 0, +1,
  140. })
  141. }
  142. // Center produces the affine transform, centered around the provided point.
  143. func (a Affine) Center(x, y float64) Affine {
  144. return I.Translate(-x, -y).Mul(a).Translate(x, y)
  145. }
  146. // CenterFit produces the affine transform, centered around the rectangles.
  147. // It is equivalent to
  148. // I.Translate(-<center of src>).Mul(a).Translate(<center of dst>)
  149. func (a Affine) CenterFit(dst, src image.Rectangle) Affine {
  150. dx := float64(dst.Min.X) + float64(dst.Dx())/2
  151. dy := float64(dst.Min.Y) + float64(dst.Dy())/2
  152. sx := float64(src.Min.X) + float64(src.Dx())/2
  153. sy := float64(src.Min.Y) + float64(src.Dy())/2
  154. return I.Translate(-sx, -sy).Mul(a).Translate(dx, dy)
  155. }