这个需求很简单,也很容易就搞定了,我的测试代码:
String name = new String(request.getParameter("name").getBytes("ISO-8859-1"),"UTF-8");;
System.out.println(name);
String path = getServletContext().getRealPath("/WEB-INF/image/6.jpeg");
File theImgFile = new File(path);
int x = 20;
int y = 60;
if(name != null && name.length() > 0){
InputStream imageIn = new FileInputStream(theImgFile);
// JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(imageIn);
// BufferedImage image = decoder.decodeAsBufferedImage();
// ImageInputStream createStream = ImageIO.createImageInputStream(imageIn);
BufferedImage image = ImageIO.read(imageIn);
Graphics g=image.getGraphics();
//设置颜色
g.setColor(new Color(Integer.parseInt("ffffff",16)));
//设置字体
Font mFont = new Font("微软雅黑",Font.BOLD,22);//默认字体
g.setFont(mFont);
FontMetrics fm = g.getFontMetrics();
int width = fm.stringWidth(name);
System.out.println("字体宽度:"+width+" 显示文字:"+name);
if(width > 0 && width < 30) {
x = 33;
}else if(width < 35 && width >= 30) {
x = 30;
}else if(width < 40 && width >= 35) {
x = 27;
}else if(width < 50 && width >= 40) {
x = 25;
}else if(width < 60 && width >= 50) {
x = 18;
}else if(width < 70 && width >= 60) {
x = 15;
}
//输出文字
g.drawString(name,x,y);
//输出数据流
response.setContentType("image/jpeg");
ServletOutputStream out = response.getOutputStream();
ImageIO.write(image, "jpeg", out);
out.close();
}
当然,这代码主要还得感谢度娘,具体时哪位哥们还是小姐姐的就忘了。
正题:需求中遇到两个大问题和一个小问题
1,我在windows下开发并且一切正常,如果拿我本机当服务器,全剧终!
当我将这个功能放到linux服务器下时出现中文乱码,这种情况按常理想到的就是编码转换的问题,但这个思路去解决这个问题并没能够解决中文乱码的问题,最后是公司技术大佬发现了是linux中jdk文字目录问题,在jre/fonts文字目录下加上我们需要的文字文件就能够正常显示中文。我们可以通过遍历检测文字目录:
GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontName = e.getAvailableFontFamilyNames();
for (int i = 0; i < fontName.length; i++) {
if("微软雅黑".equalsIgnoreCase(fontName[i])){
isWryh = true; //系统更有微软雅黑字体
}
}
这样就可以在没有我没想要的文字文件时,将最终数据的图片中乱码给去掉不现实字体。
2,这些代码我是在家中进行重新编写的,我将小工程放到虚拟机centos中运行提示:
java.lang.ClassNotFoundException: com.sun.image.codec.jpeg.JPEGCodec
这是为什么呢?这些类都时在jdk中的,为什么没有这个类呢?我将这个类所在包找到jre/lib/rt.jar放到工程lib下重新打包并部署,依然出现没有找到这个类,终于找到了原因
java.lang.ClassNotFoundException的原因:
The basic explanation is that com.sun.image.codec.jpeg.JPEGCodec
and related libraries have long been marked as depreciated,
and you should use the [ImageIO]
(http://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html)
library instead.
原来,在jdk1.7版本后,这jpeg包下的类已经不推荐,所以,果断用ImageIO替换这两个类,在最上面的代码中使用
BufferedImage image = ImageIO.read(imageIn);
3,第三个问题我只能归结问算术问题了,解决这个需求我使用的是一张带底色的图片,之后在上面动态的绘制文字,这里就要注意这个“动态”俩字。绘制的文字是取用户姓名的后两位,用户姓名后两位我们不能不怀疑有奇葩的组合:“Aa”,“AA”,“tt”,“Tt”,“WW”,“ww”,“Ww”,“测试”,“测测”,“测a”,“测t”,“测T”,“测W”.......这些组合都是有可能的,刚开始我在想是否可以通过字节数来给文字定位,最后发现这个字节数并不能很好的把文字的物理长度“诠释”出来。最后找到了这个可以计算字体宽度的API
FontMetrics fm = g.getFontMetrics();
int width = fm.stringWidth(name);
通过这字体宽度进行文字定位就很容易了。