catbase/plugins/tappd/image.go

150 lines
3.1 KiB
Go
Raw Normal View History

2022-10-14 00:19:01 +00:00
package tappd
import (
"bytes"
2022-10-14 12:31:15 +00:00
"github.com/disintegration/imageorient"
2022-10-14 00:19:01 +00:00
"github.com/fogleman/gg"
2022-10-15 14:07:55 +00:00
"github.com/gabriel-vasile/mimetype"
2022-10-14 00:19:01 +00:00
"github.com/nfnt/resize"
"github.com/rs/zerolog/log"
"github.com/velour/catbase/plugins/meme"
"image"
"image/png"
"net/http"
"net/url"
"path"
)
func (p *Tappd) getImage(url string) (image.Image, error) {
resp, err := http.Get(url)
if err != nil {
return nil, err
}
2022-10-14 12:31:15 +00:00
img, _, err := imageorient.Decode(resp.Body)
2022-10-14 00:19:01 +00:00
if err != nil {
return nil, err
}
r := img.Bounds()
w := r.Dx()
h := r.Dy()
maxSz := p.c.GetFloat64("maxImgSz", 750.0)
if w > h {
scale := maxSz / float64(w)
w = int(float64(w) * scale)
h = int(float64(h) * scale)
} else {
scale := maxSz / float64(h)
w = int(float64(w) * scale)
h = int(float64(h) * scale)
}
log.Debug().Msgf("trynig to resize to %v, %v", w, h)
img = resize.Resize(uint(w), uint(h), img, resize.Lanczos3)
r = img.Bounds()
w = r.Dx()
h = r.Dy()
log.Debug().Msgf("resized to %v, %v", w, h)
return img, nil
}
type textSpec struct {
text string
// percentage location of text center
x float64
y float64
}
func defaultSpec() textSpec {
return textSpec{
x: 0.5,
y: 0.9,
}
}
func (p *Tappd) overlay(img image.Image, texts []textSpec) ([]byte, error) {
2023-03-16 17:30:49 +00:00
font := meme.GetFont(p.c, p.c.Get("meme.font", "impact.ttf"))
2022-10-14 00:19:01 +00:00
fontSizes := []float64{48, 36, 24, 16, 12}
r := img.Bounds()
w := r.Dx()
h := r.Dy()
txts := []string{}
for _, t := range texts {
txts = append(txts, t.text)
}
2023-01-27 18:14:09 +00:00
fontSize := meme.FindFontSize(p.c, txts, font, w, h, fontSizes)
2022-10-14 00:19:01 +00:00
m := gg.NewContext(w, h)
m.DrawImage(img, 0, 0)
for _, spec := range texts {
// write some stuff on the image here
if err := m.LoadFontFace(font, fontSize); err != nil {
return nil, err
}
// Apply black stroke
m.SetHexColor("#000")
strokeSize := 6
for dy := -strokeSize; dy <= strokeSize; dy++ {
for dx := -strokeSize; dx <= strokeSize; dx++ {
// give it rounded corners
if dx*dx+dy*dy >= strokeSize*strokeSize {
continue
}
x := float64(w)*spec.x + float64(dx)
y := float64(h)*spec.y + float64(dy)
m.DrawStringAnchored(spec.text, x, y, 0.5, 0.5)
}
}
m.SetHexColor("#FFF")
x := float64(w) * spec.x
y := float64(h) * spec.y
m.DrawStringAnchored(spec.text, x, y, 0.5, 0.5)
}
i := bytes.Buffer{}
if err := png.Encode(&i, m.Image()); err != nil {
return nil, err
}
return i.Bytes(), nil
}
func (p *Tappd) getAndOverlay(id, srcURL string, texts []textSpec) (imageInfo, error) {
baseURL := p.c.Get("BaseURL", ``)
u, _ := url.Parse(baseURL)
u.Path = path.Join(u.Path, "tappd", id)
img, err := p.getImage(srcURL)
if err != nil {
return imageInfo{}, err
}
data, err := p.overlay(img, texts)
if err != nil {
return imageInfo{}, err
}
bounds := img.Bounds()
2022-10-15 14:07:55 +00:00
mime := mimetype.Detect(data)
2022-10-14 00:19:01 +00:00
info := imageInfo{
2022-10-15 14:07:55 +00:00
ID: id,
SrcURL: srcURL,
BotURL: u.String(),
Img: img,
Repr: data,
W: bounds.Dx(),
H: bounds.Dy(),
MimeType: mime.String(),
FileName: id + mime.Extension(),
2022-10-14 00:19:01 +00:00
}
p.imageMap[id] = info
log.Debug().
Interface("BotURL", info.BotURL).
Str("ID", id).
Msgf("here's some info")
return info, nil
}