继续设计公共类,之前编写的生成验证码的类,在收集资料后发现,不能直接应用在网站的建设上,但是却能够满足得到验证码的要求,如果在工作时需要使用到改类,则需要根据实际的使用情况进行修改,调试。算是一个demo类型的练手吧,接下来,我编写了生成水印的工具类,在有做验证码图片的基础后, 水印生成类的编写显得更加顺利。
现贴上类代码,供参考,希望可以互相交流提高。
public class ImageChange {
private String fileAddress; //需要被处理的图片地址
private String addStr; //添加水印的文字
private String addImageAddress; //添加图片水印的水印图片地址
/*初始化方法,默认设置所有的成员属性为空*/
public ImageChange(){
this.fileAddress = "";
this.addImageAddress = "";
this.addStr = "";
}
/*设置需要被处理的文件的地址*/
public void setFileAddress(String fileAddress) {
this.fileAddress = fileAddress;
}
/*设置添加水印的文字*/
public void setAddStr(String addStr) {
this.addStr = addStr;
}
/*设置水印图片的地址*/
public void setAddImage(String addImage) {
this.addImageAddress = addImage;
}
/*设置所有成员属性的函数*/
public void setParameter(String fileAddress,String addStr,String addImage){
this.fileAddress = fileAddress;
this.addStr = addStr;
this.addImageAddress = addImage;
}
/*向图片中添加文字水印*/
public void drawString(){
//用fileAddress找到对应的需要添加水印的文件
File oldFile = new File(this.fileAddress);
//try、catch语句,用于抛出异常
try {
//读取出fileAddress对应的文件到一个Image变量
Image image = ImageIO.read(oldFile);
//取得图片的宽和高
int width = image.getWidth(null);
int height = image.getHeight(null);
//创建一个BufferedImage变量,用于对图片的绘制操作
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//取得Graphics2D变量
Graphics2D g = bi.createGraphics();
//将需要添加水印的文件绘制到Graphics2D中。
g.drawImage(image, 0, 0, width, height, null);
//设置一个字体,最后的字号数需要根据最后的水印图片大小进行调整
Font font = new Font("黑体",Font.BOLD,25);
g.setFont(font);
g.setColor(Color.ORANGE);
//通过image的上下文,设置接下来要绘制的图形的透明度,0.0为全透明,1.0为完全不透明
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.4F));
int x = 0;
int y = 0;
//根据需要,计算出绘制水印的坐标位置
x = (width)-(25*this.addStr.length())-5;
y = height-5;
//绘制文字水印到g中。
g.drawString(this.addStr, x, y);
//使之前的绘制操作生效
g.dispose();
//将重新绘制得到的图片输出到原来的文件中
ImageIO.write(bi, "jpg", oldFile);
} catch (IOException e) {
e.printStackTrace();
}
}
/*向图片中添加图片水印*/
public void drawImage(){
//根据fileAddress得到需要添加水印的图片文件。
File oldFile = new File(this.fileAddress);
//根据addImageAddress得到水印图片
File waterFile = new File(this.addImageAddress);
//try,catch语句抛出异常
try {
//取得文件图片到Image变量中
Image oldImage = ImageIO.read(oldFile);
//获得原图片的宽和高
int width = oldImage.getWidth(null);
int height = oldImage.getHeight(null);
//创建一个BufferedImage用于图片的绘制
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//取得图片上下文
Graphics2D g = bi.createGraphics();
//心绘制出来原本的图片
g.drawImage(oldImage, 0, 0, width, height, null);
//为接下来的绘制设定透明度
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5F));
//获得水印图片
Image waterImage = ImageIO.read(waterFile);
//取得的水印图片的宽和高
int waterWidth = waterImage.getWidth(null);
int waterHeight = waterImage.getHeight(null);
//根据需要计算出绘制的坐标
int x = (width)-5-waterWidth;
int y = height-(5+25)-waterHeight;
//通过绘制函数,在原图片上绘制出水印
g.drawImage(waterImage, x, y, waterWidth, waterHeight, null);
//使之前的操作生效
g.dispose();
//输出到源文件的位置
ImageIO.write(bi, "jpg", oldFile);
} catch (IOException e) {
e.printStackTrace();
}
}
}
总结:因为是练习时编写的类代码,所以我加了大量的注释,显得有些多余,但是保证了所有人都能看懂我的思路,这也对今后的使用提供了方便。
下面是2个工具类编写时得到的经验:
1、在编写验证码类的时候,明显的觉得,计算出绘制位置是一件最麻烦的事情,字体字号都要自己设置,如果下次改进的时候,将字体字号作为参数传进来,那么计算绘制函数的公式就 不能用了,这是明显需要改进的一点。
2、我并没有把类设定为static静态的类型,原因是在掌握了问题的处理方法和理解后,再次编写显得更加简单,设定非静态类更加方便做测试时候调试,还有就是符合由浅入深的逻辑吧(强词夺理)。
3、在编写水印图片类的时候,在除了之前绘制坐标确定的问题外,发现了2点注意的地方。首先是在调用函数BufferedImage。read时, 在JDK文档中有这样的一句话,“返回一个
BufferedImage
,作为使用 ImageReader
(它是从当前已注册 ImageReader 中自动选择的)解码所提供
File
的结果。该 File
被包装在一个 ImageInputStream
中。如果没有已注册的
ImageReader
声称能够读取得到的流,则返回 null
。 ”起初不是很明白他的意思,在做junit测试的时候,我首先选择的水印图片是一张格式为ICO的文件,测试时报错,大体的意识是对应的注册机类中的枚举值出错。根据错误明白了这句文档翻译的意思,就是说不是所有的图片格式多可以通过read函数取得。还有一点也是图片格式的问题,GIF格式的图片是没办法绘制成水印图片的。
接着学习Hibernate的资料了, 下一步开始着手构造项目的基本框架,由浅入深,慢慢的调试。踏踏实实的进步。