|
|
@@ -118,6 +118,45 @@ func nearestRGBA(in *image.RGBA, out *image.RGBA, scale float64, coeffs []bool,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+func nearestNRGBA(in *image.NRGBA, out *image.NRGBA, scale float64, coeffs []bool, offset []int, filterLength int) {
|
|
|
+ newBounds := out.Bounds()
|
|
|
+ maxX := in.Bounds().Dx() - 1
|
|
|
+
|
|
|
+ for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
|
|
|
+ row := in.Pix[x*in.Stride:]
|
|
|
+ for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
|
|
|
+ var rgba [4]float32
|
|
|
+ var sum float32
|
|
|
+ start := offset[y]
|
|
|
+ ci := y * filterLength
|
|
|
+ for i := 0; i < filterLength; i++ {
|
|
|
+ if coeffs[ci+i] {
|
|
|
+ xi := start + i
|
|
|
+ switch {
|
|
|
+ case uint(xi) < uint(maxX):
|
|
|
+ xi *= 4
|
|
|
+ case xi >= maxX:
|
|
|
+ xi = 4 * maxX
|
|
|
+ default:
|
|
|
+ xi = 0
|
|
|
+ }
|
|
|
+ rgba[0] += float32(row[xi+0])
|
|
|
+ rgba[1] += float32(row[xi+1])
|
|
|
+ rgba[2] += float32(row[xi+2])
|
|
|
+ rgba[3] += float32(row[xi+3])
|
|
|
+ sum++
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*4
|
|
|
+ out.Pix[xo+0] = floatToUint8(rgba[0] / sum)
|
|
|
+ out.Pix[xo+1] = floatToUint8(rgba[1] / sum)
|
|
|
+ out.Pix[xo+2] = floatToUint8(rgba[2] / sum)
|
|
|
+ out.Pix[xo+3] = floatToUint8(rgba[3] / sum)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func nearestRGBA64(in *image.RGBA64, out *image.RGBA64, scale float64, coeffs []bool, offset []int, filterLength int) {
|
|
|
newBounds := out.Bounds()
|
|
|
maxX := in.Bounds().Dx() - 1
|
|
|
@@ -165,6 +204,53 @@ func nearestRGBA64(in *image.RGBA64, out *image.RGBA64, scale float64, coeffs []
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+func nearestNRGBA64(in *image.NRGBA64, out *image.NRGBA64, scale float64, coeffs []bool, offset []int, filterLength int) {
|
|
|
+ newBounds := out.Bounds()
|
|
|
+ maxX := in.Bounds().Dx() - 1
|
|
|
+
|
|
|
+ for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
|
|
|
+ row := in.Pix[x*in.Stride:]
|
|
|
+ for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
|
|
|
+ var rgba [4]float32
|
|
|
+ var sum float32
|
|
|
+ start := offset[y]
|
|
|
+ ci := y * filterLength
|
|
|
+ for i := 0; i < filterLength; i++ {
|
|
|
+ if coeffs[ci+i] {
|
|
|
+ xi := start + i
|
|
|
+ switch {
|
|
|
+ case uint(xi) < uint(maxX):
|
|
|
+ xi *= 8
|
|
|
+ case xi >= maxX:
|
|
|
+ xi = 8 * maxX
|
|
|
+ default:
|
|
|
+ xi = 0
|
|
|
+ }
|
|
|
+ rgba[0] += float32(uint16(row[xi+0])<<8 | uint16(row[xi+1]))
|
|
|
+ rgba[1] += float32(uint16(row[xi+2])<<8 | uint16(row[xi+3]))
|
|
|
+ rgba[2] += float32(uint16(row[xi+4])<<8 | uint16(row[xi+5]))
|
|
|
+ rgba[3] += float32(uint16(row[xi+6])<<8 | uint16(row[xi+7]))
|
|
|
+ sum++
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8
|
|
|
+ value := floatToUint16(rgba[0] / sum)
|
|
|
+ out.Pix[xo+0] = uint8(value >> 8)
|
|
|
+ out.Pix[xo+1] = uint8(value)
|
|
|
+ value = floatToUint16(rgba[1] / sum)
|
|
|
+ out.Pix[xo+2] = uint8(value >> 8)
|
|
|
+ out.Pix[xo+3] = uint8(value)
|
|
|
+ value = floatToUint16(rgba[2] / sum)
|
|
|
+ out.Pix[xo+4] = uint8(value >> 8)
|
|
|
+ out.Pix[xo+5] = uint8(value)
|
|
|
+ value = floatToUint16(rgba[3] / sum)
|
|
|
+ out.Pix[xo+6] = uint8(value >> 8)
|
|
|
+ out.Pix[xo+7] = uint8(value)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func nearestGray(in *image.Gray, out *image.Gray, scale float64, coeffs []bool, offset []int, filterLength int) {
|
|
|
newBounds := out.Bounds()
|
|
|
maxX := in.Bounds().Dx() - 1
|