Skip to content

kadai1-shinta #3

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

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions kadai1/shinta/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
testdatadir
31 changes: 31 additions & 0 deletions kadai1/shinta/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# 課題1
## 次の仕様を満たすコマンドを作って下さい
- ディレクトリを指定する

- 指定したディレクトリ以下のJPGファイルをPNGに変換(デフォルト)

- ディレクトリ以下は再帰的に処理する

- 変換前と変換後の画像形式を指定できる(オプション)

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

- mainパッケージと分離する

- 自作パッケージと標準パッケージと準標準パッケージのみ使う

- ユーザ定義型を作ってみる

- GoDocを生成してみる

## 使い方
```
# build
go build -o "任意のコマンド名"
# 例
go build -o imgcov
# 実行方法(上記の例の場合)
imgcov [-d=ディレクトリ(default ./), -p=変更対象の拡張子(default jpg), -a=変更後の拡張子(default png)]
# 変換可能な拡張子として、jpg、jpeg、png、gif としています。
```

3 changes: 3 additions & 0 deletions kadai1/shinta/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/gopherdojo/dojo7/kadai1/shinta

go 1.12
161 changes: 161 additions & 0 deletions kadai1/shinta/imageconversion/imageconversion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
Package imageconversion は画像ファイル形式の変換を行います。
optionで、実行するディレクトリと変換前と変換後の画像形式を指定できます。
option を指定しない場合、コマンドを実行するディレクトリと、 変換前の画像タイプがjpeg、変換後の画像タイプがpngになります。
変換可能な拡張子として、jpg、jpeg、png、gif としています。
*/
package imageconversion

import (
"errors"
"flag"
"image"
"image/gif"
"image/jpeg"
"image/png"
"os"
"path/filepath"
"strings"
)

// judgeArgExt は引数に設定された拡張子が変換可能なものか判別する
func judgeArgExt(preExt string, afterExt string) (err error) {
allowExtList := []string{"jpg", "jpeg", "png", "gif"}
Copy link
Member

Choose a reason for hiding this comment

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

map[string]boolを使う

argExtList := []string{preExt, afterExt}
var judgeExtFlag bool
for _, argExt := range argExtList {
// 変換前の拡張子の判定結果が正しい場合、フラグを初期化する。
if judgeExtFlag {
judgeExtFlag = false
}
// 拡張子が正しい拡張子か判定する。
for _, allowExt := range allowExtList {
if allowExt == argExt {
judgeExtFlag = true
}
}
// 拡張子判定結果が正しくない場合breakする。フラグはfalseになる。
if !judgeExtFlag {
break
}
}
if !judgeExtFlag {
err = errors.New("指定できる拡張子:" + strings.Join(allowExtList, ","))
Copy link
Member

Choose a reason for hiding this comment

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

直接returnする

}
return
}

// passArgs は引数を受け取りその引数(ディレクトリ、変換前拡張子、変換後拡張子)が正しいか判別し、引数の値を返します。
func passArgs() (dir string, preExt string, afterExt string, err error) {
d := flag.String("d", "./", "対象ディレクトリ")
p := flag.String("p", "jpg", "変換前拡張子")
a := flag.String("a", "png", "変換後拡張子")
flag.Parse()
dir, preExt, afterExt = *d, *p, *a
err = judgeArgExt(preExt, afterExt)
if err != nil {
return
}
preExt = "." + preExt
afterExt = "." + afterExt
return
}

// imageFile struct は変換対象の画像のpath(path)、拡張子を除いたファイル名(base)、拡張子(ext)を持っています。
type imageFile struct {
path string
base string
ext string
}

// getFileNameWithoutExt は対象ファイルのpathと拡張子を除いたファイル名を返します。
func getFileNameWithoutExt(path string) string {
return filepath.Base(path[:len(path)-len(filepath.Ext(path))])
}

// createImgStrunct は、imageFile structを生成し、返します。
func createImgStruct(path string) (image imageFile) {
base := getFileNameWithoutExt(path)
image = imageFile{filepath.Dir(path), base, filepath.Ext(path)}
return
}

/*
convertExec は画像ファイルを引数で指定された変換後の拡張子(defaultはpng)に変換した新しい画像ファイルを生成します。
処理が成功するとnil、errorが起きた場合、errorを返します。
*/
func convertExec(path string, afterExt string) (err error) {
img := createImgStruct(path)
targetImg, err := os.Open(img.path + "/" + img.base + img.ext)
if err != nil {
return err
}
readImg, _, err := image.Decode(targetImg)
if err != nil {
return err
}
outputImg, err := os.Create((img.path + "/" + img.base + afterExt))
if err != nil {
return err
}

switch afterExt {
case "jpeg", "jpg":
jpeg.Encode(outputImg, readImg, nil)
case "gif":
gif.Encode(outputImg, readImg, nil)
default:
png.Encode(outputImg, readImg)
}

targetImg.Close()
outputImg.Close()
Copy link
Member

Choose a reason for hiding this comment

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

エラー処理

return
Copy link
Member

Choose a reason for hiding this comment

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

不要

}

/*
convertImages は、引数で指定されたディレクトリ以下から引数で指定した変換前拡張子(defaultはjpg)のファイルを、
変換後拡張子(defaultはpng)に変換した新しい画像ファイルを生成します。
処理が成功するとnil、errorが起きた場合、errorを返します。
*/
func convertImages(dir string, preExt string, afterExt string) (err error) {
// 変換対象ファイルが jpeg or jpg かを確認する
jpgType := [2]string{".jpg", ".jpeg"}
Copy link
Member

Choose a reason for hiding this comment

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

jpgType := map[string]bool{".jpg", ".jpeg"} なら if jpgType[preExt] {} で判断できる

Copy link
Author

Choose a reason for hiding this comment

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

コメントに記載のvalue無しではなく、下記のように宣言するということであってますでしょうか?(missing key in map literal エラーになるので)

jpgType := map[string]bool{".jpg": ture, ".jpeg": true} 

var jpgFlag bool
for _, v := range jpgType {
if preExt == v {
jpgFlag = true
}
}
err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// jpeg は jpgも変換対象とする
Copy link
Member

Choose a reason for hiding this comment

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

以下、すべて対象
jpg -> jpg
jpeg -> jpeg
jpg -> jpeg
jpeg -> jpg

if jpgFlag && filepath.Ext(path) == ".jpeg" || filepath.Ext(path) == ".jpg" {
convertExec(path, afterExt)
}
if filepath.Ext(path) == preExt {
convertExec(path, afterExt)
}
return nil
})
return
Copy link
Member

Choose a reason for hiding this comment

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

return errする

}

/*
Excute は画像変換処理を実行します。
このpackageで呼び出せる唯一の関数です。
引数で、ディレクトリ(デフォルトは ./)、変換前拡張子(デフォルトは jpg)、変換後拡張子(デフォルトは png)を受け取ります。
引数が指定されない場合はデフォルトの値が適用されます。
引数で受け取ったディレクトリ以下の変換前拡張子のファイルを変換後拡張子に変換した新しいファイルを作成します。
処理が成功の場合、nilをerrorが起きた場合はerrorを返します。
*/
func Excute() error {
dir, preExt, afterExt, err := passArgs()
if err != nil {
return err
}
err = convertImages(dir, preExt, afterExt)
return err
}
15 changes: 15 additions & 0 deletions kadai1/shinta/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package main

import (
"fmt"
"os"

"github.com/gopherdojo/dojo7/kadai1/shinta/imageconversion"
)

func main() {
err := imageconversion.Excute()
if err != nil {
fmt.Fprintln(os.Stderr, err)
Copy link
Member

Choose a reason for hiding this comment

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

os.Exitで終了コードを指定する

}
}