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

課題1 #27

Open
wants to merge 2 commits 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
42 changes: 42 additions & 0 deletions kadai1/bubu/README.md
Original file line number Diff line number Diff line change
@@ -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らしい書き方ってとは?
161 changes: 161 additions & 0 deletions kadai1/bubu/cmd/converter/converter.go
Original file line number Diff line number Diff line change
@@ -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)
}
45 changes: 45 additions & 0 deletions kadai1/bubu/cmd/main.go
Original file line number Diff line number Diff line change
@@ -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 {
fmt.Println("err:", err)
os.Exit(1)
} else {
fmt.Println("Ok!")
os.Exit(0)
}
}
8 changes: 8 additions & 0 deletions kadai1/bubu/go.mod
Original file line number Diff line number Diff line change
@@ -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
)
25 changes: 25 additions & 0 deletions kadai1/bubu/go.sum
Original file line number Diff line number Diff line change
@@ -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=