123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- package drawimg
- import (
- "image"
- "image/color"
- "math"
- )
- func gaussianBlurKernel(x, sigma float64) float64 {
- return math.Exp(-(x*x)/(2*sigma*sigma)) / (sigma * math.Sqrt(2*math.Pi))
- }
- func blurHorizontal(src *image.NRGBA, kernel []float64) *image.NRGBA {
- radius := len(kernel) - 1
- width := src.Bounds().Max.X
- height := src.Bounds().Max.Y
- dst := image.NewNRGBA(image.Rect(0, 0, width, height))
- parallel(width, func(partStart, partEnd int) {
- for x := partStart; x < partEnd; x++ {
- start := x - radius
- if start < 0 {
- start = 0
- }
- end := x + radius
- if end > width-1 {
- end = width - 1
- }
- weightSum := 0.0
- for ix := start; ix <= end; ix++ {
- weightSum += kernel[absint(x-ix)]
- }
- for y := 0; y < height; y++ {
- var r, g, b, a float64
- for ix := start; ix <= end; ix++ {
- weight := kernel[absint(x-ix)]
- i := y*src.Stride + ix*4
- wa := float64(src.Pix[i+3]) * weight
- r += float64(src.Pix[i+0]) * wa
- g += float64(src.Pix[i+1]) * wa
- b += float64(src.Pix[i+2]) * wa
- a += wa
- }
- j := y*dst.Stride + x*4
- dst.Pix[j+0] = clamp(r / a)
- dst.Pix[j+1] = clamp(g / a)
- dst.Pix[j+2] = clamp(b / a)
- dst.Pix[j+3] = clamp(a / weightSum)
- }
- }
- })
- return dst
- }
- func blurVertical(src *image.NRGBA, kernel []float64) *image.NRGBA {
- radius := len(kernel) - 1
- width := src.Bounds().Max.X
- height := src.Bounds().Max.Y
- dst := image.NewNRGBA(image.Rect(0, 0, width, height))
- parallel(height, func(partStart, partEnd int) {
- for y := partStart; y < partEnd; y++ {
- start := y - radius
- if start < 0 {
- start = 0
- }
- end := y + radius
- if end > height-1 {
- end = height - 1
- }
- weightSum := 0.0
- for iy := start; iy <= end; iy++ {
- weightSum += kernel[absint(y-iy)]
- }
- for x := 0; x < width; x++ {
- var r, g, b, a float64
- for iy := start; iy <= end; iy++ {
- weight := kernel[absint(y-iy)]
- i := iy*src.Stride + x*4
- wa := float64(src.Pix[i+3]) * weight
- r += float64(src.Pix[i+0]) * wa
- g += float64(src.Pix[i+1]) * wa
- b += float64(src.Pix[i+2]) * wa
- a += wa
- }
- j := y*dst.Stride + x*4
- dst.Pix[j+0] = clamp(r / a)
- dst.Pix[j+1] = clamp(g / a)
- dst.Pix[j+2] = clamp(b / a)
- dst.Pix[j+3] = clamp(a / weightSum)
- }
- }
- })
- return dst
- }
- // Sharpen produces a sharpened version of the image.
- func Sharpen(img image.Image, radius int, sigma float64) *image.NRGBA {
- if sigma <= 0 {
- // sigma parameter must be positive!
- return Clone(img)
- }
- src := toNRGBA(img)
- blurred := Blur(img, radius, sigma)
- width := src.Bounds().Max.X
- height := src.Bounds().Max.Y
- dst := image.NewNRGBA(image.Rect(0, 0, width, height))
- parallel(height, func(partStart, partEnd int) {
- for y := partStart; y < partEnd; y++ {
- for x := 0; x < width; x++ {
- i := y*src.Stride + x*4
- for j := 0; j < 4; j++ {
- k := i + j
- val := int(src.Pix[k])<<1 - int(blurred.Pix[k])
- if val < 0 {
- val = 0
- } else if val > 255 {
- val = 255
- }
- dst.Pix[k] = uint8(val)
- }
- }
- }
- })
- return dst
- }
- // Blur produces a blurred version of the image using a Gaussian function.
- func Blur(img image.Image, radius int, sigma float64) *image.NRGBA {
- var dst *image.NRGBA
- if sigma <= 0 {
- // sigma parameter must be positive!
- return Clone(img)
- }
- src := toNRGBA(img)
- kernel := make([]float64, radius+1)
- for i := 0; i <= radius; i++ {
- kernel[i] = gaussianBlurKernel(float64(i), sigma)
- }
- dst = blurHorizontal(src, kernel)
- dst = blurVertical(dst, kernel)
- return dst
- }
- // IsTooBright assume that average brightness higher than 100 is too bright.
- func IsTooBright(img image.Image) bool {
- var (
- pixCount, totalBrightness float64
- )
- pixCount = 0
- totalBrightness = 0
- AdjustFunc(img, func(c color.NRGBA) color.NRGBA {
- brightness := 0.2126*float64(c.R) + 0.7152*float64(c.G) + 0.0722*float64(c.B)
- totalBrightness += brightness
- pixCount++
- return c
- })
- averBrightness := totalBrightness / pixCount
- return averBrightness > 100
- }
|