From 94132dd5606ac50a55a78b6bfb7e85e05a922fdf Mon Sep 17 00:00:00 2001 From: Bubu Date: Thu, 30 Jul 2020 10:32:28 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=E7=94=BB=E5=83=8F=E5=A4=89=E6=8F=9B?= =?UTF-8?q?=E3=81=AE=E5=AE=9F=E8=A3=85=E5=AE=8C=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai1/bubu/cmd/converter/converter.go | 161 +++++++++++++++++++++++++ kadai1/bubu/cmd/main.go | 45 +++++++ kadai1/bubu/go.mod | 8 ++ kadai1/bubu/go.sum | 25 ++++ 4 files changed, 239 insertions(+) create mode 100644 kadai1/bubu/cmd/converter/converter.go create mode 100644 kadai1/bubu/cmd/main.go create mode 100644 kadai1/bubu/go.mod create mode 100644 kadai1/bubu/go.sum diff --git a/kadai1/bubu/cmd/converter/converter.go b/kadai1/bubu/cmd/converter/converter.go new file mode 100644 index 0000000..2b21fd6 --- /dev/null +++ b/kadai1/bubu/cmd/converter/converter.go @@ -0,0 +1,161 @@ +/* +converter は画像変換をするパッケージになります。 +*/ +package converter + +import ( + "errors" + "fmt" + "golang.org/x/image/bmp" + "golang.org/x/image/tiff" + "image" + "image/gif" + "image/jpeg" + "image/png" + "os" + "path/filepath" + "strings" +) + +// Converter は変換元・変換後のディレクトリを表しますが、変換に関するメソッドも持っています。 +type Converter struct { + // 変換元ディレクトリ + fromDir string + // 変換後ディレクトリ + toDir string +} + +// SetDir は Convertメソッドで画像変換する変換元ディレクトリと変換先ディレクトリを指定します。 +func (c *Converter) SetDir(fromDir string, toDir string) error { + // 変換元画像ディレクトリの存在するか確認する。 + f, err := os.Stat(fromDir) + if os.IsNotExist(err) || !f.IsDir() { + return errors.New("ディレクトリが存在しないか、ディレクトリではありません。") + } + c.fromDir = fromDir + + if len(toDir) == 0 { + c.toDir = fromDir + } else { + c.toDir = toDir + } + + return nil +} + +// Convert は 指定された変換元画像フォーマットを同じく指定された変換先画像フォーマットに変換します。 +// 変換元ディレクトリと変換先ディレクトリは SetDirメソッドで指定し、変換元ディレクトリ内にあるディレクトリを +// 再帰的に検索して画像変換します。 +func (c *Converter) Convert(fromType string, toType string) error { + + fType := checkType(fromType) + if fType == "unknown" { + return errors.New("指定された変換する画像フォーマットは対応していません。") + } + + tType := checkType(toType) + if tType == "unknown" { + return errors.New("指定された変換後の画像フォーマットは対応していません。") + } + + return filepath.Walk(c.fromDir, + func(path string, info os.FileInfo, err error) error { + // 変換元ディレクトリもpathに入るので、読み飛ばす。 + if path == c.fromDir { + return nil + } + + if info.IsDir() { + // ディレクトリの場合は読み飛ばす。 + return nil + } else { + iFile, _ := os.Open(path) + defer iFile.Close() + + img, format, _ := image.Decode(iFile) + + // イメージファイルのフォーマットが指定変換元フォーマットか確認 + if fType != format { + return nil + } + + var err error + var out *os.File + + switch tType { + case "gif": + out, err = makeOutFile(path, "gif", c.fromDir, c.toDir) + if err == nil { + err = gif.Encode(out, img, nil) + } + case "jpeg": + out, err = makeOutFile(path, "jpg", c.fromDir, c.toDir) + if err == nil { + err = jpeg.Encode(out, img, nil) + } + case "png": + out, err = makeOutFile(path, "png", c.fromDir, c.toDir) + if err == nil { + err = png.Encode(out, img) + } + case "bmp": + out, err = makeOutFile(path, "bmp", c.fromDir, c.toDir) + if err == nil { + err = bmp.Encode(out, img) + } + case "tiff": + out, err = makeOutFile(path, "tiff", c.fromDir, c.toDir) + if err == nil { + err = tiff.Encode(out, img, nil) + } + } + return err + } + }) +} + +// checkType は指定された画像フォーマットが対応しているか確認します。 +func checkType(imageType string) string { + switch imageType { + case "gif": + return "gif" + case "jpeg", "jpg": + return "jpeg" + case "png": + return "png" + case "bmp": + return "bmp" + case "tiff": + return "tiff" + default: + return "unknown" + } +} + +// makeOutFile は指定されたファイルパス、変換後拡張子、ベースディレクトリから出力先ディレクトリ下に変換後の画像ディレクトリとファイルを作成します。 +func makeOutFile(filePath string, toExt string, baseDir string, toDir string) (*os.File, error) { + // ディレクトリに関する処理 + dir := filepath.Dir(filepath.Clean(filePath)) + toDir = filepath.Join(toDir, strings.Replace(dir, baseDir, "", -1)) + _, err := os.Stat(toDir) + if os.IsNotExist(err) { + if err = os.MkdirAll(toDir, 0755); err != nil { + return nil, err + } + } else if err != nil { + return nil, err + } + + // ファイルに関する処理 + ext := filepath.Ext(filePath) + fileName := filepath.Base(filePath) + outFilePath := filepath.Join(toDir, fileName[:len(fileName)-len(ext)+1]+toExt) + _, err = os.Stat(outFilePath) + if os.IsNotExist(err) { + f, err := os.Create(outFilePath) + return f, err + } else if err != nil { + return nil, err + } + return nil, fmt.Errorf("変換先ファイルが存在しているので変換を行いません。:%s", filePath) +} diff --git a/kadai1/bubu/cmd/main.go b/kadai1/bubu/cmd/main.go new file mode 100644 index 0000000..5057178 --- /dev/null +++ b/kadai1/bubu/cmd/main.go @@ -0,0 +1,45 @@ +/* +main は画像変換のmainパッケージです。 + +実行時のコマンドライン引数は下記になります。 + + -ft: + 変換する画像の形式(gif, jpeg, jpg, png, bmp, tiff) + -fdir: + 変換する画像の保存しているディレクトリ + -tt: + 変換後の画像の形式(gif, jpeg, jpg, png, bmp, tiff) + -tdir: + 変換後の画像を保存するディレクトリ +*/ +package main + +import ( + "bubu/cmd/converter" + "flag" + "fmt" + "os" +) + +// main は画像変換のメイン処理となり、コマンドライン引数の値をConverterに渡して、画像変換を実行します。 +func main() { + var ( + fromType = flag.String("ft", "jpeg", "変換する画像の形式 (gif, jpeg, jpg, png, bmp, tiff)") + fromDir = flag.String("fdir", "", "変換する画像の保存しているディレクトリ") + toType = flag.String("tt", "png", "変換後の画像の形式 (gif, jpeg, jpg, png, bmp, tiff)") + toDir = flag.String("tdir", "", "変換後の画像を保存するディレクトリ") + ) + flag.Parse() + + cnv := new(converter.Converter) + cnv.SetDir(*fromDir, *toDir) + err := cnv.Convert(*fromType, *toType) + + if err != nil { + str := fmt.Sprintf("err: %s", err) + fmt.Println(str) + os.Exit(1) + } else { + os.Exit(0) + } +} diff --git a/kadai1/bubu/go.mod b/kadai1/bubu/go.mod new file mode 100644 index 0000000..51dd53d --- /dev/null +++ b/kadai1/bubu/go.mod @@ -0,0 +1,8 @@ +module bubu + +go 1.13 + +require ( + golang.org/x/image v0.0.0-20200618115811-c13761719519 + golang.org/x/tools v0.0.0-20200727233628-55644ead90ce // indirect +) diff --git a/kadai1/bubu/go.sum b/kadai1/bubu/go.sum new file mode 100644 index 0000000..b078ab9 --- /dev/null +++ b/kadai1/bubu/go.sum @@ -0,0 +1,25 @@ +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +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/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200727233628-55644ead90ce h1:HEwYEPqqa3/M0N2Q6IgtBaf2CaxvmRiVdAhX6LR7uE4= +golang.org/x/tools v0.0.0-20200727233628-55644ead90ce/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From f432ad2da550c233e79e34bb95ffa1b68c9abc86 Mon Sep 17 00:00:00 2001 From: Bubu Date: Thu, 30 Jul 2020 19:57:40 +0900 Subject: [PATCH 2/2] =?UTF-8?q?README=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=97?= =?UTF-8?q?=E3=81=A6=E3=80=81=E7=B5=82=E4=BA=86=E3=83=A1=E3=83=83=E3=82=BB?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=81=AE=E5=87=BA=E5=8A=9B=E3=82=82=E5=AF=BE?= =?UTF-8?q?=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai1/bubu/README.md | 42 +++++++++++++++++++++++++++++++++++++++++ kadai1/bubu/cmd/main.go | 4 ++-- 2 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 kadai1/bubu/README.md diff --git a/kadai1/bubu/README.md b/kadai1/bubu/README.md new file mode 100644 index 0000000..fd44267 --- /dev/null +++ b/kadai1/bubu/README.md @@ -0,0 +1,42 @@ +# 課題1 画像変換コマンドを作ろう + +## 課題仕様 + +- ディレクトリを指定する +- 指定したディレクトリ以下のJPGファイルをPNGに変換(デフォルト) +- ディレクトリ以下は再帰的に処理する +- 変換前と変換後の画像形式を指定できる(オプション) + +## 課題条件 + +- mainパッケージと分離する +- 自作パッケージと標準パッケージと準標準パッケージのみ使う + - 準標準パッケージ:golang.org/x以下のパッケージ +- ユーザ定義型を作ってみる +- GoDocを生成してみる +- Go Modulesを使ってみる + +## どう動かすのか? +```shell script +$ go build -o conv + +$ ./conv -h +Usage of ./conv: + -fdir string + 変換する画像の保存しているディレクトリ + -ft string + 変換する画像の形式 (gif, jpeg, jpg, png, bmp, tiff) (default "jpeg") + -tdir string + 変換後の画像を保存するディレクトリ + -tt string + 変換後の画像の形式 (gif, jpeg, jpg, png, bmp, tiff) (default "png") + +# hogeディレクトリのjpeg形式のファイルをfugaディレクトにpng形式ファイルに変換して出力する。 +$ ./conv -ft=jpg -fdir=./hoge -tt=png -tdir=./fuga +Ok! +``` + +## 悩んだ事 +- とりあえず、どんなディレクトリ構成がいいのか?で悩みました。 +- もう少しスマートなエラー処理が書けないものかと…。 +- やはりGoらしい書き方ってとは? \ No newline at end of file diff --git a/kadai1/bubu/cmd/main.go b/kadai1/bubu/cmd/main.go index 5057178..b3249c0 100644 --- a/kadai1/bubu/cmd/main.go +++ b/kadai1/bubu/cmd/main.go @@ -36,10 +36,10 @@ func main() { err := cnv.Convert(*fromType, *toType) if err != nil { - str := fmt.Sprintf("err: %s", err) - fmt.Println(str) + fmt.Println("err:", err) os.Exit(1) } else { + fmt.Println("Ok!") os.Exit(0) } }