1、http://www.oschina.net/code/snippet_173630_12006 :
效果:
源代码:
1: package main
2:
3: import (
14: )
15:
const (
17: stdWidth = 100
18: stdHeight = 40
19: maxSkew = 2
20: )
21:
const (
23: fontWidth = 5
24: fontHeight = 8
25: blackChar = 1
26: )
27:
28: var font = [][]byte{
// 0
30: 0, 1, 1, 1, 0,
31: 1, 0, 0, 0, 1,
32: 1, 0, 0, 0, 1,
33: 1, 0, 0, 0, 1,
34: 1, 0, 0, 0, 1,
35: 1, 0, 0, 0, 1,
36: 1, 0, 0, 0, 1,
37: 0, 1, 1, 1, 0},
// 1
39: 0, 0, 1, 0, 0,
40: 0, 1, 1, 0, 0,
41: 1, 0, 1, 0, 0,
42: 0, 0, 1, 0, 0,
43: 0, 0, 1, 0, 0,
44: 0, 0, 1, 0, 0,
45: 0, 0, 1, 0, 0,
46: 1, 1, 1, 1, 1},
// 2
48: 0, 1, 1, 1, 0,
49: 1, 0, 0, 0, 1,
50: 0, 0, 0, 0, 1,
51: 0, 0, 0, 1, 1,
52: 0, 1, 1, 0, 0,
53: 1, 0, 0, 0, 0,
54: 1, 0, 0, 0, 0,
55: 1, 1, 1, 1, 1},
// 3
57: 1, 1, 1, 1, 0,
58: 0, 0, 0, 0, 1,
59: 0, 0, 0, 1, 0,
60: 0, 1, 1, 1, 0,
61: 0, 0, 0, 1, 0,
62: 0, 0, 0, 0, 1,
63: 0, 0, 0, 0, 1,
64: 1, 1, 1, 1, 0},
// 4
66: 1, 0, 0, 1, 0,
67: 1, 0, 0, 1, 0,
68: 1, 0, 0, 1, 0,
69: 1, 0, 0, 1, 0,
70: 1, 1, 1, 1, 1,
71: 0, 0, 0, 1, 0,
72: 0, 0, 0, 1, 0,
73: 0, 0, 0, 1, 0},
// 5
75: 1, 1, 1, 1, 1,
76: 1, 0, 0, 0, 0,
77: 1, 0, 0, 0, 0,
78: 1, 1, 1, 1, 0,
79: 0, 0, 0, 0, 1,
80: 0, 0, 0, 0, 1,
81: 0, 0, 0, 0, 1,
82: 1, 1, 1, 1, 0},
// 6
84: 0, 0, 1, 1, 1,
85: 0, 1, 0, 0, 0,
86: 1, 0, 0, 0, 0,
87: 1, 1, 1, 1, 0,
88: 1, 0, 0, 0, 1,
89: 1, 0, 0, 0, 1,
90: 1, 0, 0, 0, 1,
91: 0, 1, 1, 1, 0},
// 7
93: 1, 1, 1, 1, 1,
94: 0, 0, 0, 0, 1,
95: 0, 0, 0, 0, 1,
96: 0, 0, 0, 1, 0,
97: 0, 0, 1, 0, 0,
98: 0, 1, 0, 0, 0,
99: 0, 1, 0, 0, 0,
100: 0, 1, 0, 0, 0},
// 8
102: 0, 1, 1, 1, 0,
103: 1, 0, 0, 0, 1,
104: 1, 0, 0, 0, 1,
105: 0, 1, 1, 1, 0,
106: 1, 0, 0, 0, 1,
107: 1, 0, 0, 0, 1,
108: 1, 0, 0, 0, 1,
109: 0, 1, 1, 1, 0},
// 9
111: 0, 1, 1, 1, 0,
112: 1, 0, 0, 0, 1,
113: 1, 0, 0, 0, 1,
114: 1, 1, 0, 0, 1,
115: 0, 1, 1, 1, 1,
116: 0, 0, 0, 0, 1,
117: 0, 0, 0, 0, 1,
118: 1, 1, 1, 1, 0},
119: }
120:
struct {
122: *image.NRGBA
123: color *color.NRGBA
//a digit width
//a digit height
int
127: }
128:
129: func init() {
130: rand.Seed(int64(time.Second))
131:
132: }
133:
int) *Image {
new(Image)
136: r := image.Rect(img.width, img.height, stdWidth, stdHeight)
137: img.NRGBA = image.NewNRGBA(r)
138: img.color = &color.NRGBA{
139: uint8(rand.Intn(129)),
140: uint8(rand.Intn(129)),
141: uint8(rand.Intn(129)),
142: 0xFF}
// Draw background (10 random circles of random brightness)
144: img.calculateSizes(width, height, len(digits))
145: img.fillWithCircles(10, img.dotsize)
146: maxx := width - (img.width+img.dotsize)*len(digits) - img.dotsize
147: maxy := height - img.height - img.dotsize*2
148: x := rnd(img.dotsize*2, maxx)
149: y := rnd(img.dotsize*2, maxy)
// Draw digits.
for _, n := range digits {
152: img.drawDigit(font[n], x, y)
153: x += img.width + img.dotsize
154: }
// Draw strike-through line.
156: img.strikeThrough()
return img
158:
159: }
160:
161: func (img *Image) WriteTo(w io.Writer) (int64, error) {
return 0, png.Encode(w, img)
163:
164: }
165:
int) {
// Goal: fit all digits inside the image.
int
if width > height {
170: border = height / 5
else {
172: border = width / 5
173: }
// Convert everything to floats for calculations.
//268
//48
// fw takes into account 1-dot spacing between digits.
//6
//8
//7
// Calculate the width of a single digit taking into account only the
// width of the image.
//38
// Calculate the height of a digit from this width.
//51
// Digit too high?
if nh > h {
// Fit digits based on height.
//nh = 44
190: nw = fw / fh * nh
191: }
// Calculate dot size.
int(nh / fh)
// Save everything, making the actual width smaller by 1 dot to account
// for spacing between digits.
int(nw)
int(nh) - img.dotsize
198:
199: }
200:
int) {
202: color := img.color
203: maxx := img.Bounds().Max.X
204: maxy := img.Bounds().Max.Y
for i := 0; i < n; i++ {
206: setRandomBrightness(color, 255)
207: r := rnd(1, maxradius)
208: img.drawCircle(color, rnd(r, maxx-r), rnd(r, maxy-r), r)
209: }
210:
211: }
212:
int) {
for x := fromX; x <= toX; x++ {
215: img.Set(x, y, color)
216: }
217:
218: }
219:
int) {
221: f := 1 - radius
222: dfx := 1
223: dfy := -2 * radius
224: xx := 0
225: yy := radius
226: img.Set(x, y+radius, color)
227: img.Set(x, y-radius, color)
228: img.drawHorizLine(color, x-radius, x+radius, y)
for xx < yy {
if f >= 0 {
231: yy--
232: dfy += 2
233: f += dfy
234: }
235: xx++
236: dfx += 2
237: f += dfx
238: img.drawHorizLine(color, x-xx, x+xx, y+yy)
239: img.drawHorizLine(color, x-xx, x+xx, y-yy)
240: img.drawHorizLine(color, x-yy, x+yy, y+xx)
241: img.drawHorizLine(color, x-yy, x+yy, y-xx)
242: }
243:
244: }
245:
246: func (img *Image) strikeThrough() {
247: r := 0
248: maxx := img.Bounds().Max.X
249: maxy := img.Bounds().Max.Y
250: y := rnd(maxy/3, maxy-maxy/3)
for x := 0; x < maxx; x += r {
252: r = rnd(1, img.dotsize/3)
253: y += rnd(-img.dotsize/2, img.dotsize/2)
if y <= 0 || y >= maxy {
255: y = rnd(maxy/3, maxy-maxy/3)
256: }
257: img.drawCircle(img.color, x, y, r)
258: }
259:
260: }
261:
int) {
263: skf := rand.Float64() * float64(rnd(-maxSkew, maxSkew))
264: xs := float64(x)
// minumum radius
// maximum radius
267: y += rnd(-minr, minr)
for yy := 0; yy < fontHeight; yy++ {
for xx := 0; xx < fontWidth; xx++ {
if digit[yy*fontWidth+xx] != blackChar {
continue
272: }
// Introduce random variations.
274: or := rnd(minr, maxr)
275: ox := x + (xx * img.dotsize) + rnd(0, or/2)
276: oy := y + (yy * img.dotsize) + rnd(0, or/2)
277: img.drawCircle(img.color, ox, oy, or)
278: }
279: xs += skf
int(xs)
281: }
282:
283: }
284:
285: func setRandomBrightness(c *color.NRGBA, max uint8) {
286: minc := min3(c.R, c.G, c.B)
287: maxc := max3(c.R, c.G, c.B)
if maxc > max {
return
290: }
int(minc)
int(c.R) + n)
int(c.G) + n)
int(c.B) + n)
295:
296: }
297:
298: func min3(x, y, z uint8) (o uint8) {
299: o = x
if y < o {
301: o = y
302: }
if z < o {
304: o = z
305: }
return
307:
308: }
309:
310: func max3(x, y, z uint8) (o uint8) {
311: o = x
if y > o {
313: o = y
314: }
if z > o {
316: o = z
317: }
return
319:
320: }
321:
// rnd returns a random number in range [from, to].
323:
int {
//println(to+1-from)
return rand.Intn(to+1-from) + from
327:
328: }
329:
const (
// Standard length of uniuri string to achive ~95 bits of entropy.
332: StdLen = 16
// Length of uniurl string to achive ~119 bits of entropy, closest
// to what can be losslessly converted to UUIDv4 (122 bits).
335: UUIDLen = 20
336: )
337:
// Standard characters allowed in uniuri string.
339:
)
341:
// New returns a new random string of the standard length, consisting of
// standard characters.
344:
345: func New() string {
return NewLenChars(StdLen, StdChars)
347:
348: }
349:
// NewLen returns a new random string of the provided length, consisting of
// standard characters.
352:
int) string {
return NewLenChars(length, StdChars)
355:
356: }
357:
// NewLenChars returns a new random string of the provided length, consisting
// of the provided byte slice of allowed characters (maximum 256).
360:
int, chars []byte) string {
362: b := make([]byte, length)
// storage for random bytes.
364: clen := byte(len(chars))
365: maxrb := byte(256 - (256 % len(chars)))
366: i := 0
for {
if _, err := io.ReadFull(crand.Reader, r); err != nil {
+ err.Error())
370: }
for _, c := range r {
if c >= maxrb {
// Skip this number to avoid modulo bias.
continue
375: }
376: b[i] = chars[c%clen]
377: i++
if i == length {
return string(b)
380: }
381: }
382: }
)
384:
385: }
386:
387: func pic(w http.ResponseWriter, req *http.Request) {
388: d := make([]byte, 4)
389: s := NewLen(4)
391: d = []byte(s)
for v := range d {
393: d[v] %= 10
394: ss += strconv.FormatInt(int64(d[v]), 32)
395: }
)
397: NewImage(d, 100, 40).WriteTo(w)
398: fmt.Println(ss)
399:
400: }
401:
402: func index(w http.ResponseWriter, req *http.Request) {
)
405: w.Write([]byte(str))
406:
407: }
408:
409: func main() {
, pic)
, index)
412: s := &http.Server{
,
414: ReadTimeout: 30 * time.Second,
415: WriteTimeout: 30 * time.Second,
416: MaxHeaderBytes: 1 << 20}
417: s.ListenAndServe()
418:
419: }