utils.go 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. package imaging
  2. import (
  3. "runtime"
  4. "sync"
  5. "sync/atomic"
  6. )
  7. // parallel starts parallel image processing based on the current GOMAXPROCS value.
  8. // If GOMAXPROCS = 1 it uses no parallelization.
  9. // If GOMAXPROCS > 1 it spawns N=GOMAXPROCS workers in separate goroutines.
  10. func parallel(dataSize int, fn func(partStart, partEnd int)) {
  11. numGoroutines := 1
  12. partSize := dataSize
  13. numProcs := runtime.GOMAXPROCS(0)
  14. if numProcs > 1 {
  15. numGoroutines = numProcs
  16. partSize = dataSize / (numGoroutines * 10)
  17. if partSize < 1 {
  18. partSize = 1
  19. }
  20. }
  21. if numGoroutines == 1 {
  22. fn(0, dataSize)
  23. } else {
  24. var wg sync.WaitGroup
  25. wg.Add(numGoroutines)
  26. idx := uint64(0)
  27. for p := 0; p < numGoroutines; p++ {
  28. go func() {
  29. defer wg.Done()
  30. for {
  31. partStart := int(atomic.AddUint64(&idx, uint64(partSize))) - partSize
  32. if partStart >= dataSize {
  33. break
  34. }
  35. partEnd := partStart + partSize
  36. if partEnd > dataSize {
  37. partEnd = dataSize
  38. }
  39. fn(partStart, partEnd)
  40. }
  41. }()
  42. }
  43. wg.Wait()
  44. }
  45. }
  46. // absint returns the absolute value of i.
  47. func absint(i int) int {
  48. if i < 0 {
  49. return -i
  50. }
  51. return i
  52. }
  53. // clamp rounds and clamps float64 value to fit into uint8.
  54. func clamp(x float64) uint8 {
  55. v := int64(x + 0.5)
  56. if v > 255 {
  57. return 255
  58. }
  59. if v > 0 {
  60. return uint8(v)
  61. }
  62. return 0
  63. }