|
@@ -0,0 +1,127 @@
|
|
|
+package gaf3.demo.services.nodb.util
|
|
|
+
|
|
|
+import java.awt.Color
|
|
|
+import java.awt.Font
|
|
|
+import java.awt.Graphics
|
|
|
+import java.awt.RenderingHints
|
|
|
+import java.awt.geom.AffineTransform
|
|
|
+import java.awt.image.BufferedImage
|
|
|
+import java.io.ByteArrayOutputStream
|
|
|
+import java.util.*
|
|
|
+import javax.imageio.ImageIO
|
|
|
+import kotlin.math.PI
|
|
|
+import kotlin.math.sin
|
|
|
+
|
|
|
+object VerifyCodeHelper {
|
|
|
+
|
|
|
+ private val VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"
|
|
|
+
|
|
|
+ //生成验证码字符串,可以设置字符串长度
|
|
|
+ fun generateCode(size: Int = 4, source: String = VERIFY_CODES): String{
|
|
|
+ val result = StringBuilder()
|
|
|
+ for(i in 1..size)
|
|
|
+ result.append(source.random())
|
|
|
+ return result.toString()
|
|
|
+ }
|
|
|
+
|
|
|
+ //生成验证码图片
|
|
|
+ fun generateImage(code:String, width: Int = 200, height: Int = 80): ByteArray {
|
|
|
+ val image = BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)
|
|
|
+ val g2d = image.createGraphics()
|
|
|
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
|
|
|
+
|
|
|
+ g2d.color = Color.GRAY
|
|
|
+ g2d.fillRect(0, 0, width, height)
|
|
|
+
|
|
|
+ val c = getRandomColor(200, 250)
|
|
|
+ g2d.color = c
|
|
|
+ g2d.fillRect(0,2,width, height-4)
|
|
|
+
|
|
|
+ g2d.color = getRandomColor(160, 200)
|
|
|
+ for(i in 0 until 20){
|
|
|
+ val x = (1..width).random()
|
|
|
+ val y = (1..height).random()
|
|
|
+ val xl = (1..6).random()
|
|
|
+ val yl = (1..12).random()
|
|
|
+ g2d.drawLine(x, y, x + xl + 40, y + yl + 20)
|
|
|
+ }
|
|
|
+
|
|
|
+ val yawpRate = 0.05f
|
|
|
+ val area = (yawpRate * width * height).toInt()
|
|
|
+ for(i in 0 until area){
|
|
|
+ val x = (0 until width).random()
|
|
|
+ val y = (0 until height).random()
|
|
|
+ val rgb = getRandomIntColor()
|
|
|
+ image.setRGB(x, y, rgb)
|
|
|
+ }
|
|
|
+
|
|
|
+ shear(g2d, width, height, c)
|
|
|
+
|
|
|
+ g2d.color = getRandomColor(100, 160)
|
|
|
+ val fontSize = height - 4
|
|
|
+ g2d.font = Font("Algerian", Font.ITALIC, fontSize)
|
|
|
+ val codeSize = code.length
|
|
|
+ for(i in (0 until codeSize)){
|
|
|
+ val affine = AffineTransform()
|
|
|
+ val random = Random()
|
|
|
+ affine.setToRotation(PI / 4 * random.nextDouble() * (if(random.nextBoolean()) 1 else -1), (width.toDouble() / codeSize) * i + fontSize/2, height.toDouble()/2)
|
|
|
+ g2d.transform = affine
|
|
|
+ g2d.drawChars(code.toCharArray(), i, 1,((width-10) / codeSize) * i + 5, height/2 + fontSize/2 - 10)
|
|
|
+ }
|
|
|
+ g2d.dispose()
|
|
|
+ val output = ByteArrayOutputStream()
|
|
|
+ ImageIO.write(image, "jpg", output);
|
|
|
+ val result = output.toByteArray()
|
|
|
+ output.close()
|
|
|
+ return result
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun getRandomColor(fc: Int, bc: Int): Color {
|
|
|
+ val f = if(fc > 255) 255 else fc
|
|
|
+ val b = if(bc > 255) 255 else bc
|
|
|
+ return Color((f..b).random(), (f..b).random(), (f..b).random())
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun getRandomIntColor(): Int{
|
|
|
+ var color = 0
|
|
|
+ val rgb = arrayOf((0 until 255).random(), (0 until 255).random(), (0 until 255).random())
|
|
|
+ for(c in rgb){
|
|
|
+ color = (color shl 8) and c
|
|
|
+ }
|
|
|
+ return color
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun shear(g: Graphics, w: Int, h: Int, color: Color){
|
|
|
+ shearX(g, w, h, color)
|
|
|
+ shearY(g, w, h, color)
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun shearX(g: Graphics, w: Int, h: Int, color: Color) {
|
|
|
+ val period = (0..1).random()
|
|
|
+ val frames = 1;
|
|
|
+ val phase = (0..1).random()
|
|
|
+
|
|
|
+ for (i in 0 until h) {
|
|
|
+ val d = (period ushr 1).toDouble() * sin(i.toDouble() / period.toDouble() + (6.2831853071795862 * phase.toDouble()) / frames.toDouble());
|
|
|
+ g.copyArea(0, i, w, 1, d.toInt(), 0);
|
|
|
+ g.setColor(color);
|
|
|
+ g.drawLine(d.toInt(), i, 0, i);
|
|
|
+ g.drawLine(d.toInt() + w, i, w, i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun shearY(g: Graphics, w: Int, h: Int, color: Color) {
|
|
|
+ val period = (0 until 40).random()+ 10;
|
|
|
+ val frames = 20;
|
|
|
+ val phase = 7;
|
|
|
+ for (i in 0 until w) {
|
|
|
+ val d = (period ushr 1).toDouble() * Math.sin(i.toDouble() / period.toDouble() + (6.2831853071795862 * phase.toDouble()) / frames.toDouble());
|
|
|
+ g.copyArea(i, 0, 1, h, 0, d.toInt());
|
|
|
+ g.setColor(color);
|
|
|
+ g.drawLine(i, d.toInt(), i, 0);
|
|
|
+ g.drawLine(i, d.toInt() + h, i, h);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|