Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gift.test
26 changes: 12 additions & 14 deletions convolution.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,6 @@ func (p *convolutionFilter) Draw(dst draw.Image, src image.Image, options *Optio
// )
// dst := image.NewRGBA(g.Bounds(src.Bounds()))
// g.Draw(dst, src)
//
func Convolution(kernel []float32, normalize, alpha, abs bool, delta float32) Filter {
return &convolutionFilter{
kernel: kernel,
Expand Down Expand Up @@ -286,12 +285,13 @@ func convolve1dv(dst draw.Image, src image.Image, kernel []float32, options *Opt
pixGetter := newPixelGetter(src)
pixSetter := newPixelSetter(dst)
parallelize(options.Parallelization, srcb.Min.X, srcb.Max.X, func(start, stop int) {
srcBuf := make([]pixel, srcb.Dy())
dstBuf := make([]pixel, srcb.Dy())
buf := getPixelBuf(srcb.Dy(), srcb.Dy())
defer putPixelBuf(buf)

for x := start; x < stop; x++ {
pixGetter.getPixelColumn(x, &srcBuf)
convolveLine(dstBuf, srcBuf, weights)
pixSetter.setPixelColumn(dstb.Min.X+x-srcb.Min.X, dstBuf)
pixGetter.getPixelColumn(x, &buf.src)
convolveLine(buf.dst, buf.src, weights)
pixSetter.setPixelColumn(dstb.Min.X+x-srcb.Min.X, buf.dst)
}
})
}
Expand All @@ -311,12 +311,13 @@ func convolve1dh(dst draw.Image, src image.Image, kernel []float32, options *Opt
pixGetter := newPixelGetter(src)
pixSetter := newPixelSetter(dst)
parallelize(options.Parallelization, srcb.Min.Y, srcb.Max.Y, func(start, stop int) {
srcBuf := make([]pixel, srcb.Dx())
dstBuf := make([]pixel, srcb.Dx())
buf := getPixelBuf(srcb.Dx(), srcb.Dx())
defer putPixelBuf(buf)

for y := start; y < stop; y++ {
pixGetter.getPixelRow(y, &srcBuf)
convolveLine(dstBuf, srcBuf, weights)
pixSetter.setPixelRow(dstb.Min.Y+y-srcb.Min.Y, dstBuf)
pixGetter.getPixelRow(y, &buf.src)
convolveLine(buf.dst, buf.src, weights)
pixSetter.setPixelRow(dstb.Min.Y+y-srcb.Min.Y, buf.dst)
}
})
}
Expand Down Expand Up @@ -384,7 +385,6 @@ func (p *gausssianBlurFilter) Draw(dst draw.Image, src image.Image, options *Opt
// )
// dst := image.NewRGBA(g.Bounds(src.Bounds()))
// g.Draw(dst, src)
//
func GaussianBlur(sigma float32) Filter {
return &gausssianBlurFilter{
sigma: sigma,
Expand Down Expand Up @@ -460,7 +460,6 @@ func (p *unsharpMaskFilter) Draw(dst draw.Image, src image.Image, options *Optio
// )
// dst := image.NewRGBA(g.Bounds(src.Bounds()))
// g.Draw(dst, src)
//
func UnsharpMask(sigma, amount, threshold float32) Filter {
return &unsharpMaskFilter{
sigma: sigma,
Expand Down Expand Up @@ -567,7 +566,6 @@ func (p *hvConvolutionFilter) Draw(dst draw.Image, src image.Image, options *Opt
}
}
})

}

// Sobel creates a filter that applies a sobel operator to an image.
Expand Down
2 changes: 0 additions & 2 deletions gift_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,6 @@ func TestDrawAt(t *testing.T) {
t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix)
}
}

}

type fakeDrawImage struct {
Expand Down Expand Up @@ -448,7 +447,6 @@ func TestSubImage(t *testing.T) {
}
}
}

}

func TestDraw(t *testing.T) {
Expand Down
34 changes: 34 additions & 0 deletions pixels.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ import (
"image"
"image/color"
"image/draw"
"sync"
)

type pixel struct {
r, g, b, a float32
}

type pixelSrcDst struct {
src []pixel
dst []pixel
}

type imageType int

const (
Expand Down Expand Up @@ -491,3 +497,31 @@ func (p *pixelSetter) setPixelColumn(x int, buf []pixel) {
p.setPixel(x, y, buf[i])
}
}

var pixelBufPool = &sync.Pool{
New: func() interface{} {
return &pixelSrcDst{
src: make([]pixel, 0),
dst: make([]pixel, 0),
}
},
}

func getPixelBuf(srcLen, dstLen int) *pixelSrcDst {
v := pixelBufPool.Get().(*pixelSrcDst)
if srcLen > cap(v.src) {
v.src = make([]pixel, srcLen)
}
if dstLen > cap(v.dst) {
v.dst = make([]pixel, dstLen)
}
v.src = v.src[:srcLen]
v.dst = v.dst[:dstLen]
return v
}

func putPixelBuf(buf *pixelSrcDst) {
buf.src = buf.src[:0]
buf.dst = buf.dst[:0]
pixelBufPool.Put(buf)
}
15 changes: 8 additions & 7 deletions rank.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ func (p *rankFilter) Draw(dst draw.Image, src image.Image, options *Options) {
pixSetter := newPixelSetter(dst)

parallelize(options.Parallelization, srcb.Min.Y, srcb.Max.Y, func(start, stop int) {
pxbuf := []pixel{}
buf := getPixelBuf(0, 0)
defer putPixelBuf(buf)

var rbuf, gbuf, bbuf, abuf []float32
if p.mode == rankMedian {
Expand All @@ -72,7 +73,7 @@ func (p *rankFilter) Draw(dst draw.Image, src image.Image, options *Options) {

for y := start; y < stop; y++ {
// Init buffer.
pxbuf = pxbuf[:0]
buf.src = buf.src[:0]
for i := srcb.Min.X - kradius; i <= srcb.Min.X+kradius; i++ {
for j := y - kradius; j <= y+kradius; j++ {
kx, ky := i, j
Expand All @@ -86,7 +87,7 @@ func (p *rankFilter) Draw(dst draw.Image, src image.Image, options *Options) {
} else if ky > srcb.Max.Y-1 {
ky = srcb.Max.Y - 1
}
pxbuf = append(pxbuf, pixGetter.getPixel(kx, ky))
buf.src = append(buf.src, pixGetter.getPixel(kx, ky))
}
}

Expand Down Expand Up @@ -115,7 +116,7 @@ func (p *rankFilter) Draw(dst draw.Image, src image.Image, options *Options) {
}
}

px := pxbuf[i*ksize+j]
px := buf.src[i*ksize+j]
if p.mode == rankMedian {
rbuf = append(rbuf, px.r)
gbuf = append(gbuf, px.g)
Expand Down Expand Up @@ -165,8 +166,8 @@ func (p *rankFilter) Draw(dst draw.Image, src image.Image, options *Options) {

// Rotate buffer columns.
if x < srcb.Max.X-1 {
copy(pxbuf[0:], pxbuf[ksize:])
pxbuf = pxbuf[0 : ksize*(ksize-1)]
copy(buf.src[0:], buf.src[ksize:])
buf.src = buf.src[0 : ksize*(ksize-1)]
kx := x + 1 + kradius
if kx > srcb.Max.X-1 {
kx = srcb.Max.X - 1
Expand All @@ -178,7 +179,7 @@ func (p *rankFilter) Draw(dst draw.Image, src image.Image, options *Options) {
} else if ky > srcb.Max.Y-1 {
ky = srcb.Max.Y - 1
}
pxbuf = append(pxbuf, pixGetter.getPixel(kx, ky))
buf.src = append(buf.src, pixGetter.getPixel(kx, ky))
}
}
}
Expand Down
23 changes: 12 additions & 11 deletions resize.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,13 @@ func resizeHorizontal(dst draw.Image, src image.Image, w int, resampling Resampl
pixSetter := newPixelSetter(dst)

parallelize(options.Parallelization, srcb.Min.Y, srcb.Max.Y, func(start, stop int) {
srcBuf := make([]pixel, srcb.Dx())
dstBuf := make([]pixel, w)
buf := getPixelBuf(srcb.Dx(), w)
defer putPixelBuf(buf)

for srcy := start; srcy < stop; srcy++ {
pixGetter.getPixelRow(srcy, &srcBuf)
resizeLine(dstBuf, srcBuf, weights)
pixSetter.setPixelRow(dstb.Min.Y+srcy-srcb.Min.Y, dstBuf)
pixGetter.getPixelRow(srcy, &buf.src)
resizeLine(buf.dst, buf.src, weights)
pixSetter.setPixelRow(dstb.Min.Y+srcy-srcb.Min.Y, buf.dst)
}
})
}
Expand All @@ -167,12 +168,13 @@ func resizeVertical(dst draw.Image, src image.Image, h int, resampling Resamplin
pixSetter := newPixelSetter(dst)

parallelize(options.Parallelization, srcb.Min.X, srcb.Max.X, func(start, stop int) {
srcBuf := make([]pixel, srcb.Dy())
dstBuf := make([]pixel, h)
buf := getPixelBuf(srcb.Dy(), h)
defer putPixelBuf(buf)

for srcx := start; srcx < stop; srcx++ {
pixGetter.getPixelColumn(srcx, &srcBuf)
resizeLine(dstBuf, srcBuf, weights)
pixSetter.setPixelColumn(dstb.Min.X+srcx-srcb.Min.X, dstBuf)
pixGetter.getPixelColumn(srcx, &buf.src)
resizeLine(buf.dst, buf.src, weights)
pixSetter.setPixelColumn(dstb.Min.X+srcx-srcb.Min.X, buf.dst)
}
})
}
Expand Down Expand Up @@ -276,7 +278,6 @@ func (p *resizeFilter) Draw(dst draw.Image, src image.Image, options *Options) {
// )
// dst := image.NewRGBA(g.Bounds(src.Bounds()))
// g.Draw(dst, src)
//
func Resize(width, height int, resampling Resampling) Filter {
return &resizeFilter{
width: width,
Expand Down