Skip to content

Commit

Permalink
create kadai1/hokita
Browse files Browse the repository at this point in the history
  • Loading branch information
hokita committed Jul 6, 2020
1 parent 6a79d18 commit e43488f
Show file tree
Hide file tree
Showing 11 changed files with 284 additions and 0 deletions.
66 changes: 66 additions & 0 deletions kadai1/hokita/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# 課題 1 画像変換コマンドを作ろう

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

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

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

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

## 対応したこと
- 画像を変換
- 現状はjpg, pngのみ
- jpg, png以外はエラー表示
- 画像出力先は対象画像と同じディレクトリ
- 指定したディレクトリが無いとエラーを表示

## 動作
```shell
$ go build -o test_imgconv

$ ./test_imgconv -h
Usage of ./test_imgconv:
-from string
Conversion source extension. (default "jpg")
-to string
Conversion target extension. (default "png")

# testdata内のすべてのjpgファイルをpngに変換する
$ ./test_imgconv testdata
Conversion finished!

# testdata内のすべてのpngファイルをjpgに変換する
$ ./test_imgconv -from png -to jpg testdata
Conversion finished!

# ディレクトリの指定が無い場合はエラー
$ ./test_imgconv
Please specify a directory.

# 存在しないディレクトリの場合はエラー
$ ./test_imgconv non_exist_dir
Cannot find directory.

# 対応していない拡張子の場合はエラー
$ ./test_imgconv -from txt -to jpg testdata
Selected extension is not supported.
```

## 工夫したこと
- png, jpg以外にも拡張子が増えそうなので、`image_type`というinterfaceを作ってみた。
- 拡張子の微妙な違い(jpg, jpeg, JPGなど)にも対応できるようにした。

## わからなかったこと、むずかしかったこと
- go mod initで指定するmodule名に命名規則があるのか。
- 普段オブジェクト指向(その上動的型付け言語)で書いているので、それがgoらしいコードになっているのか不安。
- なんでもかんでも構造体メソッドにしたい願望がでてくる
3 changes: 3 additions & 0 deletions kadai1/hokita/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module imgconv

go 1.14
Empty file added kadai1/hokita/go.sum
Empty file.
64 changes: 64 additions & 0 deletions kadai1/hokita/imgconv/converter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package imgconv

import (
"image"
"os"
"path/filepath"
)

func converterFactory(from string, to string) (*Converter, error) {
fromImage, err := selectImage("." + from)
if err != nil {
return nil, err
}

toImage, err := selectImage("." + to)
if err != nil {
return nil, err
}

return &Converter{fromImage, toImage}, nil
}

type Converter struct {
fromImage ImageType
toImage ImageType
}

func (conv *Converter) Execute(path string) error {
// ignore unrelated file
if !conv.fromImage.IsMatchExt(filepath.Ext(path)) {
return nil
}

// file open
file, err := os.Open(path)
defer file.Close()
if err != nil {
return err
}

// convert to image obj
img, _, err := image.Decode(file)
if err != nil {
return err
}

// output file
out, err := os.Create(conv.SwitchExt(path))
defer out.Close()
if err != nil {
return err
}

// output image
conv.toImage.Encode(out, img)
return nil
}

func (conv *Converter) SwitchExt(path string) string {
ext := filepath.Ext(path)
toExt := conv.toImage.Extensions()[0]

return path[:len(path)-len(ext)] + toExt
}
26 changes: 26 additions & 0 deletions kadai1/hokita/imgconv/image_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package imgconv

import (
"errors"
"image"
"io"
)

type ImageType interface {
Encode(w io.Writer, m image.Image) error
IsMatchExt(ext string) bool
Extensions() []string
}

func selectImage(ext string) (ImageType, error) {
pngImage := PngImage{}
jpegImage := JpegImage{}

if pngImage.IsMatchExt(ext) {
return pngImage, nil
} else if jpegImage.IsMatchExt(ext) {
return jpegImage, nil
}

return nil, errors.New("Selected extension is not supported.")
}
41 changes: 41 additions & 0 deletions kadai1/hokita/imgconv/imgconv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package imgconv

import (
"errors"
"flag"
"os"
"path/filepath"
)

func Call() error {
var (
from = flag.String("from", "jpg", "Conversion source extension.")
to = flag.String("to", "png", "Conversion target extension.")
)
flag.Parse()
dir := flag.Arg(0)

if flag.Arg(0) == "" {
return errors.New("Please specify a directory.")
}

if f, err := os.Stat(dir); os.IsNotExist(err) || !f.IsDir() {
return errors.New("Cannot find directory.")
}

converter, err := converterFactory(*from, *to)
if err != nil {
return err
}

err = filepath.Walk(dir,
func(path string, info os.FileInfo, err error) error {
err = converter.Execute(path)
return err
})
if err != nil {
return err
}

return nil
}
29 changes: 29 additions & 0 deletions kadai1/hokita/imgconv/jpeg_image.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package imgconv

import (
"image"
"image/jpeg"
"io"
)

const QUALITY = 100

type JpegImage struct{}

func (_ JpegImage) Encode(w io.Writer, m image.Image) error {
err := jpeg.Encode(w, m, &jpeg.Options{Quality: QUALITY})
return err
}

func (ji JpegImage) IsMatchExt(ext string) bool {
for _, myExt := range ji.Extensions() {
if ext == myExt {
return true
}
}
return false
}

func (_ JpegImage) Extensions() []string {
return []string{".jpg", ".jpeg", ".JPG", ".JPEG"}
}
27 changes: 27 additions & 0 deletions kadai1/hokita/imgconv/png_image.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package imgconv

import (
"image"
"image/png"
"io"
)

type PngImage struct{}

func (_ PngImage) Encode(w io.Writer, m image.Image) error {
err := png.Encode(w, m)
return err
}

func (pi PngImage) IsMatchExt(ext string) bool {
for _, myExt := range pi.Extensions() {
if ext == myExt {
return true
}
}
return false
}

func (_ PngImage) Extensions() []string {
return []string{".png", ".PNG"}
}
28 changes: 28 additions & 0 deletions kadai1/hokita/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package main

import (
"fmt"
"imgconv/imgconv"
"os"
)

const (
ExitCodeOk int = iota
ExitCodeError
)

func main() {
os.Exit(run())
}

func run() int {
err := imgconv.Call()

if err != nil {
fmt.Fprintln(os.Stderr, err)
return ExitCodeError
}

fmt.Println("Conversion finished!")
return ExitCodeOk
}
Binary file added kadai1/hokita/testdata/dir1/gopher2.png
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/hokita/testdata/gopher1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit e43488f

Please sign in to comment.