Skip to content

Instantly share code, notes, and snippets.

@tng527
Created December 23, 2020 08:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tng527/484d77db0b86ff6c7aa13435073e1100 to your computer and use it in GitHub Desktop.
Save tng527/484d77db0b86ff6c7aa13435073e1100 to your computer and use it in GitHub Desktop.
LGTM GIF画像を生成するスクリプト
package main
import (
"bytes"
"encoding/json"
"fmt"
"image"
"image/color"
"image/draw"
"image/gif"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"path"
"github.com/golang/freetype/truetype"
jsonpointer "github.com/mattn/go-jsonpointer"
"golang.org/x/image/font"
"golang.org/x/image/font/gofont/gobold"
"golang.org/x/image/math/fixed"
)
type ImageInfo struct {
Url string
Title string
}
const getLimit = 50
func main() {
os.MkdirAll("raw", 0777)
os.MkdirAll("lgtm", 0777)
imgs := getGifUrl("anime")
for _, img := range imgs {
log.Println(img.Title)
download(img)
combineLGTM(img.Title + ".gif")
}
}
func combineLGTM(filename string) {
f, err := os.Open(path.Join("raw", filename))
if err != nil {
panic(err)
}
defer f.Close()
g, err := gif.DecodeAll(f)
if err != nil {
panic(err)
}
lgtmImage, err := generateLGTMImage(g.Image[0])
if err != nil {
panic(err)
}
var images []*image.Paletted
var delays []int
var disposals []byte
for i, img := range g.Image {
logoRectangle := image.Rectangle{image.Point{0, 0}, lgtmImage.Bounds().Size()}
draw.Draw(img, logoRectangle, lgtmImage, image.Point{0, 0}, draw.Over)
images = append(images, img)
delays = append(delays, g.Delay[i])
disposals = append(disposals, gif.DisposalNone)
}
buf := new(bytes.Buffer)
if err = gif.EncodeAll(buf, &gif.GIF{
Image: images,
Delay: delays,
Disposal: disposals,
BackgroundIndex: g.BackgroundIndex,
Config: g.Config,
}); err != nil {
panic(err)
}
file, err := os.Create(path.Join("lgtm", filename))
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
defer file.Close()
file.Write(buf.Bytes())
}
func generateLGTMImage(img *image.Paletted) (image.Image, error) {
// gif のサイズに合わせて img を生成
newImg := image.NewRGBA(img.Rect)
tt, err := truetype.Parse(gobold.TTF)
if err != nil {
return nil, err
}
log.Println(newImg.Rect.Dx())
// pixelをpointに直し、4文字分の場所を確保し、左右に若干余裕(0.8倍)をもたせる
fontsize := float64(newImg.Rect.Dx()) * 0.25 * 0.8 / 1.333
d := &font.Drawer{
Dst: newImg,
Src: image.NewUniform(color.White),
Face: truetype.NewFace(tt, &truetype.Options{
Size: fontsize,
},
),
// 横方向はfontsizeを2文字分をpixelに直した値
Dot: fixed.Point26_6{fixed.Int26_6(((float64(newImg.Rect.Dx()) / 2) - fontsize*2/1.333) * 64), fixed.Int26_6((newImg.Rect.Dy() - 20) * 64)},
}
d.DrawString("LGTM")
return newImg, nil
}
func getGifUrl(keyword string) []ImageInfo {
url := "https://api.giphy.com/v1/gifs/search"
req, _ := http.NewRequest("GET", url, nil)
params := req.URL.Query()
params.Add("api_key", os.Getenv("GIPHY_KEY"))
params.Add("q", keyword)
params.Add("limit", fmt.Sprint(getLimit))
req.URL.RawQuery = params.Encode()
fmt.Println(req.URL.String())
client := new(http.Client)
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var j interface{}
json.Unmarshal(body, &j)
var imgs []ImageInfo
for i := 0; i < getLimit; i++ { // TODO: getLimitではなく取れた値の数で回す
url, _ := jsonpointer.Get(j, "/data/"+fmt.Sprint(i)+"/images/original/url")
title, _ := jsonpointer.Get(j, "/data/"+fmt.Sprint(i)+"/title")
img := ImageInfo{Url: url.(string), Title: title.(string)}
imgs = append(imgs, img)
}
return imgs
}
func download(info ImageInfo) error {
resp, err := http.Get(info.Url)
if err != nil {
return err
}
defer resp.Body.Close()
file, err := os.Create(path.Join("raw", info.Title+".gif"))
if err != nil {
return err
}
_, err = io.Copy(file, resp.Body)
if closeErr := file.Close(); err == nil {
err = closeErr
}
return err
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment