-
Notifications
You must be signed in to change notification settings - Fork 0
Kadai1 segakazzz #1
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
base: master
Are you sure you want to change the base?
Changes from 2 commits
466d5d2
e019888
98dc649
400ec05
b08eea3
6292c2d
d2e6999
d832ddf
7fa0043
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.idea | ||
image/in/* | ||
image/out/* | ||
image/*.jpg | ||
image/*.png | ||
kadai1-segakazzz | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# 課題 1 画像変換コマンドを作ろう | ||
|
||
## 課題内容 | ||
|
||
### 次の仕様を満たすコマンドを作って下さい | ||
|
||
- ディレクトリを指定する | ||
- 指定したディレクトリ以下の JPG ファイルを PNG に変換(デフォルト) | ||
- ディレクトリ以下は再帰的に処理する | ||
- 変換前と変換後の画像形式を指定できる(オプション) | ||
|
||
### 以下を満たすように開発してください | ||
|
||
- main パッケージと分離する | ||
- 自作パッケージと標準パッケージと準標準パッケージのみ使う | ||
- 準標準パッケージ:golang.org/x 以下のパッケージ | ||
- ユーザ定義型を作ってみる | ||
- GoDoc を生成してみる | ||
- Go Modules を使ってみる | ||
|
||
## 回答・動作例 | ||
|
||
- 自作パッケージとして github.com/gopherdojo/dojo8/kadai1/segakazzz/imgconv を作成 | ||
- imgconv.RunConverter()でメインの処理を実行 | ||
- -d オプションで指定したディレクトリの画像をソースとして使用する | ||
- -d オプションで指定したディレクトリ内に out フォルダが作成され、出力される | ||
- -i オプションで入力画像の 拡張子を指定可能(jpg or png) デフォルトは jpg | ||
- -o オプションで出力画像の拡張子を指定可能(png or jpg) デフォルトは png | ||
- (補足) image フォルダ内の download.zsh 実行して、[The Cat API](https://thecatapi.com/) から jpg ファイルを 10 個ダウンロード可能 | ||
|
||
### 動作例 main.go | ||
|
||
``` | ||
$ go build -o kadai1-segakazzz | ||
$ ./kadai1-segakazzz -d [imagedir] -i [jpg|png] -o [png|jpg] | ||
``` | ||
|
||
``` | ||
package main | ||
|
||
import "github.com/gopherdojo/dojo8/kadai1/segakazzz/imgconv" | ||
|
||
func main() { | ||
imgconv.RunConverter() | ||
} | ||
|
||
``` | ||
|
||
### 感想等 | ||
|
||
- Go Modules については、使用するパッケージのバージョン管理に使用されるものと理解しましたが、今回使用したパッケージは標準パッケージのみで、バージョンを指定する必要はなさそうでしたので require の部分は書いていません。 | ||
- パッケージの書き方の標準を理解しておらず、勘に頼っているところがあるので、良い書き方を知りたいです。 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module github.com/gopherdojo/dojo8/kadai1/segakazzz | ||
|
||
go 1.14 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
github.com/gopherdojo/dojo8 v0.0.0-20200703052727-6a79d18126bf h1:lpYevjFQMxI5VNBc3WXV6Z5pDDrdppdDKwmeBoyt5BE= |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#!/bin/zsh | ||
|
||
curl https://cdn2.thecatapi.com/images/8er.jpg > 001.jpg | ||
curl https://cdn2.thecatapi.com/images/ceh.jpg > 002.jpg | ||
curl https://cdn2.thecatapi.com/images/MTU2MjQ4NA.jpg > 003.jpg | ||
curl https://cdn2.thecatapi.com/images/5qc.jpg > 004.jpg | ||
curl https://cdn2.thecatapi.com/images/962.jpg > 005.jpg | ||
curl https://cdn2.thecatapi.com/images/MTc2Mzc0Mw.jpg > 006.jpg | ||
curl https://cdn2.thecatapi.com/images/bos.jpg > 007.jpg | ||
curl https://cdn2.thecatapi.com/images/SX2DvLw7u.jpg > 008.jpg | ||
curl https://cdn2.thecatapi.com/images/9eh.jpg > 009.jpg | ||
curl https://cdn2.thecatapi.com/images/7bo.jpg > 010.jpg |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module github.com/gopherdojo/dojo8/kadai1/segakazzz/imgconv | ||
|
||
go 1.14 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
// Package imgconv is for Gopher Dojo Kadai1 | ||
package imgconv | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"image" | ||
"image/jpeg" | ||
"image/png" | ||
"io/ioutil" | ||
"log" | ||
"os" | ||
"path/filepath" | ||
"regexp" | ||
"strings" | ||
) | ||
|
||
type converter struct { | ||
dirname string | ||
input string | ||
output string | ||
} | ||
|
||
// RunConverter converts all image files in the directory which you indicate with -d option. | ||
// If the process is completed succeessfully, you will see the list of output files and "Done!" | ||
// message in the standard output. | ||
func RunConverter() { | ||
var ( | ||
dir = flag.String("d", ".", "Indicate directory to convert") | ||
in = flag.String("i", "jpg", "Indicate input image file's extension") | ||
out = flag.String("o", "png", "Indicate output image file's extension") | ||
err error | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ここで定義しなくても、36行目で定義されます。 |
||
) | ||
|
||
flag.Parse() | ||
c, err := newConverter(*dir, *in, *out) | ||
if err != nil { | ||
log.Fatal(err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
err = c.Convert() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
fmt.Println("Done!") | ||
|
||
} | ||
|
||
func newConverter(dirname string, input string, output string) (*converter, error) { | ||
switch input { | ||
case "jpg", "png": | ||
input = strings.ToLower(input) | ||
default: | ||
return &converter{}, fmt.Errorf("Input extension is not valid. Select one from jpg/png") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. エラーの際は最後の戻り値以外はゼロ値(この場合はポインタなので |
||
} | ||
switch output { | ||
case "jpg", "png": | ||
output = strings.ToLower(output) | ||
default: | ||
return &converter{}, fmt.Errorf("Output extension is not valid. Select one from jpg/png") | ||
} | ||
|
||
if input == output { | ||
return &converter{}, fmt.Errorf("Input and Output extensiton is the same. No convertion is needed") | ||
} | ||
return &converter{dirname: dirname, input: input, output: output}, nil | ||
} | ||
|
||
// Convert method converts all jpg files in dirname to png. "out" folder is generated if it doesn't exist. | ||
func (c *converter) Convert() (e error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 名前付き戻り値は必要な時以外は使わない |
||
files, e := c.getSourceFiles() | ||
if e != nil { | ||
return | ||
} | ||
e = c.convertFiles(files) | ||
if e != nil { | ||
return | ||
} | ||
return nil | ||
} | ||
|
||
func (c *converter) getSourceFiles() ([]os.FileInfo, error) { | ||
files, err := ioutil.ReadDir(c.dirname) | ||
if err != nil { | ||
return []os.FileInfo{}, err | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
return files, nil | ||
} | ||
|
||
func (c *converter) convertFiles(files []os.FileInfo) (e error) { | ||
re, e := regexp.Compile("." + c.input + "$") | ||
if e != nil { | ||
return | ||
} | ||
for _, file := range files { | ||
if re.MatchString(file.Name()) { | ||
e = c.convertSingle(file.Name()) | ||
if e != nil { | ||
return | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func (c *converter) convertSingle(filename string) (e error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 何を |
||
input := filepath.Join(c.dirname, filename) | ||
outDir := filepath.Join(c.dirname, "out") | ||
output := filepath.Join(outDir, strings.Replace(strings.ToLower(filename), "."+c.input, "."+c.output, -1)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
fmt.Println(output) | ||
if !c.dirExists(outDir) { | ||
os.Mkdir(outDir, 0755) | ||
} | ||
|
||
in, _ := os.Open(input) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. エラーは絶対無視しない |
||
var out *os.File | ||
if c.fileExists(output) { | ||
out, e = os.OpenFile(output, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) | ||
if e != nil { | ||
return | ||
} | ||
} else { | ||
out, e = os.Create(output) | ||
if e != nil { | ||
return | ||
} | ||
} | ||
defer in.Close() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
defer out.Close() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
var ( | ||
img image.Image | ||
) | ||
switch c.input { | ||
case "jpg": | ||
img, e = jpeg.Decode(in) | ||
case "png": | ||
img, e = png.Decode(in) | ||
} | ||
|
||
if e != nil { | ||
return | ||
} | ||
switch c.output { | ||
case "png": | ||
e = png.Encode(out, img) | ||
case "jpg": | ||
e = jpeg.Encode(out, img, nil) | ||
} | ||
if e != nil { | ||
return | ||
} | ||
return nil | ||
} | ||
|
||
func (c *converter) fileExists(filename string) bool { | ||
info, err := os.Stat(filename) | ||
if os.IsNotExist(err) { | ||
return false | ||
} | ||
return !info.IsDir() | ||
} | ||
|
||
func (c *converter) dirExists(dirname string) bool { | ||
info, err := os.Stat(dirname) | ||
if os.IsNotExist(err) { | ||
return false | ||
} | ||
return info.IsDir() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package main | ||
|
||
import "github.com/gopherdojo/dojo8/kadai1/segakazzz/imgconv" | ||
|
||
func main() { | ||
imgconv.RunConverter() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
テスト用のデータはtestdata以下に置くと良いです。