質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

Q&A

解決済

2回答

2942閲覧

Go言語での画像処理に使えるモジュールの存在について

belgh

総合スコア27

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

0グッド

0クリップ

投稿2021/08/16 01:18

コーディングと言うより、モジュールに関する知見をお借りしたい質問です。

背景

Go言語(echo)で、webサイトからPOSTされたpng画像の無駄な透明部分をトリミングし、
その後全体が正方形になるように加工してpng出力する処理を作ろうとしています。

質問

上記の「トリミング」と「正方形への加工」について簡単に使えるモジュール、
定番のモジュールなどはあるのでしょうか。

今実装中のものは、image/pngモジュールのみを使用して
1ピクセルずつ愚直に透明度をチェックして範囲を切り抜き、
その後別画像で正方形を作ってから、画像合成で1枚の正方形のpngとして出力させようかと考えています。

go

1for y := bounds.Min.Y; y < bounds.Max.Y; y++ { 2 for x := bounds.Min.X; x < bounds.Max.X; x++ { 3 r, g, b, a := img.At(x, y).RGBA() 4 5 // aが1以上のピクセルを境界として最小/最大のxyを算出しトリミング範囲を測定 6 } 7}

実装しながらも、画像のトリミングはかなり定番だと思われ、
そういうモジュールがあるのではないかとしばらくググったのですが、見つけられませんでした。

もしご存じの方がいましたら、ご教示お願いしますm(_ _)m

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

趣味コードでそんなに大したものでもないので、変換部分を晒してしまいます。
ここって解決後にコメントできるのかわかりませんが、どなたでも、もし突っ込みがあったら宜しくおねがいします。

go

1// png画像をトリミングして正方形にリサイズ 2func resizeImage(c echo.Context, imageByte []byte) ([]byte, error) { 3 img, err := png.Decode(bytes.NewReader(imageByte)) 4 if err != nil { 5 return nil, err 6 } 7 8 bounds := img.Bounds() 9 coordinate := image.Rectangle{ 10 Min: image.Point{ 11 X: bounds.Max.X, 12 Y: bounds.Max.Y, 13 }, 14 Max: image.Point{ 15 X: bounds.Min.X, 16 Y: bounds.Min.Y, 17 }, 18 } 19 20 for y := bounds.Min.Y; y < bounds.Max.Y; y++ { 21 for x := bounds.Min.X; x < bounds.Max.X; x++ { 22 _, _, _, a := img.At(x, y).RGBA() 23 if a > 0 { 24 if x < coordinate.Min.X { 25 coordinate.Min.X = x 26 } 27 if y < coordinate.Min.Y { 28 coordinate.Min.Y = y 29 } 30 if x > coordinate.Max.X { 31 coordinate.Max.X = x 32 } 33 if y > coordinate.Max.Y { 34 coordinate.Max.Y = y 35 } 36 } 37 } 38 } 39 40 // img(image.Image)のinterfaceにSubImageが定義されていないため、再定義する 41 type SubImager interface { 42 SubImage(r image.Rectangle) image.Image 43 } 44 // 型アサーション 45 if subimg, ok := img.(SubImager); ok { 46 cropped := subimg.SubImage(coordinate) 47 48 // 縦横のサイズが異なる場合、正方形になるように加工する 49 if coordinate.Dx() != coordinate.Dy() { 50 edgeLength := coordinate.Dx() 51 if edgeLength < coordinate.Dy() { 52 edgeLength = coordinate.Dy() 53 } 54 55 background := image.NewRGBA(image.Rect(0, 0, edgeLength, edgeLength)) 56 palette := color.RGBA{0, 0, 0, 0} 57 draw.Draw(background, background.Bounds(), &image.Uniform{palette}, image.ZP, draw.Src) 58 59 // croppedは出力するまで加工前画像の属性に過ぎないため、座標補正時にトリミング範囲を引く 60 newX := (edgeLength-coordinate.Dx())/2 - coordinate.Min.X 61 newY := (edgeLength-coordinate.Dy())/2 - coordinate.Min.Y 62 63 newRect := image.Rectangle{image.Point{newX, newY}, background.Bounds().Size()} 64 draw.Draw(background, newRect, cropped, image.Point{0, 0}, draw.Src) 65 66 // 加工済みの画像で上書き 67 cropped = background 68 } 69 70 tmp := bytes.NewBuffer([]byte{}) 71 err = png.Encode(tmp, cropped) 72 if err != nil { 73 return nil, err 74 } 75 76 return tmp.Bytes(), nil 77 } 78 79 return nil, fmt.Errorf("resize failed!") 80}

投稿2021/08/21 02:34

belgh

総合スコア27

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

さっと探してみてこれそのものは見つからなかったのでわかることだけ回答します。

  • 透過A値がゼロじゃない最小最大値の範囲をスキャンする機能は用途が限定的でライブラリ実装はなかなか見つからないと思います。
  • 範囲さえ求まればImage.SubImageで切り抜くのは標準でできます。
  • おそらく質問例のやり方とImage.SubImageがベストのような気がします(他に依存ライブラリも増やさずに済む)

投稿2021/08/20 11:47

nobonobo

総合スコア3367

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

belgh

2021/08/21 02:31

ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問