Skip to content

Commit 6f59993

Browse files
authored
Merge pull request #6 from DavidEsdrs/feat/blur
feat/blur
2 parents beaa858 + 7656688 commit 6f59993

File tree

5 files changed

+126
-0
lines changed

5 files changed

+126
-0
lines changed

configs/configs.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ type Config struct {
2828
TurnRight bool
2929
Crop string
3030
Overlay string
31+
BlurSize int
32+
Sigma float64
3133

3234
// Resize
3335
NearestNeighbor bool
@@ -182,6 +184,11 @@ func (config *Config) ParseConfig(logger logger.Logger, inputImg image.Image) (*
182184
f := filters.NewTurnRightFilter()
183185
invoker.AddProcess(f)
184186
}
187+
if config.BlurSize > 0 {
188+
logger.LogProcess("Adding blur")
189+
f, _ := filters.NewBlurFilter(logger, config.Sigma, config.BlurSize)
190+
invoker.AddProcess(f)
191+
}
185192

186193
return &invoker, nil
187194
}

filters/blur.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package filters
2+
3+
import (
4+
"image/color"
5+
6+
"github.com/DavidEsdrs/image-processing/logger"
7+
"github.com/DavidEsdrs/image-processing/utils"
8+
)
9+
10+
type BlurFilter struct {
11+
l logger.Logger
12+
sigma float64
13+
kernelSize int // this will define how blurry the image is
14+
kernel [][]float64
15+
}
16+
17+
func NewBlurFilter(l logger.Logger, sigma float64, kernelSize int) (BlurFilter, error) {
18+
kernel := utils.GaussianKernel(kernelSize, sigma)
19+
bf := BlurFilter{l: l, sigma: sigma, kernelSize: kernelSize, kernel: kernel}
20+
return bf, nil
21+
}
22+
23+
func (bf BlurFilter) Execute(tensor *[][]color.Color) error {
24+
height := len(*tensor)
25+
width := len((*tensor)[0])
26+
27+
copy := make([][]color.Color, height)
28+
for i := range copy {
29+
copy[i] = append(copy[i], (*tensor)[i]...)
30+
}
31+
32+
for y := 0; y < height; y++ {
33+
for x := 0; x < width; x++ {
34+
_, _, _, a := (*tensor)[y][x].RGBA()
35+
r, g, b := bf.getValuesForPixel(tensor, &copy, x, y)
36+
(*tensor)[y][x] = color.RGBA{
37+
R: r,
38+
G: g,
39+
B: b,
40+
A: uint8(a >> 8),
41+
}
42+
}
43+
}
44+
45+
return nil
46+
}
47+
48+
func (bf *BlurFilter) getValuesForPixel(tensor *[][]color.Color, copy *[][]color.Color, startX, startY int) (r, g, b uint8) {
49+
height := len(*tensor)
50+
width := len((*tensor)[0])
51+
52+
var rnew uint8
53+
var gnew uint8
54+
var bnew uint8
55+
56+
for y := startY; y < startY+bf.kernelSize && y < height; y++ {
57+
for x := startX; x < startX+bf.kernelSize && x < width; x++ {
58+
r, g, b, _ := (*copy)[y][x].RGBA()
59+
60+
rc := uint8(r >> 8)
61+
gc := uint8(g >> 8)
62+
bc := uint8(b >> 8)
63+
64+
w := bf.kernel[y-startY][x-startX]
65+
66+
convertedR := float64(rc) * w
67+
convertedG := float64(gc) * w
68+
convertedB := float64(bc) * w
69+
70+
rnew += uint8(convertedR)
71+
gnew += uint8(convertedG)
72+
bnew += uint8(convertedB)
73+
}
74+
}
75+
76+
return rnew, gnew, bnew
77+
}

main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ func setFlags(config *configs.Config, verbose *bool, help *bool) {
123123
flag.StringVar(&config.Crop, "c", "", "Crop image at given coordinates. Ex.: \"-c 0,1000,0,200\", xstart,xend,ystart,yend or \"-c 1000,200\", xend,yend (x and y start default to 0)")
124124
flag.IntVar(&config.Ssr, "ssr", 0, "Subsample ratio for images YCbCr. 444 = 4:4:4, 422 = 4:2:2, 420 = 4:2:0, 440 = 4:4:0, 411 = 4:1:1, 410 = 4:1:0")
125125
flag.IntVar(&config.Quality, "q", 0, "Quality of the JPEG image. 1-100")
126+
flag.IntVar(&config.BlurSize, "b", 0, "How blurry the image will be")
127+
flag.Float64Var(&config.Sigma, "s", 1.0, "Sigma value for blur")
126128

127129
// Resize
128130
flag.BoolVar(&config.NearestNeighbor, "nn", false, "Apply nearest neighbor resize algorithm")

utils/utils.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,31 @@ func ConvertIntoTensor(img image.Image) [][]color.Color {
123123

124124
return pixels
125125
}
126+
127+
func GaussianKernel(size int, sigma float64) [][]float64 {
128+
if size%2 == 0 {
129+
size++
130+
}
131+
132+
kernel := make([][]float64, size)
133+
center := size / 2
134+
sum := 0.0
135+
136+
for i := 0; i < size; i++ {
137+
kernel[i] = make([]float64, size)
138+
for j := 0; j < size; j++ {
139+
x := float64(j - center)
140+
y := float64(i - center)
141+
kernel[i][j] = math.Exp(-(x*x+y*y)/(2*sigma*sigma)) / (2 * math.Pi * sigma * sigma)
142+
sum += kernel[i][j]
143+
}
144+
}
145+
146+
for i := 0; i < size; i++ {
147+
for j := 0; j < size; j++ {
148+
kernel[i][j] /= sum
149+
}
150+
}
151+
152+
return kernel
153+
}

utils/utils_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package utils_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/DavidEsdrs/image-processing/utils"
7+
)
8+
9+
func TestGaussianKernel(t *testing.T) {
10+
res := utils.GaussianKernel(5, 1.0)
11+
t.Logf("%v", res)
12+
}

0 commit comments

Comments
 (0)