package gocaptcha import ( "image" "image/color" "image/draw" "math" "io" "image/png" "image/jpeg" "errors" "time" "math/rand" "github.com/golang/freetype" "flag" "golang.org/x/image/font" "log" "io/ioutil" "github.com/golang/freetype/truetype" "image/gif" "fmt" "os" "strings" ) var ( dpi = flag.Float64("dpi", 72, "screen resolution in Dots Per Inch") r = rand.New(rand.NewSource(time.Now().UnixNano())); FontFamily []string = make([]string,0); ) const txtChars = "AaCcDdEeFfGgHhJjKkLMmNnPpQqRrSsTtUuVvWwXxYtZ2346789"; const( //图片格式 ImageFormatPng = iota ImageFormatJpeg ImageFormatGif //验证码噪点强度 CaptchaComplexLower = iota CaptchaComplexMedium CaptchaComplexHigh ) type CaptchaImage struct { nrgba *image.NRGBA width int height int Complex int } //获取指定目录下的所有文件,不进入下一级目录搜索,可以匹配后缀过滤。 func ReadFonts(dirPth string, suffix string) (err error) { files := make([]string, 0, 10) dir, err := ioutil.ReadDir(dirPth) if err != nil { return err } PthSep := string(os.PathSeparator) suffix = strings.ToUpper(suffix) //忽略后缀匹配的大小写 for _, fi := range dir { if fi.IsDir() { // 忽略目录 continue } if strings.HasSuffix(strings.ToUpper(fi.Name()), suffix) { //匹配文件 files = append(files, dirPth+PthSep+fi.Name()) } } SetFontFamily(files...) return nil } //新建一个图片对象 func NewCaptchaImage(width int,height int,bgColor color.RGBA) (*CaptchaImage ,error){ m := image.NewNRGBA(image.Rect(0, 0, width, height)); draw.Draw(m, m.Bounds(), &image.Uniform{ bgColor }, image.ZP, draw.Src); return &CaptchaImage{ nrgba: m, height : height, width : width, },nil; } //保存图片对象 func (this *CaptchaImage)SaveImage(w io.Writer ,imageFormat int) error{ if(imageFormat == ImageFormatPng){ return png.Encode(w, this.nrgba); }; if(imageFormat == ImageFormatJpeg){ return jpeg.Encode(w,this.nrgba, &jpeg.Options{ 100 }); } if(imageFormat == ImageFormatGif){ return gif.Encode(w,this.nrgba, &gif.Options{ NumColors : 256}); } return errors.New("Not supported image format"); } //添加一个较粗的空白直线 func (captcha *CaptchaImage) DrawHollowLine()(*CaptchaImage){ first := (captcha.width / 20); end := first * 19; lineColor := color.RGBA{ R : 245,G:250,B:251,A:255}; x1 := float64(r.Intn(first)); //y1 := float64(r.Intn(y)+y); x2 := float64( r.Intn(first)+end); multiple := float64(r.Intn(5)+3)/float64(5); if(int(multiple*10) % 3 == 0){ multiple = multiple * -1.0; } w := captcha.height / 20; for ;x1 < x2; x1 ++{ y := math.Sin(x1*math.Pi*multiple/float64(captcha.width)) * float64(captcha.height/3); if(multiple < 0){ y = y + float64(captcha.height/2); } captcha.nrgba.Set(int(x1),int(y),lineColor); for i:=0;i<=w;i++{ captcha.nrgba.Set(int(x1),int(y)+i,lineColor); } } return captcha; } //画一条直线 func (captcha *CaptchaImage)Drawline(num int) (*CaptchaImage) { first := (captcha.width / 10); end := first * 9; y := captcha.height / 3; for i:=0;i= point2.X { sx = -1 } if point1.Y >= point2.Y { sy = -1 } err := dx - dy for { captcha.nrgba.Set(point1.X,point1.Y,lineColor); captcha.nrgba.Set(point1.X+1,point1.Y,lineColor); captcha.nrgba.Set(point1.X-1,point1.Y,lineColor); captcha.nrgba.Set(point1.X+2,point1.Y,lineColor); captcha.nrgba.Set(point1.X-2,point1.Y,lineColor); if point1.X == point2.X && point1.Y == point2.Y { return } e2 := err * 2 if e2 > -dy { err -= dy point1.X += sx } if e2 < dx { err += dx point1.Y += sy } } } //画边框 func (captcha *CaptchaImage) DrawBorder(borderColor color.RGBA) (*CaptchaImage){ for x :=0;x 400){ blue = 0; }else{ blue = 400 - green -red; } if(blue > 255){ blue = 255; } return color.RGBA{R:uint8(red), G : uint8(green),B:uint8(blue),A:uint8(255)}; } //生成随机字体 func RandText(num int) string { textNum := len(txtChars); text := ""; r := rand.New(rand.NewSource(time.Now().UnixNano())); for i:=0;i> 16 green := (colorVal & 0x00FF00) >> 8 blue := colorVal & 0x0000FF return color.RGBA{ R:uint8(red), G:uint8(green), B:uint8(blue), A:uint8(255), } }