Numbers are now laid out correctly. Next commits will introduce perturbations.
Dmitry Chestnykh dmitry@codingrobots.com
Thu, 21 Apr 2011 16:48:12 +0200
3 files changed,
51 insertions(+),
33 deletions(-)
M
captcha.go
→
captcha.go
@@ -44,7 +44,7 @@ rand.Seed(time.Seconds())
} func randomNumbers() []byte { - n := make([]byte, 3) + n := make([]byte, 6) if _, err := io.ReadFull(crand.Reader, n); err != nil { panic(err) }
M
cmd/main.go
→
cmd/main.go
@@ -6,6 +6,6 @@ "os"
) func main() { - img, _ := captcha.NewRandomImage(300, 80) + img, _ := captcha.NewRandomImage(230, 60) img.PNGEncode(os.Stdout) }
M
image.go
→
image.go
@@ -16,42 +16,60 @@ type CaptchaImage struct {
*image.NRGBA primaryColor image.NRGBAColor numberWidth int - dotRadius int + numberHeight int + dotSize int +} + +func (img *CaptchaImage) calculateSizes(width, height, ncount int) { + // Goal: fit all numbers into the image. + // Convert everything to floats for calculations. + w := float64(width) + h := float64(height) + // fontWidth includes 1-dot spacing between numbers + fw := float64(fontWidth) + 1 + fh := float64(fontHeight) + nc := float64(ncount) + // Calculate width of a sigle number if we only take into + // account the width + nw := w / nc + // Calculate the number height from this width + nh := nw * fh / fw + // Number height too large? + if nh > h { + // Fit numbers based on height + nh = h + nw = fw/fh * nh + } + // Calculate dot size + img.dotSize = int(nh / fh) + // Save everything, making actual width smaller by 1 dot, + // to account for spacing between numbers + img.numberWidth = int(nw) + img.numberHeight = int(nh) - img.dotSize } func NewImage(numbers []byte, width, height int) *CaptchaImage { img := new(CaptchaImage) img.NRGBA = image.NewNRGBA(width, height) img.primaryColor = image.NRGBAColor{uint8(rand.Intn(50)), uint8(rand.Intn(50)), uint8(rand.Intn(128)), 0xFF} - //width -= 30 - //height -= 30 - var border int = 0 - // if width < height { - // border = width/4 - // } else { - // border = height/4 - // } - bwidth := width - border*2 - bheight := height - border*2 - //border := 15 - //fullNumberWidth := int(float64(width/len(numbers)) * - // float64(fontWidth) / float64(fontHeight)) - var fullNumberWidth int - if float64(fontWidth)/float64(fontHeight) > float64(bwidth)/float64(bheight) { - fullNumberWidth = bheight / fontHeight * fontWidth + // We need some space, so calculate border + var border int + if width > height { + border = height/5 } else { - fullNumberWidth = bwidth / len(numbers) + border = width/5 } - // add spacing - img.numberWidth = fullNumberWidth - fullNumberWidth/fontWidth - // center numbers in image - x := border - y := border + bwidth := width-border*2 + bheight := height-border*2 + img.calculateSizes(bwidth, bheight, len(numbers)) + // Center numbers in image + x := width/2 - (img.numberWidth*len(numbers))/2 - img.dotSize + y := height/2 - img.numberHeight/2 + img.dotSize/2 setRandomBrightness(&img.primaryColor, 180) for _, n := range numbers { //y = rand.Intn(dotSize * 4) img.drawNumber(font[n], x, y) - x += fullNumberWidth + x += img.numberWidth + img.dotSize } //img.strikeThrough(img.primaryColor) return img@@ -169,10 +187,10 @@ //skf := rand.Intn(maxSkew) - maxSkew/2
//if skf < 0 { // x -= skf * numberHeight //} - d := img.numberWidth / fontWidth // number height is ignored - println(img.numberWidth) - srad := d/2 // standard (minumum) radius - mrad := d //srad + srad/2 // maximum radius + //d := img.numberWidth / fontWidth // number height is ignored + //println(img.numberWidth) + minr := img.dotSize/2 // minumum radius + maxr := img.dotSize // maximum radius // x += srad // y += srad for yy := 0; yy < fontHeight; yy++ {@@ -181,9 +199,9 @@ if number[yy*fontWidth+xx] != 1 {
continue } // introduce random variations - or := srad //rnd(srad, mrad) - ox := x + (xx * mrad) //+ rnd(0, or/2) - oy := y + (yy * mrad) //+ rnd(0, or/2) + or := rnd(minr, maxr) + ox := x + (xx * maxr) //+ rnd(0, or/2) + oy := y + (yy * maxr) //+ rnd(0, or/2) img.drawCircle(img.primaryColor, ox, oy, or) } //x += skf