“golang.org/x/image/draw”を使って色々します。
前にScaleを使いましたが、drawで他に何ができるかのサンプル付きメモ。
対象はDraw
, Copy
, DrawMask
, Transform
です。
ベースソース
基本形はこんな感じでテストしていきます。
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 |
package main import( "fmt" "os" "image" _ "image/png" "image/jpeg" "golang.org/x/image/draw" ) func main(){ //画像読み込み file_in, err := os.Open("rena.png") defer file_in.Close() if err != nil { fmt.Println("error:file\n",err) return } //画像をimage型として読み込む img, format, err := image.Decode(file_in) if err != nil { fmt.Println("error:decode\n",format,err) return } //draw テスト out := image.NewRGBA( img.Bounds() ) draw.SomeMethod() //PNG画像の作成と保存 file_out, err := os.Create("out.jpg") defer file_out.Close() if err != nil { fmt.Println("error:file\n",err) return } if err := jpeg.Encode(file_out, out, nil); err != nil { fmt.Println("error:jpg\n",err) return } } |
使わせてもらう画像はおなじみのレナさんにします。
draw.Draw
mask
をnil
にしてDrawMask
を呼びます。
1 |
draw.Draw(out, out.Bounds(), img, image.Point{100,0}, draw.Over) |
イメージソースの開始点を設定して上書きモードで描画しています。
今回はout
も同サイズでソースが(100,0)
を起点にしているので右側100px
は入力なしで黒くなっています(png出力の場合は透過される)。
draw.Copy
xのコマンドで内部的にはオプションのDstMask
がなければDrawMask
、あればNearestNeighbor.Scale
を呼びます。
微妙に使い方が違うので注意。
1 |
draw.Copy(out,image.Point{100,0}, img, img.Bounds(), draw.Over, nil) |
out
の描画開始位置を(100,0)
にしたので左100px
が黒くなります。
draw.DrawMask
Draw
やCopy
でも使われている関数。
マスクを設定して描画できます。
1 |
draw.DrawMask(out, out.Bounds(), img, image.Point{0,0}, mask, image.Point{0,0}, draw.Over) |
以下のようにマスクを用意すると円状に切り抜けます。
draw.Transform
“golang.org/x/image/math/f64″を使ってアフィン変換できます。
拡大縮小、回転、平行移動とせん断が可能です。
回転は左上(0,0)
を中心に行われるので90℃回転させるには画像サイズ分変更移動が必要になります。
1 2 3 4 5 6 7 8 9 10 |
deg := 90.0 rad := deg * math.Pi / 180 cos, sin := math.Cos(rad), math.Sin(rad) mag := 0.8 fmt.Println(cos,sin) t := f64.Aff3{ +mag * cos, -mag * sin, 512, +mag * sin, +mag * cos, 0, } draw.NearestNeighbor.Transform(out, t, img, img.Bounds(), draw.Over, nil) |
これは回転と全体縮小のコード。回転のために平行移動もしている。
X,Y方向の拡大縮小と、せん断も可能です。
1 2 3 4 5 6 7 8 |
mag := 0.5 x_mag,x_shear := 0.8,0.5 y_mag,y_shear := 1.5,0.0 fmt.Println(cos,sin) t := f64.Aff3{ +mag * cos * x_mag , -mag * sin + x_shear, 0, +mag * sin + y_shear, +mag * cos * y_mag, 0, } |
せん断によって平行四辺形(片方のせん断)、ひし形(両方のせん断)に変形可能ですが、アフィン変換では台形にはできません。
注意点
デコードした画像に直接描画しようとするとエラーになります。
これはimage.Image
がインターフェースでSet
メソッドがないためです。
image.RGBA
のようなSet
メソッドを持つ必要があります。
画像形式に基づいた形式にアサーションすることで直接書き込み可能です。
1 |
draw.Draw(img.(*image.NRGBA64), img.Bounds(), img2, image.Point{0,0}, draw.Over) |