utils.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package imaging
  2. import (
  3. "image"
  4. "math"
  5. "runtime"
  6. "sync"
  7. "sync/atomic"
  8. )
  9. var maxProcs int64
  10. // SetMaxProcs limits the number of concurrent processing goroutines to the given value.
  11. // A value <= 0 clears the limit.
  12. func SetMaxProcs(value int) {
  13. atomic.StoreInt64(&maxProcs, int64(value))
  14. }
  15. // parallel processes the data in separate goroutines.
  16. func parallel(start, stop int, fn func(<-chan int)) {
  17. count := stop - start
  18. if count < 1 {
  19. return
  20. }
  21. procs := runtime.GOMAXPROCS(0)
  22. limit := int(atomic.LoadInt64(&maxProcs))
  23. if procs > limit && limit > 0 {
  24. procs = limit
  25. }
  26. if procs > count {
  27. procs = count
  28. }
  29. c := make(chan int, count)
  30. for i := start; i < stop; i++ {
  31. c <- i
  32. }
  33. close(c)
  34. var wg sync.WaitGroup
  35. for i := 0; i < procs; i++ {
  36. wg.Add(1)
  37. go func() {
  38. defer wg.Done()
  39. fn(c)
  40. }()
  41. }
  42. wg.Wait()
  43. }
  44. // absint returns the absolute value of i.
  45. func absint(i int) int {
  46. if i < 0 {
  47. return -i
  48. }
  49. return i
  50. }
  51. // clamp rounds and clamps float64 value to fit into uint8.
  52. func clamp(x float64) uint8 {
  53. v := int64(x + 0.5)
  54. if v > 255 {
  55. return 255
  56. }
  57. if v > 0 {
  58. return uint8(v)
  59. }
  60. return 0
  61. }
  62. func reverse(pix []uint8) {
  63. if len(pix) <= 4 {
  64. return
  65. }
  66. i := 0
  67. j := len(pix) - 4
  68. for i < j {
  69. pi := pix[i : i+4 : i+4]
  70. pj := pix[j : j+4 : j+4]
  71. pi[0], pj[0] = pj[0], pi[0]
  72. pi[1], pj[1] = pj[1], pi[1]
  73. pi[2], pj[2] = pj[2], pi[2]
  74. pi[3], pj[3] = pj[3], pi[3]
  75. i += 4
  76. j -= 4
  77. }
  78. }
  79. func toNRGBA(img image.Image) *image.NRGBA {
  80. if img, ok := img.(*image.NRGBA); ok {
  81. return &image.NRGBA{
  82. Pix: img.Pix,
  83. Stride: img.Stride,
  84. Rect: img.Rect.Sub(img.Rect.Min),
  85. }
  86. }
  87. return Clone(img)
  88. }
  89. // rgbToHSL converts a color from RGB to HSL.
  90. func rgbToHSL(r, g, b uint8) (float64, float64, float64) {
  91. rr := float64(r) / 255
  92. gg := float64(g) / 255
  93. bb := float64(b) / 255
  94. max := math.Max(rr, math.Max(gg, bb))
  95. min := math.Min(rr, math.Min(gg, bb))
  96. l := (max + min) / 2
  97. if max == min {
  98. return 0, 0, l
  99. }
  100. var h, s float64
  101. d := max - min
  102. if l > 0.5 {
  103. s = d / (2 - max - min)
  104. } else {
  105. s = d / (max + min)
  106. }
  107. switch max {
  108. case rr:
  109. h = (gg - bb) / d
  110. if g < b {
  111. h += 6
  112. }
  113. case gg:
  114. h = (bb-rr)/d + 2
  115. case bb:
  116. h = (rr-gg)/d + 4
  117. }
  118. h /= 6
  119. return h, s, l
  120. }
  121. // hslToRGB converts a color from HSL to RGB.
  122. func hslToRGB(h, s, l float64) (uint8, uint8, uint8) {
  123. var r, g, b float64
  124. if s == 0 {
  125. v := clamp(l * 255)
  126. return v, v, v
  127. }
  128. var q float64
  129. if l < 0.5 {
  130. q = l * (1 + s)
  131. } else {
  132. q = l + s - l*s
  133. }
  134. p := 2*l - q
  135. r = hueToRGB(p, q, h+1/3.0)
  136. g = hueToRGB(p, q, h)
  137. b = hueToRGB(p, q, h-1/3.0)
  138. return clamp(r * 255), clamp(g * 255), clamp(b * 255)
  139. }
  140. func hueToRGB(p, q, t float64) float64 {
  141. if t < 0 {
  142. t++
  143. }
  144. if t > 1 {
  145. t--
  146. }
  147. if t < 1/6.0 {
  148. return p + (q-p)*6*t
  149. }
  150. if t < 1/2.0 {
  151. return q
  152. }
  153. if t < 2/3.0 {
  154. return p + (q-p)*(2/3.0-t)*6
  155. }
  156. return p
  157. }