ires 0.3.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/ext/ires/image.go +87 -87
- data/ext/ires/ires.go +67 -65
- data/ext/ires/uri.go +30 -30
- data/lib/ires/service.rb +4 -3
- data/lib/ires/version.rb +1 -1
- data/lib/ires/view_helper.rb +5 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 573e3e3d26bbe6a54df1d21e5445287b94eb628e
|
4
|
+
data.tar.gz: a29209459ec9bb7dea651db214c3440db9cbd09c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7dfe086ce436074e319636b71eafa3736721c71a0c3c7bb175723e4279c15f6282d3aa72bc181d080798440612f2f70ba8ccaa3b40b2deebaad40f58a86ea3dc
|
7
|
+
data.tar.gz: f10ae44af632f4ed0fae261a3e26cba54985006e95913350fcde7cbba1e618037bccd5e0c69775c28cc9c2648f1498a37d51f78d115c061d87f440211feb1cde
|
data/README.md
CHANGED
@@ -11,10 +11,10 @@
|
|
11
11
|
|
12
12
|
```erb
|
13
13
|
<!-- Usually -->
|
14
|
-
<%= ires_tag(
|
14
|
+
<%= ires_tag(path: "image_01.jpg", width: 90, height: 120) %>
|
15
15
|
|
16
16
|
<!-- Using image_tag options -->
|
17
|
-
<%= ires_tag(
|
17
|
+
<%= ires_tag(path: "http://example.com/image_02.jpg", width: 200, height: 200, Ires::Mode::CROP, alt: "example image") %>
|
18
18
|
```
|
19
19
|
|
20
20
|
### Get resize path
|
@@ -47,7 +47,7 @@ Filter of resize image.
|
|
47
47
|
Default: **30days**
|
48
48
|
|
49
49
|
```erb
|
50
|
-
<%= ires_tag(
|
50
|
+
<%= ires_tag(path: '/image.jpg', width: 400, height: 300, expire: 7.days) %>
|
51
51
|
```
|
52
52
|
|
53
53
|
### Saved directory
|
data/ext/ires/image.go
CHANGED
@@ -1,48 +1,48 @@
|
|
1
1
|
package ires
|
2
2
|
|
3
3
|
import (
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
4
|
+
"bytes"
|
5
|
+
"image"
|
6
|
+
"image/gif"
|
7
|
+
"image/jpeg"
|
8
|
+
"image/png"
|
9
|
+
"io"
|
10
|
+
"io/ioutil"
|
11
|
+
"net/http"
|
12
|
+
"os"
|
13
|
+
"path"
|
14
|
+
"strings"
|
15
|
+
"time"
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
"github.com/nfnt/resize"
|
18
|
+
"github.com/oliamb/cutter"
|
19
19
|
)
|
20
20
|
|
21
21
|
// Check expiration date
|
22
22
|
func (i *Ires) DeleteExpireImage() {
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
23
|
+
today := time.Now().Format("20060102")
|
24
|
+
dir := i.readImageDir()
|
25
|
+
files, err := ioutil.ReadDir(dir)
|
26
|
+
if err != nil {
|
27
|
+
return
|
28
|
+
}
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
30
|
+
for _, file := range files {
|
31
|
+
findName := file.Name()
|
32
|
+
matched, _ := path.Match(today+"_*", findName)
|
33
|
+
if matched {
|
34
|
+
deleteImage(path.Join(dir, findName))
|
35
|
+
}
|
36
|
+
}
|
37
37
|
}
|
38
38
|
|
39
39
|
// Input image type is Local or HTTP
|
40
40
|
func (i *Ires) CheckLocal() {
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
if strings.Index(i.URI, "http") == -1 {
|
42
|
+
i.IsLocal = true
|
43
|
+
} else {
|
44
|
+
i.IsLocal = false
|
45
|
+
}
|
46
46
|
}
|
47
47
|
|
48
48
|
// Input image
|
@@ -50,11 +50,11 @@ func (i *Ires) inputImage() bool {
|
|
50
50
|
if i.IsLocal {
|
51
51
|
img, format := localImage(i.URI)
|
52
52
|
i.InputImage = &InputImage{
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
53
|
+
Image: img,
|
54
|
+
Format: format,
|
55
|
+
URI: i.URI,
|
56
|
+
}
|
57
|
+
i.setConfig()
|
58
58
|
return true
|
59
59
|
}
|
60
60
|
return i.downloadImage()
|
@@ -63,30 +63,30 @@ func (i *Ires) inputImage() bool {
|
|
63
63
|
// Save http image
|
64
64
|
func (i *Ires) downloadImage() bool {
|
65
65
|
res, err := http.Get(i.URI)
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
66
|
+
if err != nil {
|
67
|
+
return false
|
68
|
+
}
|
69
|
+
defer res.Body.Close()
|
70
70
|
|
71
|
-
|
72
|
-
|
71
|
+
header, r := copyReader(res.Body)
|
72
|
+
format := formatSearch(r)
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
74
|
+
img, _, err := image.Decode(io.MultiReader(header, res.Body))
|
75
|
+
if err != nil {
|
76
|
+
return false
|
77
|
+
}
|
78
78
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
79
|
+
distURI := i.imageURI(true)
|
80
|
+
i.InputImage = &InputImage{
|
81
|
+
Image: img,
|
82
|
+
Format: format,
|
83
|
+
URI: distURI,
|
84
|
+
}
|
85
85
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
86
|
+
if createImage(img, distURI, format) {
|
87
|
+
i.setConfig()
|
88
|
+
return true
|
89
|
+
}
|
90
90
|
return false
|
91
91
|
}
|
92
92
|
|
@@ -114,7 +114,7 @@ func createImage(img image.Image, path, format string) bool {
|
|
114
114
|
func localImage(uri string) (image.Image, string) {
|
115
115
|
file, err := os.Open(uri)
|
116
116
|
if err != nil {
|
117
|
-
|
117
|
+
return nil, ""
|
118
118
|
}
|
119
119
|
defer file.Close()
|
120
120
|
|
@@ -124,29 +124,29 @@ func localImage(uri string) (image.Image, string) {
|
|
124
124
|
|
125
125
|
img, _, err := image.Decode(io.MultiReader(header, file))
|
126
126
|
if err != nil {
|
127
|
-
|
127
|
+
return nil, ""
|
128
128
|
}
|
129
129
|
return img, format
|
130
130
|
}
|
131
131
|
|
132
132
|
// Set image config
|
133
133
|
func (i *Ires) setConfig() {
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
134
|
+
file, err := os.Open(i.InputImage.URI)
|
135
|
+
if err != nil {
|
136
|
+
panic(err)
|
137
|
+
}
|
138
|
+
defer file.Close()
|
139
139
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
140
|
+
conf, _, err := image.DecodeConfig(file)
|
141
|
+
if err != nil {
|
142
|
+
panic(err)
|
143
|
+
}
|
144
|
+
i.InputImage.Config = conf
|
145
145
|
}
|
146
146
|
|
147
147
|
// Resizing & Cropping
|
148
148
|
func (i *Ires) resizeToCrop() image.Image {
|
149
|
-
|
149
|
+
inputImg := i.InputImage.Image
|
150
150
|
var outputImg image.Image
|
151
151
|
isAsp, conf := i.isValidAspectRatio()
|
152
152
|
|
@@ -237,21 +237,21 @@ func copyReader(body io.Reader) (io.Reader, io.Reader) {
|
|
237
237
|
|
238
238
|
// Valid resize type
|
239
239
|
func (i *Ires) validResizeType() bool {
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
240
|
+
config := i.InputImage.Config
|
241
|
+
valid := false
|
242
|
+
switch i.ResizeType {
|
243
|
+
case All:
|
244
|
+
valid = true
|
245
|
+
case Smaller:
|
246
|
+
if config.Width < i.Width && config.Height < i.Height {
|
247
|
+
valid = true
|
248
|
+
}
|
249
|
+
case Larger:
|
250
|
+
if i.Width <= config.Width && i.Height <= config.Height {
|
251
|
+
valid = true
|
252
|
+
}
|
253
|
+
default:
|
254
|
+
valid = true
|
255
|
+
}
|
256
|
+
return valid
|
257
257
|
}
|
data/ext/ires/ires.go
CHANGED
@@ -1,56 +1,58 @@
|
|
1
1
|
package ires
|
2
2
|
|
3
3
|
import (
|
4
|
-
|
4
|
+
"image"
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
"github.com/nfnt/resize"
|
7
|
+
"github.com/oliamb/cutter"
|
8
8
|
)
|
9
9
|
|
10
10
|
type Mode int
|
11
|
+
|
11
12
|
const (
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
Resize Mode = iota
|
14
|
+
Crop
|
15
|
+
ResizeToCrop
|
15
16
|
)
|
16
17
|
|
17
18
|
type ResizeType int
|
19
|
+
|
18
20
|
const (
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
All ResizeType = iota
|
22
|
+
Smaller
|
23
|
+
Larger
|
22
24
|
)
|
23
25
|
|
24
26
|
type (
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
27
|
+
// Size is ...
|
28
|
+
Size struct {
|
29
|
+
Width, Height int
|
30
|
+
}
|
31
|
+
|
32
|
+
// InputImage is ...
|
33
|
+
InputImage struct {
|
34
|
+
Image image.Image
|
35
|
+
Config image.Config
|
36
|
+
Format string
|
37
|
+
URI string
|
38
|
+
}
|
39
|
+
|
40
|
+
// Ires is ...
|
41
|
+
Ires struct {
|
42
|
+
Size
|
43
|
+
ResizeType
|
44
|
+
Mode
|
45
|
+
*InputImage
|
46
|
+
URI string
|
47
|
+
Dir string
|
48
|
+
Expire string
|
49
|
+
IsLocal bool
|
50
|
+
}
|
49
51
|
)
|
50
52
|
|
51
53
|
// Resize is ...
|
52
54
|
func (i *Ires) Resize() string {
|
53
|
-
|
55
|
+
i.Mode = Resize
|
54
56
|
distURI := i.imageURI(false)
|
55
57
|
// When the image exists, return the image path
|
56
58
|
if isExistsImage(distURI) {
|
@@ -63,46 +65,46 @@ func (i *Ires) Resize() string {
|
|
63
65
|
|
64
66
|
var outputImg image.Image
|
65
67
|
if i.validResizeType() {
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
68
|
+
outputImg = resize.Resize(uint(i.Width), uint(i.Height), i.InputImage.Image, resize.Lanczos3)
|
69
|
+
} else {
|
70
|
+
outputImg = i.InputImage.Image
|
71
|
+
}
|
70
72
|
createImage(outputImg, distURI, i.InputImage.Format)
|
71
73
|
return i.targetImageURI(distURI)
|
72
74
|
}
|
73
75
|
|
74
76
|
// Crop is Crop ...
|
75
77
|
func (i *Ires) Crop() string {
|
76
|
-
|
77
|
-
|
78
|
+
i.Mode = Crop
|
79
|
+
distURI := i.imageURI(false)
|
78
80
|
// When the image exists, return the image path
|
79
81
|
if isExistsImage(distURI) {
|
80
|
-
|
81
|
-
|
82
|
+
return i.targetImageURI(distURI)
|
83
|
+
}
|
82
84
|
|
83
85
|
if !i.inputImage() {
|
84
86
|
return i.URI
|
85
87
|
}
|
86
88
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
89
|
+
var outputImg image.Image
|
90
|
+
if i.validResizeType() {
|
91
|
+
outputImg, _ = cutter.Crop(i.InputImage.Image, cutter.Config{
|
92
|
+
Width: i.Width,
|
93
|
+
Height: i.Height,
|
94
|
+
Mode: cutter.Centered,
|
95
|
+
Options: cutter.Copy,
|
96
|
+
})
|
97
|
+
} else {
|
98
|
+
outputImg = i.InputImage.Image
|
99
|
+
}
|
100
|
+
createImage(outputImg, distURI, i.InputImage.Format)
|
101
|
+
return i.targetImageURI(distURI)
|
100
102
|
}
|
101
103
|
|
102
104
|
// ResizeToCrop is ...
|
103
105
|
func (i *Ires) ResizeToCrop() string {
|
104
|
-
|
105
|
-
|
106
|
+
i.Mode = ResizeToCrop
|
107
|
+
distURI := i.imageURI(false)
|
106
108
|
// When the image exists, return the image path
|
107
109
|
if isExistsImage(distURI) {
|
108
110
|
return i.targetImageURI(distURI)
|
@@ -112,12 +114,12 @@ func (i *Ires) ResizeToCrop() string {
|
|
112
114
|
return i.URI
|
113
115
|
}
|
114
116
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
117
|
+
var outputImg image.Image
|
118
|
+
if i.validResizeType() {
|
119
|
+
outputImg = i.resizeToCrop()
|
120
|
+
} else {
|
121
|
+
outputImg = i.InputImage.Image
|
122
|
+
}
|
123
|
+
createImage(outputImg, distURI, i.InputImage.Format)
|
124
|
+
return i.targetImageURI(distURI)
|
123
125
|
}
|
data/ext/ires/uri.go
CHANGED
@@ -40,36 +40,36 @@ func (i *Ires) imageURI(original bool) string {
|
|
40
40
|
|
41
41
|
// Generate image name
|
42
42
|
func (i *Ires) imageName(original bool) string {
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
43
|
+
splitPath := strings.Split(i.URI, "/")
|
44
|
+
|
45
|
+
// ex. sample.jpg
|
46
|
+
fileName := splitPath[len(splitPath)-1]
|
47
|
+
// ex. .jpg
|
48
|
+
ext := filepath.Ext(fileName)
|
49
|
+
|
50
|
+
name := strings.Replace(fileName, ext, "", 1)
|
51
|
+
|
52
|
+
extInfo := strings.Split(ext, "?")
|
53
|
+
if len(extInfo) > 1 {
|
54
|
+
ext = extInfo[0]
|
55
|
+
name += "_" + strings.Join(extInfo[1:], "")
|
56
|
+
}
|
57
|
+
|
58
|
+
var prefix string
|
59
|
+
if original {
|
60
|
+
prefix = "original"
|
61
|
+
} else {
|
62
|
+
switch i.Mode {
|
63
|
+
case Resize:
|
64
|
+
prefix = prefixSize(i.Size) + "_resize"
|
65
|
+
case Crop:
|
66
|
+
prefix = prefixSize(i.Size) + "_crop"
|
67
|
+
case ResizeToCrop:
|
68
|
+
prefix = prefixSize(i.Size) + "_resize_to_crop"
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
return i.Expire + "_" + name + "_" + prefix + ext
|
73
73
|
}
|
74
74
|
|
75
75
|
// Create prefix by size
|
data/lib/ires/service.rb
CHANGED
@@ -8,7 +8,8 @@ module Ires
|
|
8
8
|
class << self
|
9
9
|
# Resize image path
|
10
10
|
# @return [String]
|
11
|
-
def path(path:, width
|
11
|
+
def path(path:, width: nil, height: nil, type: Type::ALL, mode: Mode::RESIZE, expire: 30.days)
|
12
|
+
raise ArgumentError, "Either width or height is required" if width.nil? && height.nil?
|
12
13
|
os = Ires::Os.current
|
13
14
|
return nil if os.nil?
|
14
15
|
|
@@ -22,8 +23,8 @@ module Ires
|
|
22
23
|
|
23
24
|
ires_element = {
|
24
25
|
path: full_path,
|
25
|
-
width: width,
|
26
|
-
height: height,
|
26
|
+
width: width || 0,
|
27
|
+
height: height || 0,
|
27
28
|
mode: mode,
|
28
29
|
type: type,
|
29
30
|
dir: dir,
|
data/lib/ires/version.rb
CHANGED
data/lib/ires/view_helper.rb
CHANGED
@@ -8,11 +8,13 @@ module Ires
|
|
8
8
|
module ViewHelper
|
9
9
|
# Image resize
|
10
10
|
# @return [image_tag]
|
11
|
-
def ires_tag(path:, width
|
11
|
+
def ires_tag(path:, width: nil, height: nil, type: Type::ALL, mode: Mode::RESIZE, expire: 30.days, **option)
|
12
|
+
raise ArgumentError, "Either width or height is required" if width.nil? && height.nil?
|
13
|
+
|
12
14
|
image = Ires::Service.path(
|
13
15
|
path: path,
|
14
|
-
width: width,
|
15
|
-
height: height,
|
16
|
+
width: width || 0,
|
17
|
+
height: height || 0,
|
16
18
|
mode: mode,
|
17
19
|
type: type,
|
18
20
|
expire: expire
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ires
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- enta0701
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-11-
|
11
|
+
date: 2018-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|