diff --git a/kadai1/ramenjuniti/Makefile b/kadai1/ramenjuniti/Makefile new file mode 100644 index 0000000..55e5687 --- /dev/null +++ b/kadai1/ramenjuniti/Makefile @@ -0,0 +1,14 @@ +BIN := iconv + +.PHONY: test +test: + go test -cover -v ./... + +.PHONY: build +build: test + go build -o $(BIN) + +.PHONY: clean +clean: + rm $(BIN) + go clean diff --git a/kadai1/ramenjuniti/README.md b/kadai1/ramenjuniti/README.md new file mode 100644 index 0000000..8d20082 --- /dev/null +++ b/kadai1/ramenjuniti/README.md @@ -0,0 +1,31 @@ +# iconv + +## Description + +課題1(画像変換コマンドを作ろう)を実装したもの + +以下のパッケージで構成されています + +- main +- target +- imgconv + +## Usage + +``` +iconv -in {変換前の形式} -out {変換したい形式} {ディレクトリ} +``` + +jpg, png, gif, tif, bmp に対応しています + +## Build + +```bash +make build +``` + +## Test + +```bash +make test +``` diff --git a/kadai1/ramenjuniti/go.mod b/kadai1/ramenjuniti/go.mod new file mode 100644 index 0000000..64730b3 --- /dev/null +++ b/kadai1/ramenjuniti/go.mod @@ -0,0 +1,5 @@ +module github.com/gopherdojo/dojo5/kadai1/ramenjuniti + +go 1.12 + +require golang.org/x/image v0.0.0-20190523035834-f03afa92d3ff diff --git a/kadai1/ramenjuniti/go.sum b/kadai1/ramenjuniti/go.sum new file mode 100644 index 0000000..e1df7c3 --- /dev/null +++ b/kadai1/ramenjuniti/go.sum @@ -0,0 +1,3 @@ +golang.org/x/image v0.0.0-20190523035834-f03afa92d3ff h1:+2zgJKVDVAz/BWSsuniCmU1kLCjL88Z8/kv39xCI9NQ= +golang.org/x/image v0.0.0-20190523035834-f03afa92d3ff/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/kadai1/ramenjuniti/imgconv/imgconv.go b/kadai1/ramenjuniti/imgconv/imgconv.go new file mode 100644 index 0000000..5666f6d --- /dev/null +++ b/kadai1/ramenjuniti/imgconv/imgconv.go @@ -0,0 +1,69 @@ +package imgconv + +import ( + "image" + "image/gif" + "image/jpeg" + "image/png" + "os" + "path/filepath" + + "golang.org/x/image/bmp" + "golang.org/x/image/tiff" +) + +// ImgData デコードされた画像データが入る +type ImgData struct { + Path string + Data image.Image +} + +// Decode pathの画像をデコードし、ImgDataに入れる +func Decode(path string) (*ImgData, error) { + file, err := os.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + + img, _, err := image.Decode(file) + if err != nil { + return nil, err + } + + return &ImgData{Path: path, Data: img}, nil +} + +// Encode iのDataをout形式のファイルにエンコードし、ファイル作成 +// jpg, png, gif, tif, bmpに対応 +func (i *ImgData) Encode(out string) error { + file, err := os.Create(rmExt(i.Path) + "." + out) + if err != nil { + return err + } + + switch out { + case "png": + err = png.Encode(file, i.Data) + case "jpg", "jpeg": + err = jpeg.Encode(file, i.Data, nil) + case "gif": + err = gif.Encode(file, i.Data, nil) + case "tif", "tiff": + err = tiff.Encode(file, i.Data, nil) + case "bmp": + err = bmp.Encode(file, i.Data) + } + + if err != nil { + return err + } + defer file.Close() + + return nil +} + +// rmExt pathの拡張子を除いた文字列を返す +func rmExt(path string) string { + return path[:len(path)-len(filepath.Ext(path))] +} diff --git a/kadai1/ramenjuniti/imgconv/imgconv_test.go b/kadai1/ramenjuniti/imgconv/imgconv_test.go new file mode 100644 index 0000000..ae74da0 --- /dev/null +++ b/kadai1/ramenjuniti/imgconv/imgconv_test.go @@ -0,0 +1,64 @@ +package imgconv + +import ( + "os" + "testing" +) + +var tests = []struct { + name string + path string + out string + outFile string +}{ + { + name: "jpg to png", + path: "../testdata/imgconv/sample.jpg", + out: "png", + outFile: "../testdata/imgconv/sample.png", + }, + { + name: "jpg to gif", + path: "../testdata/imgconv/sample.jpg", + out: "gif", + outFile: "../testdata/imgconv/sample.gif", + }, + { + name: "jpg to tif", + path: "../testdata/imgconv/sample.jpg", + out: "tif", + outFile: "../testdata/imgconv/sample.tif", + }, + { + name: "jpg to bmp", + path: "../testdata/imgconv/sample.jpg", + out: "bmp", + outFile: "../testdata/imgconv/sample.bmp", + }, +} + +func TestConvert(t *testing.T) { + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + img, err := Decode(test.path) + if err != nil { + t.Fatalf("unexpected error %v", err) + } + + err = img.Encode(test.out) + if err != nil { + t.Fatalf("unexpected error %v", err) + } + + _, err = os.Stat(test.outFile) + if err != nil { + t.Fatalf("did not create %v", test.outFile) + } + + err = os.Remove(test.outFile) + if err != nil { + t.Fatalf("cannot remove %v", test.outFile) + } + }) + } +} diff --git a/kadai1/ramenjuniti/main.go b/kadai1/ramenjuniti/main.go new file mode 100644 index 0000000..d2c9c48 --- /dev/null +++ b/kadai1/ramenjuniti/main.go @@ -0,0 +1,71 @@ +package main + +import ( + "flag" + "log" + + "github.com/gopherdojo/dojo5/kadai1/ramenjuniti/imgconv" + "github.com/gopherdojo/dojo5/kadai1/ramenjuniti/target" +) + +func main() { + in := flag.String("in", "jpg", "file type before conversion") + out := flag.String("out", "png", "file type to convert") + formats := []string{"jpg", "png", "gif", "tif", "bmp"} + + flag.Parse() + args := flag.Args() + + if len(args) == 0 { + log.Fatal("directory not specified") + } + + if *in == "jpeg" { + *in = "jpg" + } + if *in == "tiff" { + *in = "tif" + } + if *out == "jpeg" { + *out = "jpg" + } + if *out == "tiff" { + *out = "tif" + } + + if !canConv(*in, formats) { + log.Fatalf("cannot convert %v file", *in) + } + if !canConv(*out, formats) { + log.Fatalf("cannot convert %v file", *out) + } + + for _, arg := range args { + targets, err := target.Get(arg, *in) + if err != nil { + log.Fatal(err) + } + + for _, t := range targets { + img, err := imgconv.Decode(t) + if err != nil { + log.Fatal(err) + } + + err = img.Encode(*out) + if err != nil { + log.Fatal(err) + } + } + } +} + +// canConv tがconvに含まれるかどうかをboolで返す +func canConv(f string, formats []string) bool { + for _, v := range formats { + if f == v { + return true + } + } + return false +} diff --git a/kadai1/ramenjuniti/target/target.go b/kadai1/ramenjuniti/target/target.go new file mode 100644 index 0000000..8c480eb --- /dev/null +++ b/kadai1/ramenjuniti/target/target.go @@ -0,0 +1,25 @@ +package target + +import ( + "os" + "path/filepath" +) + +// Get root下のin形式のファイルのパスが入ったsliceとerrを返す +func Get(root, in string) ([]string, error) { + targets := []string{} + + err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { + if filepath.Ext(path) == "."+in { + targets = append(targets, path) + } + + return nil + }) + + if err != nil { + return targets, err + } + + return targets, nil +} diff --git a/kadai1/ramenjuniti/target/target_test.go b/kadai1/ramenjuniti/target/target_test.go new file mode 100644 index 0000000..1231a1b --- /dev/null +++ b/kadai1/ramenjuniti/target/target_test.go @@ -0,0 +1,84 @@ +package target + +import ( + "reflect" + "testing" +) + +var tests = []struct { + name string + root string + in string + targets []string +}{ + { + name: "get jpg files", + root: "../testdata/target", + in: "jpg", + targets: []string{ + "../testdata/target/jpg/sample1.jpg", + "../testdata/target/jpg/sample2.jpg", + "../testdata/target/jpg/sample3.jpg", + }, + }, + { + name: "get png files", + root: "../testdata/target", + in: "png", + targets: []string{ + "../testdata/target/png/sample1.png", + "../testdata/target/png/sample2.png", + "../testdata/target/png/sample3.png", + }, + }, + { + name: "get gif files", + root: "../testdata/target", + in: "gif", + targets: []string{ + "../testdata/target/gif/sample1.gif", + "../testdata/target/gif/sample2.gif", + "../testdata/target/gif/sample3.gif", + }, + }, + { + name: "get tif files", + root: "../testdata/target", + in: "tif", + targets: []string{ + "../testdata/target/tif/sample1.tif", + "../testdata/target/tif/sample2.tif", + "../testdata/target/tif/sample3.tif", + }, + }, + { + name: "get bmp files", + root: "../testdata/target", + in: "bmp", + targets: []string{ + "../testdata/target/bmp/sample1.bmp", + "../testdata/target/bmp/sample2.bmp", + "../testdata/target/bmp/sample3.bmp", + }, + }, + { + name: "no file", + root: "../testdata/target", + in: "hoge", + targets: []string{}, + }, +} + +func TestGet(t *testing.T) { + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got, err := Get(test.root, test.in) + if err != nil { + t.Fatalf("unexpected error %v", err) + } + if !reflect.DeepEqual(got, test.targets) { + t.Fatalf("got targets: %v, want targets: %v", got, test.targets) + } + }) + } +} diff --git a/kadai1/ramenjuniti/testdata/imgconv/sample.jpg b/kadai1/ramenjuniti/testdata/imgconv/sample.jpg new file mode 100644 index 0000000..30a491d Binary files /dev/null and b/kadai1/ramenjuniti/testdata/imgconv/sample.jpg differ diff --git a/kadai1/ramenjuniti/testdata/target/bmp/sample1.bmp b/kadai1/ramenjuniti/testdata/target/bmp/sample1.bmp new file mode 100644 index 0000000..f1888bc Binary files /dev/null and b/kadai1/ramenjuniti/testdata/target/bmp/sample1.bmp differ diff --git a/kadai1/ramenjuniti/testdata/target/bmp/sample2.bmp b/kadai1/ramenjuniti/testdata/target/bmp/sample2.bmp new file mode 100644 index 0000000..f1888bc Binary files /dev/null and b/kadai1/ramenjuniti/testdata/target/bmp/sample2.bmp differ diff --git a/kadai1/ramenjuniti/testdata/target/bmp/sample3.bmp b/kadai1/ramenjuniti/testdata/target/bmp/sample3.bmp new file mode 100644 index 0000000..f1888bc Binary files /dev/null and b/kadai1/ramenjuniti/testdata/target/bmp/sample3.bmp differ diff --git a/kadai1/ramenjuniti/testdata/target/gif/sample1.gif b/kadai1/ramenjuniti/testdata/target/gif/sample1.gif new file mode 100644 index 0000000..b58879b Binary files /dev/null and b/kadai1/ramenjuniti/testdata/target/gif/sample1.gif differ diff --git a/kadai1/ramenjuniti/testdata/target/gif/sample2.gif b/kadai1/ramenjuniti/testdata/target/gif/sample2.gif new file mode 100644 index 0000000..b58879b Binary files /dev/null and b/kadai1/ramenjuniti/testdata/target/gif/sample2.gif differ diff --git a/kadai1/ramenjuniti/testdata/target/gif/sample3.gif b/kadai1/ramenjuniti/testdata/target/gif/sample3.gif new file mode 100644 index 0000000..b58879b Binary files /dev/null and b/kadai1/ramenjuniti/testdata/target/gif/sample3.gif differ diff --git a/kadai1/ramenjuniti/testdata/target/jpg/sample1.jpg b/kadai1/ramenjuniti/testdata/target/jpg/sample1.jpg new file mode 100644 index 0000000..30a491d Binary files /dev/null and b/kadai1/ramenjuniti/testdata/target/jpg/sample1.jpg differ diff --git a/kadai1/ramenjuniti/testdata/target/jpg/sample2.jpg b/kadai1/ramenjuniti/testdata/target/jpg/sample2.jpg new file mode 100644 index 0000000..30a491d Binary files /dev/null and b/kadai1/ramenjuniti/testdata/target/jpg/sample2.jpg differ diff --git a/kadai1/ramenjuniti/testdata/target/jpg/sample3.jpg b/kadai1/ramenjuniti/testdata/target/jpg/sample3.jpg new file mode 100644 index 0000000..30a491d Binary files /dev/null and b/kadai1/ramenjuniti/testdata/target/jpg/sample3.jpg differ diff --git a/kadai1/ramenjuniti/testdata/target/png/sample1.png b/kadai1/ramenjuniti/testdata/target/png/sample1.png new file mode 100644 index 0000000..ddbf9a1 Binary files /dev/null and b/kadai1/ramenjuniti/testdata/target/png/sample1.png differ diff --git a/kadai1/ramenjuniti/testdata/target/png/sample2.png b/kadai1/ramenjuniti/testdata/target/png/sample2.png new file mode 100644 index 0000000..ddbf9a1 Binary files /dev/null and b/kadai1/ramenjuniti/testdata/target/png/sample2.png differ diff --git a/kadai1/ramenjuniti/testdata/target/png/sample3.png b/kadai1/ramenjuniti/testdata/target/png/sample3.png new file mode 100644 index 0000000..ddbf9a1 Binary files /dev/null and b/kadai1/ramenjuniti/testdata/target/png/sample3.png differ diff --git a/kadai1/ramenjuniti/testdata/target/tif/sample1.tif b/kadai1/ramenjuniti/testdata/target/tif/sample1.tif new file mode 100644 index 0000000..6eca38f Binary files /dev/null and b/kadai1/ramenjuniti/testdata/target/tif/sample1.tif differ diff --git a/kadai1/ramenjuniti/testdata/target/tif/sample2.tif b/kadai1/ramenjuniti/testdata/target/tif/sample2.tif new file mode 100644 index 0000000..6eca38f Binary files /dev/null and b/kadai1/ramenjuniti/testdata/target/tif/sample2.tif differ diff --git a/kadai1/ramenjuniti/testdata/target/tif/sample3.tif b/kadai1/ramenjuniti/testdata/target/tif/sample3.tif new file mode 100644 index 0000000..6eca38f Binary files /dev/null and b/kadai1/ramenjuniti/testdata/target/tif/sample3.tif differ