package com.hphoto.server; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.GraphicsEnvironment; import java.awt.RenderingHints; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Properties; import java.util.Random; import javax.imageio.ImageIO; import com.hphoto.image.Captcha; import com.hphoto.image.RippleFilter; import com.hphoto.image.TransformFilter; import com.hphoto.image.TwirlFilter; public class VerifyCodeImage { private Properties properties; private String[] font = { "Arial", "Courier" }; private Color[] color = { Color.black, Color.blue, //Color.orange, new Color(179,21,17), new Color(10,131,31), new Color(140,89,47), new Color(94,95,41), new Color(18,73,118), new Color(81,23,115), new Color(90,90,90), new Color(113,37,129) }; private static char[] captchars = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', '0', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; private Random generator = new Random(); public VerifyCodeImage(){ } public VerifyCodeImage(Properties properties){ this.properties = properties; } private String word; public String getWord(){ return getWord(4); } public String getWord(int length){ String result = ""; for (int i = 0; i < length; i++) { result += captchars[generator.nextInt(captchars.length - 1) + 1]; } this.word = result; return result; } public void setWord(String word){ this.word = word; } int fontSize = 18; private Font getFont(){ return getFont(fontSize); } private Font getFont(int size){ return new Font(font[generator.nextInt(font.length - 1) +1],Font.BOLD,size); } public void setFontSize(int size){ fontSize = size; } private Color getColor(){ return color[(int) (Math.random()*color.length)]; } public String saveVerifyImage(int width,int height,OutputStream out) throws IOException{ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_INDEXED); Graphics2D g = (Graphics2D) image.getGraphics(); g.setColor(new Color(0xFFFFFF)); g.fillRect(0, 0, width, height); String word; if(this.word == null) word = getWord(4); else word = this.word; //total width; float w = (float) (width * 0.9F); //toatl height; float h = (float) (height * 0.2F); //every word width int d = (int) (w / word.length()); RenderingHints hints = new RenderingHints( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); hints.add(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY)); g.setRenderingHints(hints); Font font = getFont(); char[] wc = word.toCharArray(); FontRenderContext frc = g.getFontRenderContext(); g.setColor(getColor()); g.setFont(font); GlyphVector gv = font.createGlyphVector(frc, wc); double charWitdth = gv.getVisualBounds().getWidth(); int startPosX = (int)(width - charWitdth) / 2; g.drawChars(wc,0,wc.length, startPosX , height/2 + (int)(height*0.1)); /* for (int i = 0;i<wc.length;i++) { char[] itchar = new char[]{wc[i]}; GlyphVector gv = font.createGlyphVector(frc, itchar); double charWitdth = gv.getVisualBounds().getWidth(); g.drawChars(itchar,0,itchar.length, startPosX , height/2 + 10 ); startPosX += d; //g.drawChars(itchar,0,itchar.length,(int)((((float) (width * 0.1F)) + d*i)) ,height/2 + 10); }// for next char array. */ Captcha ca = captcha[generator.nextInt(captcha.length)]; ca.setRange(w); image = ca.getDistortedImage(image); ImageIO.write(image, "JPEG",out); return word; } Captcha[] captcha = { new Ripple(), new Twirl() }; class Ripple implements Captcha{ public Ripple(){}; private int fil[] = { RippleFilter.SINE//, //RippleFilter.NOISE }; private int ripple = 0; public BufferedImage getDistortedImage(BufferedImage image){ RippleFilter wfilter = new RippleFilter(); ripple = fil[0];//[generator.nextInt(fil.length - 1) +1]; wfilter.setWaveType(ripple); wfilter.setXAmplitude(ripple); wfilter.setYAmplitude(generator.nextFloat()+1.0f); wfilter.setXWavelength(generator.nextInt(5)+8F); wfilter.setYWavelength(generator.nextInt(3)+2F); wfilter.setEdgeAction(TransformFilter.WRAP); ColorModel dstCM = image.getColorModel(); BufferedImage dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(image.getWidth(), image.getHeight()), dstCM.isAlphaPremultiplied(), null); return wfilter.filter(image, dst); } public void setRange(float width) { } private float getFloat(){ float value; value = generator.nextInt(4)+3.6f; if(ripple == RippleFilter.NOISE){ value = generator.nextInt(4)+1.6f; } return value; } } class Twirl implements Captcha{ float w; public Twirl(){} public BufferedImage getDistortedImage(BufferedImage image) { TwirlFilter filter = new TwirlFilter(); filter.setCentreX(0.4f); filter.setCentreY(0.4f); float angle = getFloat(); filter.setAngle(angle); filter.setRadius(w / 2 + 5); ColorModel dstCM = image.getColorModel(); BufferedImage dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(image.getWidth(), image.getHeight()), dstCM.isAlphaPremultiplied(), null); return filter.filter(image, dst); } public void setRange(float width) { this.w = width; } private float getFloat(){ float angle; while (true){ angle = (float)(generator.nextFloat()); if ( angle > 0.2F && angle < 0.6){ break; } } return generator.nextInt() % 2 == 0 ? angle : -angle; } } public static void main(String[] arg) throws Exception{ new VerifyCodeImage().saveVerifyImage(140, 70, new FileOutputStream(new File(System.currentTimeMillis()+ ".jpg"))); } }