You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
5.4 KiB
183 lines
5.4 KiB
package org.ros.chatto.captcha;
|
|
|
|
import javax.imageio.ImageIO;
|
|
|
|
import java.awt.Color;
|
|
import java.awt.Graphics2D;
|
|
import java.awt.RenderingHints;
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.IOException;
|
|
import java.util.Random;
|
|
|
|
/**
|
|
* This class represents a simple captcha consisting
|
|
* of an image {@code png} and its text value.
|
|
* Comic Neue Bold Font.
|
|
* Capital english letters {@code ONLY}.
|
|
*
|
|
* @since 1.3
|
|
* @author Gennadiy Golovin
|
|
*/
|
|
public final class SimpleCaptcha {
|
|
|
|
private BufferedImage imagePng;
|
|
private char[] text;
|
|
|
|
/**
|
|
* Initializes a newly created default object
|
|
* consisting of 8 capital english letters.
|
|
*/
|
|
public SimpleCaptcha() {
|
|
this.text = getRandomChars();
|
|
|
|
try {
|
|
generateCaptcha();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initializes a newly created object, which length
|
|
* depends on the passed {@code int} parameter,
|
|
* which {@code MUST} be greater than 0.
|
|
* If the condition is not met, initializes a newly
|
|
* created default object consisting of 8 symbols.
|
|
*
|
|
* @param length the quantity of symbols, that the
|
|
* captcha consists of, greater than 0.
|
|
*/
|
|
public SimpleCaptcha(int length) {
|
|
if (length < 1) {
|
|
this.text = getRandomChars();
|
|
} else {
|
|
this.text = getRandomChars(length);
|
|
}
|
|
|
|
try {
|
|
generateCaptcha();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initializes a newly created object based on the passed
|
|
* {@link String} parameter, consisting of capital english
|
|
* letters. If the condition is not met, initializes a newly
|
|
* created default object consisting of 8 capital english letters.
|
|
*
|
|
* @param text the text string with the value of the captcha,
|
|
* length greater than 0.
|
|
*/
|
|
public SimpleCaptcha(String text) {
|
|
if (text == null || text.equals("")) {
|
|
this.text = getRandomChars();
|
|
} else {
|
|
this.text = text.toCharArray();
|
|
}
|
|
|
|
try {
|
|
generateCaptcha();
|
|
} catch (IOException e) {
|
|
this.text = getRandomChars();
|
|
try {
|
|
generateCaptcha();
|
|
} catch (IOException ex) {
|
|
ex.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the picture with captcha
|
|
*
|
|
* @return {@link BufferedImage}
|
|
*/
|
|
public BufferedImage getImagePng() {
|
|
return imagePng;
|
|
}
|
|
|
|
/**
|
|
* Returns the text value of the captcha
|
|
*
|
|
* @return {@link String}
|
|
*/
|
|
public String getText() {
|
|
return String.valueOf(text);
|
|
}
|
|
|
|
//////// //////// //////// //////// //////// //////// //////// ////////
|
|
|
|
private char[] getRandomChars() {
|
|
return getRandomChars(8);
|
|
}
|
|
|
|
private char[] getRandomChars(int quantity) {
|
|
|
|
char[] randomString = new char[quantity];
|
|
|
|
Random random = new Random();
|
|
|
|
int capitalLetter;
|
|
|
|
for (int i = 0; i < quantity; i++) {
|
|
capitalLetter = 65 + random.nextInt(26);
|
|
randomString[i] = (char) capitalLetter;
|
|
}
|
|
|
|
return randomString;
|
|
}
|
|
|
|
private void generateCaptcha() throws IOException {
|
|
int charsQuantity = this.text.length;
|
|
BufferedImage[] images = new BufferedImage[charsQuantity];
|
|
|
|
for (int i = 0; i < charsQuantity; i++) {
|
|
images[i] = ImageIO.read(SimpleCaptcha.class.getResourceAsStream("/pictures/" + this.text[i] + ".png"));
|
|
if (i % 2 == 0) {
|
|
images[i] = rotateImage(images[i], 25);
|
|
} else {
|
|
images[i] = rotateImage(images[i], -20);
|
|
}
|
|
}
|
|
|
|
int imageSize = 30;
|
|
int rotatedImageSize = (int) Math.sqrt(imageSize * imageSize * 2);
|
|
|
|
BufferedImage captchaImg = new BufferedImage(rotatedImageSize * (charsQuantity - 1) / 10 * 6 + rotatedImageSize, rotatedImageSize, BufferedImage.TYPE_INT_ARGB);
|
|
Graphics2D graphics2d = captchaImg.createGraphics();
|
|
graphics2d.setBackground(Color.WHITE);
|
|
graphics2d.clearRect(0, 0, captchaImg.getWidth(), captchaImg.getHeight());
|
|
for (int i = 0; i < charsQuantity; i++) {
|
|
captchaImg.getGraphics().drawImage(images[i], rotatedImageSize * i / 10 * 6, 0, null);
|
|
}
|
|
graphics2d.dispose();
|
|
this.imagePng = captchaImg;
|
|
}
|
|
|
|
private BufferedImage rotateImage(BufferedImage buffImage, double angle) {
|
|
|
|
double radian = Math.toRadians(angle);
|
|
double sin = Math.abs(Math.sin(radian));
|
|
double cos = Math.abs(Math.cos(radian));
|
|
|
|
int width = buffImage.getWidth();
|
|
int height = buffImage.getHeight();
|
|
|
|
int nWidth = (int) Math.floor((double) width * cos + (double) height * sin);
|
|
int nHeight = (int) Math.floor((double) height * cos + (double) width * sin);
|
|
|
|
BufferedImage rotatedImage = new BufferedImage(nWidth, nHeight, BufferedImage.TYPE_INT_ARGB);
|
|
|
|
Graphics2D graphics = rotatedImage.createGraphics();
|
|
|
|
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
|
|
graphics.translate((nWidth - width) / 2, (nHeight - height) / 2);
|
|
graphics.rotate(radian, (double) (width / 2), (double) (height / 2));
|
|
graphics.drawImage(buffImage, 0, 0,null);
|
|
graphics.dispose();
|
|
|
|
return rotatedImage;
|
|
}
|
|
}
|