java 生成二维码、可带LOGO、可去白边
1.准备工作
所需jar包:
JDK 1.6:
commons-codec-1.11.jar
core-2.2.jar
javase-2.2.jar
JDK 1.7:
commons-codec-1.11.jar
core-3.2.1.jar
javase-3.2.1.jar
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import org.apache.commons.codec.binary.Base64OutputStream;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; /**
* 维码处理工具类
* @explain
* @author Marydon
* @creationTime 2018年11月23日下午3:16:55
* @version 2.0
* @since 1.0
* @email marydon20170307@163.com
*/
public class QRcodeUtils {
// base64编码集
public static final String CHARSET = "UTF-8";
// 二维码高度
public static final int HEIGHT = 150;
// 二维码宽度
public static final int WIDTH = 150;
// 二维码外边距
public static final int MARGIN = 0;
// 二维码图片格式
private static final String FORMAT = "jpg";
}
2.生成二维码
/**
* 生成二维码
* @explain
* @param data 字符串(二维码实际内容)
* @return
*/
public static BufferedImage createQRCode(String data) {
return createQRCode(data, WIDTH, HEIGHT, MARGIN);
} /**
* 生成二维码
* @explain
* @param data 字符串(二维码实际内容)
* @param width 宽
* @param height 高
* @param margin 外边距,单位:像素,只能为整数,否则:报错
* @return BufferedImage
*/
public static BufferedImage createQRCode(String data, int width, int height, int margin) {
BitMatrix matrix;
try {
// 设置QR二维码参数
Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>(2);
// 纠错级别(H为最高级别)
// L级:约可纠错7%的数据码字
// M级:约可纠错15%的数据码字
// Q级:约可纠错25%的数据码字
// H级:约可纠错30%的数据码字
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 字符集
hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
// 边框,(num * 10)
hints.put(EncodeHintType.MARGIN, 0);// num
// 编码内容,编码类型,生成图片宽度,生成图片高度,设置参数
matrix = new MultiFormatWriter().encode(data, BarcodeFormat.QR_CODE,
width, height, hints);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
return MatrixToImageWriter.toBufferedImage(matrix);
}
说明:
网上说,EncodeHintType.MARGIN的取值区间为[0,4],但是经过实际测试,当把它的值设为负整数、正整数的时候都不会报错,但不是能是小数;
去白边,将EncodeHintType.MARGIN的值设为0的方法,根本无效,因为源码中并没有通过这个参数来设置白边的宽度;
大致过程:先根据内容生成二维码,然后根据指定的宽高,对原来的二维码进行放大或缩小,白色边框的宽度=要求的宽高-放大或缩小后的二维码的宽高。
com\google\zxing\qrcode\QRCodeWriter.class源码解读
private static BitMatrix renderResult(QRCode code, int width, int height, int quietZone)
{
ByteMatrix input = code.getMatrix();
if (input == null)
throw new IllegalStateException(); int inputWidth = input.getWidth();
int inputHeight = input.getHeight();
int qrWidth = inputWidth + quietZone * 2;
int qrHeight = inputHeight + quietZone * 2;
int outputWidth = Math.max(width, qrWidth);
int outputHeight = Math.max(height, qrHeight); int multiple = Math.min(outputWidth / qrWidth, outputHeight / qrHeight);
// 有白色边框的罪魁祸首:leftPadding和topPadding
int leftPadding = (outputWidth - inputWidth * multiple) / 2;
int topPadding = (outputHeight - inputHeight * multiple) / 2; BitMatrix output = new BitMatrix(outputWidth, outputHeight); int inputY = 0; for (int outputY = topPadding; inputY < inputHeight; )
{
int inputX = 0; for (int outputX = leftPadding; inputX < inputWidth; ) {
if (input.get(inputX, inputY) == 1)
output.setRegion(outputX, outputY, multiple, multiple);
++inputX; outputX += multiple;
}
++inputY; outputY += multiple;
} return output;
}
3.去白边
在createQRCode()方法中添加如下代码:
// 裁减白边(强制减掉白边)
if (margin == 0) {
bitMatrix = deleteWhite(bitMatrix);
}
具体实现方法:
/**
* 强制将白边去掉
* @explain
* 虽然生成二维码时,已经将margin的值设为了0,但是在实际生成二维码时有时候还是会生成白色的边框,边框的宽度为10px;
* 白边的生成还与设定的二维码的宽、高及二维码内容的多少(内容越多,生成的二维码越密集)有关;
* 因为是在生成二维码之后,才将白边裁掉,所以裁剪后的二维码(实际二维码的宽、高)肯定不是你想要的尺寸,只能自己一点点试喽!
* @param matrix
* @return 裁剪后的二维码(实际二维码的大小)
*/
private static BitMatrix deleteWhite(BitMatrix matrix) {
int[] rec = matrix.getEnclosingRectangle();
int resWidth = rec[2] + 1;
int resHeight = rec[3] + 1; BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
resMatrix.clear();
for (int i = 0; i < resWidth; i++) {
for (int j = 0; j < resHeight; j++) {
if (matrix.get(i + rec[0], j + rec[1]))
resMatrix.set(i, j);
}
} int width = resMatrix.getWidth();
int height = resMatrix.getHeight();
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, resMatrix.get(x, y) ? 0 : 255);// 0-黑色;255-白色
}
} return resMatrix;
}
说明:这种方法只能去除普通的二维码的白边,不能去除带LOGO的二维码的白边。
4.生成带logo的二维码
/**
* 生成带logo的二维码
* @explain 宽、高、外边距使用定义好的值
* @param data 字符串(二维码实际内容)
* @param logoFile logo图片文件对象
* @return BufferedImage
*/
public static BufferedImage createQRCodeWithLogo(String data, File logoFile) {
return createQRCodeWithLogo(data, WIDTH, HEIGHT, MARGIN, logoFile);
} /**
* 生成带logo的二维码
* @explain 自定义二维码的宽和高
* @param data 字符串(二维码实际内容)
* @param width 宽
* @param height 高
* @param logoFile logo图片文件对象
* @return BufferedImage
* @return
*/
public static BufferedImage createQRCodeWithLogo(String data, int width, int height, int margin, File logoFile) {
BufferedImage combined = null;
try {
BufferedImage qrcode = createQRCode(data, width, height, margin);
BufferedImage logo = ImageIO.read(logoFile);
int deltaHeight = height - logo.getHeight();
int deltaWidth = width - logo.getWidth();
combined = new BufferedImage(height, width, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) combined.getGraphics();
g.drawImage(qrcode, 0, 0, null);
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f));
g.drawImage(logo, (int) Math.round(deltaWidth / 2), (int) Math.round(deltaHeight / 2), null);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
return combined;
}
5.以什么样的方式返回二维码
/**
* 将二维码信息写入文件中
* @explain
* @param image
* @param file 用于存储二维码的文件对象
*/
public static void writeToFile(BufferedImage image, File file) {
try {
ImageIO.write(image, FORMAT, file);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
} /**
* 将二维码信息写入流中
* @explain
* @param image
* @param 文件stream
*/
public static void writeToStream(BufferedImage image, OutputStream stream) {
try {
ImageIO.write(image, FORMAT, stream);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
} /**
* 获取base64格式的二维码
* @explain 图片类型:jpg
* 展示:<img src="data:image/jpeg;base64,base64Str"/>
* @param image
* @return base64
*/
public static String writeToString(BufferedImage image) {
String base64Str;
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
OutputStream os = new Base64OutputStream(bos);
writeToStream(image, os);
// 按指定字符集进行转换并去除换行符
base64Str = bos.toString(CHARSET).replace("\r\n", "");
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
return base64Str;
}
6.base64生成图片
/**
* 将base64转成图片
* @explain
* @param base64 base64格式图片
* @param file 用于存储二维码的文件对象
*/
public static void base64ToImage(String base64, File file) {
FileOutputStream os;
try {
Base64 d = new Base64();
byte[] bs = d.decode(base64);
os = new FileOutputStream(file.getAbsolutePath());
os.write(bs);
os.close();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
7.测试
见文末推荐
2018/11/29
添加二维码边框参数设置;
代码优化。
2018/11/30
添加去除白边功能。
java 生成二维码、可带LOGO、可去白边的更多相关文章
- java生成二维码(带logo)
之前写过一篇不带logo的二维码实现方式,採用QRCode和ZXing两种方式 http://blog.csdn.net/xiaokui_wingfly/article/details/3947618 ...
- java 生成二维码后叠加LOGO并转换成base64
1.代码 见文末推荐 2.测试 测试1:生成base64码 public static void main(String[] args) throws Exception { String dat ...
- JAVA使用qrcode生成二维码(带logo/不带logo)
/** * */ package qrcode; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Image; i ...
- (转)ZXing生成二维码和带logo的二维码,模仿微信生成二维码效果
场景:移动支付需要对二维码的生成与部署有所了解,掌握目前主流的二维码生成技术. 1 ZXing 生成二维码 首先说下,QRCode是日本人开发的,ZXing是google开发,barcode4j也是老 ...
- 利用PHP QR Code生成二维码(带logo)
转自:http://www.cnblogs.com/txw1958/p/phpqrcode.html HP QR Code是一个PHP二维码生成类库,利用它可以轻松生成二维码,官网提供了下载和多个演示 ...
- php--------php库生成二维码和有logo的二维码
php生成二维码和带有logo的二维码,上一篇博客讲的是js实现二维码:php--------使用js生成二维码. 今天写的这个小案例是使用php库生成二维码: 效果图: 使用了 php ...
- 使用PHP生成二维码支持自定义logo
require_once 'phpqrcode/phpqrcode.php'; //引入类库 $text = "https://www.baidu.com/";//要生成二维码的文 ...
- 利用JAVA生成二维码
本文章整理于慕课网的学习视频<JAVA生成二维码>,如果想看视频内容请移步慕课网. 维基百科上对于二维码的解释. 二维条码是指在一维条码的基础上扩展出另一维具有可读性的条码,使用黑白矩形图 ...
- java生成二维码打印到浏览器
java生成二维码打印到浏览器 解决方法: pom.xml的依赖两个jar包: <!-- https://mvnrepository.com/artifact/com.google.zxin ...
随机推荐
- JAVAWEB开发之HttpServletResponse和HttpServletRequest详解(上)(各种乱码、验证码、重定向和转发)
HttpServletResponse简介 Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象.和代表响应的response对象 request和re ...
- Promise is rejected: Error: 2 UNKNOWN: error starting container: API error (404): {"message":"network build-blockchain-insurance-app_default not found"}出错的解决方案
错误描述: docker logs web 现象: > blockchain-for-insurance@2.1.0 serve /app > cross-env NODE_ENV=pro ...
- Verilog 加法器和减法器(7)
在计算机中浮点数 表示通常采用IEEE754规定的格式,具体参考以下文章. https://www.cnblogs.com/mikewolf2002/p/10095995.html 下面我们在Veri ...
- 一些NLP相关的JD,作参考
NLP 应用研发工程师 - AI Lab工作城市: 上海岗位描述:1.用户搜索意图识别,分词和词性标注,实体词标注 2.利用机器学习.NLP 技术优化文本分类.语义理解及信息抽取岗位要求:1.有自然语 ...
- 第十三章 redis-cluster原理
一.基本定义 虚拟槽slot分区算法,优点是扩容缩容简单:直接把slot及每个slot上的数据进行缩放即可 redis定义了0-16383(总共为16384个slot,即214个slot) slot会 ...
- DEV控件之ChartControl 属性设置【转】
DEV控件之ChartControl用法 一.总体概述 这个控件包含3层,最外面的chartControl层.中间的XYDiagram层.最里面的Series层.功能非常强大,但同时使用起来也相对复杂 ...
- laravel 5.5 跨域问题解决方案
一.laravel-Cors 安装 在终端执行安装命令如下: composer require barryvdh/laravel-cors 添加服务提供商 在Laravel配置文件app.php的pr ...
- 【Scala】Scala-Option-Null的蹊跷
Scala-Option-Null的蹊跷 scala Some(null)_百度搜索 scala - Why Some(null) isn't considered None? - Stack Ove ...
- 我们为何放弃Eclipse,投奔IntelliJ IDEA
本文来源于我在InfoQ中文站原创的文章,原文地址是:http://www.infoq.com/cn/news/2013/11/why-drop-eclipse-use-intellij Nikita ...
- [Functional Programming] Using JS, FP approach with Arrow or State Monad
Using Naive JS: const {modify, get} = require('crocks/State'); const K = require('crocks/combinators ...