func nearestGray16(in *image.Gray16, out *image.Gray16, 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 gray 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 xi < 0: xi = 0 case xi >= maxX: xi = 2 * maxX default: xi *= 2 } gray += float32(uint16(row[xi+0])<<8 | uint16(row[xi+1])) sum++ } } offset := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*2 value := floatToUint16(gray / sum) out.Pix[offset+0] = uint8(value >> 8) out.Pix[offset+1] = uint8(value) } } }
func resizeGray16(in *image.Gray16, out *image.Gray16, scale float64, coeffs []int32, 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 gray int64 var sum int64 start := offset[y] ci := y * filterLength for i := 0; i < filterLength; i++ { coeff := coeffs[ci+i] if coeff != 0 { xi := start + i switch { case uint(xi) < uint(maxX): xi *= 2 case xi >= maxX: xi = 2 * maxX default: xi = 0 } gray += int64(coeff) * int64(uint16(row[xi+0])<<8|uint16(row[xi+1])) sum += int64(coeff) } } offset := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*2 value := clampUint16(gray / sum) out.Pix[offset+0] = uint8(value >> 8) out.Pix[offset+1] = uint8(value) } } }
// Interpolate uint16/pixel images. func interpolate1x16(src *image.Gray16, dstW, dstH int) image.Image { srcRect := src.Bounds() srcW := srcRect.Dx() srcH := srcRect.Dy() ww, hh := uint64(dstW), uint64(dstH) dx, dy := uint64(srcW), uint64(srcH) n, sum := dx*dy, make([]uint64, dstW*dstH) for y := 0; y < srcH; y++ { pixOffset := src.PixOffset(0, y) for x := 0; x < srcW; x++ { // Get the source pixel. val64 := uint64(binary.BigEndian.Uint16([]byte(src.Pix[pixOffset+0 : pixOffset+2]))) pixOffset += 2 // Spread the source pixel over 1 or more destination rows. py := uint64(y) * hh for remy := hh; remy > 0; { qy := dy - (py % dy) if qy > remy { qy = remy } // Spread the source pixel over 1 or more destination columns. px := uint64(x) * ww index := (py/dy)*ww + (px / dx) for remx := ww; remx > 0; { qx := dx - (px % dx) if qx > remx { qx = remx } qxy := qx * qy sum[index] += val64 * qxy index++ px += qx remx -= qx } py += qy remy -= qy } } } dst := image.NewGray16(image.Rect(0, 0, dstW, dstH)) index := 0 for y := 0; y < dstH; y++ { pixOffset := dst.PixOffset(0, y) for x := 0; x < dstW; x++ { binary.BigEndian.PutUint16(dst.Pix[pixOffset+0:pixOffset+2], uint16(sum[index]/n)) pixOffset += 2 index++ } } return dst }
func resize1x16(src *image.Gray16, dstW, dstH int) image.Image { srcRect := src.Bounds() srcW := srcRect.Dx() srcH := srcRect.Dy() dstW64, dstH64 := uint64(dstW), uint64(dstH) srcW64, srcH64 := uint64(srcW), uint64(srcH) dst := image.NewGray16(image.Rect(0, 0, dstW, dstH)) var x, y uint64 dstI := 0 for y = 0; y < dstH64; y++ { srcY := int(y * srcH64 / dstH64) for x = 0; x < dstW64; x++ { srcX := int(x * srcW64 / dstW64) srcI := 2 * (srcY*srcW + srcX) copy(dst.Pix[dstI:dstI+2], src.Pix[srcI:srcI+2]) dstI += 2 } } return dst }