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

segakazzz / 課題2 #14

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
7 changes: 7 additions & 0 deletions kadai1/segakazzz/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.idea
testdata/in/*
testdata/out/*
testdata/*.jpg
testdata/*.png
kadai1-segakazzz

52 changes: 52 additions & 0 deletions kadai1/segakazzz/README.md
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 の部分は書いていません。
- パッケージの書き方の標準を理解しておらず、勘に頼っているところがあるので、良い書き方を知りたいです。
3 changes: 3 additions & 0 deletions kadai1/segakazzz/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/gopherdojo/dojo8/kadai1/segakazzz

go 1.14
1 change: 1 addition & 0 deletions kadai1/segakazzz/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github.com/gopherdojo/dojo8 v0.0.0-20200703052727-6a79d18126bf h1:lpYevjFQMxI5VNBc3WXV6Z5pDDrdppdDKwmeBoyt5BE=
176 changes: 176 additions & 0 deletions kadai1/segakazzz/imgconv/imgconv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// Package imgconv is for Gopher Dojo Kadai1
package imgconv

import (
"flag"
"fmt"
"image"
"image/jpeg"
"image/png"
"io/ioutil"
"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() error {
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")
)

flag.Parse()
c, err := newConverter(*dir, *in, *out)
if err != nil {
// log.Fatal(err)
return err
}
err = c.Convert()
if err != nil {
// log.Fatal(err)
return err
}
fmt.Println("Done!")
return nil
}

func newConverter(dirname string, input string, output string) (*converter, error) {
switch input {
case "jpg", "png":
input = strings.ToLower(input)
default:
return nil, fmt.Errorf("Input extension is not valid. Select one from jpg/png")
}
switch output {
case "jpg", "png":
output = strings.ToLower(output)
default:
return nil, fmt.Errorf("Output extension is not valid. Select one from jpg/png")
}

if input == output {
return nil, 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() error {
files, e := c.getSourceFiles()
if e != nil {
return e
}
e = c.convertFiles(files)
if e != nil {
return e
}
return nil
}

func (c *converter) getSourceFiles() ([]os.FileInfo, error) {
files, err := ioutil.ReadDir(c.dirname)
if err != nil {
return nil, err
}
return files, nil
}

func (c *converter) convertFiles(files []os.FileInfo) error {
re, e := regexp.Compile("." + c.input + "$")
if e != nil {
return e
}
for _, file := range files {
if re.MatchString(file.Name()) {
e = c.convertSingle(file.Name())
if e != nil {
return e
}
}
}
return nil
}

func (c *converter) convertSingle(filename string) (e error) {
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))
fmt.Println(output)
if !c.dirExists(outDir) {
os.Mkdir(outDir, 0755)
}

in, e := os.Open(input)
if e != nil {
return e
}

defer func() {
e = in.Close()
}()

var out *os.File
if c.fileExists(output) {
out, e = os.OpenFile(output, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
} else {
out, e = os.Create(output)
}
if e != nil {
return e
}

defer func() {
e = out.Close()
}()

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 e
}
switch c.output {
case "png":
e = png.Encode(out, img)
case "jpg":
e = jpeg.Encode(out, img, nil)
}
if e != nil {
return e
}
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()
}
15 changes: 15 additions & 0 deletions kadai1/segakazzz/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package main

import (
"os"

"github.com/gopherdojo/dojo8/kadai1/segakazzz/imgconv"
)

func main() {
err := imgconv.RunConverter()
if err != nil {
os.Exit(1)
}
os.Exit(0)
}
12 changes: 12 additions & 0 deletions kadai1/segakazzz/testdata/download.zsh
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
6 changes: 6 additions & 0 deletions kadai2/segakazzz/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.DS_Store
testdata/*.jpg
testdata/*.png
testdata/out
testdata/test
testdata/error
Loading