Go言語でピクセル補完的なプログラムを書いてみる その5

ここまでPlaygroundのみで動くものを提示してきましたが、ローカル環境で動いて画像をファイルに出力するものも提示していきます。
Playgroundのものは今まで通りで、ブログにはローカルでコンパイル出来るソースコードを貼っていきます。

画像を単色で塗りつぶしてPNGフォーマットでファイルに保存する


package main

import (
    "errors"
    "fmt"
    "image"
    "image/color"
    "image/png"
    "log"
    "os"
)

func main() {
    rect := image.Rect(0, 0, 100, 100)
    img := image.NewNRGBA(rect)
    col := color.NRGBA{R: 255, G: 0, B: 0, A: 255}
    err := fill(img, col)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    f, err := os.Create("image.png")
    if err != nil {
        log.Fatal(err)
    }
    if err := png.Encode(f, img); err != nil {
        f.Close()
        log.Fatal(err)
    }
    f.Close()
}

func fill(img *image.NRGBA, col color.Color) error {
    if img == nil {
        return errors.New("img is nil")
    }
    rect := img.Rect
    for v := rect.Min.Y; v < rect.Max.Y; v++ {
        for h := rect.Min.X; h < rect.Max.X; h++ {
            img.Set(h, v, col)
        }
    }
    return nil
}

osパッケージのCreate関数にファイルの名前の文字列を渡してファイルを作成しています。
ファイルディスクリプタとerrorの二つの戻り値を返します。


f, err := os.Create("image.png")

エラーが発生していないかをチェックしています。
エラーの時はエラー表示して終了します。


if err != nil {
    log.Fatal(err)
}

log.Fatal関数

Fatal関数は渡されたエラーを表示してプログラムを終了します。
プログラムが続行できないなどの致命的なエラーが発生したときに使用します。
Print()の後に、os.Exit(1)を呼び出すのと同等です。


ここではシンプルステートメントのあるif文を使っています。
まずpng.Encode関数に先ほどのファイルディスクリプタとimgを渡して、img内の画像をPNGにエンコードしてファイルに書き込みます。
そしてpng.Encodeの返すエラーをerr変数で受けてから、エラーがあるかを調べています。
エラーがある場合はファイルディスクリプタをクローズしてから、エラー終了しています。


if err := png.Encode(f, img); err != nil {
    f.Close()
    log.Fatal(err)
}

シンプルステートメントのあるif

シンプルステートメントがある場合はシンプルステートメントが先に実行された後に、後の式が評価されます。


if [変数X] := f(); [変数x] < [変数y] {}

PNGファイルを作成した後は、ファイルディスクリプタを閉じてプログラムを終了しています。


    f.Close()
}

defer

エラー処理で分岐するためにファイルディスクリプタを閉じるコードが複数あり、うっかり閉じ忘れる場合があります。
そういう時にdeferが使えます。
deferのあとに関数またはメソッドを指定すると、deferを記述している関数からリターンする直前に指定した関数またはメソッドをが実行されます。
複数指定している場合はLIFOの順序で実行されます。
つまり先に指定したものが後に実行されます。
これを使ってコードを書き換えてみましょう。


f, err := os.Create("image.png")
if err != nil {
    log.Fatal(err)
}
defer f.Close()
if err := png.Encode(f, img); err != nil {
    log.Fatal(err)
}

この記事へのコメント

最近のトラックバック