使用Java2D绘图——jsp中的验证码

那天突然看到了一些中文的验证码,所以想写一些东西,帮助大家了解一下在jsp页面中如何生成自己的验证码

一、简介

在 Java 2 平台之前,语言中的图形功能相当简单,仅限于单像素厚度的实线;少数几个几何图形(如椭圆、弧和多边形);和基本的画图功能。随着 Java 2D API(它包含一个真正的功能集)的出现,所有的一切都改变了。

Java 2D API是JFC (Java Fundation Classes)的一员,JFC 指的是包含在 Java 2 平台内的一整套图形和用户界面技术,包括 AWT 和 Swing 等。Java 2D加强了传统AWT( Abstract Windowing Toolkit )的描绘功能。在 JDK1.2中已经支援 Java 2D 的使用。透过Java 2D API ,Programmer 可以轻松地描绘出任意的几何图形、运用不同的填色效果、对图形做旋转( rotate)、缩放( scale)、扭曲( shear)等。当然,2D API还有许多增强AWT能力的部分,像是处理影像档案可以有不同的滤镜(filter)效果、对於任意的几何图形亦能做碰撞侦测(hit detection)、图形重叠混色计算(composite)等功能。后面将会对这些技术做概略性地介绍。

这个 API 的核心是由 java.awt.Graphics2D 类提供的,该类是 java.awt.Graphics 的一个子类。API 的其它部分由 java.awt 层次结构中的其它包提供,包括 java.awt.color 、 java.awt.font 和 java.awt.geom 。

Java 2D API 的文本功能也相当强大。它们包括:

  • 使用抗锯齿处理和微调(hinting)以达到更好的输出质量
  • 可以使用系统安装的所有字体
  • 可以将对图形对象的操作(旋转、缩放、着色、剪切等等)应用到文本上。
  • 支持向字符串添加内嵌属性(如字体、尺寸、深浅,甚至图像)
  • 支持双向文本(启用从右到左的字符顺序,就象您在阿拉伯语和希伯来语中可能遇到的一样)
  • 第一光标和第二光标能够浏览同时包含从右到左和从左到右字符顺序的文本。
  • 先进的字体度量功能,超过旧的 java.awt.FontMetrics 类中的相应功能
  • 排版功能可以实现单词换行和调整多行文本
  • 二、Java 2D API Packages JDK中关于2D API的Packages如下所述: 2.1 java.awt 包

    java.awt包含了一些新增的2D API 类别(classes)和界面(interfaces )。其中 Graphics2D继承自 java.awt.Graphics ,是描绘2D图形的物件(object)。如同前版本的JDK所使用的绘图模式一样,当有物件要被描绘时,paint或是update method会自动根据适当的 Graphics Context 来做绘图的工作。所谓的Graphics Context是与Graphics Object相关状态属性(state attribute)的集合。在Graphics2D中新增了许多状态属性,像是Stroke、 Paint、Clip、 Transform等。

    2.2 java.awt.geom 包

    java.awt.geom 包提供一些有关二维几何的类,如 Arc2D 、 Line2D 、 Rectangle2D 、 Ellipse2D 和 CubicCurve2D 。

    这些类允许各种几何图形建立在双精度或浮点精度的坐标系上。例如, newEllipse2D.Float(x,y,w,h) 将在 (x,y) 点上构造一个以宽为 w、高为 h 的矩形为边界的椭圆,其中 x、y、w和 h都为浮点值。

    在这个包里还有 AffineTransform 类,它是组成 2D API 的核心元素。仿射转换指的是平行线在转换后还保持平行。这种类型的转换示例包括如下的操作:平移、旋转、缩放、剪切或者这些操作的组合。每一个转换都可以 用一个 3x3 的矩阵来表示,该矩阵规定转换的源点和目标点之间的映射。

    AffineTransform 类的实例可以直接从一个浮点值的矩阵中创建,尽管通常情况下是通过规定一个或多个平移、旋转、缩放或剪切操作来创建。多数情况下是使用双精度值,并且角度是用弧度来度量的(而不是 Arc2D 类中使用的度)。

    java.awt.geom 则包含可以勾勒任何形状的 GeneralPath类别。它可以由许多不同种类的subpath构成,像是lines和 quadratic curves 等。为了兼顾方便性,此package中更定义了许多基本几何图形,包括Arc2D 、CubicCurve2D、 Line2D等。这些类别都有两种型态,分别是Float precision与Double precision。此外,还有一种特别的图形类别:Area,它支援Constructive Area Geometry( CGA)。CGA是对既有图形物件做布尔运算(Boolean Operation)而产生新图形物件的过程。Areas支援联集( union)、交集( intersection)、差集(subtraction )、Exclusive OR (XOR)等布尔运算。最後, AffineTransform 类别则提供图形物件做Scale、Shear 、Rotate等座标上的转换。

    2.3 java.awt.font 包

    java.awt.font 中定义了 TextLayout类别,负责建构text shape、执行适当的 text operations,如碰撞侦测与打光 (highlighting)等,以及决定text的适当位置与顺序。

  • 2.4 java.awt.image 包 Java 2D API支援三种影像模式。包括 producer/consumer (push) model、 immediatemode model和 pipeine(pull) model。Push model 在前版本的JDK中支援。而Pull model 则在即将出现的 Java Advanced Imaging AP中会支援。於此,我们只探讨JDK1.2中出现的Immediate mode imaging model。在此model下, Programmer可以透过2D API对image data( BufferedImage or Raster)做滤镜的效果。在Package java.awt.image中,immediate mode imaging APIs 可以被归为六大类: interfaces、image data classes、 image operation classes、sample model classes、 color model classes和 exceptions。其中 operation classes 即定义了许多 filter ,包括了 AffinTransformOp 、BandCombineOp、 ColorConvertOp、 ConvolveOp、 LookupOp、 RescaleOp等。透过以上所提之滤镜,可以做到 geometrically transform、blur、 sharpen、enhance contrast、 threshold和color correct images等效果。 2.5 java.awt.color 包

    Package java.awt.color定义了class ColorSpace。此class提供Programmer转换色盘的method。

    2.6 java.awt.print 包

    Java Printing API提供Programmer 列印AWT和Java 2D graphics(composit ed graphics和 images)的method。并可让User设定 print的属性,如双面列印等。

    2.7 java.awt.Graphics2D 类

    这个类是 java.awt.Graphics (该类在 Java 2 发行前就提供图形功能)的一个子类。这样安排的原因是:向后兼容。组件的着色还是通过调用它们的 paint() 方法,它使用一个 Graphics 对象。

    尽管在语言的当前版本中,这个对象真是一个 Graphics2D 对象。这意味着, paint() 方法可以将 Graphics 对象作为一个 Graphics 对象使用(使用旧的画图方法),或者将其强制转换成 Graphics2D 对象。如果使用第二种选择,就可以使用 2D API 的所有附加功能。

  • 三、Java 2D Programming初步 了解了Java 2D API 各相关的package资讯之後,可以进一步地实做一些简单的Applications来体认2D的美妙。在那之前,我们先学习一些基本的2D programming codes 。 3.1基本步骤

    绘图的第一个步骤是产生 Graphics2D Object 。 接著是设定你所 要的状态属性。例如你想要对一物件做渐层式的填色,可以设定属性 Paint为 GradientPaint。最後再呼叫 Graphics2D所提供的redering method ,fill或是draw,完成整个绘图的程序。以下即是此基本步骤的范例程代码:

    import java.awt.*;
    
    import java.awt.geom.*;
    
    public void paint(Graphics g)
    {
       Ellipse2D.Float shape;
       GradientPaint gp;
       // create a Graphics2D
    
       Graphics2D g2 = (Graphics2D) g ;
    
       // create a Ellipse2D (x,y,w,h)
    
       shape = new Ellipse2D.Float (200,200,60,60);
    
       // create a Cyclic GradientPaint 
    
       // (x1,y1,color1,x2,y2,color2, boolean cyclic)
    
       gp = new GradientPaint (180,190,Color.yellow,220,210,Color.red,true);
    
       g2.setPaint(gp);
    
       g2.fill(shape);
    
    }

    3.2 如何画线

    在jdk尚未支援 2D图形之前, Programmer只可以画出直的、相同粗细的线条。现在,我们就教您如何透过2D API绘出不同粗细的线条及圆滑的曲线。在package java.awt.geom中提供了Line2D、 QuadCurve2D及 CubicCurve2D等 classes,让 Programmer轻松地绘出想要的线条。范例代码如下所示:

    import java.awt.geom.*;
    …
    Line2D.Float line;
    
    CubicCurve2D.Float cubic;
    
    // create a Line2D
    
    line = new Line2D.Float(20,390,200,390);
    
    // create a CubicCurve2D,比直线多了两个控制点
    
    cubic = new CubicCurve2D.Float(70,100,120,50,170,270,220,100);
    
    // 设定描绘的粗细
    
    g2. setStroke(new BasicStroke(2.0f));
    
    g2.setColor(Color.blue);
    
    g2.draw(line);
    
    line = new Line2D.Float(30,400,250,400);
    
    // 设定描绘的粗细
    
    g2. setStroke(new BasicStroke(5.0f));
    
    g2.draw(line);

    3.3显示字串

    透过Java 2D, Programmer可以显示更细致的文字。如范例代码的效果:显示出外边为淡蓝色的字串 " Font Test "。

    import java.awt.font.*;
    …
    
    Shape sha;
    
    FontRenderContext frc =g2.getFontRenderContext();
    
    TextLayout tl = new TextLayout("Font Test",new Font("Modern",
                                               Font.BOLD+Font.ITALIC,20),frc);
    
    sha=tl.getOutline(AffineTransform.getTranslateInstance(50,380));
    
    g2.setColor(Color.blue);
    
    g2.setStroke(new BasicStroke(2.0f));
    
    g2.draw(sha);
    
    g2.setColor(Color.white);
    
    g2.fill(sha);

    3.4图档处理

    之前,若希望图形有滤镜的效果,必须透过可以处理图形的绘图软体来帮忙。在2D API中则提供了一些简单的method,使得 Programmer可以直接用程式码来对图形作滤镜效果的控制。下面即介绍其中一种效果。范例代码如下所示:

    float[] elements = {0.0f, -1.0f, 0.0f,-1.0f, 4.f, -1.0f,0.0f, -1.0f, 0.0f};
    
    Image img = Toolkit.getDefaultToolkit().getImage("boat.gif");
    
    int w = img.getWidth(this);
    int h = img.getHeight(this);
    
    BufferedImage bi = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
    
    Graphics2D big = bi.createGraphics();
    
    big.drawImage(img,0,0,this);
    
    BufferedImageOp biop = null;
    
    AffineTransform at = new AffineTransform();
    
    BufferedImage bimg = new BufferedImage(img.getWidth(this),img.getHeight(this),
                                              BufferedImage.TYPE_INT_RGB);
    
    Kernel kernel = new Kernel(3,3,elements);
    
    ConvolveOp cop = new ConvolveOp(kernel,ConvolveOp.EDGE_NO_OP,null);
    
    cop.filter(bi,bimg);
    
    biop = newAffineTransformOp(at,AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
    
    g2 = (Graphics2D)this.getGraphics();
    
    g2.drawImage(bimg,biop,0,0);
  • 四、Java 2D 工作的一个示例

    清单 1 包含一个使用部分 Java 2D 方法的基本示例的代码,加上几个其它的方法。这是一个完整的程序,但只是接触了 2D API 所提供的功能的皮毛。

    清单 1. 一个简单的 Java 2D 示例

    import java.awt.*;
    import java.awt.geom.*;
    public class J2D extends Frame {
        public static void main(String args[]) { new J2D(); }
        public J2D() {
            setSize(220,180);
            setVisible(true);
        }
        public void paint(Graphics g) {
            // 获得一个Graphics2D对象
            Graphics2D g2 = (Graphics2D)g;
            // 设置绘制质量
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
            // 定义线性色度分级
            GradientPaint gp = new GradientPaint(0, 60, Color.red,
                                                 0, 120, Color.yellow);
            Ellipse2D r = new Ellipse2D.Float(30, 60, 160, 60);
            g2.setPaint(gp);
            g2.fill(r);
            // 设置旋转
            g2.transform(AffineTransform.getRotateInstance(Math.PI/8));
            g2.setFont(new Font("Serif", Font.BOLD, 85));
            g2.setPaint(Color.blue);
            // 设置透明度
            g2.setComposite(AlphaComposite.getInstance(
                                           AlphaComposite.SRC_OVER, 0.5f));
            g2.drawString("J2D",50,70);
        }
    本文链接:http://www.snowdi.com/444.html → 转载请注明文章出自雪頔网
    

你可能感兴趣的:(jsp,生成验证码,java绘图,java,java,jsp,图形,api,import,image)