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