parent
5d92cd4458
commit
f5e32fac77
|
@ -0,0 +1,4 @@
|
||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.9
|
|
@ -0,0 +1,37 @@
|
||||||
|
> Package captcha provides a simple API for captcha generation
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
[![GoDoc](https://godoc.org/github.com/steambap/captcha?status.svg)](https://godoc.org/github.com/steambap/captcha)
|
||||||
|
[![Build Status](https://travis-ci.org/steambap/captcha.svg)](https://travis-ci.org/steambap/captcha)
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## install
|
||||||
|
```
|
||||||
|
go get github.com/steambap/captcha
|
||||||
|
```
|
||||||
|
|
||||||
|
## usage
|
||||||
|
```Go
|
||||||
|
func handle(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// create a captcha of 150x50px
|
||||||
|
data, _ := captcha.New(150, 50)
|
||||||
|
|
||||||
|
// session come from other library such as gorilla/sessions
|
||||||
|
session.Values["captcha"] = data.Text
|
||||||
|
session.Save(r, w)
|
||||||
|
// send image data to client
|
||||||
|
data.WriteTo(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
[documentation](https://godoc.org/github.com/steambap/captcha) |
|
||||||
|
[example](example/main.go)
|
||||||
|
|
||||||
|
## sample image
|
||||||
|
![image](example/captcha.png)
|
||||||
|
|
||||||
|
## License
|
||||||
|
[MIT](LICENSE.md)
|
12
captcha.go
12
captcha.go
|
@ -149,7 +149,7 @@ func drawSineCurve(img *image.NRGBA, opts *Options) {
|
||||||
if flip {
|
if flip {
|
||||||
yFlip = -1.0
|
yFlip = -1.0
|
||||||
}
|
}
|
||||||
curveColor := randomDarkGray()
|
curveColor := randomDarkColor()
|
||||||
|
|
||||||
for x1 := xStart; x1 <= xEnd; x1++ {
|
for x1 := xStart; x1 <= xEnd; x1++ {
|
||||||
y := math.Sin(math.Pi*angle*float64(x1)/float64(opts.width)) * curveHeight * yFlip
|
y := math.Sin(math.Pi*angle*float64(x1)/float64(opts.width)) * curveHeight * yFlip
|
||||||
|
@ -157,10 +157,12 @@ func drawSineCurve(img *image.NRGBA, opts *Options) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func randomDarkGray() color.Gray {
|
func randomDarkColor() hsva {
|
||||||
gray := rng.Intn(128) + 20
|
hue := float64(rng.Intn(361)) / 360
|
||||||
|
saturation := 0.6 + rng.Float64() * 0.2
|
||||||
|
value := 0.25 + rng.Float64() * 0.2
|
||||||
|
|
||||||
return color.Gray{Y: uint8(gray)}
|
return hsva{h: hue, s:saturation, v:value, a:uint8(255)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func drawText(text string, img *image.NRGBA, opts *Options) error {
|
func drawText(text string, img *image.NRGBA, opts *Options) error {
|
||||||
|
@ -177,7 +179,7 @@ func drawText(text string, img *image.NRGBA, opts *Options) error {
|
||||||
fontScale := 1 + rng.Float64()*0.5
|
fontScale := 1 + rng.Float64()*0.5
|
||||||
fontSize := float64(opts.height) / fontScale
|
fontSize := float64(opts.height) / fontScale
|
||||||
ctx.SetFontSize(fontSize)
|
ctx.SetFontSize(fontSize)
|
||||||
ctx.SetSrc(image.NewUniform(randomDarkGray()))
|
ctx.SetSrc(image.NewUniform(randomDarkColor()))
|
||||||
x := fontSpacing*idx + fontSpacing/int(fontSize)
|
x := fontSpacing*idx + fontSpacing/int(fontSize)
|
||||||
y := opts.height/6 + rng.Intn(opts.height/3) + int(fontSize/2)
|
y := opts.height/6 + rng.Intn(opts.height/3) + int(fontSize/2)
|
||||||
pt := freetype.Pt(x, y)
|
pt := freetype.Pt(x, y)
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
|
@ -1,11 +1,11 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/format"
|
"go/format"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
package captcha
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
type hsva struct {
|
||||||
|
h, s, v float64
|
||||||
|
a uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://gist.github.com/mjackson/5311256
|
||||||
|
func (c hsva) RGBA() (r, g, b, a uint32) {
|
||||||
|
var i = math.Floor(c.h * 6)
|
||||||
|
var f = c.h*6 - i
|
||||||
|
var p = c.v * (1.0 - c.s)
|
||||||
|
var q = c.v * (1.0 - f*c.s)
|
||||||
|
var t = c.v * (1 - (1-f)*c.s)
|
||||||
|
|
||||||
|
var red, green, blue float64
|
||||||
|
switch int(i) % 6 {
|
||||||
|
case 0:
|
||||||
|
red, green, blue = c.v, t, p
|
||||||
|
case 1:
|
||||||
|
red, green, blue = q, c.v, p
|
||||||
|
case 2:
|
||||||
|
red, green, blue = p, c.v, t
|
||||||
|
case 3:
|
||||||
|
red, green, blue = p, q, c.v
|
||||||
|
case 4:
|
||||||
|
red, green, blue = t, p, c.v
|
||||||
|
case 5:
|
||||||
|
red, green, blue = c.v, p, q
|
||||||
|
}
|
||||||
|
|
||||||
|
r = uint32(red * 255)
|
||||||
|
r |= r << 8
|
||||||
|
g = uint32(green * 255)
|
||||||
|
g |= g << 8
|
||||||
|
b = uint32(blue * 255)
|
||||||
|
b |= b << 8
|
||||||
|
a = uint32(c.a)
|
||||||
|
a |= a << 8
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package captcha
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image/color"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHSVAInterface(t *testing.T) {
|
||||||
|
var _ color.Color = hsva{}
|
||||||
|
}
|
Reference in New Issue