resize.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. package image
  2. import (
  3. "image"
  4. "image/color"
  5. )
  6. // average convert the sums to averages and returns the result.
  7. func average(sum []uint64, w, h int, n uint64) *image.RGBA {
  8. ret := image.NewRGBA(image.Rect(0, 0, w, h))
  9. for y := 0; y < h; y++ {
  10. for x := 0; x < w; x++ {
  11. index := 4 * (y*w + x)
  12. pix := ret.Pix[y*ret.Stride+x*4:]
  13. pix[0] = uint8(sum[index+0] / n)
  14. pix[1] = uint8(sum[index+1] / n)
  15. pix[2] = uint8(sum[index+2] / n)
  16. pix[3] = uint8(sum[index+3] / n)
  17. }
  18. }
  19. return ret
  20. }
  21. // ResizeRGBA returns a scaled copy of the RGBA image slice r of m.
  22. // The returned image has width w and height h.
  23. func ResizeRGBA(m *image.RGBA, r image.Rectangle, w, h int) *image.RGBA {
  24. ww, hh := uint64(w), uint64(h)
  25. dx, dy := uint64(r.Dx()), uint64(r.Dy())
  26. // See comment in Resize.
  27. n, sum := dx*dy, make([]uint64, 4*w*h)
  28. for y := r.Min.Y; y < r.Max.Y; y++ {
  29. pix := m.Pix[(y-r.Min.Y)*m.Stride:]
  30. for x := r.Min.X; x < r.Max.X; x++ {
  31. // Get the source pixel.
  32. p := pix[(x-r.Min.X)*4:]
  33. r64 := uint64(p[0])
  34. g64 := uint64(p[1])
  35. b64 := uint64(p[2])
  36. a64 := uint64(p[3])
  37. // Spread the source pixel over 1 or more destination rows.
  38. py := uint64(y) * hh
  39. for remy := hh; remy > 0; {
  40. qy := dy - (py % dy)
  41. if qy > remy {
  42. qy = remy
  43. }
  44. // Spread the source pixel over 1 or more destination columns.
  45. px := uint64(x) * ww
  46. index := 4 * ((py/dy)*ww + (px / dx))
  47. for remx := ww; remx > 0; {
  48. qx := dx - (px % dx)
  49. if qx > remx {
  50. qx = remx
  51. }
  52. qxy := qx * qy
  53. sum[index+0] += r64 * qxy
  54. sum[index+1] += g64 * qxy
  55. sum[index+2] += b64 * qxy
  56. sum[index+3] += a64 * qxy
  57. index += 4
  58. px += qx
  59. remx -= qx
  60. }
  61. py += qy
  62. remy -= qy
  63. }
  64. }
  65. }
  66. return average(sum, w, h, n)
  67. }
  68. // ResizeNRGBA returns a scaled copy of the RGBA image slice r of m.
  69. // The returned image has width w and height h.
  70. func ResizeNRGBA(m *image.NRGBA, r image.Rectangle, w, h int) *image.RGBA {
  71. ww, hh := uint64(w), uint64(h)
  72. dx, dy := uint64(r.Dx()), uint64(r.Dy())
  73. // See comment in Resize.
  74. n, sum := dx*dy, make([]uint64, 4*w*h)
  75. for y := r.Min.Y; y < r.Max.Y; y++ {
  76. pix := m.Pix[(y-r.Min.Y)*m.Stride:]
  77. for x := r.Min.X; x < r.Max.X; x++ {
  78. // Get the source pixel.
  79. p := pix[(x-r.Min.X)*4:]
  80. r64 := uint64(p[0])
  81. g64 := uint64(p[1])
  82. b64 := uint64(p[2])
  83. a64 := uint64(p[3])
  84. r64 = (r64 * a64) / 255
  85. g64 = (g64 * a64) / 255
  86. b64 = (b64 * a64) / 255
  87. // Spread the source pixel over 1 or more destination rows.
  88. py := uint64(y) * hh
  89. for remy := hh; remy > 0; {
  90. qy := dy - (py % dy)
  91. if qy > remy {
  92. qy = remy
  93. }
  94. // Spread the source pixel over 1 or more destination columns.
  95. px := uint64(x) * ww
  96. index := 4 * ((py/dy)*ww + (px / dx))
  97. for remx := ww; remx > 0; {
  98. qx := dx - (px % dx)
  99. if qx > remx {
  100. qx = remx
  101. }
  102. qxy := qx * qy
  103. sum[index+0] += r64 * qxy
  104. sum[index+1] += g64 * qxy
  105. sum[index+2] += b64 * qxy
  106. sum[index+3] += a64 * qxy
  107. index += 4
  108. px += qx
  109. remx -= qx
  110. }
  111. py += qy
  112. remy -= qy
  113. }
  114. }
  115. }
  116. return average(sum, w, h, n)
  117. }
  118. // Resample returns a resampled copy of the image slice r of m.
  119. // The returned image has width w and height h.
  120. func Resample(m image.Image, r image.Rectangle, w, h int) *image.RGBA {
  121. if w < 0 || h < 0 {
  122. return nil
  123. }
  124. if w == 0 || h == 0 || r.Dx() <= 0 || r.Dy() <= 0 {
  125. return image.NewRGBA(image.Rect(0, 0, w, h))
  126. }
  127. curw, curh := r.Dx(), r.Dy()
  128. img := image.NewRGBA(image.Rect(0, 0, w, h))
  129. for y := 0; y < h; y++ {
  130. for x := 0; x < w; x++ {
  131. // Get a source pixel.
  132. subx := x * curw / w
  133. suby := y * curh / h
  134. r32, g32, b32, a32 := m.At(subx, suby).RGBA()
  135. r := uint8(r32 >> 8)
  136. g := uint8(g32 >> 8)
  137. b := uint8(b32 >> 8)
  138. a := uint8(a32 >> 8)
  139. img.SetRGBA(x, y, color.RGBA{r, g, b, a})
  140. }
  141. }
  142. return img
  143. }