|
|
@@ -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 @@ func (img *CaptchaImage) drawNumber(number []byte, x, y int) {
|
|
|
//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 @@ func (img *CaptchaImage) drawNumber(number []byte, x, y int) {
|
|
|
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
|