🐻

Goを使って紅葉満開の景色を生成しようとしたらシャカチキっぽくなった話。(Goのimageライブラリを使って画像生成してみた)

2021/12/25に公開

はじめに

この記事は鈴鹿高専 Advent Calendar 2021 25日目の記事です。
https://qiita.com/advent-calendar/2021/snct

Goの学習がてら、imageライブラリを使って枯れた紅葉の景色を復活させました。 できませんでした。

imageライブラリとは?

Package image implements a basic 2-D image library.
(パッケージ image は,基本的な2次元画像ライブラリを実装しています。)

https://pkg.go.dev/image

なるほど、名前そのままですね。

ではこれを使って京都旅行で撮った写真の色を変更していきます。
目標は紅葉が満開担っている写真です。

書いたコード

package main

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

func main() {
	in, _ := os.Open("momiji.png")
	out, _ := os.Create("momijicopy.png")

	var (
		i      uint8
		j      uint8
		n      uint8
		crange uint8
		srange uint8
		wtclist := []color.RGBA{}
	)

	crange = 40
	start = 70
	
	aclist := [...]color.RGBA{
		{240, 44, 48, 255},
		{210, 71, 29, 255},
		{210, 20, 14, 255},
		{239, 99, 82, 255},
	}

	for i = 0; i < crange; i++ {
		for j = 0; j < crange; j++ {
			for n = 0; n < crange; n++ {
				wtcc := color.RGBA{start + i, start + j, start + n, 255}

				wtclist = append(wtclist, wtcc)
			}
		}
	}


	img, _ := png.Decode(in)
	bounds := img.Bounds()

	dest := image.NewRGBA(bounds)

	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X; x < bounds.Max.X; x++ {
			color := img.At(x, y)
			for i := 0; i < len(wtclist); i++ {
				if color == wtclist[i] && y < 1200 {
					color = aclist[rand.Intn(len(aclist))]
				}
			}
			dest.Set(x, y, color)
		}
	}
	png.Encode(out, dest)
}

使っている関数等の解説

func Decode

func Decode(r io.Reader) (image.Image, error)

PNG画像を読み取り、それをImage型として返す関数です。

コード例

img, _ := png.Decode(in)

Image.Bounds

type Image interface {
    Bounds() Rectangle
}

その画像の最小のx,y座標と最大のx,y座標が格納されたRectangle型を返します。

コード例

bounds := img.Bounds()

func NewRGBA

func NewRGBA(r Rectangle) *RGBA

生成する画像のベースになるものです。

コード例

dest := image.NewRGBA(bounds)

Image.At

type Image interface {
    At(x, y int) color.Color
}

指定した座標のカラーコードをRGBAの形で返します。

コード例

color := img.At(x, y)

func (*RGBA) Set

func (p *RGBA) Set(x, y int, c color.Color)

指定した座標に、渡したカラーコードを設定します。

コード例

dest.Set(x, y, color)

func Encode

func Encode(w io.Writer, m image.Image) error

渡したImage型の変数の値を任意の形式ででファイルに書き込みます。今回はimage/pngを使っているのでpng型です。

コード例

png.Encode(out, dest)

実際にコードを動かしてみる

では実際に動かしてみます。コードの中身は単純で、画像の構成するカラーコードを1ピクセルずつを読み込み、RGBの(70~110,70~110,70~110)の64000通りのカラーコードに当てはまったら、指定したカラーコードに置き換える処理です。読み込んだRGBのRの値が範囲外の時点で弾くなどの処理もあったのですが、めんどくさいので書いてません。

ではドキドキの結果発表です。どことなくライザップ感がありますね。

12月初頭、あんなに散っていた紅葉は.......










劇的な変化を遂げました。

なんだか微妙ですね

コードを書き始める前から予想はついてました

てかPhotoshopでええやん

結果

シャカチキレッドペッパーになりました。

Discussion