LoginSignup
5
1

More than 3 years have passed since last update.

Goでの画像生成

Posted at

この記事はtomowarkar ひとりAdvent Calendar 2019の11日目の記事です。

記事を書く時間が取れず、またストックもないのでどんどんと簡素化していくのがわかりますね笑

今回はGoで640×400のpng画像を生成をしていきます。

ランダム生成

  1. int Slice で描画するフィールドを生成(ランダム)
  2. 1.を元にpngファイル生成
  3. ローカル保存

をしていきます。

コード

package main

import (
    "image"
    "image/color"
    "image/png"
    "math/rand"
    "os"
)

var (
    khaki         = color.RGBA{240, 230, 140, 255}
    darkgoldenrod = color.RGBA{184, 134, 11, 255}
    royalblue     = color.RGBA{65, 105, 225, 255}
    seagreen      = color.RGBA{46, 139, 87, 255}
    width         = 640
    height        = 400
)

func setField() []int {
    field := make([]int, width*height)
    for i := 0; i < len(field); i++ {
        field[i] = rand.Intn(4)
    }
    return field
}

func main() {
    field := setField()
    img := image.NewRGBA(image.Rect(0, 0, width, height))
    for x := 0; x < width; x++ {
        for y := 0; y < height; y++ {
            switch field[y*height+x] {
            case 1:
                img.Set(x, y, khaki)
            case 2:
                img.Set(x, y, royalblue)
            case 3:
                img.Set(x, y, seagreen)
            default:
                img.Set(x, y, darkgoldenrod)
            }
        }
    }
    f, _ := os.Create("./img/image.png")
    defer f.Close()
    png.Encode(f, img)
}

結果

image1.png

ランダム生成(倍率指定)

これでは少し描画粒度が細かいので、倍率を指定して描画粒度を荒くしていきます。

差分のみの表示なので詳しく知りたい方はソースコードまでどうぞ。

コード


-   width         = 640
-   height        = 400

+   width         = 16
+   height        = 10
+   scale         = 40


-   img := image.NewRGBA(image.Rect(0, 0, width, height))
-   for x := 0; x < width; x++ {
-       for y := 0; y < height; y++ {
-           switch field[y*height+x] {

+   img := image.NewRGBA(image.Rect(0, 0, width*scale, height*scale))
+   for x := 0; x < width*scale; x++ {
+       for y := 0; y < height*scale; y++ {
+           switch field[y/scale*height+x/scale] {

結果

image1.png

おまけ

今回紹介したコードを走らせても、同じ画像しか生成されないと思います。
これはフィールド生成の乱数の初期シード値が固定されているためです。

なので以下のようにsetFieldの関数内で時刻をもとにシード値を設定してやります。
これで毎回違ったフィールドが生成されます。

rand.Seed(time.Now().UnixNano())

画像生成時に指定するファイルパスも固定化してしまうと上書きで更新されてしまうので、タイムスタンプを入れることで上書きを防ぎ新たなファイルを作ることができます。

t := time.Now()
timestamp := fmt.Sprintf("%04d%02d%02d%02d%02d%02d",
    t.Year(), t.Month(), t.Day(),
    t.Hour(), t.Minute(), t.Second(),
)
fpath := fmt.Sprintf("./img/image%s.png", timestamp)

どちらも詳細はソースコードで!

おわりに

以上明日も頑張ります!!
tomowarkar ひとりAdvent Calendar Advent Calendar 2019

参考

画像生成周り

https://yourbasic.org/golang/create-image/
https://golang.org/pkg/image/

Goでの乱数

時間のフォーマット

5
1
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
5
1