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) }