diff --git a/README.md b/README.md
index 8ae867e..96b6bc1 100644
--- a/README.md
+++ b/README.md
@@ -438,17 +438,20 @@ builder.SetResources(rotate.WithXxx(), ...)
## Captcha Image Data
### JPEGImageData object method
- Get() image.Image
-- ToBytes() []byte
-- ToBytesWithQuality(imageQuality int) []byte
-- ToBase64() string
-- ToBase64WithQuality(imageQuality int) string
+- ToBytes() ([]byte, error)
+- ToBytesWithQuality(imageQuality int) ([]byte, error)
+- ToBase64() (string, error)
+- ToBase64Data() (string, error)
+- ToBase64WithQuality(imageQuality int) (string, error)
+- ToBase64DataWithQuality(imageQuality int) (string, error)
- SaveToFile(filepath string, quality int) error
### PNGImageData object method
- Get() image.Image
-- ToBytes() []byte
-- ToBase64() string
+- ToBytes() ([]byte, error)
+- ToBase64() (string, error)
+- ToBase64Data() (string, error)
- SaveToFile(filepath string) error
@@ -462,9 +465,9 @@ builder.SetResources(rotate.WithXxx(), ...)
-
Solid ✔
- MinProgram
- UniApp
+- Flutter App
- Android App
- IOS App
-- Flutter App
- ...
diff --git a/README_zh.md b/README_zh.md
index 2ef0fec..8a47701 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -455,17 +455,20 @@ func loadPng(p string) (image.Image, error) {
### JPEGImageData
- Get() image.Image 获取原图像
-- ToBytes() []byte 转为JPEG字节数组
-- ToBytesWithQuality(imageQuality int) []byte 指定清晰度转为JPEG字节数组
-- ToBase64() string 转为 JPEG Base64 字符串
-- ToBase64WithQuality(imageQuality int) string 指定清晰度转为 JPEG Base64 字符串
+- ToBytes() ([]byte, error) 转为JPEG字节数组
+- ToBytesWithQuality(imageQuality int) ([]byte, error) 指定清晰度转为JPEG字节数组
+- ToBase64() (string, error) 转为 JPEG Base64 字符串
+- ToBase64Data() (string, error) 转为 JPEG Base64 字符串,带 "data:image/jpeg;base64," 前缀
+- ToBase64WithQuality(imageQuality int) (string, error) 指定清晰度转为 JPEG Base64 字符串
+- ToBase64DataWithQuality(imageQuality int) (string, error) 指定清晰度转为 JPEG Base64 字符串,带 "data:image/jpeg;base64," 前缀
- SaveToFile(filepath string, quality int) error 保存 JPEG 到文件
### PNGImageData
- Get() image.Image 获取原图像
-- ToBytes() []byte 转为PNG字节数组
-- ToBase64() string 转为 PNG Base64 字符串
+- ToBytes() ([]byte, error) 转为PNG字节数组
+- ToBase64() (string, error) 转为 PNG Base64 字符串
+- ToBase64Data() (string, error) 转为 PNG Base64 字符串,带 "data:image/png;base64," 前缀
- SaveToFile(filepath string) error 保存 PNG 到文件
diff --git a/v2/base/canvas/canvas.go b/v2/base/canvas/canvas.go
index 1e2d308..d4e7885 100644
--- a/v2/base/canvas/canvas.go
+++ b/v2/base/canvas/canvas.go
@@ -13,9 +13,8 @@ import (
// CreatePaletteCanvas is to the canvas that creates the palette
func CreatePaletteCanvas(width, height int, colour []color.RGBA) Palette {
- p := []color.Color{
- color.RGBA{R: 0xFF, G: 0xFF, B: 0xFF, A: 0x00},
- }
+ p := make([]color.Color, 0, len(colour)+1)
+ p = append(p, color.RGBA{R: 0xFF, G: 0xFF, B: 0xFF, A: 0x00})
for _, co := range colour {
p = append(p, co)
diff --git a/v2/base/canvas/nrgba.go b/v2/base/canvas/nrgba.go
index 1b1f971..147f5fc 100644
--- a/v2/base/canvas/nrgba.go
+++ b/v2/base/canvas/nrgba.go
@@ -7,7 +7,6 @@
package canvas
import (
- "fmt"
"image"
"image/color"
"math"
@@ -75,9 +74,7 @@ func (n *nRGBA) DrawString(params *DrawStringParams, pt fixed.Point26_6) error {
fontColor := image.NewUniform(params.Color)
dc.SetSrc(fontColor)
- text := fmt.Sprintf("%s", params.Text)
-
- if _, err := dc.DrawString(text, pt); err != nil {
+ if _, err := dc.DrawString(params.Text, pt); err != nil {
return err
}
diff --git a/v2/base/canvas/palette.go b/v2/base/canvas/palette.go
index 21a0548..4c2ff57 100644
--- a/v2/base/canvas/palette.go
+++ b/v2/base/canvas/palette.go
@@ -7,7 +7,6 @@
package canvas
import (
- "fmt"
"image"
"image/color"
"math"
@@ -239,9 +238,7 @@ func (p *palette) DrawString(params *DrawStringParams, pt fixed.Point26_6) error
fontColor := image.NewUniform(params.Color)
dc.SetSrc(fontColor)
- text := fmt.Sprintf("%s", params.Text)
-
- if _, err := dc.DrawString(text, pt); err != nil {
+ if _, err := dc.DrawString(params.Text, pt); err != nil {
return err
}
diff --git a/v2/base/codec/codec.go b/v2/base/codec/codec.go
index cccaa8c..c3874eb 100644
--- a/v2/base/codec/codec.go
+++ b/v2/base/codec/codec.go
@@ -9,17 +9,19 @@ package codec
import (
"bytes"
"encoding/base64"
- "fmt"
"image"
"image/jpeg"
"image/png"
)
+const pngBasePrefix = "data:image/png;base64,"
+const jpegBasePrefix = "data:image/jpeg;base64,"
+
// EncodePNGToByte is to encode the png into a byte array
-func EncodePNGToByte(img image.Image) (ret []byte) {
+func EncodePNGToByte(img image.Image) (ret []byte, err error) {
var buf bytes.Buffer
- if err := png.Encode(&buf, img); err != nil {
- panic(err.Error())
+ if err = png.Encode(&buf, img); err != nil {
+ return
}
ret = buf.Bytes()
buf.Reset()
@@ -27,10 +29,10 @@ func EncodePNGToByte(img image.Image) (ret []byte) {
}
// EncodeJPEGToByte is to encode the image into a byte array
-func EncodeJPEGToByte(img image.Image, quality int) (ret []byte) {
+func EncodeJPEGToByte(img image.Image, quality int) (ret []byte, err error) {
var buf bytes.Buffer
- if err := jpeg.Encode(&buf, img, &jpeg.Options{Quality: quality}); err != nil {
- panic(err.Error())
+ if err = jpeg.Encode(&buf, img, &jpeg.Options{Quality: quality}); err != nil {
+ return
}
ret = buf.Bytes()
buf.Reset()
@@ -55,12 +57,41 @@ func DecodeByteToPng(b []byte) (img image.Image, err error) {
return
}
+// EncodePNGToBase64Data is to encode the png into string
+func EncodePNGToBase64Data(img image.Image) (string, error) {
+ base64Str, err := EncodePNGToBase64(img)
+ if err != nil {
+ return "", err
+ }
+
+ return pngBasePrefix + base64Str, nil
+}
+
+// EncodeJPEGToBase64Data is to encode the image into string
+func EncodeJPEGToBase64Data(img image.Image, quality int) (string, error) {
+ base64Str, err := EncodeJPEGToBase64(img, quality)
+ if err != nil {
+ return "", err
+ }
+
+ return jpegBasePrefix + base64Str, nil
+}
+
// EncodePNGToBase64 is to encode the png into string
-func EncodePNGToBase64(img image.Image) string {
- return fmt.Sprintf("data:%s;base64,%s", "image/png", base64.StdEncoding.EncodeToString(EncodePNGToByte(img)))
+func EncodePNGToBase64(img image.Image) (string, error) {
+ byteCode, err := EncodePNGToByte(img)
+ if err != nil {
+ return "", err
+ }
+ return base64.StdEncoding.EncodeToString(byteCode), nil
}
// EncodeJPEGToBase64 is to encode the image into string
-func EncodeJPEGToBase64(img image.Image, quality int) string {
- return fmt.Sprintf("data:%s;base64,%s", "image/jpeg", base64.StdEncoding.EncodeToString(EncodeJPEGToByte(img, quality)))
+func EncodeJPEGToBase64(img image.Image, quality int) (string, error) {
+ byteCode, err := EncodeJPEGToByte(img, quality)
+ if err != nil {
+ return "", err
+ }
+
+ return base64.StdEncoding.EncodeToString(byteCode), nil
}
diff --git a/v2/base/helper/helper.go b/v2/base/helper/helper.go
index d1a8d21..dd0732a 100644
--- a/v2/base/helper/helper.go
+++ b/v2/base/helper/helper.go
@@ -11,7 +11,6 @@ import (
"image/color"
"math"
"os"
- "regexp"
"strconv"
"unicode"
"unicode/utf8"
@@ -28,7 +27,7 @@ func t2x(t int64) string {
return result
}
-// FormatAlpha is to formatting transparent
+// FormatAlpha is formatting transparent
func FormatAlpha(val float32) uint8 {
a := math.Min(float64(val), 1)
alpha := a * 255
@@ -51,11 +50,14 @@ func HexToRgb(hex string) (int64, int64, int64) {
return r, g, b
}
+var ColorHexFormatErr = errors.New("hex color must start with '#'")
+var ColorInvalidErr = errors.New("hexToByte component invalid")
+
// ParseHexColor is to turn the hex color to RGB color
func ParseHexColor(s string) (c color.RGBA, err error) {
c.A = 0xff
if s[0] != '#' {
- return c, errors.New("hex color must start with '#'")
+ return c, ColorHexFormatErr
}
hexToByte := func(b byte) byte {
@@ -67,7 +69,7 @@ func ParseHexColor(s string) (c color.RGBA, err error) {
case b >= 'A' && b <= 'F':
return b - 'A' + 10
}
- err = errors.New("hexToByte component invalid")
+ err = ColorInvalidErr
return 0
}
@@ -82,7 +84,7 @@ func ParseHexColor(s string) (c color.RGBA, err error) {
c.G = hexToByte(s[2]) * 17
c.B = hexToByte(s[3]) * 17
default:
- err = errors.New("hexToByte component invalid")
+ err = ColorInvalidErr
}
return
}
@@ -112,7 +114,7 @@ func InArrayWithStr(items []string, s string) bool {
// IsChineseChar is to detect whether it is Chinese
func IsChineseChar(str string) bool {
for _, r := range str {
- if unicode.Is(unicode.Scripts["Han"], r) || (regexp.MustCompile("[\u3002\uff1b\uff0c\uff1a\u201c\u201d\uff08\uff09\u3001\uff1f\u300a\u300b]").MatchString(string(r))) {
+ if unicode.Is(unicode.Scripts["Han"], r) {
return true
}
}
diff --git a/v2/base/imagedata/base.go b/v2/base/imagedata/base.go
index 6ad5c6d..b6d2544 100644
--- a/v2/base/imagedata/base.go
+++ b/v2/base/imagedata/base.go
@@ -7,6 +7,7 @@
package imagedata
import (
+ "errors"
"image"
"image/jpeg"
"image/png"
@@ -14,6 +15,9 @@ import (
"path"
)
+var ImageEmptyErr = errors.New("image is empty")
+var ImageMissingDataErr = errors.New("missing image data")
+
// saveToFile .
func saveToFile(img image.Image, filepath string, isTransparent bool, quality int) error {
var file *os.File
diff --git a/v2/base/imagedata/jpegdata.go b/v2/base/imagedata/jpegdata.go
index 0ade5db..3933afd 100644
--- a/v2/base/imagedata/jpegdata.go
+++ b/v2/base/imagedata/jpegdata.go
@@ -7,7 +7,6 @@
package imagedata
import (
- "fmt"
"image"
"github.com/wenlng/go-captcha/v2/base/codec"
@@ -17,10 +16,12 @@ import (
// JPEGImageData .
type JPEGImageData interface {
Get() image.Image
- ToBytes() []byte
- ToBytesWithQuality(imageQuality int) []byte
- ToBase64() string
- ToBase64WithQuality(imageQuality int) string
+ ToBytes() ([]byte, error)
+ ToBytesWithQuality(imageQuality int) ([]byte, error)
+ ToBase64() (string, error)
+ ToBase64WithQuality(imageQuality int) (string, error)
+ ToBase64Data() (string, error)
+ ToBase64DataWithQuality(imageQuality int) (string, error)
SaveToFile(filepath string, quality int) error
}
@@ -46,25 +47,25 @@ func (c *jpegImageDta) Get() image.Image {
// SaveToFile is to save JPEG as a file
func (c *jpegImageDta) SaveToFile(filepath string, quality int) error {
if c.image == nil {
- return fmt.Errorf("missing image data")
+ return ImageMissingDataErr
}
return saveToFile(c.image, filepath, false, quality)
}
// ToBytes is to convert JPEG into byte array
-func (c *jpegImageDta) ToBytes() []byte {
+func (c *jpegImageDta) ToBytes() ([]byte, error) {
if c.image == nil {
- return []byte{}
+ return []byte{}, ImageEmptyErr
}
return codec.EncodeJPEGToByte(c.image, option.QualityNone)
}
// ToBytesWithQuality is to convert JPEG into byte array with quality
-func (c *jpegImageDta) ToBytesWithQuality(imageQuality int) []byte {
+func (c *jpegImageDta) ToBytesWithQuality(imageQuality int) ([]byte, error) {
if c.image == nil {
- return []byte{}
+ return []byte{}, ImageEmptyErr
}
if imageQuality <= option.QualityNone && imageQuality >= option.QualityLevel5 {
@@ -73,19 +74,40 @@ func (c *jpegImageDta) ToBytesWithQuality(imageQuality int) []byte {
return codec.EncodeJPEGToByte(c.image, option.QualityNone)
}
+// ToBase64Data is to convert JPEG into base64
+func (c *jpegImageDta) ToBase64Data() (string, error) {
+ if c.image == nil {
+ return "", ImageEmptyErr
+ }
+
+ return codec.EncodeJPEGToBase64Data(c.image, option.QualityNone)
+}
+
+// ToBase64DataWithQuality is to convert JPEG into base64 with quality
+func (c *jpegImageDta) ToBase64DataWithQuality(imageQuality int) (string, error) {
+ if c.image == nil {
+ return "", ImageEmptyErr
+ }
+
+ if imageQuality <= option.QualityNone && imageQuality >= option.QualityLevel5 {
+ return codec.EncodeJPEGToBase64Data(c.image, imageQuality)
+ }
+ return codec.EncodeJPEGToBase64Data(c.image, option.QualityNone)
+}
+
// ToBase64 is to convert JPEG into base64
-func (c *jpegImageDta) ToBase64() string {
+func (c *jpegImageDta) ToBase64() (string, error) {
if c.image == nil {
- return ""
+ return "", ImageEmptyErr
}
return codec.EncodeJPEGToBase64(c.image, option.QualityNone)
}
// ToBase64WithQuality is to convert JPEG into base64 with quality
-func (c *jpegImageDta) ToBase64WithQuality(imageQuality int) string {
+func (c *jpegImageDta) ToBase64WithQuality(imageQuality int) (string, error) {
if c.image == nil {
- return ""
+ return "", ImageEmptyErr
}
if imageQuality <= option.QualityNone && imageQuality >= option.QualityLevel5 {
diff --git a/v2/base/imagedata/pngdata.go b/v2/base/imagedata/pngdata.go
index 3f595a8..0febcb7 100644
--- a/v2/base/imagedata/pngdata.go
+++ b/v2/base/imagedata/pngdata.go
@@ -7,7 +7,6 @@
package imagedata
import (
- "fmt"
"image"
"github.com/wenlng/go-captcha/v2/base/codec"
@@ -17,8 +16,9 @@ import (
// PNGImageData .
type PNGImageData interface {
Get() image.Image
- ToBytes() []byte
- ToBase64() string
+ ToBytes() ([]byte, error)
+ ToBase64() (string, error)
+ ToBase64Data() (string, error)
SaveToFile(filepath string) error
}
@@ -44,25 +44,32 @@ func (c *pngImageDta) Get() image.Image {
// SaveToFile is to save PNG as a file
func (c *pngImageDta) SaveToFile(filepath string) error {
if c.image == nil {
- return fmt.Errorf("missing image data")
+ return ImageMissingDataErr
}
return saveToFile(c.image, filepath, true, option.QualityNone)
}
// ToBytes is to convert PNG into byte array
-func (c *pngImageDta) ToBytes() []byte {
+func (c *pngImageDta) ToBytes() ([]byte, error) {
if c.image == nil {
- return []byte{}
+ return []byte{}, ImageEmptyErr
}
-
return codec.EncodePNGToByte(c.image)
}
+// ToBase64Data is to convert PNG into base64
+func (c *pngImageDta) ToBase64Data() (string, error) {
+ if c.image == nil {
+ return "", ImageEmptyErr
+ }
+ return codec.EncodePNGToBase64Data(c.image)
+}
+
// ToBase64 is to convert PNG into base64
-func (c *pngImageDta) ToBase64() string {
+func (c *pngImageDta) ToBase64() (string, error) {
if c.image == nil {
- return ""
+ return "", ImageEmptyErr
}
return codec.EncodePNGToBase64(c.image)
}
diff --git a/v2/base/logger/logger.go b/v2/base/logger/logger.go
index 034cf49..88216a6 100644
--- a/v2/base/logger/logger.go
+++ b/v2/base/logger/logger.go
@@ -34,6 +34,8 @@ func New() Logger {
var _ Logger = (*logx)(nil)
+var Logx = New()
+
// logx .
type logx struct {
l *log.Logger
diff --git a/v2/click/click.go b/v2/click/click.go
index cf9bc34..0598750 100644
--- a/v2/click/click.go
+++ b/v2/click/click.go
@@ -7,7 +7,7 @@
package click
import (
- "fmt"
+ "errors"
"image"
"image/color"
"math"
@@ -22,7 +22,7 @@ import (
)
// Version # of captcha
-const Version = "2.0.0"
+const Version = "2.0.2"
// Captcha .
type Captcha interface {
@@ -41,6 +41,14 @@ const (
var _ Captcha = (*captcha)(nil)
+var EmptyShapesErr = errors.New("empty shapes")
+var EmptyCharacterErr = errors.New("empty character")
+var CharRangeLenErr = errors.New("character length must be large than to 'rangeLen.Max'")
+var ShapesRangeLenErr = errors.New("total number of shapes must be large than to 'rangeLen.Max'")
+var ShapesTypeErr = errors.New("shape must be is image type")
+var EmptyBackgroundImageErr = errors.New("no background image")
+var ModeSupportErr = errors.New("mode not supported")
+
// captcha .
type captcha struct {
version string
@@ -181,7 +189,7 @@ func (c *captcha) genShapes() ([]string, error) {
length := random.RandInt(c.opts.rangeLen.Min, c.opts.rangeLen.Max)
shapeNames := c.genRandShape(length)
if len(shapeNames) == 0 {
- return []string{}, fmt.Errorf("click captcha err: %v", "no shapes generation")
+ return []string{}, EmptyShapesErr
}
return shapeNames, nil
}
@@ -191,14 +199,14 @@ func (c *captcha) genChars() ([]string, error) {
length := random.RandInt(c.opts.rangeLen.Min, c.opts.rangeLen.Max)
chars := c.genRandChar(length)
if len(chars) == 0 {
- return []string{}, fmt.Errorf("click captcha err: %v", "no character generation")
+ return []string{}, EmptyCharacterErr
}
return chars, nil
}
// genDots is to generate an orderly dot list
func (c *captcha) genDots(imageSize *option.Size, size *option.RangeVal, values []string, padding int) map[int]*Dot {
- var dots = make(map[int]*Dot)
+ var dots = make(map[int]*Dot, len(values))
width := imageSize.Width
height := imageSize.Height
if padding > 0 {
@@ -255,7 +263,7 @@ func (c *captcha) genDots(imageSize *option.Size, size *option.RangeVal, values
if c.mode == ModeShape {
dots[i].Shape = value
} else {
- dots[i].Text = fmt.Sprintf("%s", value)
+ dots[i].Text = value
}
}
@@ -266,17 +274,17 @@ func (c *captcha) genDots(imageSize *option.Size, size *option.RangeVal, values
func (c *captcha) check() error {
if c.mode == ModeText {
if len(c.resources.chars) < c.opts.rangeLen.Max {
- return fmt.Errorf("click captcha err: chars must be large than to %d", c.opts.rangeLen.Max)
+ return CharRangeLenErr
}
return nil
} else if c.mode == ModeShape {
if len(c.resources.shapes) < c.opts.rangeLen.Max {
- return fmt.Errorf("click captcha err: shapes must be large than to %d", c.opts.rangeLen.Max)
+ return ShapesRangeLenErr
}
- for name, img := range c.resources.shapeMaps {
+ for _, img := range c.resources.shapeMaps {
if img == nil {
- return fmt.Errorf("click captcha err: [%s] shape must be is image type", name)
+ return ShapesTypeErr
}
}
@@ -284,10 +292,10 @@ func (c *captcha) check() error {
}
if len(c.resources.rangBackgrounds) == 0 {
- return fmt.Errorf("click captcha err: no rang backgroun image")
+ return EmptyBackgroundImageErr
}
- return fmt.Errorf("click captcha err: %v", "mode not supported")
+ return ModeSupportErr
}
// rangeCheckDots is to generate random detection points
diff --git a/v2/click/draw.go b/v2/click/draw.go
index 70928a0..f6e1cd0 100644
--- a/v2/click/draw.go
+++ b/v2/click/draw.go
@@ -104,10 +104,6 @@ func (d *drawImage) DrawWithNRGBA(params *DrawImageParams) (image.Image, error)
// DrawWithPalette is to draw with a palette
func (d *drawImage) DrawWithPalette(params *DrawImageParams, tColors []color.Color, bgColors []color.Color) (image.Image, error) {
dots := params.CaptchaDrawDot
- p := []color.Color{
- color.RGBA{R: 0xFF, G: 0xFF, B: 0xFF, A: 0x00},
- }
- p = append(p, tColors...)
nBgColors := make([]color.Color, 0, len(bgColors))
for _, bgColor := range bgColors {
@@ -115,6 +111,10 @@ func (d *drawImage) DrawWithPalette(params *DrawImageParams, tColors []color.Col
aa := helper.FormatAlpha(params.ThumbDisturbAlpha)
nBgColors = append(nBgColors, color.RGBA{R: uint8(r), G: uint8(g), B: uint8(b), A: aa})
}
+
+ var p = make([]color.Color, 0, len(tColors)+len(nBgColors)+1)
+ p = append(p, color.RGBA{R: 0xFF, G: 0xFF, B: 0xFF, A: 0x00})
+ p = append(p, tColors...)
p = append(p, nBgColors...)
cvs := canvas.NewPalette(image.Rect(0, 0, params.Width, params.Height), p)
@@ -183,17 +183,16 @@ func (d *drawImage) DrawWithPalette(params *DrawImageParams, tColors []color.Col
func (d *drawImage) DrawWithNRGBA2(params *DrawImageParams, tColors []color.Color, bgColors []color.Color) (image.Image, error) {
dots := params.CaptchaDrawDot
- p := []color.Color{
- color.RGBA{R: 0xFF, G: 0xFF, B: 0xFF, A: 0x00},
- }
- p = append(p, tColors...)
-
nBgColors := make([]color.Color, 0, len(bgColors))
for _, bgColor := range bgColors {
r, g, b, _ := bgColor.RGBA()
aa := helper.FormatAlpha(params.ThumbDisturbAlpha)
nBgColors = append(nBgColors, color.RGBA{R: uint8(r), G: uint8(g), B: uint8(b), A: aa})
}
+
+ var p = make([]color.Color, 0, len(tColors)+len(nBgColors)+1)
+ p = append(p, color.RGBA{R: 0xFF, G: 0xFF, B: 0xFF, A: 0x00})
+ p = append(p, tColors...)
p = append(p, nBgColors...)
ccvs := canvas.NewNRGBA(image.Rect(0, 0, params.Width, params.Height), true)
@@ -309,6 +308,7 @@ func (d *drawImage) randomDrawSlimLine(m canvas.Palette, num int, colorB []color
func (d *drawImage) DrawDotImage(dot *DrawDot, params *DrawImageParams) (canvas.NRGBA, *canvas.AreaRect, error) {
cColor, _ := helper.ParseHexColor(dot.Color)
cColor.A = helper.FormatAlpha(params.Alpha)
+
var cImage image.Image
var err error
if dot.DrawType == DrawTypeImage {
@@ -320,19 +320,11 @@ func (d *drawImage) DrawDotImage(dot *DrawDot, params *DrawImageParams) (canvas.
return nil, nil, err
}
- var colorArr = []color.RGBA{
- cColor,
- }
-
shadowColorHex := shadowColor
if params.ShadowColor != "" {
shadowColorHex = params.ShadowColor
}
-
sColor, _ := helper.ParseHexColor(shadowColorHex)
- if params.ShowShadow {
- colorArr = append(colorArr, sColor)
- }
cvs := canvas.CreateNRGBACanvas(dot.Width+10, dot.Height+10, true)
if params.ShowShadow {
@@ -387,10 +379,11 @@ func (d *drawImage) DrawStringImage(dot *DrawDot, textColor color.Color) (canvas
// DrawShapeImage is to draw shape image
func (d *drawImage) DrawShapeImage(dot *DrawDot, cColor color.Color) (canvas.NRGBA, error) {
cr, cg, cb, ca := cColor.RGBA()
+
var colorArr = []color.RGBA{
{R: uint8(cr), G: uint8(cg), B: uint8(cb), A: uint8(ca)},
}
-
+
ncvs := canvas.CreateNRGBACanvas(dot.Width+10, dot.Height+10, true)
var bounds image.Rectangle
var img image.Image
diff --git a/v2/click/option.go b/v2/click/option.go
index 0a7fc19..2a63664 100644
--- a/v2/click/option.go
+++ b/v2/click/option.go
@@ -7,11 +7,16 @@
package click
import (
+ "errors"
+
"github.com/wenlng/go-captcha/v2/base/logger"
"github.com/wenlng/go-captcha/v2/base/option"
"golang.org/x/image/font"
)
+var ColorLenErr = errors.New("the color length must be less than or equal to 255")
+var RangeVerifyLenErr = errors.New("the max value of 'rangeVerifyLen' must be less than or equal to the min value of 'rangeLen'")
+
// Options .
type Options struct {
fontDPI int
@@ -236,7 +241,7 @@ func WithRangeSize(val option.RangeVal) Option {
func WithRangeColors(colors []string) Option {
return func(opts *Options) {
if len(colors) > 255 {
- logger.New().Errorf("withRangeColors error: the max value of rangColors must be less than or equal to 255")
+ logger.Logx.Warnf("withRangeColors(): %v", ColorLenErr)
return
}
@@ -290,7 +295,7 @@ func WithRangeThumbImageSize(val option.Size) Option {
func WithRangeVerifyLen(val option.RangeVal) Option {
return func(opts *Options) {
if val.Max > opts.rangeLen.Min {
- logger.New().Errorf("withRangeVerifyLen error: the max value of rangeVerifyLen must be less than or equal to the min value of rangeLen")
+ logger.Logx.Warnf("withRangeVerifyLen(): %v", RangeVerifyLenErr)
return
}
@@ -316,7 +321,7 @@ func WithRangeThumbSize(val option.RangeVal) Option {
func WithRangeThumbColors(val []string) Option {
return func(opts *Options) {
if len(val) > 255 {
- logger.New().Errorf("withRangeThumbColors error: the max value of rangeThumbColors must be less than or equal to 255")
+ logger.Logx.Warnf("WithRangeThumbColors(): %v", ColorLenErr)
return
}
opts.rangeThumbColors = val
@@ -327,7 +332,7 @@ func WithRangeThumbColors(val []string) Option {
func WithRangeThumbBgColors(val []string) Option {
return func(opts *Options) {
if len(val) > 255 {
- logger.New().Errorf("withRangeThumbBgColors error: the max value of rangeThumbBgColors must be less than or equal to 255")
+ logger.Logx.Warnf("withRangeThumbBgColors(): %v", ColorLenErr)
return
}
diff --git a/v2/rotate/draw.go b/v2/rotate/draw.go
index 1a77b36..520e2a9 100644
--- a/v2/rotate/draw.go
+++ b/v2/rotate/draw.go
@@ -51,6 +51,7 @@ type drawImage struct {
// DrawWithCropCircle is to draw a crop circle
func (d *drawImage) DrawWithCropCircle(params *DrawCropCircleImageParams) (image.Image, error) {
bgImage := params.Background
+
bgBounds := bgImage.Bounds()
cvs := canvas.CreateNRGBACanvas(bgImage.Bounds().Dx(), bgImage.Bounds().Dy(), true)
draw.Draw(cvs.Get(), bgImage.Bounds(), bgImage, image.Point{}, draw.Over)
diff --git a/v2/rotate/option.go b/v2/rotate/option.go
index 550802c..5ccd07a 100644
--- a/v2/rotate/option.go
+++ b/v2/rotate/option.go
@@ -66,7 +66,7 @@ func WithImageSquareSize(val int) Option {
// WithRangeAnglePos .
func WithRangeAnglePos(vals []option.RangeVal) Option {
return func(opts *Options) {
- var newVals = make([]*option.RangeVal, 0)
+ var newVals = make([]*option.RangeVal, 0, len(vals))
for i := 0; i < len(vals); i++ {
val := vals[i]
newVals = append(newVals, &option.RangeVal{Min: val.Min, Max: val.Max})
diff --git a/v2/rotate/rotate.go b/v2/rotate/rotate.go
index c509f3b..2ea3293 100644
--- a/v2/rotate/rotate.go
+++ b/v2/rotate/rotate.go
@@ -7,7 +7,7 @@
package rotate
import (
- "fmt"
+ "errors"
"image"
"github.com/wenlng/go-captcha/v2/base/helper"
@@ -18,7 +18,7 @@ import (
)
// Version # of captcha
-const Version = "2.0.0"
+const Version = "2.0.2"
// Captcha .
type Captcha interface {
@@ -30,6 +30,9 @@ type Captcha interface {
var _ Captcha = (*captcha)(nil)
+var EmptyImageErr = errors.New("no image")
+var ImageTypeErr = errors.New("image must be is image.Image type")
+
// captcha .
type captcha struct {
version string
@@ -170,11 +173,11 @@ func (c *captcha) genBlock(imageSize int, thumbImageSquareSize int) *Block {
// check is to check the captcha parameter
func (c *captcha) check() error {
if len(c.resources.rangImages) == 0 {
- return fmt.Errorf("rotate captcha err: no rang image")
+ return EmptyImageErr
}
for _, img := range c.resources.rangImages {
if img == nil {
- return fmt.Errorf("rotate captcha err: image must be is image.Image type")
+ return ImageTypeErr
}
}
return nil
diff --git a/v2/slide/option.go b/v2/slide/option.go
index 7517619..a6ae616 100644
--- a/v2/slide/option.go
+++ b/v2/slide/option.go
@@ -108,7 +108,7 @@ func WithRangeGraphSize(val option.RangeVal) Option {
// WithRangeGraphAnglePos .
func WithRangeGraphAnglePos(vals []option.RangeVal) Option {
return func(opts *Options) {
- var newVals = make([]*option.RangeVal, 0)
+ var newVals = make([]*option.RangeVal, 0, len(vals))
for i := 0; i < len(vals); i++ {
val := vals[i]
newVals = append(newVals, &option.RangeVal{Min: val.Min, Max: val.Max})
diff --git a/v2/slide/slide.go b/v2/slide/slide.go
index 9bff8ee..54ceb3d 100644
--- a/v2/slide/slide.go
+++ b/v2/slide/slide.go
@@ -7,7 +7,7 @@
package slide
import (
- "fmt"
+ "errors"
"image"
"math"
@@ -20,7 +20,7 @@ import (
)
// Version # of captcha
-const Version = "2.0.0"
+const Version = "2.0.2"
type Mode int
@@ -39,6 +39,13 @@ type Captcha interface {
var _ Captcha = (*captcha)(nil)
+var GraphImageErr = errors.New("graph image is incorrect")
+var GenerateDataErr = errors.New("generate data failed")
+var ImageTypeErr = errors.New("tile image must be is image.Image type")
+var ShadowImageTypeErr = errors.New("tile shadow image must be is image.Image type")
+var MaskImageTypeErr = errors.New("tile shadow image must be is image.Image type")
+var EmptyBackgroundImageErr = errors.New("no background image")
+
// captcha .
type captcha struct {
version string
@@ -100,7 +107,7 @@ func (c *captcha) Generate() (CaptchaData, error) {
overlayImage, shadowImage, maskImage := c.genGraph()
if overlayImage == nil || shadowImage == nil || maskImage == nil {
- return nil, fmt.Errorf("the graph image is incorrect")
+ return nil, GraphImageErr
}
blocks, tilePoint := c.genGraphBlocks(c.opts.imageSize, c.opts.rangeGraphSize, c.opts.genGraphNumber)
@@ -116,7 +123,7 @@ func (c *captcha) Generate() (CaptchaData, error) {
}
if block == nil {
- return nil, fmt.Errorf("gen captcha data failed")
+ return nil, GenerateDataErr
}
var masterImage, masterBgImage, tileImage image.Image
@@ -309,16 +316,16 @@ func (c *captcha) genGraph() (maskImage, shadowImage, templateImage image.Image)
func (c *captcha) check() error {
for _, tile := range c.resources.rangGraphImage {
if tile.OverlayImage == nil {
- return fmt.Errorf("slide captcha err: tile image must be is image.Image type")
+ return ImageTypeErr
} else if tile.ShadowImage == nil {
- return fmt.Errorf("slide captcha err: tile shadow image must be is image.Image type")
+ return ShadowImageTypeErr
} else if tile.MaskImage == nil {
- return fmt.Errorf("slide captcha err: tile mask image must be is image.Image type")
+ return MaskImageTypeErr
}
}
if len(c.resources.rangBackgrounds) == 0 {
- return fmt.Errorf("slide captcha err: no rang backgroun image")
+ return EmptyBackgroundImageErr
}
return nil
diff --git a/v2/tests/click_text_test.go b/v2/tests/click_text_test.go
index 37b351e..6a2bc41 100644
--- a/v2/tests/click_text_test.go
+++ b/v2/tests/click_text_test.go
@@ -19,6 +19,7 @@ func init() {
click.WithRangeLen(option.RangeVal{Min: 4, Max: 6}),
click.WithRangeVerifyLen(option.RangeVal{Min: 2, Max: 4}),
click.WithDisabledRangeVerifyLen(true),
+ click.WithIsThumbNonDeformAbility(false),
)
fontN, err := loadFont("../.cache/fzshengsksjw_cu.ttf")
@@ -26,15 +27,22 @@ func init() {
log.Fatalln(err)
}
+ fontN2, err := loadFont("../.cache/yrdzst-bold.ttf")
+ if err != nil {
+ log.Fatalln(err)
+ }
+
bgImage, err := loadPng("../.cache/bg.png")
if err != nil {
log.Fatalln(err)
}
builder.SetResources(
+ click.WithChars([]string{"鼓", "鼎", "默", "黔", "黑", "黎", "黍", "黄", "麻", "麸", "麦", "鹿"}),
//click.WithChars([]string{"这", "是", "随", "机", "的", "文", "本", "种", "子", "呀"}),
- click.WithChars([]string{"A1", "B2", "C3", "D4", "E5", "F6", "G7", "H8", "I9", "J0"}),
+ //click.WithChars([]string{"A1", "B2", "C3", "D4", "E5", "F6", "G7", "H8", "I9", "J0"}),
click.WithFonts([]*truetype.Font{
+ fontN2,
fontN,
}),
click.WithBackgrounds([]image.Image{
@@ -61,8 +69,8 @@ func TestClickTextCaptcha(t *testing.T) {
dots, _ := json.Marshal(dotData)
fmt.Println(string(dots))
- fmt.Println(captData.GetMasterImage().ToBase64())
- fmt.Println(captData.GetThumbImage().ToBase64())
+ fmt.Println(captData.GetMasterImage().ToBase64Data())
+ fmt.Println(captData.GetThumbImage().ToBase64Data())
err = captData.GetMasterImage().SaveToFile("../.cache/master.jpg", option.QualityNone)
if err != nil {