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

Kadai3-1 yashiken #25

Open
wants to merge 23 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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
converter
.DS_Store
kadai3-1/yashiken/typinggame
23 changes: 23 additions & 0 deletions kadai1/yashiken/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# 課題1 回答
Copy link
Member

Choose a reason for hiding this comment

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

課題ごとに分けてほしいですー

## 仕様
- 引数に指定したディレクトリ配下の特定の形式の画像を指定した形式へ変換する
- デフォルトでは、jpg形式をpng形式に変換する
- jpg, jpeg, png, gif間の変換に対応。
- オプションで、変換前後のファイル形式を指定する
- -s オプションで、変換するファイル形式を指定
- -d オプションで、変換後のファイル形式を指定する
- 実行後、変換前のファイルは削除されず、変換前の画像が格納されているディレクトリに新たにファイルが生成される

## 使い方
```
go build -o converter
./converter -s jpg -d png <path/to/directry>
```

## 気になっている点
- convertパッケージの実装
- ユーザー定義型Converterを定義したが、この実装に若干不安がある点。
- convertパッケージのテストコード
- テストに共通部分があり、冗長であるように思われる点。
- TestDecode, TestEncodeのerrorがnilか否かの判定はチェックできたが、戻り値が正常であるかを判定するロジックを組めていない点。
- encode関数でwriterを定義する部分で、エラー発生するケースがわからず、テストができていない点。
106 changes: 106 additions & 0 deletions kadai1/yashiken/convert/convert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
convertパッケージは、イメージファイルの形式を変換するためのパッケージです。
jpg, jpeg, png, gifの形式変換に対応しています。
*/
package convert

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

// Converterは変換前後のファイル形式を表現します。
type Converter struct {
// 変換前のファイル形式
ExtSrc string
// 変換後のファイル形式
ExtCnv string
}

// Converは、受け取ったファイルパスの画像ファイルを指定した形式に変換します
func (c *Converter) Convert(path string) error {
// 変換前のファイルのデコード
data, err := c.decode(path)
if err != nil {
return err
}

// 指定したファイル形式へのエンコード
err = c.encode(path, data)
if err != nil {
return err
}
return nil

}

// decodeは指定したファイルパスのファイルの読み取り、デコードを行います
func (c *Converter) decode(path string) (image.Image, error) {
// ファイルの読み取り
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()

// ファイル形式に応じたデコード処理
switch c.ExtSrc {
// jpg, jpegの場合
case "jpg", "jpeg":
img, err := jpeg.Decode(file)
if err != nil {
return nil, err
}

return img, nil
// pngの場合
case "png":
img, err := png.Decode(file)
if err != nil {
return nil, err
}

return img, nil
// gifの場合
case "gif":
img, err := gif.Decode(file)
if err != nil {
return nil, err
}

return img, nil
}
// 非対応のファイル形式を指定した場合、エラーを返却
return nil, fmt.Errorf("extension %s is not supported.", c.ExtSrc)

}

// encodeは、image.Image型のデータを、特定の形式にエンコードし、指定したパスにファイルを作成します。
func (c *Converter) encode(filepath string, data image.Image) error {
// 書き込み先の指定
writer, err := os.Create(strings.TrimSuffix(filepath, path.Ext(filepath)) + "." + c.ExtCnv)
if err != nil {
return err
}

// 変換先のファイル形式に応じたエンコード処理とファイル生成
switch c.ExtCnv {
// jpg, jpegの場合
case "jpg", "jpeg":
return jpeg.Encode(writer, data, nil)
// pngの場合
case "png":
return png.Encode(writer, data)
// gifの場合
case "gif":
return gif.Encode(writer, data, nil)
}
// 非対応のファイル形式の場合
return fmt.Errorf("convert to extension %s is not supported.", c.ExtCnv)
}
164 changes: 164 additions & 0 deletions kadai1/yashiken/convert/convert_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package convert

import (
"os"
"testing"
"image"
)

// TestMainは、テストで変換した画像ファイルを消去するための関数です。
func TestMain(m *testing.M) {
code := m.Run()

os.Remove("test-images/Moon_cvt.bmp")
os.Remove("test-images/Moon_cvt.gif")
os.Remove("test-images/Moon_cvt.jpeg")
os.Remove("test-images/Moon_cvt.jpg")
os.Remove("test-images/Moon_cvt.png")
os.Remove("test-images/Moon.bmp")

os.Exit(code)
}

// decodeのテストです。
func TestDecode(t *testing.T) {
var Condition {
input string,
expection *image.Image
}
// 引数のファイルが存在しない場合のテストケース
path := "noexist"
c := &Converter{}
// エラーを返すことの確認
_, err := c.decode(path)
if err == nil {
t.Error("decodeはnilでないerrorを返すべきです")
}

// jpgファイルを変換する場合
c1 := &Converter{ExtSrc: "jpg"}
// 引数で指定したファイルの拡張子がxxx.jpgであるにも関わらず、
// ファイル形式がjpgでない場合のテストケース
_, err = c1.decode("test-images/dummy.jpg")
if err == nil {
t.Error("decodeはnilでないerrorを返すべきです")
}
// 正常にファイルを指定した場合、処理が成功することの確認
_, err = c1.decode("test-images/Moon.jpg")
if err != nil {
t.Error("decodeはnil以外のerrorを返すべきではありません")
}

// jpegファイルを変換する場合
c2 := &Converter{ExtSrc: "jpeg"}
// 引数で指定したファイルの拡張子がxxx.jpegであるにも関わらず、
// ファイル形式がjpegでない場合のテストケース
_, err = c2.decode("test-images/dummy.jpeg")
if err == nil {
t.Error("decodeはnilでないerrorを返すべきです")
}
// 正常にファイルを指定した場合、処理が成功することの確認
_, err = c2.decode("test-images/Moon.jpeg")
if err != nil {
t.Error("decodeはnil以外のerrorを返すべきではありません")
}

// pngファイルを変換する場合
c3 := &Converter{ExtSrc: "png"}
// 引数で指定したファイルの拡張子がxxx.pngであるにも関わらず、
// ファイル形式がpngでない場合のテストケース
_, err = c3.decode("test-images/dummy.png")
if err == nil {
t.Error("decodeはnilでないerrorを返すべきです")
}
// 正常にファイルを指定した場合、処理が成功することの確認
_, err = c3.decode("test-images/Moon.png")
if err != nil {
t.Error("decodeはnil以外のerrorを返すべきではありません")
}

// gifファイルを変換する場合
c4 := &Converter{ExtSrc: "gif"}
// 引数で指定したファイルの拡張子がxxx.gifであるにも関わらず、
// ファイル形式がgifでない場合のテストケース
_, err = c4.decode("test-images/dummy.gif")
if err == nil {
t.Error("decodeはnilでないerrorを返すべきです")
}
// 正常にファイルを指定した場合、処理が成功することの確認
_, err = c4.decode("test-images/Moon.gif")
if err != nil {
t.Error("decodeはnil以外のerrorを返すべきではありません")
}

// 対応していないファイル形式を指定した場合のテストケース
c5 := &Converter{ExtSrc: "bmp"}

// エラーを返すことを確認
_, err = c5.decode("test-images/test.bmp")
if err == nil {
t.Error("decodeはnilでないerrorを返すべきです")
}

}

// encodeのテストです
func TestEncode(t *testing.T) {
// テストファイル(jpg)から、デコードしたデータを取得
c := &Converter{ExtSrc: "jpg"}
srcPath := "test-images/Moon.jpg"
data, _ := c.decode(srcPath)

// jpgファイルへのエンコードが成功するか確認
c1 := &Converter{ExtCnv: "jpg"}
if err := c1.encode("test-images/Moon_cvt.jpg", data); err != nil {
t.Error("encodeが返すerrorはnilであるべきです")
}

// jpegファイルへのエンコードが成功するか確認
c2 := &Converter{ExtCnv: "jpeg"}
if err := c2.encode("test-images/Moon_cvt.jpg", data); err != nil {
t.Error("encodeが返すerrorはnilであるべきです")
}

// pngファイルへのエンコードが成功するか確認
c3 := &Converter{ExtCnv: "png"}
if err := c3.encode("test-images/Moon_cvt.jpg", data); err != nil {
t.Error("encodeが返すerrorはnilであるべきです")
}

// gifファイルへのエンコードが成功するか確認
c4 := &Converter{ExtCnv: "gif"}
if err := c4.encode("test-images/Moon_cvt.jpg", data); err != nil {
t.Error("encodeが返すerrorはnilであるべきです")
}

// 対応していないファイル形式を指定した場合、処理が失敗することの確認
c5 := &Converter{ExtCnv: "bmp"}
if err := c5.encode("test-images/Moon_cvt.jpg", data); err == nil {
t.Error("encodeはnilでないerrorを返すべきです")
}
}

// Convertのテストです。
func TestConvert(t *testing.T) {
// 存在しないファイルを指定した場合にエラーを返すことの確認
path := "noexist"
c1 := &Converter{ExtSrc: "jpg", ExtCnv: "png"}
if err := c1.Convert(path); err == nil {
t.Error("Convertはnilでないerrorを返すべきです")
}

// 対応していないファイル形式を指定した場合にエラーを返すことの確認
path = "test-images/Moon.jpg"
c2 := &Converter{ExtSrc: "jpg", ExtCnv: "bmp"}
if err := c2.Convert(path); err == nil {
t.Error("Convertはnilでないerrorを返すべきです")
}

// 対応するファイル形式間での変換処理が正常に終了することの確認
c3 := &Converter{ExtSrc: "jpg", ExtCnv: "png"}
if err := c3.Convert(path); err != nil {
t.Error("encodeが返すerrorはnilであるべきです")
}
}
Binary file added kadai1/yashiken/convert/test-images/Moon.gif
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/yashiken/convert/test-images/Moon.jpeg
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/yashiken/convert/test-images/Moon.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/yashiken/convert/test-images/Moon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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/yashiken/convert/test-images/test.bmp
Binary file not shown.
5 changes: 5 additions & 0 deletions kadai1/yashiken/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/gopherdojo/dojo6

go 1.12

require golang.org/x/tools/gopls v0.1.3 // indirect
10 changes: 10 additions & 0 deletions kadai1/yashiken/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190710153321-831012c29e42 h1:4IOeC7p+OItq3+O5BWkcmVu2uBe3jekXau5S4QZX9DU=
golang.org/x/tools v0.0.0-20190710153321-831012c29e42/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools/gopls v0.1.3 h1:CB5ECiPysqZrwxcyRjN+exyZpY0gODTZvNiqQi3lpeo=
golang.org/x/tools/gopls v0.1.3/go.mod h1:vrCQzOKxvuiZLjCKSmbbov04oeBQQOb4VQqwYK2PWIY=
Binary file added kadai1/yashiken/images/go.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/yashiken/images/gopher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions kadai1/yashiken/info/info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
infoパッケージは、指定されたディレクトリに格納されたイメージファイルの名前を取り出すためのパッケージです。
*/
package info

import (
"io/ioutil"
"path/filepath"
)

/*
GetFilePathは、指定されたディレクトリ配下に格納された、
特定の拡張子を持つ画像ファイルのファイルパス一覧を返します。
*/
func GetFilePath(dir, ext string) ([]string, error) {
// ディレクトリ配下のファイル情報を取得
files, err := ioutil.ReadDir(dir)
if err != nil {
return nil, err
}
// ファイルパスを格納するためのスライスを生成
paths := make([]string, 0)

// ファイルパスを順次格納
for _, file := range files {
// ディレクトリがある場合、再帰的に処理
if file.IsDir() {
p, err := GetFilePath(filepath.Join(dir, file.Name()), ext)
if err != nil {
return nil, err
}
paths = append(paths, p...)
}
// スライスに追加
path := filepath.Join(dir, file.Name())
if filepath.Ext(path) == "."+ext {
paths = append(paths, filepath.Join(dir, file.Name()))
}
}
return paths, nil
}
33 changes: 33 additions & 0 deletions kadai1/yashiken/info/info_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package info

import (
"reflect"
"testing"
)

func TestGetFilePath(t *testing.T) {
// ファイルが存在しない場合のテストケース
dir := "noexist"
ext := "jpg"
_, err := GetFilePath(dir, ext)
if err == nil {
t.Error("存在しないディレクトリを引数に指定した場合、GetFilePathはnilでないerrorを返すべきです")
}

//
dir = "test.txt"
_, err = GetFilePath(dir, ext)
if err == nil {
t.Error("ディレクトリでないファイルを引数に指定した場合、GetFilePathはnilでないerrorを返すべきです")
}

dir = "test-images"
paths, err := GetFilePath(dir, ext)
if err != nil {
t.Error("ディレクトリを指定した場合、errorはnilであるべきです")
}
if !reflect.DeepEqual(paths, []string{"test-images/Moon.jpg", "test-images/test2-images/momiji.jpg"}) {
t.Error("GetFilePathが正しいファイルパスが格納されたスライスを返していません")
}

}
Binary file added kadai1/yashiken/info/test-images/Moon.jpeg
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/yashiken/info/test-images/Moon.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/yashiken/info/test-images/Moon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading