画像形式の変換
最初は画像形式の変換の説明
jpg を png にしたり webp にしたりなどです。
ちなみに Golang では webp の Encode は標準でサポートされていないので今回は https://github.com/chai2010/webp を使用します。
package main
import (
"flag"
"fmt"
"github.com/chai2010/webp"
"image"
"image/gif"
"image/jpeg"
"image/png"
"os"
"strings"
)
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()
slice := strings.Split(args[1], ".")
switch slice[len(slice)-1] {
case "jpeg", "jpg":
jpeg.Encode(fso, img, &jpeg.Options{})
case "png":
png.Encode(fso, img)
case "gif":
gif.Encode(fso, img, nil)
case "webp":
webp.Encode(fso, img, &webp.Options{Lossless: true})
default:
}
}
こんなコードを用意して下記のように実行すると変換されます。
$ go run main.go test.jpg hoge.png
$ go run main.go test.jpg hoge.webp
元画像 |
変換後(gif) |
|
|
画像の切り抜き
続いて画像の一部を切り抜く方法を説明
package main
import (
"fmt"
"image"
"image/jpeg"
"os"
)
type SubImager interface {
SubImage(r image.Rectangle) image.Image
}
func main() {
f, err := os.Open("test.jpg")
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("out.jpg")
if err != nil {
fmt.Println("create:", err)
return
}
defer fso.Close()
cimg := img.(SubImager).SubImage(image.Rect(50, 0, 150, 100))
jpeg.Encode(fso, cimg, &jpeg.Options{Quality: 100}) // Quality を指定しないと荒すぎる画像が出来上がるよ
}
image.Rect で横は 50px ~ 150px 縦は 0px ~ 100px まで切り取るという指定をしています。
こうして出来上がったのが下記の画像
元画像 |
切り取り後 |
|
|
画像の合成
最後に画像の合成
2 つの画像を重ね合わせるなどして合成する方法を説明します。
package main
import (
"fmt"
"golang.org/x/image/draw"
"image"
"image/color"
"image/jpeg"
"os"
)
type SubImager interface {
SubImage(r image.Rectangle) image.Image
}
func main() {
f, err := os.Open("test.jpg")
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("out.jpg")
if err != nil {
fmt.Println("create:", err)
return
}
defer fso.Close()
m := image.NewRGBA(image.Rect(0, 0, 200, 200))
c := color.RGBA{0, 0, 255, 255}
draw.Draw(m, m.Bounds(), &image.Uniform{c}, image.ZP, draw.Src)
rct := image.Rectangle{image.Point{25, 25}, m.Bounds().Size()}
draw.Draw(m, rct, img, image.Point{0, 0}, draw.Src)
jpeg.Encode(fso, m, &jpeg.Options{Quality: 100})
}
こうして出来上がったのが下記の画像
元画像 |
合成後 |
|
|
上記では青い画像を作成して合成を行なったがもちろん既存の画像を使うことも可能で下記のように書く
// 上記の defer fso.Close() まで略
f2, _ := os.Open("hoge.jpg") // 元になる画像
img2, _, _ := image.Decode(f2)
rgba := image.NewRGBA(image.Rectangle{image.Point{0, 0}, image.Point{200, 200}}) // RGB形式の画像を用意する
draw.Draw(rgba, image.Rectangle{image.Point{0, 0}, img2.Bounds().Size()}, img2, image.Point{0, 0}, draw.Src) // 元になる画像を描画する
rct := image.Rectangle{image.Point{25, 25}, img2.Bounds().Size()} // 元画像への描画位置を決める
draw.Draw(rgba, rct, img, image.Point{0, 0}, draw.Src) // 乗せる画像を描画
jpeg.Encode(fso, rgba, &jpeg.Options{Quality: 100})
}
これで出来上がるのが下記の画像
終わりに
ちょっと長くなってしまったので今日はここまで
続きは次週とかに書くかもしれない