mirror of https://github.com/status-im/resize.git
Fix wrong boundary calculation (bug #17)
This fix doesn't currently work concurrently. This will be fixed in another commit.
This commit is contained in:
parent
03982f698d
commit
e950449c49
122
converter.go
122
converter.go
|
@ -41,28 +41,26 @@ func clampUint16(in int64) uint16 {
|
|||
}
|
||||
|
||||
func resizeGeneric(in image.Image, out *image.RGBA64, scale float64, coeffs []int32, offset []int, filterLength int) {
|
||||
oldBounds := image.Rect(0, 0, in.Bounds().Dx(), in.Bounds().Dy())
|
||||
newBounds := out.Bounds()
|
||||
maxX := in.Bounds().Dx() - 1
|
||||
|
||||
for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
|
||||
for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
|
||||
var rgba [4]int64
|
||||
var sum int64
|
||||
start := offset[y]
|
||||
start := offset[y-newBounds.Min.Y]
|
||||
ci := (y - newBounds.Min.Y) * filterLength
|
||||
for i := 0; i < filterLength; i++ {
|
||||
coeff := coeffs[ci+i]
|
||||
if coeff != 0 {
|
||||
xi := start + i
|
||||
switch {
|
||||
case uint(xi) < uint(oldBounds.Max.X):
|
||||
break
|
||||
case xi >= oldBounds.Max.X:
|
||||
xi = oldBounds.Min.X
|
||||
default:
|
||||
xi = oldBounds.Max.X - 1
|
||||
case xi < 0:
|
||||
xi = 0
|
||||
case xi >= maxX:
|
||||
xi = maxX
|
||||
}
|
||||
r, g, b, a := in.At(xi, x).RGBA()
|
||||
r, g, b, a := in.At(xi+in.Bounds().Min.X, x+in.Bounds().Min.Y).RGBA()
|
||||
rgba[0] += int64(coeff) * int64(r)
|
||||
rgba[1] += int64(coeff) * int64(g)
|
||||
rgba[2] += int64(coeff) * int64(b)
|
||||
|
@ -89,29 +87,27 @@ func resizeGeneric(in image.Image, out *image.RGBA64, scale float64, coeffs []in
|
|||
}
|
||||
|
||||
func resizeRGBA(in *image.RGBA, out *image.RGBA, scale float64, coeffs []int16, offset []int, filterLength int) {
|
||||
oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
|
||||
newBounds := out.Bounds()
|
||||
minX := oldBounds.Min.X * 4
|
||||
maxX := (oldBounds.Max.X - oldBounds.Min.X - 1) * 4
|
||||
maxX := in.Bounds().Dx() - 1
|
||||
|
||||
for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
|
||||
row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
|
||||
row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
|
||||
for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
|
||||
var rgba [4]int32
|
||||
var sum int32
|
||||
start := offset[y]
|
||||
start := offset[y-newBounds.Min.Y]
|
||||
ci := (y - newBounds.Min.Y) * filterLength
|
||||
for i := 0; i < filterLength; i++ {
|
||||
coeff := coeffs[ci+i]
|
||||
if coeff != 0 {
|
||||
xi := start + i
|
||||
switch {
|
||||
case uint(xi) < uint(oldBounds.Max.X):
|
||||
xi *= 4
|
||||
case xi >= oldBounds.Max.X:
|
||||
xi = maxX
|
||||
case xi < 0:
|
||||
xi = 0
|
||||
case xi >= maxX:
|
||||
xi = 4 * maxX
|
||||
default:
|
||||
xi = minX
|
||||
xi *= 4
|
||||
}
|
||||
rgba[0] += int32(coeff) * int32(row[xi+0])
|
||||
rgba[1] += int32(coeff) * int32(row[xi+1])
|
||||
|
@ -131,29 +127,27 @@ func resizeRGBA(in *image.RGBA, out *image.RGBA, scale float64, coeffs []int16,
|
|||
}
|
||||
|
||||
func resizeRGBA64(in *image.RGBA64, out *image.RGBA64, scale float64, coeffs []int32, offset []int, filterLength int) {
|
||||
oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
|
||||
newBounds := out.Bounds()
|
||||
minX := oldBounds.Min.X * 8
|
||||
maxX := (oldBounds.Max.X - oldBounds.Min.X - 1) * 8
|
||||
maxX := in.Bounds().Dx() - 1
|
||||
|
||||
for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
|
||||
row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
|
||||
row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
|
||||
for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
|
||||
var rgba [4]int64
|
||||
var sum int64
|
||||
start := offset[y]
|
||||
start := offset[y-newBounds.Min.Y]
|
||||
ci := (y - newBounds.Min.Y) * filterLength
|
||||
for i := 0; i < filterLength; i++ {
|
||||
coeff := coeffs[ci+i]
|
||||
if coeff != 0 {
|
||||
xi := start + i
|
||||
switch {
|
||||
case uint(xi) < uint(oldBounds.Max.X):
|
||||
xi *= 8
|
||||
case xi >= oldBounds.Max.X:
|
||||
xi = maxX
|
||||
case xi < 0:
|
||||
xi = 0
|
||||
case xi >= maxX:
|
||||
xi = 8 * maxX
|
||||
default:
|
||||
xi = minX
|
||||
xi *= 8
|
||||
}
|
||||
rgba[0] += int64(coeff) * int64(uint16(row[xi+0])<<8|uint16(row[xi+1]))
|
||||
rgba[1] += int64(coeff) * int64(uint16(row[xi+2])<<8|uint16(row[xi+3]))
|
||||
|
@ -181,29 +175,25 @@ func resizeRGBA64(in *image.RGBA64, out *image.RGBA64, scale float64, coeffs []i
|
|||
}
|
||||
|
||||
func resizeGray(in *image.Gray, out *image.Gray, scale float64, coeffs []int16, offset []int, filterLength int) {
|
||||
oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
|
||||
newBounds := out.Bounds()
|
||||
minX := oldBounds.Min.X
|
||||
maxX := (oldBounds.Max.X - oldBounds.Min.X - 1)
|
||||
maxX := in.Bounds().Dx() - 1
|
||||
|
||||
for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
|
||||
row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
|
||||
row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
|
||||
for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
|
||||
var gray int32
|
||||
var sum int32
|
||||
start := offset[y]
|
||||
start := offset[y-newBounds.Min.Y]
|
||||
ci := (y - newBounds.Min.Y) * filterLength
|
||||
for i := 0; i < filterLength; i++ {
|
||||
coeff := coeffs[ci+i]
|
||||
if coeff != 0 {
|
||||
xi := start + i
|
||||
switch {
|
||||
case uint(xi) < uint(oldBounds.Max.X):
|
||||
break
|
||||
case xi >= oldBounds.Max.X:
|
||||
case xi < 0:
|
||||
xi = 0
|
||||
case xi >= maxX:
|
||||
xi = maxX
|
||||
default:
|
||||
xi = minX
|
||||
}
|
||||
gray += int32(coeff) * int32(row[xi])
|
||||
sum += int32(coeff)
|
||||
|
@ -217,29 +207,27 @@ func resizeGray(in *image.Gray, out *image.Gray, scale float64, coeffs []int16,
|
|||
}
|
||||
|
||||
func resizeGray16(in *image.Gray16, out *image.Gray16, scale float64, coeffs []int32, offset []int, filterLength int) {
|
||||
oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
|
||||
newBounds := out.Bounds()
|
||||
minX := oldBounds.Min.X * 2
|
||||
maxX := (oldBounds.Max.X - oldBounds.Min.X - 1) * 2
|
||||
maxX := in.Bounds().Dx() - 1
|
||||
|
||||
for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
|
||||
row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
|
||||
row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
|
||||
for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
|
||||
var gray int64
|
||||
var sum int64
|
||||
start := offset[y]
|
||||
start := offset[y-newBounds.Min.Y]
|
||||
ci := (y - newBounds.Min.Y) * filterLength
|
||||
for i := 0; i < filterLength; i++ {
|
||||
coeff := coeffs[ci+i]
|
||||
if coeff != 0 {
|
||||
xi := start + i
|
||||
switch {
|
||||
case uint(xi) < uint(oldBounds.Max.X):
|
||||
xi *= 2
|
||||
case xi >= oldBounds.Max.X:
|
||||
xi = maxX
|
||||
case xi < 0:
|
||||
xi = 0
|
||||
case xi >= maxX:
|
||||
xi = 2 * maxX
|
||||
default:
|
||||
xi = minX
|
||||
xi *= 2
|
||||
}
|
||||
gray += int64(coeff) * int64(uint16(row[xi+0])<<8|uint16(row[xi+1]))
|
||||
sum += int64(coeff)
|
||||
|
@ -255,29 +243,27 @@ func resizeGray16(in *image.Gray16, out *image.Gray16, scale float64, coeffs []i
|
|||
}
|
||||
|
||||
func resizeYCbCr(in *ycc, out *ycc, scale float64, coeffs []int16, offset []int, filterLength int) {
|
||||
oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
|
||||
newBounds := out.Bounds()
|
||||
minX := oldBounds.Min.X * 3
|
||||
maxX := (oldBounds.Max.X - oldBounds.Min.X - 1) * 3
|
||||
maxX := in.Bounds().Dx() - 1
|
||||
|
||||
for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
|
||||
row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
|
||||
row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
|
||||
for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
|
||||
var p [3]int32
|
||||
var sum int32
|
||||
start := offset[y]
|
||||
start := offset[y-newBounds.Min.Y]
|
||||
ci := (y - newBounds.Min.Y) * filterLength
|
||||
for i := 0; i < filterLength; i++ {
|
||||
coeff := coeffs[ci+i]
|
||||
if coeff != 0 {
|
||||
xi := start + i
|
||||
switch {
|
||||
case uint(xi) < uint(oldBounds.Max.X):
|
||||
xi *= 3
|
||||
case xi >= oldBounds.Max.X:
|
||||
xi = maxX
|
||||
case xi < 0:
|
||||
xi = 0
|
||||
case xi >= maxX:
|
||||
xi = 3 * maxX
|
||||
default:
|
||||
xi = minX
|
||||
xi *= 3
|
||||
}
|
||||
p[0] += int32(coeff) * int32(row[xi+0])
|
||||
p[1] += int32(coeff) * int32(row[xi+1])
|
||||
|
@ -295,28 +281,26 @@ func resizeYCbCr(in *ycc, out *ycc, scale float64, coeffs []int16, offset []int,
|
|||
}
|
||||
|
||||
func nearestYCbCr(in *ycc, out *ycc, scale float64, coeffs []bool, offset []int, filterLength int) {
|
||||
oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
|
||||
newBounds := out.Bounds()
|
||||
minX := oldBounds.Min.X * 3
|
||||
maxX := (oldBounds.Max.X - oldBounds.Min.X - 1) * 3
|
||||
maxX := in.Bounds().Dx() - 1
|
||||
|
||||
for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
|
||||
row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
|
||||
row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
|
||||
for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
|
||||
var p [3]float32
|
||||
var sum float32
|
||||
start := offset[y]
|
||||
start := offset[y-newBounds.Min.Y]
|
||||
ci := (y - newBounds.Min.Y) * filterLength
|
||||
for i := 0; i < filterLength; i++ {
|
||||
if coeffs[ci+i] {
|
||||
xi := start + i
|
||||
switch {
|
||||
case uint(xi) < uint(oldBounds.Max.X):
|
||||
xi *= 3
|
||||
case xi >= oldBounds.Max.X:
|
||||
xi = maxX
|
||||
case xi < 0:
|
||||
xi = 0
|
||||
case xi >= maxX:
|
||||
xi = 3 * maxX
|
||||
default:
|
||||
xi = minX
|
||||
xi *= 3
|
||||
}
|
||||
p[0] += float32(row[xi+0])
|
||||
p[1] += float32(row[xi+1])
|
||||
|
|
12
filters.go
12
filters.go
|
@ -80,14 +80,14 @@ func lanczos3(in float64) float64 {
|
|||
}
|
||||
|
||||
// range [-256,256]
|
||||
func createWeights8(dy, minx, filterLength int, blur, scale float64, kernel func(float64) float64) ([]int16, []int, int) {
|
||||
func createWeights8(dy, filterLength int, blur, scale float64, kernel func(float64) float64) ([]int16, []int, int) {
|
||||
filterLength = filterLength * int(math.Max(math.Ceil(blur*scale), 1))
|
||||
filterFactor := math.Min(1./(blur*scale), 1)
|
||||
|
||||
coeffs := make([]int16, dy*filterLength)
|
||||
start := make([]int, dy)
|
||||
for y := 0; y < dy; y++ {
|
||||
interpX := scale*(float64(y)+0.5) + float64(minx)
|
||||
interpX := scale * (float64(y) + 0.5)
|
||||
start[y] = int(interpX) - filterLength/2 + 1
|
||||
interpX -= float64(start[y])
|
||||
for i := 0; i < filterLength; i++ {
|
||||
|
@ -100,14 +100,14 @@ func createWeights8(dy, minx, filterLength int, blur, scale float64, kernel func
|
|||
}
|
||||
|
||||
// range [-65536,65536]
|
||||
func createWeights16(dy, minx, filterLength int, blur, scale float64, kernel func(float64) float64) ([]int32, []int, int) {
|
||||
func createWeights16(dy, filterLength int, blur, scale float64, kernel func(float64) float64) ([]int32, []int, int) {
|
||||
filterLength = filterLength * int(math.Max(math.Ceil(blur*scale), 1))
|
||||
filterFactor := math.Min(1./(blur*scale), 1)
|
||||
|
||||
coeffs := make([]int32, dy*filterLength)
|
||||
start := make([]int, dy)
|
||||
for y := 0; y < dy; y++ {
|
||||
interpX := scale*(float64(y)+0.5) + float64(minx)
|
||||
interpX := scale * (float64(y) + 0.5)
|
||||
start[y] = int(interpX) - filterLength/2 + 1
|
||||
interpX -= float64(start[y])
|
||||
for i := 0; i < filterLength; i++ {
|
||||
|
@ -119,14 +119,14 @@ func createWeights16(dy, minx, filterLength int, blur, scale float64, kernel fun
|
|||
return coeffs, start, filterLength
|
||||
}
|
||||
|
||||
func createWeightsNearest(dy, minx, filterLength int, blur, scale float64) ([]bool, []int, int) {
|
||||
func createWeightsNearest(dy, filterLength int, blur, scale float64) ([]bool, []int, int) {
|
||||
filterLength = filterLength * int(math.Max(math.Ceil(blur*scale), 1))
|
||||
filterFactor := math.Min(1./(blur*scale), 1)
|
||||
|
||||
coeffs := make([]bool, dy*filterLength)
|
||||
start := make([]int, dy)
|
||||
for y := 0; y < dy; y++ {
|
||||
interpX := scale*(float64(y)+0.5) + float64(minx)
|
||||
interpX := scale * (float64(y) + 0.5)
|
||||
start[y] = int(interpX) - filterLength/2 + 1
|
||||
interpX -= float64(start[y])
|
||||
for i := 0; i < filterLength; i++ {
|
||||
|
|
86
nearest.go
86
nearest.go
|
@ -35,27 +35,25 @@ func floatToUint16(x float32) uint16 {
|
|||
}
|
||||
|
||||
func nearestGeneric(in image.Image, out *image.RGBA64, scale float64, coeffs []bool, offset []int, filterLength int) {
|
||||
oldBounds := image.Rect(0, 0, in.Bounds().Dx(), in.Bounds().Dy())
|
||||
newBounds := out.Bounds()
|
||||
maxX := in.Bounds().Dx() - 1
|
||||
|
||||
for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
|
||||
for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
|
||||
var rgba [4]float32
|
||||
var sum float32
|
||||
start := offset[y]
|
||||
start := offset[y-newBounds.Min.Y]
|
||||
ci := (y - newBounds.Min.Y) * filterLength
|
||||
for i := 0; i < filterLength; i++ {
|
||||
if coeffs[ci+i] {
|
||||
xi := start + i
|
||||
switch {
|
||||
case uint(xi) < uint(oldBounds.Max.X):
|
||||
break
|
||||
case xi >= oldBounds.Max.X:
|
||||
xi = oldBounds.Min.X
|
||||
default:
|
||||
xi = oldBounds.Max.X - 1
|
||||
case xi < 0:
|
||||
xi = 0
|
||||
case xi >= maxX:
|
||||
xi = maxX
|
||||
}
|
||||
r, g, b, a := in.At(xi, x).RGBA()
|
||||
r, g, b, a := in.At(xi+in.Bounds().Min.X, x+in.Bounds().Min.Y).RGBA()
|
||||
rgba[0] += float32(r)
|
||||
rgba[1] += float32(g)
|
||||
rgba[2] += float32(b)
|
||||
|
@ -82,28 +80,26 @@ func nearestGeneric(in image.Image, out *image.RGBA64, scale float64, coeffs []b
|
|||
}
|
||||
|
||||
func nearestRGBA(in *image.RGBA, out *image.RGBA, scale float64, coeffs []bool, offset []int, filterLength int) {
|
||||
oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
|
||||
newBounds := out.Bounds()
|
||||
minX := oldBounds.Min.X * 4
|
||||
maxX := (oldBounds.Max.X - oldBounds.Min.X - 1) * 4
|
||||
maxX := in.Bounds().Dx() - 1
|
||||
|
||||
for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
|
||||
row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
|
||||
row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
|
||||
for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
|
||||
var rgba [4]float32
|
||||
var sum float32
|
||||
start := offset[y]
|
||||
start := offset[y-newBounds.Min.Y]
|
||||
ci := (y - newBounds.Min.Y) * filterLength
|
||||
for i := 0; i < filterLength; i++ {
|
||||
if coeffs[ci+i] {
|
||||
xi := start + i
|
||||
switch {
|
||||
case uint(xi) < uint(oldBounds.Max.X):
|
||||
xi *= 4
|
||||
case xi >= oldBounds.Max.X:
|
||||
xi = maxX
|
||||
case xi < 0:
|
||||
xi = 0
|
||||
case xi >= maxX:
|
||||
xi = 4 * maxX
|
||||
default:
|
||||
xi = minX
|
||||
xi *= 4
|
||||
}
|
||||
rgba[0] += float32(row[xi+0])
|
||||
rgba[1] += float32(row[xi+1])
|
||||
|
@ -123,28 +119,26 @@ func nearestRGBA(in *image.RGBA, out *image.RGBA, scale float64, coeffs []bool,
|
|||
}
|
||||
|
||||
func nearestRGBA64(in *image.RGBA64, out *image.RGBA64, scale float64, coeffs []bool, offset []int, filterLength int) {
|
||||
oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
|
||||
newBounds := out.Bounds()
|
||||
minX := oldBounds.Min.X * 8
|
||||
maxX := (oldBounds.Max.X - oldBounds.Min.X - 1) * 8
|
||||
maxX := in.Bounds().Dx() - 1
|
||||
|
||||
for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
|
||||
row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
|
||||
row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
|
||||
for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
|
||||
var rgba [4]float32
|
||||
var sum float32
|
||||
start := offset[y]
|
||||
start := offset[y-newBounds.Min.Y]
|
||||
ci := (y - newBounds.Min.Y) * filterLength
|
||||
for i := 0; i < filterLength; i++ {
|
||||
if coeffs[ci+i] {
|
||||
xi := start + i
|
||||
switch {
|
||||
case uint(xi) < uint(oldBounds.Max.X):
|
||||
xi *= 8
|
||||
case xi >= oldBounds.Max.X:
|
||||
xi = maxX
|
||||
case xi < 0:
|
||||
xi = 0
|
||||
case xi >= maxX:
|
||||
xi = 8 * maxX
|
||||
default:
|
||||
xi = minX
|
||||
xi *= 8
|
||||
}
|
||||
rgba[0] += float32(uint16(row[xi+0])<<8 | uint16(row[xi+1]))
|
||||
rgba[1] += float32(uint16(row[xi+2])<<8 | uint16(row[xi+3]))
|
||||
|
@ -172,28 +166,24 @@ func nearestRGBA64(in *image.RGBA64, out *image.RGBA64, scale float64, coeffs []
|
|||
}
|
||||
|
||||
func nearestGray(in *image.Gray, out *image.Gray, scale float64, coeffs []bool, offset []int, filterLength int) {
|
||||
oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
|
||||
newBounds := out.Bounds()
|
||||
minX := oldBounds.Min.X
|
||||
maxX := (oldBounds.Max.X - oldBounds.Min.X - 1)
|
||||
maxX := in.Bounds().Dx() - 1
|
||||
|
||||
for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
|
||||
row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
|
||||
row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
|
||||
for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
|
||||
var gray float32
|
||||
var sum float32
|
||||
start := offset[y]
|
||||
start := offset[y-newBounds.Min.Y]
|
||||
ci := (y - newBounds.Min.Y) * filterLength
|
||||
for i := 0; i < filterLength; i++ {
|
||||
if coeffs[ci+i] {
|
||||
xi := start + i
|
||||
switch {
|
||||
case uint(xi) < uint(oldBounds.Max.X):
|
||||
break
|
||||
case xi >= oldBounds.Max.X:
|
||||
case xi < 0:
|
||||
xi = 0
|
||||
case xi >= maxX:
|
||||
xi = maxX
|
||||
default:
|
||||
xi = minX
|
||||
}
|
||||
gray += float32(row[xi])
|
||||
sum++
|
||||
|
@ -207,28 +197,26 @@ func nearestGray(in *image.Gray, out *image.Gray, scale float64, coeffs []bool,
|
|||
}
|
||||
|
||||
func nearestGray16(in *image.Gray16, out *image.Gray16, scale float64, coeffs []bool, offset []int, filterLength int) {
|
||||
oldBounds := image.Rect(0, 0, in.Rect.Dx(), in.Rect.Dy())
|
||||
newBounds := out.Bounds()
|
||||
minX := oldBounds.Min.X * 2
|
||||
maxX := (oldBounds.Max.X - oldBounds.Min.X - 1) * 2
|
||||
maxX := in.Bounds().Dx() - 1
|
||||
|
||||
for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
|
||||
row := in.Pix[(x-oldBounds.Min.Y)*in.Stride:]
|
||||
row := in.Pix[(x-newBounds.Min.X)*in.Stride:]
|
||||
for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
|
||||
var gray float32
|
||||
var sum float32
|
||||
start := offset[y]
|
||||
start := offset[y-newBounds.Min.Y]
|
||||
ci := (y - newBounds.Min.Y) * filterLength
|
||||
for i := 0; i < filterLength; i++ {
|
||||
if coeffs[ci+i] {
|
||||
xi := start + i
|
||||
switch {
|
||||
case uint(xi) < uint(oldBounds.Max.X):
|
||||
xi *= 2
|
||||
case xi >= oldBounds.Max.X:
|
||||
xi = maxX
|
||||
case xi < 0:
|
||||
xi = 0
|
||||
case xi >= maxX:
|
||||
xi = 2 * maxX
|
||||
default:
|
||||
xi = minX
|
||||
xi *= 2
|
||||
}
|
||||
gray += float32(uint16(row[xi+0])<<8 | uint16(row[xi+1]))
|
||||
sum++
|
||||
|
|
50
resize.go
50
resize.go
|
@ -91,7 +91,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
|
|||
}
|
||||
|
||||
taps, kernel := interp.kernel()
|
||||
cpus := runtime.NumCPU()
|
||||
cpus := 1 //runtime.NumCPU() TODO
|
||||
wg := sync.WaitGroup{}
|
||||
|
||||
// Generic access to image.Image is slow in tight loops.
|
||||
|
@ -103,7 +103,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
|
|||
result := image.NewRGBA(image.Rect(0, 0, int(width), int(height)))
|
||||
|
||||
// horizontal filter, results in transposed temporary image
|
||||
coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX, kernel)
|
||||
coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(temp, i, cpus).(*image.RGBA)
|
||||
|
@ -115,7 +115,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
|
|||
wg.Wait()
|
||||
|
||||
// horizontal filter on transposed image, result is not transposed
|
||||
coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY, kernel)
|
||||
coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), taps, blur, scaleY, kernel)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(result, i, cpus).(*image.RGBA)
|
||||
|
@ -133,7 +133,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
|
|||
temp := newYCC(image.Rect(0, 0, input.Bounds().Dy(), int(width)), input.SubsampleRatio)
|
||||
result := newYCC(image.Rect(0, 0, int(width), int(height)), input.SubsampleRatio)
|
||||
|
||||
coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX, kernel)
|
||||
coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
|
||||
in := imageYCbCrToYCC(input)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
|
@ -145,7 +145,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
|
|||
}
|
||||
wg.Wait()
|
||||
|
||||
coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY, kernel)
|
||||
coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), taps, blur, scaleY, kernel)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(result, i, cpus).(*ycc)
|
||||
|
@ -162,7 +162,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
|
|||
result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height)))
|
||||
|
||||
// horizontal filter, results in transposed temporary image
|
||||
coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX, kernel)
|
||||
coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(temp, i, cpus).(*image.RGBA64)
|
||||
|
@ -174,7 +174,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
|
|||
wg.Wait()
|
||||
|
||||
// horizontal filter on transposed image, result is not transposed
|
||||
coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY, kernel)
|
||||
coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), taps, blur, scaleY, kernel)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(result, i, cpus).(*image.RGBA64)
|
||||
|
@ -191,7 +191,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
|
|||
result := image.NewGray(image.Rect(0, 0, int(width), int(height)))
|
||||
|
||||
// horizontal filter, results in transposed temporary image
|
||||
coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX, kernel)
|
||||
coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(temp, i, cpus).(*image.Gray)
|
||||
|
@ -203,7 +203,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
|
|||
wg.Wait()
|
||||
|
||||
// horizontal filter on transposed image, result is not transposed
|
||||
coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY, kernel)
|
||||
coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), taps, blur, scaleY, kernel)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(result, i, cpus).(*image.Gray)
|
||||
|
@ -220,7 +220,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
|
|||
result := image.NewGray16(image.Rect(0, 0, int(width), int(height)))
|
||||
|
||||
// horizontal filter, results in transposed temporary image
|
||||
coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX, kernel)
|
||||
coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(temp, i, cpus).(*image.Gray16)
|
||||
|
@ -232,7 +232,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
|
|||
wg.Wait()
|
||||
|
||||
// horizontal filter on transposed image, result is not transposed
|
||||
coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY, kernel)
|
||||
coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), taps, blur, scaleY, kernel)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(result, i, cpus).(*image.Gray16)
|
||||
|
@ -249,7 +249,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
|
|||
result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height)))
|
||||
|
||||
// horizontal filter, results in transposed temporary image
|
||||
coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), img.Bounds().Min.X, taps, blur, scaleX, kernel)
|
||||
coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), taps, blur, scaleX, kernel)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(temp, i, cpus).(*image.RGBA64)
|
||||
|
@ -261,7 +261,7 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
|
|||
wg.Wait()
|
||||
|
||||
// horizontal filter on transposed image, result is not transposed
|
||||
coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY, kernel)
|
||||
coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), taps, blur, scaleY, kernel)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(result, i, cpus).(*image.RGBA64)
|
||||
|
@ -287,7 +287,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
|
|||
result := image.NewRGBA(image.Rect(0, 0, int(width), int(height)))
|
||||
|
||||
// horizontal filter, results in transposed temporary image
|
||||
coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX)
|
||||
coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(temp, i, cpus).(*image.RGBA)
|
||||
|
@ -299,7 +299,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
|
|||
wg.Wait()
|
||||
|
||||
// horizontal filter on transposed image, result is not transposed
|
||||
coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY)
|
||||
coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(result, i, cpus).(*image.RGBA)
|
||||
|
@ -317,7 +317,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
|
|||
temp := newYCC(image.Rect(0, 0, input.Bounds().Dy(), int(width)), input.SubsampleRatio)
|
||||
result := newYCC(image.Rect(0, 0, int(width), int(height)), input.SubsampleRatio)
|
||||
|
||||
coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX)
|
||||
coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX)
|
||||
in := imageYCbCrToYCC(input)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
|
@ -329,7 +329,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
|
|||
}
|
||||
wg.Wait()
|
||||
|
||||
coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY)
|
||||
coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(result, i, cpus).(*ycc)
|
||||
|
@ -346,7 +346,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
|
|||
result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height)))
|
||||
|
||||
// horizontal filter, results in transposed temporary image
|
||||
coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX)
|
||||
coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(temp, i, cpus).(*image.RGBA64)
|
||||
|
@ -358,7 +358,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
|
|||
wg.Wait()
|
||||
|
||||
// horizontal filter on transposed image, result is not transposed
|
||||
coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY)
|
||||
coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(result, i, cpus).(*image.RGBA64)
|
||||
|
@ -375,7 +375,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
|
|||
result := image.NewGray(image.Rect(0, 0, int(width), int(height)))
|
||||
|
||||
// horizontal filter, results in transposed temporary image
|
||||
coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX)
|
||||
coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(temp, i, cpus).(*image.Gray)
|
||||
|
@ -387,7 +387,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
|
|||
wg.Wait()
|
||||
|
||||
// horizontal filter on transposed image, result is not transposed
|
||||
coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY)
|
||||
coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(result, i, cpus).(*image.Gray)
|
||||
|
@ -404,7 +404,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
|
|||
result := image.NewGray16(image.Rect(0, 0, int(width), int(height)))
|
||||
|
||||
// horizontal filter, results in transposed temporary image
|
||||
coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), input.Bounds().Min.X, taps, blur, scaleX)
|
||||
coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(temp, i, cpus).(*image.Gray16)
|
||||
|
@ -416,7 +416,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
|
|||
wg.Wait()
|
||||
|
||||
// horizontal filter on transposed image, result is not transposed
|
||||
coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY)
|
||||
coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(result, i, cpus).(*image.Gray16)
|
||||
|
@ -433,7 +433,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
|
|||
result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height)))
|
||||
|
||||
// horizontal filter, results in transposed temporary image
|
||||
coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), img.Bounds().Min.X, taps, blur, scaleX)
|
||||
coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(temp, i, cpus).(*image.RGBA64)
|
||||
|
@ -445,7 +445,7 @@ func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image,
|
|||
wg.Wait()
|
||||
|
||||
// horizontal filter on transposed image, result is not transposed
|
||||
coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), temp.Bounds().Min.X, taps, blur, scaleY)
|
||||
coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY)
|
||||
wg.Add(cpus)
|
||||
for i := 0; i < cpus; i++ {
|
||||
slice := makeSlice(result, i, cpus).(*image.RGBA64)
|
||||
|
|
Loading…
Reference in New Issue