diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a9e5d5f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,4 @@ +language: go + +go: + - 1.9 \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..9fbeb54 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +> Package captcha provides a simple API for captcha generation + +
+ +[![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) + +
+ +## 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) diff --git a/captcha.go b/captcha.go index 069be28..1716fd2 100644 --- a/captcha.go +++ b/captcha.go @@ -36,8 +36,8 @@ type Options struct { // It defaults to 2. CurveNumber int - width int - height int + width int + height int } func newDefaultOption(width, height int) *Options { @@ -149,7 +149,7 @@ func drawSineCurve(img *image.NRGBA, opts *Options) { if flip { yFlip = -1.0 } - curveColor := randomDarkGray() + curveColor := randomDarkColor() for x1 := xStart; x1 <= xEnd; x1++ { 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 { - gray := rng.Intn(128) + 20 +func randomDarkColor() hsva { + 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 { @@ -174,10 +176,10 @@ func drawText(text string, img *image.NRGBA, opts *Options) error { fontSpacing := opts.width / len(text) for idx, char := range text { - fontScale := 1 + rng.Float64() * 0.5 + fontScale := 1 + rng.Float64()*0.5 fontSize := float64(opts.height) / fontScale ctx.SetFontSize(fontSize) - ctx.SetSrc(image.NewUniform(randomDarkGray())) + ctx.SetSrc(image.NewUniform(randomDarkColor())) x := fontSpacing*idx + fontSpacing/int(fontSize) y := opts.height/6 + rng.Intn(opts.height/3) + int(fontSize/2) pt := freetype.Pt(x, y) diff --git a/example/captcha.png b/example/captcha.png new file mode 100644 index 0000000..abdd5a5 Binary files /dev/null and b/example/captcha.png differ diff --git a/fonts/gen.go b/fonts/gen.go index e50392f..fbdb431 100644 --- a/fonts/gen.go +++ b/fonts/gen.go @@ -1,11 +1,11 @@ package main import ( - "io/ioutil" - "log" "bytes" "fmt" "go/format" + "io/ioutil" + "log" "path/filepath" ) @@ -37,4 +37,4 @@ func main() { if err := ioutil.WriteFile(filepath.Join("../", "font.go"), dst, 0666); err != nil { log.Fatal(err) } -} \ No newline at end of file +} diff --git a/hsva.go b/hsva.go new file mode 100644 index 0000000..3035419 --- /dev/null +++ b/hsva.go @@ -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 +} diff --git a/hsva_test.go b/hsva_test.go new file mode 100644 index 0000000..da6b69e --- /dev/null +++ b/hsva_test.go @@ -0,0 +1,10 @@ +package captcha + +import ( + "image/color" + "testing" +) + +func TestHSVAInterface(t *testing.T) { + var _ color.Color = hsva{} +}