2026-05-26 18:27:37 +02:00

85 lines
2.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package itemimage
import (
"bytes"
"fmt"
"image"
"image/jpeg"
"math"
"golang.org/x/image/draw"
_ "golang.org/x/image/webp"
"printer.backend/internal/svgtemplate"
)
// EmbedDPI matches plate PDF rasterization; embedded pixels need not exceed this resolution.
const EmbedDPI = 300
const jpegEmbedQuality = 88
// prepareRaster decodes and downscales image data so the resulting SVG stays small enough for rsvg-convert.
func prepareRaster(data []byte, d svgtemplate.Data) ([]byte, string, error) {
img, _, err := image.Decode(bytes.NewReader(data))
if err != nil {
return nil, "", fmt.Errorf("decode image: %w", err)
}
maxW := mmToPx(d.OuterWidth)
maxH := mmToPx(d.OuterHeight)
if maxW < 1 {
maxW = 1
}
if maxH < 1 {
maxH = 1
}
covered := scaleCover(img, maxW, maxH)
rgba := image.NewNRGBA(image.Rect(0, 0, maxW, maxH))
draw.CatmullRom.Scale(rgba, rgba.Bounds(), covered, covered.Bounds(), draw.Over, nil)
var buf bytes.Buffer
if err := jpeg.Encode(&buf, rgba, &jpeg.Options{Quality: jpegEmbedQuality}); err != nil {
return nil, "", fmt.Errorf("encode jpeg: %w", err)
}
return buf.Bytes(), "image/jpeg", nil
}
func mmToPx(mm float64) int {
return int(math.Ceil(mm / 25.4 * EmbedDPI))
}
// scaleCover returns an image scaled to cover dw×dh (center crop), for preserveAspectRatio slice.
func scaleCover(src image.Image, dw, dh int) image.Image {
sb := src.Bounds()
sw, sh := sb.Dx(), sb.Dy()
if sw <= 0 || sh <= 0 {
return image.NewNRGBA(image.Rect(0, 0, dw, dh))
}
scale := math.Max(float64(dw)/float64(sw), float64(dh)/float64(sh))
nw := int(math.Ceil(float64(sw) * scale))
nh := int(math.Ceil(float64(sh) * scale))
scaled := image.NewNRGBA(image.Rect(0, 0, nw, nh))
draw.CatmullRom.Scale(scaled, scaled.Bounds(), src, sb, draw.Over, nil)
x0 := (nw - dw) / 2
y0 := (nh - dh) / 2
if x0 < 0 {
x0 = 0
}
if y0 < 0 {
y0 = 0
}
if nw < dw {
dw = nw
}
if nh < dh {
dh = nh
}
cropped := image.NewNRGBA(image.Rect(0, 0, dw, dh))
draw.Draw(cropped, cropped.Bounds(), scaled, image.Point{x0, y0}, draw.Src)
return cropped
}