forked from tanitall/memo
/
fetch.go
148 lines (134 loc) · 4.03 KB
/
fetch.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package pic
import (
"github.com/jchavannes/jgo/jerr"
"github.com/memocash/memo/app/config"
"github.com/memocash/memo/app/res"
"github.com/memocash/memo/app/util"
"github.com/nfnt/resize"
"github.com/oliamb/cutter"
"image"
"image/jpeg"
"image/png"
"io"
"net/http"
"os"
"strconv"
"strings"
)
const (
ResizeLg = 640
ResizeMed = 128
ResizeSm = 24
)
// Call when a profile pic doesn't exist on the file system.
func FetchProfilePic(url string, address string) error {
if ! util.ValidateImgurDirectLink(url) {
return jerr.New("invalid imgur link")
}
response, err := http.Get(url)
if err != nil {
return jerr.Get("couldn't fetch remote image", err)
}
defer response.Body.Close()
if _, err := os.Stat(res.PicPath); os.IsNotExist(err) {
err = os.Mkdir(res.PicPath, 0755)
if err != nil {
return jerr.Get("unable to create pic path", err)
}
}
var fileEnding = "jpg"
if strings.HasSuffix(url, "png") {
fileEnding = "png"
}
profilePicName := res.PicPath + address
file, err := os.Create(profilePicName + "." + fileEnding)
if err != nil {
return jerr.Get("couldn't create image file", err)
}
_, err = io.Copy(file, response.Body)
if err != nil {
return jerr.Get("couldn't save image file", err)
}
err = file.Close()
if err != nil {
return jerr.Get("error closing file", err)
}
// Resize. vipsthumbnail (super fast) integration is off by default.
if !config.GetFilePaths().UseVipsThumbnail {
file, err := os.Open(profilePicName + "." + fileEnding)
if err != nil {
return jerr.Get("couldn't open fetched profile pic", err)
}
// Decode jpeg into image.Image.
var img image.Image
if fileEnding == "jpg" {
img, err = jpeg.Decode(file)
if err != nil {
return jerr.Get("couldn't decode jpg profile pic", err)
}
} else {
img, err = png.Decode(file)
if err != nil {
return jerr.Get("couldn't decode png profile pic", err)
}
}
widths := []int{ResizeSm, ResizeMed, ResizeLg}
for _, width := range widths {
// Some square crop handling.
ratio := float32(img.Bounds().Max.X) / float32(img.Bounds().Max.Y)
ratioY := float32(img.Bounds().Max.Y) / float32(img.Bounds().Max.X)
if ratioY > ratio {
ratio = ratioY
}
resizeWidth := uint(float32(width) * ratio)
// Resize to resizeWidth using Lanczos resampling and preserve aspect ratio.
resizedImg := resize.Resize(resizeWidth, 0, img, resize.Lanczos3)
croppedImg, err := cutter.Crop(resizedImg, cutter.Config{
Width: width,
Height: width,
Mode: cutter.Centered,
})
if err != nil {
return jerr.Get("error cropping image", err)
}
out, err := os.Create(profilePicName + "-" + strconv.Itoa(width) + "x" + strconv.Itoa(width) + "." + fileEnding)
if err != nil {
return jerr.Get("couldn't create profile pic file", err)
}
// Write new image to file.
if fileEnding == "jpg" {
err = jpeg.Encode(out, croppedImg, nil)
if err != nil {
return jerr.Get("error encoding cropped image", err)
}
} else {
err = png.Encode(out, croppedImg)
if err != nil {
return jerr.Get("error encoding cropped image", err)
}
}
err = out.Close()
if err != nil {
return jerr.Get("error saving cropped image", err)
}
}
} else {
err = ResizeExternally(profilePicName+"."+fileEnding, profilePicName+"-"+strconv.Itoa(ResizeSm)+"x"+strconv.Itoa(ResizeSm)+"."+fileEnding, ResizeSm, ResizeSm)
if err != nil {
return jerr.Get("couldn't resize image file", err)
}
err = ResizeExternally(profilePicName+"."+fileEnding, profilePicName+"-"+strconv.Itoa(ResizeMed)+"x"+strconv.Itoa(ResizeMed)+"."+fileEnding, ResizeMed, ResizeMed)
if err != nil {
return jerr.Get("couldn't resize image file", err)
}
err = ResizeExternally(profilePicName+"."+fileEnding, profilePicName+"-"+strconv.Itoa(ResizeLg)+"x"+strconv.Itoa(ResizeLg)+"."+fileEnding, ResizeLg, ResizeLg)
if err != nil {
return jerr.Get("couldn't resize image file", err)
}
}
err = os.Remove(profilePicName + "." + fileEnding)
if err != nil {
return jerr.Get("error removing profile pic", err)
}
return nil
}