87 lines
1.8 KiB
Go
87 lines
1.8 KiB
Go
package gallery
|
|
|
|
import (
|
|
"context"
|
|
"math"
|
|
|
|
"github.com/InfinityTools/go-binpack2d"
|
|
)
|
|
|
|
type Gallery struct {
|
|
GridWith int
|
|
GridHeight int
|
|
Images []Image
|
|
}
|
|
type Set struct {
|
|
SM Gallery
|
|
LG Gallery
|
|
XLG Gallery
|
|
}
|
|
|
|
func (s *Service) GetGallerySet(ctx context.Context) (gallerySet Set, err error) {
|
|
gallerySet.SM, err = s.GetGallery(ctx, 50)
|
|
if err != nil {
|
|
return
|
|
}
|
|
gallerySet.LG, err = s.GetGallery(ctx, 80)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
gallerySet.XLG, err = s.GetGallery(ctx, 120)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *Service) GetGallery(ctx context.Context, width int) (gallery Gallery, err error) {
|
|
imgs, err := s.GetImages(ctx)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
packer := binpack2d.Create(width, 999999)
|
|
|
|
for len(imgs) > 0 {
|
|
unused := make([]Image, 0, len(imgs))
|
|
for _, img := range imgs {
|
|
adjustImageSize(&img, 200)
|
|
rect, ok := packer.Insert(img.Width, img.Height, binpack2d.RULE_BEST_SHORT_SIDE_FIT)
|
|
if !ok {
|
|
unused = append(unused, img)
|
|
continue
|
|
}
|
|
|
|
img.X = rect.X
|
|
img.Y = rect.Y
|
|
|
|
gallery.Images = append(gallery.Images, img)
|
|
}
|
|
imgs = unused
|
|
}
|
|
|
|
packer.ShrinkBin(false)
|
|
|
|
gallery.GridHeight = packer.GetHeight()
|
|
gallery.GridWith = packer.GetWidth()
|
|
|
|
return
|
|
}
|
|
|
|
// adjustImageSize adjusts the image size so that the aspect ratio stays the same
|
|
// but the image area is the given parameter.
|
|
func adjustImageSize(img *Image, area int) {
|
|
// Calculate the original aspect ratio (W / H)
|
|
aspectRatio := float64(img.Width) / float64(img.Height)
|
|
|
|
// Calculate new height and width using the derived formulas
|
|
newHeight := math.Sqrt(float64(area) / aspectRatio)
|
|
newWidth := newHeight * aspectRatio
|
|
|
|
// Round to the nearest integer to minimize precision loss
|
|
img.Width = int(math.Round(newWidth))
|
|
img.Height = int(math.Round(newHeight))
|
|
}
|