Created
December 23, 2020 08:48
-
-
Save tng527/484d77db0b86ff6c7aa13435073e1100 to your computer and use it in GitHub Desktop.
LGTM GIF画像を生成するスクリプト
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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