golangで以下のような画像処理のお試し。
- jpeg,pngの保存
- 座標ごとに処理
- 画像読み込み
- リサイズ
- 重ね合わせ
- 文字を入れる(日本語)
動作テスト
まずは簡単なテストから。
osパッケージでファイル出力、imageパッケージで画像処理します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package main import ( "os" "image" "image/jpeg" "image/color" ) func grad(img *image.RGBA) { rect := img.Rect for h := rect.Min.Y; h < rect.Max.Y; h++ { for v := rect.Min.X; v < rect.Max.X; v++ { img.Set(v, h, color.RGBA{ uint8(255*h/rect.Max.Y), uint8(255*v/rect.Max.X), uint8(255*v*h/(rect.Max.X*rect.Max.Y)), 0}) } } } func main() { //Rect引数は x, y, w, h img := image.NewRGBA( image.Rect(0,0,100,100) ) grad(img) //ファイル作成と後始末 file, _ := os.Create("test.jpg") defer file.Close() if err != nil { fmt.Println("error:file\n",err) return } // JPEG出力 if err := jpeg.Encode(file, img, &jpeg.Options{100}); err != nil { fmt.Println("error:jpeg\n",err) return } } |
y座標に比例してR(赤)、x座標に比例してG(緑)、右下ほどB(青)が増加します。
画像読み込みと編集
先ほど作った画像を反転させてみます。
画像のエンコード、デコードには使いたい画像のフォーマットに対応したパッケージを読み込んでおく必要があります。
読み込まないと"image: unknown format"
エラー。
他で使わない場合はエイリアスに_
を設定する。
またImage.At
のRGBA()
は16bit
なので処理する前に変換が必要です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
package main import ( "fmt" "os" "image" _ "image/jpeg"//for Decode "image/png" "image/color" ) func rev(rgba *image.RGBA, img image.Image) { rect := rgba.Rect for h := rect.Min.Y; h < rect.Max.Y; h++ { for v := rect.Min.X; v < rect.Max.X; v++ { //fmt.Println(img.At(v, h).RGBA()) //=>64764 64853 64311 65535とかになる //ビット数がわかっているので右シフトする手もある //r, g, b, a := img.At(v, h).RGBA() //r, g, b, a = r>>8, g>>8, b>>8, a>>8 _c := color.RGBAModel.Convert(img.At(v, h)).(color.RGBA) rgba.Set(v, h, color.RGBA{ uint8(255-_c.R), uint8(255-_c.G), uint8(255-_c.B), 255}) } } } func main() { //画像読み込み file_in, err := os.Open("test.jpg") defer file_in.Close() if err != nil { fmt.Println("error:file\n",err) return } //画像をimage型として読み込む inImg, format, err := image.Decode(file_in) if err != nil { fmt.Println("error:decode\n",format,err) return } //RGBAを用意して反転処理 ib := inImg.Bounds() out := image.NewRGBA(ib) rev(out,inImg) //PNG出力 file_out, err := os.Create("test.png") defer file_out.Close() if err != nil { fmt.Println("error:file\n",err) return } if err := png.Encode(file_out, out); err != nil { fmt.Println("error:png\n",err) return } } |
アルファ値は255が不透明なのも注意。またNRGBAにしてもいいです。
サイズ変更と重ね合わせ
リサイズは面倒そうなので外部パッケージを使おうとGithubで「golang image」とかを検索した感じだとnfnt/resizeが人気。
今回はデフォルトのimage/draw
より機能の多い公式のパッケージを使ってみる。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
go get golang.org/x/image/draw ... import "golang.org/x/image/draw" ... out := image.NewRGBA( image.Rect(0,0,200,100) ) //最近傍補間を使ったスケーリング draw.NearestNeighbor.Scale(out, out.Bounds(), inImg1, inImg1.Bounds(), draw.Over, nil) //右に50pxずらす draw.Draw(out, out.Bounds(), inImg2, image.Point{-50,0}, draw.Over) |
リサイズの際の補完方法は4通りあります。
- NearestNeighbor:最近傍法
- ApproxBiLinear:双一次近似
- BiLinear:双一次補間
- CatmullRom:スプライト曲線
画像によるけど下ほど品質が高くて時間がかかります。
文字(日本語)の画像化
リサイズと同じように公式の外部パッケージをメインに使います。
日本語を使いたいので、好きなフォントを使えるようにロード関数を作る。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
func fontload(fname string)([]byte){ file, err := os.Open(fname) defer file.Close() if err != nil { fmt.Println("error:file\n",err) return nil } bytes,err := ioutil.ReadAll(file) if err != nil { fmt.Println("error:fileread\n",err) return nil } return bytes } |
フォント用に外部パッケージを3つ追加。
- “github.com/golang/freetype/truetype”
- “golang.org/x/image/font”
- “golang.org/x/image/math/fixed”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
fontstr := "てすとTexTテスト" fontsize:= 24.0 ft, err := truetype.Parse(fontload("VL-PGothic-Regular.ttf")) if err != nil { fmt.Println("font",err) return } opt := truetype.Options{Size:fontsize} face := truetype.NewFace(ft, &opt) d := &font.Drawer{ Dst: out, Src: image.NewUniform(color.White), Face: face, } d.Dot.X = (fixed.I(200) - d.MeasureString(fontstr)) / 2 d.Dot.Y = fixed.I(50+int(fontsize/2)) d.DrawString(fontstr) |
パッケージを使ってはいますが、かなり簡単に書けます。