-
Notifications
You must be signed in to change notification settings - Fork 60
/
Copy pathcaptcha.go
129 lines (112 loc) · 3.16 KB
/
captcha.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
package gocaptcha
import (
"errors"
"image"
"image/color"
"image/draw"
"image/gif"
"image/jpeg"
"image/png"
"io"
"math/rand"
)
const (
// DefaultDPI 默认的dpi
DefaultDPI = 72.0
// DefaultBlurKernelSize 默认模糊卷积核大小
DefaultBlurKernelSize = 2
// DefaultBlurSigma 默认模糊sigma值
DefaultBlurSigma = 0.65
// DefaultAmplitude 默认图片扭曲的振幅
DefaultAmplitude = 20
//DefaultFrequency 默认图片扭曲的波频率
DefaultFrequency = 0.05
)
var TextCharacters = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
const (
ImageFormatPng ImageFormat = iota
ImageFormatJpeg
ImageFormatGif
)
// ImageFormat 图片格式
type ImageFormat int
type CaptchaImage struct {
nrgba *image.NRGBA
width int
height int
Complex int
Error error
}
// New 新建一个图片对象
func New(width int, height int, bgColor color.RGBA) *CaptchaImage {
m := image.NewNRGBA(image.Rect(0, 0, width, height))
draw.Draw(m, m.Bounds(), &image.Uniform{C: bgColor}, image.Point{}, draw.Src)
return &CaptchaImage{
nrgba: m,
height: height,
width: width,
}
}
// Encode 编码图片
func (captcha *CaptchaImage) Encode(w io.Writer, imageFormat ImageFormat) error {
if imageFormat == ImageFormatPng {
return png.Encode(w, captcha.nrgba)
}
if imageFormat == ImageFormatJpeg {
return jpeg.Encode(w, captcha.nrgba, &jpeg.Options{Quality: 100})
}
if imageFormat == ImageFormatGif {
return gif.Encode(w, captcha.nrgba, &gif.Options{NumColors: 256})
}
return errors.New("not supported image format")
}
// DrawLine 画直线.
func (captcha *CaptchaImage) DrawLine(drawer LineDrawer, lineColor color.Color) *CaptchaImage {
if captcha.Error != nil {
return captcha
}
y := captcha.nrgba.Bounds().Dy()
point1 := image.Point{X: captcha.nrgba.Bounds().Min.X + 1, Y: rand.Intn(y)}
point2 := image.Point{X: captcha.nrgba.Bounds().Max.X - 1, Y: rand.Intn(y)}
captcha.Error = drawer.DrawLine(captcha.nrgba, point1, point2, lineColor)
return captcha
}
// DrawBorder 画边框.
func (captcha *CaptchaImage) DrawBorder(borderColor color.RGBA) *CaptchaImage {
if captcha.Error != nil {
return captcha
}
for x := 0; x < captcha.width; x++ {
captcha.nrgba.Set(x, 0, borderColor)
captcha.nrgba.Set(x, captcha.height-1, borderColor)
}
for y := 0; y < captcha.height; y++ {
captcha.nrgba.Set(0, y, borderColor)
captcha.nrgba.Set(captcha.width-1, y, borderColor)
}
return captcha
}
// DrawNoise 画噪点.
func (captcha *CaptchaImage) DrawNoise(complex NoiseDensity, noiseDrawer NoiseDrawer) *CaptchaImage {
if captcha.Error != nil {
return captcha
}
captcha.Error = noiseDrawer.DrawNoise(captcha.nrgba, complex)
return captcha
}
// DrawText 写字.
func (captcha *CaptchaImage) DrawText(textDrawer TextDrawer, text string) *CaptchaImage {
if captcha.Error != nil {
return captcha
}
captcha.Error = textDrawer.DrawString(captcha.nrgba, text)
return captcha
}
// DrawBlur 对图片进行模糊处理
func (captcha *CaptchaImage) DrawBlur(drawer BlurDrawer, kernelSize int, sigma float64) *CaptchaImage {
if captcha.Error != nil {
return captcha
}
captcha.Error = drawer.DrawBlur(captcha.nrgba, kernelSize, sigma)
return captcha
}