2022-07-21 15:25:10 +00:00
|
|
|
package cowboy
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"image"
|
|
|
|
"image/draw"
|
|
|
|
"image/png"
|
2022-07-22 13:14:00 +00:00
|
|
|
"math"
|
2022-07-21 15:25:10 +00:00
|
|
|
"os"
|
|
|
|
"path"
|
2022-07-22 21:06:55 +00:00
|
|
|
"sync"
|
2022-07-21 15:25:10 +00:00
|
|
|
|
|
|
|
"github.com/nfnt/resize"
|
2022-07-22 21:06:55 +00:00
|
|
|
"github.com/rs/zerolog/log"
|
2022-07-21 15:25:10 +00:00
|
|
|
"github.com/velour/catbase/plugins/emojy"
|
|
|
|
)
|
|
|
|
|
2022-07-22 21:06:55 +00:00
|
|
|
var (
|
2022-07-22 22:27:20 +00:00
|
|
|
cowboyCache = map[string]image.Image{}
|
2022-07-22 21:06:55 +00:00
|
|
|
cowboyMutex = sync.Mutex{}
|
|
|
|
)
|
|
|
|
|
2022-07-22 13:44:42 +00:00
|
|
|
func getEmojy(emojyPath, baseEmojyURL, name string) (image.Image, error) {
|
|
|
|
files, _, err := emojy.AllFiles(emojyPath, baseEmojyURL)
|
2022-07-21 15:25:10 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
fname, ok := files[name]
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("could not find emojy: %s", name)
|
|
|
|
}
|
|
|
|
f, err := os.Open(fname)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
img, _, err := image.Decode(f)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return img, nil
|
|
|
|
}
|
|
|
|
|
2022-07-23 04:17:44 +00:00
|
|
|
func getCowboyHat(emojyPath, overlay string) (image.Image, error) {
|
|
|
|
emojies, _, err := emojy.AllFiles(emojyPath, "")
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
overlay, ok := emojies[overlay]
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("could not find overlay %s", overlay)
|
|
|
|
}
|
|
|
|
overlay = path.Clean(overlay)
|
|
|
|
f, err := os.Open(overlay)
|
2022-07-21 15:25:10 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
img, _, err := image.Decode(f)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return img, nil
|
|
|
|
}
|
|
|
|
|
2022-07-23 04:17:44 +00:00
|
|
|
func cowboyifyImage(emojyPath, overlay string, input image.Image) (image.Image, error) {
|
|
|
|
hat, err := getCowboyHat(emojyPath, overlay)
|
2022-07-21 15:25:10 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-07-22 13:14:00 +00:00
|
|
|
inputW, inputH := float64(input.Bounds().Max.X), float64(input.Bounds().Max.Y)
|
2022-07-21 15:25:10 +00:00
|
|
|
hatW, hatH := float64(hat.Bounds().Max.X), float64(hat.Bounds().Max.Y)
|
2022-07-22 13:14:00 +00:00
|
|
|
targetSZ := math.Max(inputW, inputH)
|
|
|
|
dst := image.NewRGBA(image.Rect(0, 0, int(targetSZ), int(targetSZ)))
|
|
|
|
newH := uint(targetSZ / hatW * hatH)
|
|
|
|
hat = resize.Resize(uint(targetSZ), newH, hat, resize.Lanczos3)
|
2022-07-21 15:25:10 +00:00
|
|
|
draw.Draw(dst, input.Bounds(), input, image.Point{}, draw.Src)
|
|
|
|
draw.Draw(dst, hat.Bounds(), hat, image.Point{}, draw.Over)
|
|
|
|
return dst, nil
|
|
|
|
}
|
|
|
|
|
2022-07-23 04:17:44 +00:00
|
|
|
func cowboy(emojyPath, baseEmojyURL, overlay, name string) (image.Image, error) {
|
2022-07-22 21:06:55 +00:00
|
|
|
cowboyMutex.Lock()
|
|
|
|
defer cowboyMutex.Unlock()
|
|
|
|
if img, ok := cowboyCache[name]; ok {
|
|
|
|
log.Debug().Msgf(":cowboy_using_cached_image: %s", name)
|
|
|
|
return img, nil
|
|
|
|
}
|
2022-07-23 04:17:44 +00:00
|
|
|
log.Debug().Msgf(":cowboy_generating_image: %s with overlay %s", name, overlay)
|
2022-07-22 21:06:55 +00:00
|
|
|
emjy, err := getEmojy(emojyPath, baseEmojyURL, name)
|
2022-07-21 15:25:10 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-07-23 04:17:44 +00:00
|
|
|
img, err := cowboyifyImage(emojyPath, overlay, emjy)
|
2022-07-22 22:27:20 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
cowboyCache[name] = img
|
|
|
|
return img, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func encode(img image.Image, err error) ([]byte, error) {
|
2022-07-21 15:25:10 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
w := bytes.NewBuffer([]byte{})
|
|
|
|
err = png.Encode(w, img)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return w.Bytes(), nil
|
|
|
|
}
|
2022-07-22 21:06:55 +00:00
|
|
|
|
|
|
|
func cowboyClearCache() {
|
|
|
|
cowboyMutex.Lock()
|
|
|
|
defer cowboyMutex.Unlock()
|
2022-07-22 22:27:20 +00:00
|
|
|
cowboyCache = map[string]image.Image{}
|
2022-07-22 21:06:55 +00:00
|
|
|
}
|