zoukankan      html  css  js  c++  java
  • 创建了一个JAVA画图功能图形库

    通过JAVA可以很容易绘制出各种各样的图形,如矩形,方型,椭圆以及正圆等,直线和文本当然更不再话下。主要是通过BufferedImage和Graphics2D实现。做了一个demo演示,效果如下:

    下面来描述实现过程。
    库文件主要包括两个类文本:FontProperty和PrintGraphics。其中FontProperty用于定义字体的各个属性,如粗体、斜体、下划线等等;PrintGraphics主要定义各种图形的绘制功能。

    先看FontProperty.java:

    public class FontProperty{
    boolean bBold; //是否粗体
    boolean bItalic; //是否斜体
    boolean bUnderLine; //是否下划线
    boolean bStrikeout; //是否删除线
    int iSize; //字体大小
    String sFace; //字体类型,默认留空("")即可,表示使用系统默认字体,当然也可以指定如"宋体"
     
    //设置字体参数
    public void setF(boolean bBold, boolean bItalic, boolean bUnderLine, boolean bStrikeout, int iSize, String sFace){
    this.bBold = bBold;
    this.bItalic = bItalic;
    this.bUnderLine = bUnderLine;
    this.bStrikeout = bStrikeout;
    this.iSize = iSize;
    this.sFace = sFace;
    }
    }

    该文件很简单,就只有一个设置字体属性的方法。

    接着看PrintGraphics.java文件:

    import java.awt.*;
    import java.awt.geom.*;
    import javax.swing.*;
    import java.io.File;
    import java.awt.image.BufferedImage;
    import javax.imageio.ImageIO;
    import java.util.Hashtable;
    import java.awt.font.TextAttribute;
    import javax.swing.JFrame;
     
    public class PrintGraphics{
     
    public BufferedImage bi = null;
    public Graphics2D g2 = null;
    public double length = 0.0;
    public int width;
     
    /**
    * 获取图像的实际长度
    * 因为画布定义的长度是其宽度的10倍,所以最后会根据使用的实际长度进行截取
    */

    public int getLength(){
    return (int)this.length+20;
    }
     
    /**
    * 初始化画布BufferedImage和画笔Graphics2D,其中宽度为参数,长度为宽度的10倍
    * 画布背景为白色,画笔为黑色
    */

    public void initBuff(int width){
    int height = 10*width;
    this.bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    this.g2 = (Graphics2D)this.bi.getGraphics();
    this.g2.setBackground(Color.WHITE);
    this.g2.clearRect(0, 0, width, height);
    this.g2.setPaint(Color.BLACK);
    this.width = width;
    }
     
    // 根据初始的字体属性值对字体进行设置
    public Font setFontProperty(FontProperty fp){
    int fontStyle = 0;
    int fontFlag = 0;
     
    if(fp.sFace != ""){
    String fontNames[];
    //获取系统所有字体列表,然后判断用户指定的字体是否存在
    fontNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
    for(int i=0;i<fontNames.length;i++){
    if(fontNames[i].equals(fp.sFace)){
    fontFlag = 1;
    break;
    }
    }
    //如果不存在则留空,表示使用系统默认字体
    if(fontFlag == 0){
    System.out.println("Your font face \"" + fp.sFace + "\" is not exist, default is used.");
    fp.sFace = "";
    }
    }
     
    Font font = null;
     
    //设置粗体
    if(fp.bBold){
    fontStyle = 1;
    font = new Font(fp.sFace, Font.BOLD, fp.iSize);
    }
     
    //设置斜体
    if(fp.bItalic){
    if(fontStyle == 0){
    fontStyle = 1;
    font = new Font(fp.sFace, Font.ITALIC, fp.iSize);
    }
    else{
    font = new Font(fp.sFace, Font.BOLD|Font.ITALIC, fp.iSize);
    }
    }
     
    //设置常规体
    if(fontStyle == 0){
    font = new Font(fp.sFace, Font.PLAIN, fp.iSize);
    }
     
    //设置下划线和删除线
    if(fp.bUnderLine || fp.bStrikeout){
    Hashtable<TextAttribute, Object> map = new Hashtable<TextAttribute, Object>();
    if(fp.bUnderLine){
    map.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
    }
    if(fp.bStrikeout){
    map.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
    }
    font = font.deriveFont(map);
    }
    return font;
    }
     
    //设置线宽
    public Stroke setLineWidth(double width){
    String f = "" + width + "f";
    Stroke stk = new BasicStroke(Float.parseFloat(f));
    return stk;
    }
     
    //使用指定的字体绘制文本,其中(x,y)是指文本起始位置的左下点坐标,所以y不可为0
    public void drawText(double x, double y, String nStr, FontProperty fp){
    Font font = this.setFontProperty(fp);
    this.g2.setFont(font);
    this.g2.drawString(nStr, (int)x, (int)y);
    if(this.length < y){
    this.length = y;
    }
    }
     
    //使用指定的宽度绘制直线,其中(x1,y1)为起始点坐标,(x2,y2)为终点坐标
    public void drawLine(double x1, double y1, double x2, double y2, double w){
    Stroke stk = this.setLineWidth(w);
    this.g2.setStroke(stk);
    this.g2.draw(new Line2D.Double(x1, y1, x2, y2));
    //获取画布实际使用长度,下同
    double max = 0;
    max = y1>y2?y1:y2;
    if(this.length < max){
    this.length = max;
    }
    }
     
    //使用指定的宽度绘制矩形或方型,其中(x1,y1)为左上角坐标,width和height分别指定矩形或方型的宽度及高度
    public void drawRectangle(double x, double y, double width, double height, double w){
    Stroke stk = this.setLineWidth(w);
    this.g2.setStroke(stk);
    this.g2.draw(new Rectangle2D.Double(x, y, width, height));
    if(this.length < y+height){
    this.length = y+height;
    }
    }
     
    //使用指定的宽度绘制椭圆或正圆,其中(x1,y1)为圆的外切矩形或方型的左上角坐标,(x2,y2)为圆的外切矩形或方型的右下角坐标
    public void drawEllips(double x1, double y1, double x2, double y2, double w){
    Stroke stk = this.setLineWidth(w);
    this.g2.setStroke(stk);
    Rectangle2D rect=new Rectangle2D.Double();
    rect.setFrameFromDiagonal(x1, y1, x2, y2);
    Ellipse2D ellipse=new Ellipse2D.Double();
    ellipse.setFrame(rect);
    this.g2.draw(ellipse);
    double max = 0;
    max = y1>y2?y1:y2;
    if(this.length < max){
    this.length = max;
    }
    }
     
    //插入指定路径的图片,其中(x,y)是指图片起始位置的左上点坐标
    public void drawImage(double x, double y, String pathname){
    try{
    BufferedImage image=ImageIO.read(new File(pathname));
    this.g2.drawImage(image, (int)x, (int)y, null);
    if(this.length < y+image.getHeight()){
    this.length = y+image.getHeight();
    }
    }catch(java.io.IOException ioe){ioe.printStackTrace();}
    }
     
    //将图像通过frame窗口显示出来
    public void printShow(){
    JFrame jframe = new JFrame();
    jframe.setTitle("Preview Image");
    //设置frame是,长度和宽度都适当的增加了一点,这样最终的图片周边会留点白边,比较好看
    jframe.setSize(this.width+20, this.getLength()+40);
    //为frame窗口添加关闭属性
    jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    //根据实际图像长度截取图像,(0,0)表示图像左上点坐标,后两个参数表示右下角坐标
    BufferedImage img = this.bi.getSubimage(0,0,this.width,this.getLength());
    ImageIcon ii = new ImageIcon(img);
    JLabel lb = new JLabel(ii);
    jframe.add(lb);
     
    //显示frame窗口
    jframe.setVisible(true);
    //销毁g2对象
    this.g2.dispose();
    }
    }


    程序里面都有详细的注释信息,所以不难看懂的。

    最后写一个测试demo.java程序:

    import java.io.File;
    import java.awt.image.BufferedImage;
    import javax.imageio.ImageIO;
     
    class Demo{
    public static void main(String[] args){
     
    //获取画图实例
    PrintGraphics pg = new PrintGraphics();
    //初始化画布,宽度为576px,则长度为5760px
    pg.initBuff(576);
     
    //插入一张图片,根据自己的图片位置进行更改即可
    pg.drawImage(30, 0, "/home/zwang/tmp/logo.gif");
     
    //获取字体实例
    FontProperty fp = new FontProperty();
    //初始化字体,黑体,24号
    fp.setF(true, false, false, false, 24, "");
    //绘制文本
    pg.drawText(215, 45, "北京威控睿博科技有限公司", fp);
     
    //绘制直线
    pg.drawLine(0, 70, 576, 70, 5.0);
     
    //绘制各种格式的文本
    fp.setF(false, false, false, false, 18, "");
    pg.drawText(150, 95, "这是一行普通文体", fp);
     
    fp.setF(true, false, false, false, 18, "");
    pg.drawText(150, 120, "这是一行粗体文体", fp);
     
    fp.setF(false, true, false, false, 18, "");
    pg.drawText(150, 145, "这是一行斜体文体", fp);
     
    fp.setF(false, false, true, false, 18, "");
    pg.drawText(150, 170, "这是一行下划线文体", fp);
     
    fp.setF(false, false, false, true, 18, "");
    pg.drawText(150, 195, "这是一行删除线文体", fp);
     
    fp.setF(true, true, true, true, 18, "");
    pg.drawText(150, 220, "这是一行混合格式文体", fp);
     
    pg.drawLine(0, 230, 576, 230, 2.0);
     
    //绘制矩形及说明文本
    fp.setF(false, false, false, false, 15, "");
    pg.drawRectangle(10, 250, 360, 180, 2.0);
    pg.drawText(135, 340, "线宽2.0的矩形", fp);
     
    //绘制方形及说明文本
    pg.drawRectangle(380, 250, 180, 180, 4.0);
    pg.drawText(420, 340, "线宽4.0的方形", fp);
     
    //绘制椭圆及说明文本
    pg.drawEllips(10, 450, 370, 630, 3.0);
    pg.drawText(135, 540, "线宽3.0的椭圆", fp);
     
    //绘制正圆及说明文本
    pg.drawEllips(380, 450, 560, 630, 6.0);
    pg.drawText(420, 540, "线宽6.0的正圆", fp);
     
    pg.drawLine(0, 650, 576, 650, 4.0);
     
    //显示图像窗口
    pg.printShow();
     
    //将图像保存到指定位置的jpg格式文件,当然也可以为png及其它格式
    BufferedImage img=pg.bi.getSubimage(0,0,576,pg.getLength());
    //pg.g2.dispose(); //free g2
     
    //可根据实际系统更改这个路径
    File file = new File("/tmp/demo.jpg");
    try{
    ImageIO.write(img, "jpg", file);
    }catch(java.io.IOException ioe){ioe.printStackTrace();}
    }
    }

    Demo文件的注释也很详细的,都是调用前面两个库文件定义的功能函数,最后会将图像通过窗口显示出来,同时会保存到/tmp/demo.jpg。显示效果见文档开始。

    可以将三个java文件放到同一目录下,然后编译并运行:

    $ javac demo.java
    $ java Demo

    注意,根据你的实际情况,demo.java中的两处路径可能需要修改一下。

    说明:该方案仅适用于PC环境,如果是Android系统,需要其它方法实现,后面会讨论Android下如何实现。

  • 相关阅读:
    Bump Mapping综述 (转)
    二进制表示(转)
    3D局部光照模型 (转)
    关于DEVMODE的数据结构显示设备的属性(转)
    The C++ Programming Language(一)
    The C++ Programming Language(二)
    linux_redhat9下安装FTP服务器
    oracle下用户相关问题整理
    Linux的基本命令学习与shell基本内容学习(2)
    winxp系统32位平台下利用oracle10g自带的DBCA(database configuration assistant)工具创建数据库
  • 原文地址:https://www.cnblogs.com/wzc0066/p/2948166.html
Copyright © 2011-2022 走看看