GUIプログラミングやゲームでなくとも、画像をリサイズしたい時がありますよね。当ブログでは、1つの元となる画像からレスポンシブ対応するためにリサイズして複数サイズの画像を生成しています。
Go言語では、画像を簡単にリサイズしてアルゴリズムも指定できる素晴らしいライブラリがあるので、今回はそれをご紹介していきます。
今回は横幅1280px、縦幅765pxの『test.jpg』という画像ファイルを用意し、それを読み込んで横幅を300pxに縮小し、『test1.jpg』という名前でファイルに保存しています。
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 | package main import ( "image/jpeg" "log" "os" "github.com/nfnt/resize" ) func main() { file, err := os.Open("test.jpg") if err != nil { log.Fatal(err) } img, err := jpeg.Decode(file) if err != nil { log.Fatal(err) } file.Close() m := resize.Resize(300, 0, img, resize.Lanczos3) out, err := os.Create("test1.jpg") if err != nil { log.Fatal(err) } defer out.Close() err = jpeg.Encode(out, m, nil) if err != nil { log.Fatal(err) } } |
では、コードを解説していきます。
1 2 3 4 5 6 7 | import ( "image/jpeg" "log" "os" "github.com/nfnt/resize" ) |
『image/jpeg』は jpeg画像を扱うためのパッケージです。『log』はログを出力するために、『os』は OSの様々な機能を使うためのパッケージであり、今回はファイルを開いたり、新規作成するために使用します。
『github.com/nfnt/resize』は画像をリサイズするためのライブラリで、以下のコマンドでダウンロードとインストールをしておいてください。
go get github.com/nfnt/resize
1 2 3 4 | file, err := os.Open("test.jpg") if err != nil { log.Fatal(err) } |
『os』パッケージの『Open』関数の第一引数にファイル名である『test.jpge』を指定して開きます。戻り値の『file』はファイルデスクリプタで、ファイルからデータを読み込んだり書き込むのに必要となります。
1 2 3 4 5 | img, err := jpeg.Decode(file) if err != nil { log.Fatal(err) } file.Close() |
『jpeg』パッケージの『Decode』関数に、先ほどの『file』を渡してデコードして画像データを取り込みます。jpeg画像は圧縮されているので、元の画像データに戻す必要があり、この戻す操作をデコードと言います。
最後は『Close』関数を読んで閉じておいてください。
1
| m := resize.Resize(300, 0, img, resize.Lanczos3) |
『resize』パッケージの『Resize』関数を使って画像のリサイズを行います。
第一引数にリサイズ後の横幅を指定します。第二引数にはリサイズ後の縦幅を指定するのですが、ゼロを指定すると横幅に合わせて縦横の比率を保ったままリサイズされます。
第三引数にはデコードした画像データを渡し、最後にアルゴリズムを指定します。今回は『Lanczos3』を指定しました。
1 2 3 4 5 | out, err := os.Create("test1.jpg") if err != nil { log.Fatal(err) } defer out.Close() |
『os』パッケージの『Create』関数に新規作成したいファイル名を指定して、リサイズした画像データを保存するためのファイルを用意します。
用が済んだら自動的に閉じるように『defer out.Close()』を書いておきます。
1 2 3 4 | err = jpeg.Encode(out, m, nil) if err != nil { log.Fatal(err) } |
『jpeg』パッケージの『Encode』関数を使って、画像データをjpegにエンコードします。
第一引数に保存する先のファイル、第二引数に画像データ、第三引数にはクオリティーを指定します。クオリティーは0〜100まであり、より圧縮したい場合は70〜80くらいを指定すると良いかもしれません。
クオリティーの指定には次のような構造体を使用します。
1 2 3 | type Options struct { Quality int } |
アルゴリズム別に出力された画像の容量などをざっくり比較していきます。まずは元画像を、そして出力画像容量が小さかった順にご紹介していきます。
元画像は先ほどのコードでも使用した横幅1280px、縦幅765pxのものです。以下のリサイズ後の画像は横幅を800pxにして縮小しています。
25,580byte
26,160byte
27,093byte
27,293byte
27,318byte
27,591byte
文字や線画、写真等で最適なアルゴリズムは異なりそうですが、Bilinear が一番サイズが小さくなりました。Lancros3 が一番大きいですね。
横幅を300pxにしての縮小も試してみると『NearestNeighhor』で出力された画像が『Lancros2』の次に容量の大きなものとなり、縮小サイズによっては多少の変動があるかもしれません。
ぱっと見では、どの画像も同じような感じですね(笑)
今回使用したライブラリ『nfnt/resize』は画像のリサイズとしても使えますし、クオリティーの数値を変えたりすれば更なる圧縮も可能なものです。
フォルダの中にある画像を全て、サーバーにアップロードした画像を全て、リサイズしたり圧縮する際に活用してみてはいかがでしょうか。