1
0

More than 1 year has passed since last update.

Go言語でOG:image用の画像を生成するAPIを作成してみた

Posted at

はじめに

おそらく、やい、確実にNode.js系のライブラリを使って作成した方が簡単だと思います
Goでももっと簡単に直感的に作る方法はあると思いますが

リポジトリ

まず、はじめにFigmaでレイアウトを決める

  1. 1200x630の画像を作成します(なんか1200x630が推奨サイズらしいから)
  2. ほか色々とレイアウトを決めましょう
  3. フォントの種類・文字の太さ・文字を折り返す長さを決める
    1. 今回は910px以上の文字サイズになったら折り返すようにしました
    2. タイトル: Noto Sans Japanese - Midumu を使っています
    3. ユーザー名: Noto Sans Japanese - Regular を使っています

↓ できたものがこちらになります

FigmaのデザインをGoで再現する

Figma上でCSSの情報を見ることができます

image.png

背景色の情報をGoで表現する

これがFigmaから取得した背景色の色です。こちらは透明色(Alpha)を使っていますが、RGBAよりRGB表現の画像の方が使いやすいのでRGBAをRGBに変換しましょう

background: linear-gradient(105deg, #FFC5C1 0%, rgba(217, 140, 218, 0.29) 25%, rgba(255, 246, 167, 0.68) 69.43%, rgba(122, 239, 255, 0.37) 100%);

Alphaを使っている場合は、こう言ったツールを使いましょう

// 1200x630の画像を生成
width := 1200
height := 630
dc := gg.NewContext(width, height)

// 左上から右下に向かってグラデーション
grad := gg.NewLinearGradient(0, 0, float64(width), float64(height))
grad.AddColorStop(0, color.RGBA{255, 197, 193, 255})
grad.AddColorStop(0.25, color.RGBA{244, 222, 244, 255})
grad.AddColorStop(0.6943, color.RGBA{255, 249, 195, 255})
grad.AddColorStop(1, color.RGBA{206, 249, 255, 255})
dc.SetFillStyle(grad)

// 画像全体の矩形を描画してグラデーションを適用
dc.DrawRectangle(0, 0, float64(width), float64(height))
dc.Fill()

このコードでこのようなグラデーションの画像の生成が出来ます
image.png

グラデーションの上に白い図形を追加する

Figmaから取得したCSSをもとにPaddingの設定をやりましょう

// 図形のサイズと位置を計算
rectWidth := width - 2*43
rectHeight := height - 2*41
rectX := 43
rectY := 41

// 背景色を設定
dc.SetColor(color.RGBA{255, 255, 255, 255})
dc.DrawRoundedRectangle(float64(rectX), float64(rectY), float64(rectWidth), float64(rectHeight), 16)
dc.Fill()

白い図形が追加されました
image.png

タイトルを表示する

私はバイナリで動かす前提で作っていますので、embedを使ってフォントを埋め込んでいます

//go:embed embed/NotoSansJP-Medium.otf
var fontTitle []byte
/* 〜〜〜〜〜〜〜〜 中略 〜〜〜〜〜〜〜〜 */
// フォントを読み込む
fontFace, err := opentype.Parse(fontTitle)
if err != nil {
    http.Error(w, "Failed to parse font", http.StatusInternalServerError)
    return
}

face, err := opentype.NewFace(fontFace, &opentype.FaceOptions{
    Size: 64,
    DPI:  72,
})

if err != nil {
    http.Error(w, "Failed to create font face", http.StatusInternalServerError)
    return
}
dc.SetFontFace(face)

// 文字を挿入
dc.SetRGB(0, 0, 0) // 文字色を黒に設定

maxWidth := 910.0
title := "Go言語でOG:imageを作成してみる!!"
formatTitle := ""

tmp := 0.0
for _, word := range title {
    fw, _ := dc.MeasureString(string(word))
    if tmp+fw > maxWidth {
        formatTitle += "\n"
        tmp = 0.0
    }

    formatTitle += string(word)
    tmp += fw
}

x := 145.0
y := 175.0
for _, line := range strings.Split(formatTitle, "\n") {
    dc.DrawString(line, x, y)
    y += 82
}

このようにフォントが追加されます
image.png

ユーザー名を追加

上の一緒のことをやるだけなので(ry

image.png

サイトなり、好きロゴを入れる(それっぽくなる)

//go:embed embed/logo.png
var logo []byte
/* 〜〜〜〜〜〜〜〜 中略 〜〜〜〜〜〜〜〜 */
// サイトのロゴを挿入
logoImg, _, err := image.Decode(strings.NewReader(string(logo)))
if err != nil {
    http.Error(w, "Failed to decode logo image", http.StatusInternalServerError)
    return
}

// ロゴのサイズを変更
resizedLogoImg := resize.Resize(0, 150, logoImg, resize.Lanczos3)

// ロゴを挿入
dc.DrawImage(resizedLogoImg, 800, 430)

Figmaで作ったやつと同じようなやつができました!
image.png

大体、同じものができました!!(発色が少し違う)

Figmaで作成したやつ Goで生成したやつ
Frame 1.png image.png

最後に

最初でも言ってますが、Goでやることでは無いと思います。
私は趣味でWebサイト作ってまして、OG:imageに対応するためにReactで作っているWebサイトをNext.jsで書き直しています。その流れでOGイメージもNext.jsで作ろうとしたんですが、作るのが難しくて 私がフロント素人なものでGoに逃げました。

私の𝕏(Twitter)はこちらです。エンジニアのフォロワーさんが少ないので、フォローしていただけたら嬉しいです

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0