Skip to content

Commit e43488f

Browse files
committed
create kadai1/hokita
1 parent 6a79d18 commit e43488f

File tree

11 files changed

+284
-0
lines changed

11 files changed

+284
-0
lines changed

kadai1/hokita/README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# 課題 1 画像変換コマンドを作ろう
2+
3+
## 課題内容
4+
### 次の仕様を満たすコマンドを作って下さい
5+
6+
- ディレクトリを指定する
7+
- 指定したディレクトリ以下の JPG ファイルを PNG に変換(デフォルト)
8+
- ディレクトリ以下は再帰的に処理する
9+
- 変換前と変換後の画像形式を指定できる(オプション)
10+
11+
### 以下を満たすように開発してください
12+
13+
- main パッケージと分離する
14+
- 自作パッケージと標準パッケージと準標準パッケージのみ使う
15+
- 準標準パッケージ:golang.org/x 以下のパッケージ
16+
- ユーザ定義型を作ってみる
17+
- GoDoc を生成してみる
18+
- Go Modules を使ってみる
19+
20+
## 対応したこと
21+
- 画像を変換
22+
- 現状はjpg, pngのみ
23+
- jpg, png以外はエラー表示
24+
- 画像出力先は対象画像と同じディレクトリ
25+
- 指定したディレクトリが無いとエラーを表示
26+
27+
## 動作
28+
```shell
29+
$ go build -o test_imgconv
30+
31+
$ ./test_imgconv -h
32+
Usage of ./test_imgconv:
33+
-from string
34+
Conversion source extension. (default "jpg")
35+
-to string
36+
Conversion target extension. (default "png")
37+
38+
# testdata内のすべてのjpgファイルをpngに変換する
39+
$ ./test_imgconv testdata
40+
Conversion finished!
41+
42+
# testdata内のすべてのpngファイルをjpgに変換する
43+
$ ./test_imgconv -from png -to jpg testdata
44+
Conversion finished!
45+
46+
# ディレクトリの指定が無い場合はエラー
47+
$ ./test_imgconv
48+
Please specify a directory.
49+
50+
# 存在しないディレクトリの場合はエラー
51+
$ ./test_imgconv non_exist_dir
52+
Cannot find directory.
53+
54+
# 対応していない拡張子の場合はエラー
55+
$ ./test_imgconv -from txt -to jpg testdata
56+
Selected extension is not supported.
57+
```
58+
59+
## 工夫したこと
60+
- png, jpg以外にも拡張子が増えそうなので、`image_type`というinterfaceを作ってみた。
61+
- 拡張子の微妙な違い(jpg, jpeg, JPGなど)にも対応できるようにした。
62+
63+
## わからなかったこと、むずかしかったこと
64+
- go mod initで指定するmodule名に命名規則があるのか。
65+
- 普段オブジェクト指向(その上動的型付け言語)で書いているので、それがgoらしいコードになっているのか不安。
66+
- なんでもかんでも構造体メソッドにしたい願望がでてくる

kadai1/hokita/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module imgconv
2+
3+
go 1.14

kadai1/hokita/go.sum

Whitespace-only changes.

kadai1/hokita/imgconv/converter.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package imgconv
2+
3+
import (
4+
"image"
5+
"os"
6+
"path/filepath"
7+
)
8+
9+
func converterFactory(from string, to string) (*Converter, error) {
10+
fromImage, err := selectImage("." + from)
11+
if err != nil {
12+
return nil, err
13+
}
14+
15+
toImage, err := selectImage("." + to)
16+
if err != nil {
17+
return nil, err
18+
}
19+
20+
return &Converter{fromImage, toImage}, nil
21+
}
22+
23+
type Converter struct {
24+
fromImage ImageType
25+
toImage ImageType
26+
}
27+
28+
func (conv *Converter) Execute(path string) error {
29+
// ignore unrelated file
30+
if !conv.fromImage.IsMatchExt(filepath.Ext(path)) {
31+
return nil
32+
}
33+
34+
// file open
35+
file, err := os.Open(path)
36+
defer file.Close()
37+
if err != nil {
38+
return err
39+
}
40+
41+
// convert to image obj
42+
img, _, err := image.Decode(file)
43+
if err != nil {
44+
return err
45+
}
46+
47+
// output file
48+
out, err := os.Create(conv.SwitchExt(path))
49+
defer out.Close()
50+
if err != nil {
51+
return err
52+
}
53+
54+
// output image
55+
conv.toImage.Encode(out, img)
56+
return nil
57+
}
58+
59+
func (conv *Converter) SwitchExt(path string) string {
60+
ext := filepath.Ext(path)
61+
toExt := conv.toImage.Extensions()[0]
62+
63+
return path[:len(path)-len(ext)] + toExt
64+
}

kadai1/hokita/imgconv/image_type.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package imgconv
2+
3+
import (
4+
"errors"
5+
"image"
6+
"io"
7+
)
8+
9+
type ImageType interface {
10+
Encode(w io.Writer, m image.Image) error
11+
IsMatchExt(ext string) bool
12+
Extensions() []string
13+
}
14+
15+
func selectImage(ext string) (ImageType, error) {
16+
pngImage := PngImage{}
17+
jpegImage := JpegImage{}
18+
19+
if pngImage.IsMatchExt(ext) {
20+
return pngImage, nil
21+
} else if jpegImage.IsMatchExt(ext) {
22+
return jpegImage, nil
23+
}
24+
25+
return nil, errors.New("Selected extension is not supported.")
26+
}

kadai1/hokita/imgconv/imgconv.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package imgconv
2+
3+
import (
4+
"errors"
5+
"flag"
6+
"os"
7+
"path/filepath"
8+
)
9+
10+
func Call() error {
11+
var (
12+
from = flag.String("from", "jpg", "Conversion source extension.")
13+
to = flag.String("to", "png", "Conversion target extension.")
14+
)
15+
flag.Parse()
16+
dir := flag.Arg(0)
17+
18+
if flag.Arg(0) == "" {
19+
return errors.New("Please specify a directory.")
20+
}
21+
22+
if f, err := os.Stat(dir); os.IsNotExist(err) || !f.IsDir() {
23+
return errors.New("Cannot find directory.")
24+
}
25+
26+
converter, err := converterFactory(*from, *to)
27+
if err != nil {
28+
return err
29+
}
30+
31+
err = filepath.Walk(dir,
32+
func(path string, info os.FileInfo, err error) error {
33+
err = converter.Execute(path)
34+
return err
35+
})
36+
if err != nil {
37+
return err
38+
}
39+
40+
return nil
41+
}

kadai1/hokita/imgconv/jpeg_image.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package imgconv
2+
3+
import (
4+
"image"
5+
"image/jpeg"
6+
"io"
7+
)
8+
9+
const QUALITY = 100
10+
11+
type JpegImage struct{}
12+
13+
func (_ JpegImage) Encode(w io.Writer, m image.Image) error {
14+
err := jpeg.Encode(w, m, &jpeg.Options{Quality: QUALITY})
15+
return err
16+
}
17+
18+
func (ji JpegImage) IsMatchExt(ext string) bool {
19+
for _, myExt := range ji.Extensions() {
20+
if ext == myExt {
21+
return true
22+
}
23+
}
24+
return false
25+
}
26+
27+
func (_ JpegImage) Extensions() []string {
28+
return []string{".jpg", ".jpeg", ".JPG", ".JPEG"}
29+
}

kadai1/hokita/imgconv/png_image.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package imgconv
2+
3+
import (
4+
"image"
5+
"image/png"
6+
"io"
7+
)
8+
9+
type PngImage struct{}
10+
11+
func (_ PngImage) Encode(w io.Writer, m image.Image) error {
12+
err := png.Encode(w, m)
13+
return err
14+
}
15+
16+
func (pi PngImage) IsMatchExt(ext string) bool {
17+
for _, myExt := range pi.Extensions() {
18+
if ext == myExt {
19+
return true
20+
}
21+
}
22+
return false
23+
}
24+
25+
func (_ PngImage) Extensions() []string {
26+
return []string{".png", ".PNG"}
27+
}

kadai1/hokita/main.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"imgconv/imgconv"
6+
"os"
7+
)
8+
9+
const (
10+
ExitCodeOk int = iota
11+
ExitCodeError
12+
)
13+
14+
func main() {
15+
os.Exit(run())
16+
}
17+
18+
func run() int {
19+
err := imgconv.Call()
20+
21+
if err != nil {
22+
fmt.Fprintln(os.Stderr, err)
23+
return ExitCodeError
24+
}
25+
26+
fmt.Println("Conversion finished!")
27+
return ExitCodeOk
28+
}
92.4 KB
Loading

0 commit comments

Comments
 (0)