画像のリサイズ
まずは画像の縦横のサイズを半分にしてみます。
package main import ( "flag" "fmt" "image" "image/jpeg" "os" "golang.org/x/image/draw" ) func main() { flag.Parse() args := flag.Args() f, err := os.Open(args[0]) if err != nil { fmt.Println("open:", err) return } defer f.Close() img, _, err := image.Decode(f) if err != nil { fmt.Println("decode:", err) return } fso, err := os.Create(args[1]) if err != nil { fmt.Println("create:", err) return } defer fso.Close() rct := img.Bounds() dst := image.NewRGBA(image.Rect(0, 0, rct.Dx() / 2, rct.Dy() / 2)) // ここで 1/2 のサイズ指定をしている draw.CatmullRom.Scale(dst, dst.Bounds(), img, rct, draw.Over, nil) jpeg.Encode(fso, dst, &jpeg.Options{Quality: 100}) }
元の画像が 150x150 なので 1/2 することで 75x75 の画像が出来上がります。
それが下記の画像
元画像 | 切り取り後 |
今回は width と height 両方を 1/2 しましたが image.Rect(0, 0, rct.Dx() / 2, rct.Dy() / 2) の部分を image.Rect(0, 0, 100, 50) などに変更すると下記のような画像が出来上がります
元画像 | 切り取り後 |
アスペクト比を無視して縮小が行われるので潰れた画像が出来上がってしまう。
そこでアスペクト比を維持したまま長辺のサイズを指定するというのを実現するのが下記のコード
// 上記の defer fso.Close() まで略 arg, _ := strconv.ParseFloat(args[2], 64) rct := img.Bounds() var w, h int if rct.Dx() > rct.Dy() { // 横長画像 m := arg / float64(rct.Dx()) w = int(arg) h = int(float64(rct.Dy()) * m) } else { // 縦長画像 m := arg / float64(rct.Dy()) w = int(float64(rct.Dx()) * m) h = int(arg) } dst := image.NewRGBA(image.Rect(0, 0, w, h)) draw.CatmullRom.Scale(dst, dst.Bounds(), img, rct, draw.Over, nil) jpeg.Encode(fso, dst, &jpeg.Options{Quality: 100}) }
わかりやすいように横長の画像を使用
150 × 84 を使用して下記のように長辺(今回は横)を 100 で指定する
$ go run main.go test.jpg out.jpg 100
すると下記のような 100 × 56 が出来上がる
元画像 | 切り取り後 |
終わりに
前回の記事の内容と組み合わせると golang だけで様々な画像加工ができるのではないでしょうか?
計算とかめんどくさいという人は https://github.com/nfnt/resize を使うのも良いかもしれません。