Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InoAyaka / 課題1 #4

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions kadai1/InoAyaka/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# <課題1>【TRY】画像変換コマンドを作ろう
## 概要
### 次の仕様を満たすコマンドを作って下さい

- ディレクトリを指定する
- 指定したディレクトリ以下のJPGファイルをPNGに変換(デフォルト)
- ディレクトリ以下は再帰的に処理する
- 変換前と変換後の画像形式を指定できる(オプション)


### 以下を満たすように開発してください

- mainパッケージと分離する
- 自作パッケージと標準パッケージと準標準パッケージのみ使う
- 準標準パッケージ:golang.org/x以下のパッケージ
- ユーザ定義型を作ってみる
- GoDocを生成してみる
- Go Modulesを使ってみる


## 使い方
```
$ go build -o imageConv
$
$ ./imageConv -h
Usage of ./imageConv:
-af string
Image format after conversion (default "png")
-bf string
Image format before conversion (default "jpg")
-dir string
Directory containing images to be converted
$
$
```

実行例
```
$ ./imageConv -bf=png -af=gif -dir=./image
```

### 感想

- mainパッケージと自作パッケージの分離をどこにするのか悩みました。(画像変換部分のみを切り出して自作パッケージにしましたが、ディレクトリを渡して検索〜変換までの一連の処理をパッケージに纏めた方が良かったのかもしれないと考えています。)
- errの扱いについても、errを返してmainで一貫して処理を行うのか、それぞれで行うべきなのか悩んだ点になります。
- 画像変換を行うImageConverter()での、errチェックを行う部分が適切かも少し不安な点ではあります。
84 changes: 84 additions & 0 deletions kadai1/InoAyaka/converter/converter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//Package converter は指定されたパスに対し、画像変換を行います。
//(対応形式:jpg,png,gif,bmp,tiff)
package converter

import (
"fmt"
"image"
"image/gif"
"image/jpeg"
"image/png"
"os"
"regexp"
"strings"

"golang.org/x/image/bmp"
"golang.org/x/image/tiff"
)

//Args ImageConverter()を使う際に指定が必要となる引数
type Args struct {
FilePath string //変換対象となるファイル名
Bf string //変換前 画像形式
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

フィールド名は略さない

Af string //変換後 画像形式
}

//ImageConverter 指定した画像形式に変換を行います。
func ImageConverter(a Args) error {

f, err := os.Open(a.FilePath)
if err != nil {
return addFileName(err, a.FilePath)
}
defer f.Close()

//ファイルオブジェクトを画像オブジェクトに変換
img, _, err := image.Decode(f)
if err != nil {
return addFileName(err, f.Name())
}

//変換後のファイルパス
rep := regexp.MustCompile("(?i)" + a.Bf + "$")
outFilePath := rep.ReplaceAllString(f.Name(), a.Af)

//変換後ファイルの新規作成
out, err := os.Create(outFilePath)
if err != nil {
return addFileName(err, f.Name())
}

//変換する画像形式に応じてエンコードする
switch strings.ToLower(a.Af) {
case "jpg":
err = jpeg.Encode(out, img, &jpeg.Options{Quality: jpeg.DefaultQuality})
case "png":
err = png.Encode(out, img)
case "gif":
err = gif.Encode(out, img, &gif.Options{NumColors: 256, Quantizer: nil, Drawer: nil})
case "bmp":
err = bmp.Encode(out, img)
case "tiff":
err = tiff.Encode(out, img, &tiff.Options{Compression: 0, Predictor: true})
default:
fmt.Println("The specified image format is not supported. : " + f.Name())
}

//エンコード時にエラーが返ってきていないかチェック
if err != nil {
return addFileName(err, out.Name())
}

if err := out.Close(); err != nil {
return addFileName(err, out.Name())
}

return nil

}

//addFileName どのファイルでエラーになったか分かるようにerrにファイル名を付加して返します。
func addFileName(err error, f string) error {
err = fmt.Errorf("%v\nerrFile : %s", err, f)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

関数にせず、fmt.Errorf("%w: %s", out.Name())のようにラップした方がよいです。
https://golang.org/pkg/fmt/#Errorf
ログとかのことを考えるとエラーメッセージは改行入れないほうがいいです。

return err
}
5 changes: 5 additions & 0 deletions kadai1/InoAyaka/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/gopherdojo/dojo8/kadai1/InAyk

go 1.14

require golang.org/x/image v0.0.0-20200618115811-c13761719519
4 changes: 4 additions & 0 deletions kadai1/InoAyaka/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
github.com/gopherdojo/dojo8 v0.0.0-20200703052727-6a79d18126bf h1:lpYevjFQMxI5VNBc3WXV6Z5pDDrdppdDKwmeBoyt5BE=
golang.org/x/image v0.0.0-20200618115811-c13761719519 h1:1e2ufUJNM3lCHEY5jIgac/7UTjd6cgJNdatjPdFWf34=
golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
75 changes: 75 additions & 0 deletions kadai1/InoAyaka/imageConv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//画像変換を行います。
package main

import (
"flag"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/gopherdojo/dojo8/kadai1/InAyk/converter"
)

//オプション指定
var bf = flag.String("bf", "jpg", "Image format before conversion")
var af = flag.String("af", "png", "Image format after conversion")
var dir = flag.String("dir", "", "Directory containing images to be converted")

func main() {
//オプションの解析
flag.Parse()

//入力されたディレクトリのチェックをかける
if err := checkDir(); err != nil {
//入力チェックで返ってきたらエラーを出力し、プログラムを終了させる
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}

convert()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

エラー処理はしなくてよい?


}

//checkDir 指定されたディレクトリのチェックを行います。
//チェック内容:引数の値、ディレクトリの存在、ディレクトリを表しているか
func checkDir() error {
//引数の数チェック
if *dir == "" {
return fmt.Errorf("No directory specified")
}

//ディレクトリの存在チェック & ディレクトリを表しているかどうか
if m, err := os.Stat(*dir); os.IsNotExist(err) {
return err
} else if !m.IsDir() {
return fmt.Errorf("%s : not a directory", *dir)
}

return nil

}

//convert 指定ディレクトリに対し、画像変換を行います。
func convert() {

ca := converter.Args{
Bf: strings.ToLower(*bf),
Af: strings.ToLower(*af),
}

//ディレクトリを再帰的にチェック
filepath.Walk(*dir, func(path string, info os.FileInfo, err error) error {

//対象の画像形式のみ画像変換ImageConverter()の実行
if strings.ToLower(filepath.Ext(path)) == "."+*bf {
ca.FilePath = path
if err := converter.ImageConverter(ca); err != nil {
//エラーが返ってきても、エラーを表示しプログラムは続行
fmt.Fprintln(os.Stderr, err)
}
}
return nil
})

}