refining the Rain drop captcha
This commit is contained in:
parent
beb184d7a9
commit
a207b9dee6
|
@ -3,6 +3,7 @@ package lc
|
|||
import java.awt.image.BufferedImage
|
||||
import java.awt.RenderingHints
|
||||
import java.awt.Font
|
||||
import java.awt.font.TextAttribute
|
||||
import java.awt.Color
|
||||
import java.io.ByteArrayOutputStream
|
||||
import javax.imageio.ImageIO
|
||||
|
@ -23,19 +24,32 @@ class Drop {
|
|||
class RainDropsCP extends ChallengeProvider {
|
||||
private val alphabet = "abcdefghijklmnopqrstuvwxyz"
|
||||
private val n = 6
|
||||
private val bgColor = new Color(245, 245, 245)
|
||||
private val textColor = new Color(248, 248, 248)
|
||||
private val textHighlightColor = new Color(208, 208, 255)
|
||||
|
||||
def getId = "FilterChallenge"
|
||||
|
||||
private def extendDrops(drops: Array[Drop], steps: Int, xOffset: Int) = {
|
||||
drops.map(d => {
|
||||
val nd = new Drop()
|
||||
nd.x + xOffset*steps
|
||||
nd.y + d.yOffset*steps
|
||||
nd
|
||||
})
|
||||
}
|
||||
|
||||
def returnChallenge(): Challenge = {
|
||||
val r = new scala.util.Random
|
||||
val secret = Stream.continually(r.nextInt(alphabet.size)).map(alphabet).take(n).mkString
|
||||
// val secret = "mmmmmm"
|
||||
val width = 450
|
||||
val height = 100
|
||||
val imgType = BufferedImage.TYPE_INT_RGB
|
||||
val xOffset = 1+r.nextInt(2)
|
||||
val xBias = (height / 10) - 2
|
||||
val drops = Array.fill[Drop](1500)( new Drop())
|
||||
for (d <- drops) {
|
||||
val dropsOrig = Array.fill[Drop](600)( new Drop())
|
||||
for (d <- dropsOrig) {
|
||||
d.x = r.nextInt(width) - (xBias/2)*xOffset
|
||||
d.yOffset = 6+r.nextInt(6)
|
||||
d.y = r.nextInt(height)
|
||||
|
@ -44,10 +58,17 @@ class RainDropsCP extends ChallengeProvider {
|
|||
d.colorChange *= -1
|
||||
}
|
||||
}
|
||||
val drops = dropsOrig ++ extendDrops(dropsOrig, 2, xOffset) ++ extendDrops(dropsOrig, 4, xOffset)
|
||||
|
||||
val baseFont = new Font(Font.MONOSPACED, Font.BOLD, 80)
|
||||
val attributes = new java.util.HashMap[TextAttribute, Object]()
|
||||
attributes.put(TextAttribute.TRACKING, Double.box(0.2))
|
||||
attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_EXTRABOLD)
|
||||
val spacedFont = baseFont.deriveFont(attributes)
|
||||
|
||||
val baos = new ByteArrayOutputStream();
|
||||
val ios = new MemoryCacheImageOutputStream(baos);
|
||||
val writer = new GifSequenceWriter(ios, imgType, 100, true);
|
||||
val writer = new GifSequenceWriter(ios, imgType, 60, true);
|
||||
for(i <- 0 until 30){
|
||||
val yOffset = 5+r.nextInt(5)
|
||||
val canvas = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)
|
||||
|
@ -55,7 +76,7 @@ class RainDropsCP extends ChallengeProvider {
|
|||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
|
||||
|
||||
// clear the canvas
|
||||
g.setColor(Color.WHITE)
|
||||
g.setColor(bgColor)
|
||||
g.fillRect(0, 0, canvas.getWidth, canvas.getHeight)
|
||||
|
||||
// paint the rain
|
||||
|
@ -66,8 +87,10 @@ class RainDropsCP extends ChallengeProvider {
|
|||
d.y += d.yOffset
|
||||
d.color += d.colorChange
|
||||
if (d.x > width+xOffset || d.y > height+d.yOffset) {
|
||||
d.x = r.nextInt(width) - xBias*xOffset
|
||||
d.y = 0
|
||||
val ySteps = 1 + height / d.yOffset
|
||||
d.x -= xOffset*ySteps
|
||||
d.y -= yOffset*ySteps
|
||||
|
||||
}
|
||||
if (d.color > 200 || d.color < 21) {
|
||||
d.colorChange *= -1
|
||||
|
@ -75,15 +98,15 @@ class RainDropsCP extends ChallengeProvider {
|
|||
}
|
||||
|
||||
// center the text
|
||||
g.setFont(new Font("Sans", Font.BOLD, 70))
|
||||
g.setFont(spacedFont)
|
||||
val textWidth = g.getFontMetrics().charsWidth(secret.toCharArray, 0, secret.toCharArray.length)
|
||||
val textX = (width - textWidth)/2
|
||||
|
||||
// paint the top outline
|
||||
g.setColor(Color.BLUE)
|
||||
g.setColor(textHighlightColor)
|
||||
g.drawString(secret, textX, 69)
|
||||
// paint the text
|
||||
g.setColor(Color.WHITE)
|
||||
g.setColor(textColor)
|
||||
g.drawString(secret, textX, 70)
|
||||
|
||||
g.dispose()
|
||||
|
|
Loading…
Reference in New Issue