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

# Wataru / boru 課題1 #2

Open
wants to merge 3 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
2 changes: 2 additions & 0 deletions kadai1/wataboru/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.idea
.DS_Store
52 changes: 52 additions & 0 deletions kadai1/wataboru/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# 課題 1 【TRY】画像変換コマンドを作ろう

## 次の仕様を満たすコマンドを作って下さい

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

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

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

### 動作手順

```
$ go build -o imgconv
$ ./imgconv -h
Usage of ./imgconv:
-a string
Input extension after conversion. (short) (default "png")
-after --after=jpg
Input extension after conversion.
ex) --after=jpg (default "png")
-b string
Input extension before conversion. (short) (default "jpg")
-before --before=png
Input extension before conversion.
ex) --before=png (default "jpg")
-d string
Input target Directory. (short)
-dir --dir=./convert_image
Input target Directory.
ex) --dir=./convert_image
$ ./imgconv -d ./testdate
or
$ ./imgconv -d ./testdate -b png -a gif
or
$ ./imgconv -d ./testdate -b jpeg -a tiff
```

### 感想等

- 前提として、@tenntennさんの公開されている[handsonプロジェクト](https://github.com/tenntenn/gohandson/tree/master/imgconv/ja)と似ている内容でして、以前やったことがありました。
- そちらに無い部分として、tiff変換やbmp変換の追加などを行いました。
- GoModulesを利用したく、`golang.org/x/image`を導入しました
Copy link
Member

Choose a reason for hiding this comment

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

👍

- 様々なソースをみていると、変数名やコマンド名が自分は冗長かな?と感じています。Go話者の方は短く記載するものなのでしょうか。
55 changes: 55 additions & 0 deletions kadai1/wataboru/commands/imageconverter/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package main

import (
"github.com/gopherdojo/dojo8/kadai1/wataboru/imageconverter"

"flag"
"fmt"
"os"
)

const (
// ExitCodeSuccess is the exit code on success
ExitCodeSuccess = 0
// ExitCodeError is the exit code when failed
ExitCodeError = 1
// ExitCodeError is the exit code when failed
ExitCodeInvalidDirectoryError = 2
)

var (
args imageconverter.Args
)

func init() {
flag.StringVar(&args.Directory, "dir", "", "Input target Directory.\n ex) `--dir=./convert_image`")
flag.StringVar(&args.Directory, "d", "", "Input target Directory. (short)")
flag.StringVar(&args.BeforeExtension, "before", "jpg", "Input extension before conversion.\n ex) `--before=png`")
flag.StringVar(&args.BeforeExtension, "b", "jpg", "Input extension before conversion. (short)")
flag.StringVar(&args.AfterExtension, "after", "png", "Input extension after conversion.\n ex) `--after=jpg`")
flag.StringVar(&args.AfterExtension, "a", "png", "Input extension after conversion. (short)")
flag.Parse()
}

func run() int {
if args.Directory == "" {
fmt.Fprintln(os.Stderr, "Input target Directory.\n ex) `--dir=./convert_image`")
return ExitCodeInvalidDirectoryError
}

if _, err := os.Stat(args.Directory); os.IsNotExist(err) {
fmt.Fprintln(os.Stderr, "Target directory is not found.")
return ExitCodeInvalidDirectoryError
}

if err := imageconverter.Convert(args); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
return ExitCodeError
}

return ExitCodeSuccess
}

func main() {
os.Exit(run())
}
5 changes: 5 additions & 0 deletions kadai1/wataboru/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/gopherdojo/dojo8/kadai1/wataboru

go 1.14

require golang.org/x/image v0.0.0-20200618115811-c13761719519
3 changes: 3 additions & 0 deletions kadai1/wataboru/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
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=
84 changes: 84 additions & 0 deletions kadai1/wataboru/imageconverter/ImageConverter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package imageconverter

import (
"fmt"
"image"
"image/gif"
"image/jpeg"
"image/png"
"os"
"path/filepath"
"strings"

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

type Args struct {
Directory string
BeforeExtension string
AfterExtension string
}

func convertImage(source, dest string) (err error) {
sourceFile, err := os.Open(source)
if err != nil {
return fmt.Errorf("file could not be opened. target: %s", source)
}
defer sourceFile.Close()

destFile, err := os.Create(dest)
if err != nil {
return fmt.Errorf("image file could not be created. target: %s", dest)
}

defer func(returnErr error) {
if returnErr == nil {
err = destFile.Close()
Copy link
Author

Choose a reason for hiding this comment

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

@tenntenn
こちら、分かる限り修正してみました。
一点質問がありまして、defer内で呼び出し元にエラーを返す処理を実現するため、名前付き戻り値を使ってしまっています。

他の方のレビューの中で、「何をreturnしたか追いづらいので、名前付き戻り値はできるだけ使わない。」とあったので、名前付き戻り値を使わずにどのように呼び出し元にエラーを返したら良いか教えていただきたいです。

Copy link
Member

Choose a reason for hiding this comment

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

このパターンのみ使わないとどうにもならないので使っても大丈夫です!

Copy link
Author

Choose a reason for hiding this comment

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

@tenntenn
なるほど!そうなんですね。
一応その他の場所は明示的にreturnに渡す様にしました。

}
}(err)

img, _, err := image.Decode(sourceFile)
if err != nil {
return err
}

switch strings.ToLower(filepath.Ext(dest)) {
case ".png":
err = png.Encode(destFile, img)
case ".jpg", ".jpeg":
err = jpeg.Encode(destFile, img, &jpeg.Options{Quality: jpeg.DefaultQuality})
case ".gif":
err = gif.Encode(destFile, img, &gif.Options{256, nil, nil})
case ".bmp":
err = bmp.Encode(destFile, img)
case ".tiff":
err = tiff.Encode(destFile, img, nil)
default:
err = fmt.Errorf("image file could not be created due to an unknown extension. target: %s", dest)
}

return err
}

// 指定したディレクトリ以下のJPGファイルをPNGに変換(デフォルト)
// ディレクトリ以下は再帰的に処理する
// 変換前と変換後の画像形式を指定できる(オプション)
func Convert(args Args) error {
return filepath.Walk(args.Directory, func(path string, info os.FileInfo, err error) error {
if err != nil {
return fmt.Errorf("prevent panic by handling failure accessing a path %q: %v\n", path, err)
}

ext := strings.ToLower(filepath.Ext(path))
if "."+args.BeforeExtension != ext {
return nil
}

return convertImage(path, replaceExt(info.Name(), "."+args.AfterExtension))
})
}

func replaceExt(filePath, toExt string) string {
return filePath[:len(filePath)-len(filepath.Ext(filePath))] + toExt
}
Binary file added kadai1/wataboru/testdata/free-icon.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added kadai1/wataboru/testdata/sub/free-icon.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.