FloorMaterialAnalyzer/internal/imageproc/transform.go

80 lines
1.9 KiB
Go
Raw Normal View History

2026-07-27 03:03:51 +00:00
package imageproc
import (
"image"
"image/color"
xdraw "golang.org/x/image/draw"
)
func Crop(src image.Image, rect image.Rectangle) image.Image {
b := src.Bounds()
rect = rect.Intersect(b)
if rect.Empty() {
rect = b
}
dst := image.NewRGBA(image.Rect(0, 0, rect.Dx(), rect.Dy()))
for y := rect.Min.Y; y < rect.Max.Y; y++ {
for x := rect.Min.X; x < rect.Max.X; x++ {
dst.Set(x-rect.Min.X, y-rect.Min.Y, src.At(x, y))
}
}
return dst
}
func ResizeToMax(src image.Image, maxDim int) image.Image {
if maxDim <= 0 {
return src
}
b := src.Bounds()
w, h := b.Dx(), b.Dy()
if w <= maxDim && h <= maxDim {
return normalizeRGBA(src)
}
nw, nh := w, h
if w >= h {
nw = maxDim
nh = max(1, h*maxDim/w)
} else {
nh = maxDim
nw = max(1, w*maxDim/h)
}
dst := image.NewRGBA(image.Rect(0, 0, nw, nh))
xdraw.CatmullRom.Scale(dst, dst.Bounds(), src, b, xdraw.Over, nil)
return dst
}
func ResizeToFill(src image.Image, width, height int) image.Image {
if width <= 0 || height <= 0 {
return normalizeRGBA(src)
}
b := src.Bounds()
srcRatio := float64(b.Dx()) / float64(b.Dy())
dstRatio := float64(width) / float64(height)
crop := b
if srcRatio > dstRatio {
cropW := int(float64(b.Dy()) * dstRatio)
x0 := b.Min.X + (b.Dx()-cropW)/2
crop = image.Rect(x0, b.Min.Y, x0+cropW, b.Max.Y)
} else if srcRatio < dstRatio {
cropH := int(float64(b.Dx()) / dstRatio)
y0 := b.Min.Y + (b.Dy()-cropH)/2
crop = image.Rect(b.Min.X, y0, b.Max.X, y0+cropH)
}
dst := image.NewRGBA(image.Rect(0, 0, width, height))
xdraw.CatmullRom.Scale(dst, dst.Bounds(), src, crop, xdraw.Over, nil)
return dst
}
func normalizeRGBA(src image.Image) image.Image {
b := src.Bounds()
dst := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
xdraw.Draw(dst, dst.Bounds(), src, b.Min, xdraw.Src)
return dst
}
func rgba8(c color.Color) (int, int, int) {
r, g, b, _ := c.RGBA()
return int(r >> 8), int(g >> 8), int(b >> 8)
}