Java实现高可定制的二维码生成
2014-09-30 10:14
423 查看
开篇废话
不是第一次写二维码生成的代码,但是是第一次把它整理清晰并做成高可定制的。具体生成实现都是和网上的差不多用了com.swetake.util.Qrcode进行关键处理。但是这篇文章的不同之处在于不是为了简单的实现,而是为了实现高可定制的功能。很多时候要用二维码,但是实际上二维码的场景还是很多的。打印在纸巾上的是二维码,做成大海报的也是二维码,嵌入logo的是二维码,不嵌入logo的也是二维码。为了让这个工具类使用场景更广,特地封装了一个配置类,根据配置进行更多的处理,最终定制二维码的生成。
额,个人比较懒,就不贴全部代码了,这里之列出一些关键实现,没啥技术难点,只是注释得多,方便理解。
ok,开始……
关键代码
1、模式设置
// 设定编码容错级别 qrcode.setQrcodeErrorCorrect(c.getLevel()); // 设定编码模式 qrcode.setQrcodeVersion(c.getEncodeMode()); // 设定编码版本 qrcode.setQrcodeVersion(c.getVersion());
2、字符转化
// 转化字符串为byte数组,用于二维码编码作为参数 byte[] buff = source.getBytes(charset); boolean[][] bRect; try { // 进行编码处理,超长将会在这里抛出异常 bRect = qrcode.calQrcode(buff); } catch (Exception e) { // 这里如果出现异常,一般是超长了,所以这里抛出异常 throw new QRCodeGenerateException("Generate qrcode exception." + "Please check your generate config and check the source string." + "The exception offen by the source string is too long." + "The source string is : " + source + "[" + source.getBytes(charset).length + "]", e); }
3、绘图设置
// 默认使用BufferedImage.TYPE_INT_RGB生成图像,暂不支持自定义 BufferedImage bi = new BufferedImage(c.getWidth(), c.getHeight(), BufferedImage.TYPE_INT_RGB); // 创建图像 Graphics2D g = bi.createGraphics(); if(c.getBackgroundColor() != null){ // 设置背景色为白色 g.setBackground(c.getBackgroundColor()); } // 清空区域 g.clearRect(0, 0, c.getWidth(), c.getHeight()); // 设置前景色为黑色,即填充色 g.setColor(c.getColor());
4、进行绘图
try { // 根据byte矩阵进行绘图 for (int i = 0; i < bRect.length; i++) { for (int j = 0; j < bRect.length; j++) { if (bRect[j][i]) { // 这里的fill影响边 g.fillRect(j * c.getOffset() + c.getPixoff(), i * c.getOffset() + c.getPixoff(), c.getOffset(), c.getOffset()); } } } //如果设定嵌入的logo文件不为空,则执行嵌入操作 if(logo != null){ insertLogo(logo, c, g); } //这里不进行异常处理,直接抛出,但要进行释放处理 } finally { // 释放图像 g.dispose(); // 刷新缓存区 bi.flush(); }
5、保存图片
//根据uri协议获取对应输出流 OutputStream os = getOutputStream(target); //写入io,默认jepg压缩,暂不支持其他格式图像 ImageIO.write(bi, c.getFormat(), os);
其他功能实现
1、插入logo的实现
/** * 插入logo到二维码中央 * @param logo logo源 * @param config 二维码生成配置 * @param g 绘制Graphics2D对象 * @throws IOException 绘制时可能产生的IO一场 * @throws MalformedURLException 解析logo源可能出现的URL地址错误异常 * @see #build(URI, String, String, URI, QRCodeGenerateConfig) */ private void insertLogo(URI logo, QRCodeGenerateConfig config, Graphics2D g) throws IOException, MalformedURLException { //获取Image对象。 Image img = getLogoResource(logo); //定义logo绘制参数 int logoX,logoY,logoW,logoH; //获取logo大小 logoW = config.getLogoWidth(); logoH = config.getLogoHeight(); //计算logo坐标 logoX = (config.getWidth() - logoW) / 2; logoY = (config.getHeight() - logoH) / 2; //这里不验证实际数值是否为负数,因此如果由配置不当造成的异常,就不管了 //绘制logo try{ g.drawImage(img, logoX, logoY, logoW, logoH, null); }catch(Exception ee){ // 这里如果出现异常,一般是超长了,所以这里抛出异常 throw new QRCodeGenerateException("Draw logo exception,please check your generate config.",ee); } }
2、getLogoResource的实现
/** * 根据logo源URI获取logo的Image对象 * @param logo logo源URI * @return Image对象 * @throws IOException 获取时可能产生的IO异常 * @throws MalformedURLException 解析URL类logo资源时可能出现的URL地址错误异常 * @see #build(URI, String, String, URI, QRCodeGenerateConfig) */ private Image getLogoResource(URI logo) throws IOException, MalformedURLException { Image img; if ("http".equalsIgnoreCase(logo.getScheme())) { img = ImageIO.read(logo.toURL()); } else if ("https".equalsIgnoreCase(logo.getScheme())) { img = ImageIO.read(logo.toURL()); } else if ("file".equalsIgnoreCase(logo.getScheme())) { File f = new File(logo); img = ImageIO.read(f); } else { //不支持的协议直接抛出异常 throw new QRCodeGenerateException("Insert logo image into qrcode exception,the uri scheme is not support.We only support the scheme such as http,https and file.\n" + logo.toString()); } return img; }
3、getOutputStream的实现
/** * 根据目标URI地址获取输出流 * @param target 目标URI * @return 输出流 * @throws MalformedURLException 解析目标URI可能出现的URL地址错误异常 * @throws IOException 打开输出流可能出现的IO异常 * @throws FileNotFoundException 打开文件类型的URI时可能出现的文件不存在异常 * @see #build(URI, String, String, URI, QRCodeGenerateConfig) */ private OutputStream getOutputStream(URI target) throws MalformedURLException, IOException, FileNotFoundException { OutputStream os; if ("http".equalsIgnoreCase(target.getScheme())) { os = getHttpOutputStream(target); } else if ("https".equalsIgnoreCase(target.getScheme())) { os = getHttpOutputStream(target); } else if ("file".equalsIgnoreCase(target.getScheme())) { File f = new File(target); os = new FileOutputStream(f); } else { //不支持的协议直接抛出异常 throw new QRCodeGenerateException("Save qrcode image exception,the uri scheme is not support.We only support the scheme such as http,https and file.\n" + target.toString()); } return os; }
相关定义
1、引用
import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import javax.imageio.ImageIO; import com.swetake.util.Qrcode;
2、核心实现方法定义
/** * 生成带Logo的二维码,自定义配置的生成方式 * @param logo 嵌入中间的logo来源Uri * @param source 源字符串 * @param charset 编码 * @param target 生成的二维码图片要保存的目标URI * @param config 二维码生成配置 * @throws QRCodeGenerateException 二维码生成异常 * @throws UnsupportedEncodingException 指定的编码不支持 * @throws IOException 二维码图片保存产生的IO异常 */ public void build(URI logo, String source, String charset, URI target, QRCodeGenerateConfig config) throws QRCodeGenerateException, UnsupportedEncodingException, IOException;
3、config类关键字段
/** * 二维码版本,默认为5 */ private int version = 5; /** * 二维码编码模式,默认为B */ private QRCodeEncodeMode encodeMode = QRCodeEncodeMode.B; /** * 二维码容错级别,默认为M */ private QRCodeLevel level = QRCodeLevel.M; /** * 生成二维码的宽度 */ private int width = 115; /** * 生成二维码的高度 */ private int height = 115; /** * 生成二维码嵌入的logo宽度 */ private int logoWidth = 30; /** * 生成二维码嵌入的logo高度 */ private int logoHeight = 30; /** * 像素大小 */ private int offset = 3; /** * 偏移量 */ private int pixoff = 2; /** * 二维码图像保存格式 */ private String format = "jpeg"; /** * 二维码图像背景色 */ private Color backgroundColor = Color.WHITE; /** * 二维码图像前景色 */ private Color color = Color.BLACK;
其它说明
1、建议的宽高及偏移量配置比例[适用默认版本和容错级别*]
二维码图像本身宽度和高度 —— 1:1 二维码LOGO图像宽度和高度 —— 1:1 二维码图像本身宽度和LOGO图像宽度 —— 23:6[115:30] 二维码图像本身高度和LOGO图像高度 —— 23:6[115:30] 二维码图像本身宽度和像素大小 —— 115:3 二维码图像本身高度和像素大小 —— 115:3 二维码图像本身宽度和偏移量 —— 115:2 二维码图像本身高度和偏移量 —— 115:2 二维码像素大小和偏移量 —— 3:2
2、参考资料
QRCode中文说明备注
默认配置说明
版本5,容错级别为M,宽高115,logo宽高30,像素大小3,偏移量2,生成jpeg格式图片,背景色白色,画笔颜色黑色
说明由于默认宽高是115,因此打印出来可能会比较小,如果需要打印大图片,则需要参考比例进行图像放大。
结果示例图:
相关文章推荐
- java二维码生成与解析代码实现
- java零碎要点---用java实现生成二维码,与解析代码实现
- java二维码生成与解析代码实现
- java实现生成二维码
- java二维码生成与解析代码实现
- java二维码生成与解析代码实现 .
- java二维码生成与解析代码实现
- java实现二维码的生成和解析。
- java二维码生成与解析代码实现
- java二维码生成与解析代码实现
- java二维码生成与解析代码实现
- java二维码生成与解析代码实现
- 二维码生成与解析代码实现 java
- java二维码生成与解析代码实现
- java二维码生成与解析代码实现
- java二维码生成与解析代码实现 <转载自http://blog.csdn.net/about58238/article/details/7494704>
- java二维码生成与解析代码实现
- java二维码生成与解析代码实现
- java实现二维码的生成和解析
- java二维码生成与解析代码实现