65 lines
1.5 KiB
Go
65 lines
1.5 KiB
Go
package storage
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"image"
|
|
"image/png"
|
|
"io"
|
|
|
|
// Import image formats for decoding
|
|
_ "image/gif"
|
|
_ "image/jpeg"
|
|
|
|
"golang.org/x/image/draw"
|
|
)
|
|
|
|
// IconSizes defines the icon sizes to generate
|
|
var IconSizes = []int{32, 64, 128}
|
|
|
|
// ProcessIcon reads an image and generates icons at multiple sizes
|
|
func (s *Storage) ProcessIcon(appID string, r io.Reader) error {
|
|
// Decode the image
|
|
img, _, err := image.Decode(r)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to decode image: %w", err)
|
|
}
|
|
|
|
// Validate square dimensions
|
|
bounds := img.Bounds()
|
|
if bounds.Dx() != bounds.Dy() {
|
|
return fmt.Errorf("icon must be square, got %dx%d", bounds.Dx(), bounds.Dy())
|
|
}
|
|
|
|
// Minimum size check
|
|
if bounds.Dx() < 128 {
|
|
return fmt.Errorf("icon must be at least 128x128, got %dx%d", bounds.Dx(), bounds.Dy())
|
|
}
|
|
|
|
// Generate each size
|
|
for _, size := range IconSizes {
|
|
resized := resizeImage(img, size, size)
|
|
|
|
var buf bytes.Buffer
|
|
if err := png.Encode(&buf, resized); err != nil {
|
|
return fmt.Errorf("failed to encode icon-%d: %w", size, err)
|
|
}
|
|
|
|
if err := s.SaveIcon(appID, size, buf.Bytes()); err != nil {
|
|
return fmt.Errorf("failed to save icon-%d: %w", size, err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// resizeImage resizes an image to the specified dimensions using high-quality interpolation
|
|
func resizeImage(src image.Image, width, height int) image.Image {
|
|
dst := image.NewRGBA(image.Rect(0, 0, width, height))
|
|
|
|
// Use CatmullRom for high-quality downscaling
|
|
draw.CatmullRom.Scale(dst, dst.Bounds(), src, src.Bounds(), draw.Over, nil)
|
|
|
|
return dst
|
|
}
|