Skip to content

Commit

Permalink
Implements imgconv
Browse files Browse the repository at this point in the history
  • Loading branch information
tanaka0325 committed Jul 6, 2020
1 parent 6a79d18 commit e6d67ac
Show file tree
Hide file tree
Showing 10 changed files with 273 additions and 0 deletions.
58 changes: 58 additions & 0 deletions kadai1/tanaka0325/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Image Converter

## Spec

```
## 次の仕様を満たすコマンドを作って下さい
- ディレクトリを指定する
- 指定したディレクトリ以下のJPGファイルをPNGに変換(デフォルト)
- ディレクトリ以下は再帰的に処理する
- 変換前と変換後の画像形式を指定できる(オプション)
## 以下を満たすように開発してください
- mainパッケージと分離する
- 自作パッケージと標準パッケージと準標準パッケージのみ使う
- 準標準パッケージ:golang.org/x以下のパッケージ
- ユーザ定義型を作ってみる
- GoDocを生成してみる
- Go Modulesを使ってみる
```

## Usage

```zsh
# build
$ go build -o ./imgconv

# display help
$ ./imgconv -h
Usage of ./imgconv:
-f string
file extention before convert (default "jpg")
-n dry run
-t string
file extention after convert (default "png")

# single directory
$ ./imgconv images

# multi directories
$ ./imgconv images images2

# customize ext
$ ./imgconv -f png -t gif images

# dry run
$ ./imgconv -n images
images/sample1.jpg => images/sample1.png
images2/img/sample3.jpg => images2/img/sample3.png
images2/sample2.jpg => images2/sample2.png
```

## 感想

- long option(?) はどうやってやれば良いのだろうか
- そもそも作りとしてこれで良いのだろうか・・・めっちゃ悩みました

81 changes: 81 additions & 0 deletions kadai1/tanaka0325/converter/conv_image.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package converter

import (
"fmt"
"image"
"image/gif"
"image/jpeg"
"image/png"
"io"
"os"

"golang.org/x/image/bmp"
"golang.org/x/image/tiff"
)

type convImage struct {
filename string
fromExt string
toExt string
image image.Image
}

func (i *convImage) decode() error {
r, err := os.Open(i.filename + "." + i.fromExt)
if err != nil {
return err
}
defer r.Close()

img, err := decodeHelper(r, i.fromExt)
if err != nil {
return fmt.Errorf("decode error: %w", err)
}

i.image = img
return nil
}

func decodeHelper(r io.Reader, ext string) (image.Image, error) {
switch ext {
case "png":
return png.Decode(r)
case "jpg", "jpeg":
return jpeg.Decode(r)
case "gif":
return gif.Decode(r)
case "bmp":
return bmp.Decode(r)
case "tiff", "tif":
return tiff.Decode(r)
}
return nil, fmt.Errorf("%s is not allowed", ext)
}

func (i *convImage) encode() error {
w, err := os.Create(i.filename + "." + i.toExt)
if err != nil {
return err
}
defer func() error {
if err := w.Close(); err != nil {
return err
}
return nil
}()

switch i.toExt {
case "png":
return png.Encode(w, i.image)
case "jpg", "jpeg":
return jpeg.Encode(w, i.image, nil)
case "gif":
return gif.Encode(w, i.image, nil)
case "bmp":
return gif.Encode(w, i.image, nil)
case "tiff", "tif":
return gif.Encode(w, i.image, nil)
}

return fmt.Errorf("cannot encode image")
}
104 changes: 104 additions & 0 deletions kadai1/tanaka0325/converter/convert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package converter

import (
"flag"
"fmt"
"log"
"os"
"path/filepath"
"strings"
)

// flags
var (
allowedExts = exts{"png", "jpg", "jpeg", "gif", "bmp", "tiff", "tif"}
f = flag.String("f", "jpg", "file extention before convert")
t = flag.String("t", "png", "file extention after convert")
dryRun = flag.Bool("n", false, "dry run")
)

// Convert is to convert image file format
func Convert() {
// check options ext
flag.Parse()
to := strings.ToLower(*t)
from := strings.ToLower(*f)
targetExts := []string{to, from}
for _, e := range targetExts {
if err := allowedExts.include(e); err != nil {
log.Fatal(fmt.Errorf("%w. ext is only allowd in %s", err, allowedExts))
}
}

// get target image paths from args
dns := flag.Args()
udns := uniq(dns)
paths, err := getPaths(udns, from)
if err != nil {
log.Fatal(err)
}

// convert
imgs, err := createConvImages(paths, from, to)
if err != nil {
log.Fatal(err)
}
for _, img := range imgs {
if err := img.decode(); err != nil {
log.Fatal(err)
}

if *dryRun {
fmt.Println(img.filename+"."+img.fromExt, "=>", img.filename+"."+img.toExt)
} else {
if err := img.encode(); err != nil {
log.Fatal(err)
}
}
}
}

func uniq(s []string) []string {
m := map[string]bool{}
u := []string{}

for _, v := range s {
if !m[v] {
m[v] = true
u = append(u, v)
}
}

return u
}

func getPaths(dns []string, from string) ([]string, error) {
paths := []string{}

for _, dn := range dns {
if err := filepath.Walk(dn, func(path string, info os.FileInfo, err error) error {
if filepath.Ext(path) == "."+from {
paths = append(paths, path)
}
return nil
}); err != nil {
return nil, err
}
}

return paths, nil
}

func createConvImages(paths []string, from, to string) ([]convImage, error) {
images := []convImage{}
for _, p := range paths {
i := convImage{
filename: strings.Replace(p, "."+from, "", 1),
fromExt: strings.ToLower(from),
toExt: strings.ToLower(to),
}
images = append(images, i)
}

return images, nil
}
14 changes: 14 additions & 0 deletions kadai1/tanaka0325/converter/exts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package converter

import "errors"

type exts []string

func (es exts) include(w string) error {
for _, e := range es {
if e == w {
return nil
}
}
return errors.New(w + " is not allowed")
}
5 changes: 5 additions & 0 deletions kadai1/tanaka0325/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/gopherdojo/dojo8/kadai1/tanaka0325

go 1.14

require golang.org/x/image v0.0.0-20200618115811-c13761719519
4 changes: 4 additions & 0 deletions kadai1/tanaka0325/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
github.com/gopherdojo/dojo8 v0.0.0-20200703052727-6a79d18126bf h1:lpYevjFQMxI5VNBc3WXV6Z5pDDrdppdDKwmeBoyt5BE=
golang.org/x/image v0.0.0-20200618115811-c13761719519 h1:1e2ufUJNM3lCHEY5jIgac/7UTjd6cgJNdatjPdFWf34=
golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Binary file added kadai1/tanaka0325/images/sample1.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/tanaka0325/images2/img/sample3.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/tanaka0325/images2/sample2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions kadai1/tanaka0325/imgconv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package main

import "github.com/gopherdojo/dojo8/kadai1/tanaka0325/converter"

func main() {
converter.Convert()
}

0 comments on commit e6d67ac

Please sign in to comment.