发布时间:2023-07-08 17:00
二维条形码能够在横向和纵向两个方位同时表达信息,因此能在很小的面积内表达大量的信息。
二维码又称二维条码,常见的二维码为QR Code,QR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型。
二维条码/二维码(2-dimensional bar code)是用某种特定的几何图形按一定规律在平面(二维方向上)分布的、黑白相间的、记录数据符号信息的图形;在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实现信息自动处理:它具有条码技术的一些共性:每种码制有其特定的字符集;每个字符占有一定的宽度;具有一定的校验功能等。同时还具有对不同行的信息自动识别功能、及处理图形旋转变化点。
zxing项目是谷歌推出的用来识别多种格式条形码的开源项目。在Zxing中,使用BitMatrix
来描述一个二维码,在其内部存储一个看似boolean
值的矩阵数组。这个类很好的抽象了二维码。
zxing有多个人在维护,覆盖主流编程语言,也是目前还在维护的较受欢迎的二维码扫描开源项目之一,主要的核心代码在core
文件夹里面。
https://github.com/zxing/zxing/wiki/Getting-Started-Developinghttps://github.com/zxing/zxing/wiki/Getting-Started-Developing
只使用zxing-core包,那么我们最多可以得到一个BitMatrix
, 我们想要看见二维码,则还需要将其转换成一个图片,而图片在不同的平台则是以不同的形式存在的。如png文件, jpg文件、Android的Bitmap, Java SE的 BufferedImage.
com.google.zxing
core
3.1.0
com.google.zxing
javase
3.1.0
/**
* 用zxing创建普通二维码
* @param width
* @param height
* @param format
* @param content
* @param path
* @return
*/
public static BufferedImage createImage(int width, int height,String format , String content ,String path) {
HashMap map = new HashMap();
//设置容错等级
map.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
//定义字符集,我们设置为utf-8
map.put(EncodeHintType.CHARACTER_SET, \"UTF-8\");
//设置边距,二维码边距空白宽度为0
map.put(EncodeHintType.MARGIN, 2);
BufferedImage image = null;
try {
//生成二维码对象
BitMatrix bitMatrix = new MultiFormatWriter()
.encode(content, BarcodeFormat.QR_CODE, width, height, map);
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, bitMatrix.get(x, y) ? 0xFF000000 : 0XFFFFFFFF);
}
}
Path file = new File(path).toPath();
ImageIO.write(image, format, file.toFile());
} catch (WriterException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
main方法中
public static void main(String[] args) {
createImage(300,300,\"png\",\"用zxing创建普通二维码\",\"D:\\\\QRCode\\\\zxingNormal.png\");
}
/**
* 给二维码插入logo图片
* @param image
* @param logoPath
* @return
*/
public static BufferedImage insertLogo(BufferedImage image, InputStream logoPath) {
try {
BufferedImage logo = ImageIO.read(logoPath);
int width = logo.getWidth();
int height = logo.getHeight();
if (width > 100) {
width = 100;
}
if (height > 100) {
height = 100;
}
//压缩Logo
Image logoTemp = logo.getScaledInstance(width, height, Image.SCALE_SMOOTH);
BufferedImage bfImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//获取画布
Graphics graphics = bfImage.getGraphics();
//画logoTemp
graphics.drawImage(logoTemp, 0, 0, null);
graphics.dispose();
//获取原二维码
Graphics2D graphicsQRCode = image.createGraphics();
//logo插入二维码,定义位置x,y 中间位置
int x = (image.getWidth() - width) / 2;
int y = (image.getHeight() - height) / 2;
//压缩后的logo画进二维码
graphicsQRCode.drawImage(logoTemp, x, y, null);
//logo的四个角圆滑 两个6定义弧度
Shape shape = new RoundRectangle2D.Float(x, y, width, height, 6, 6);
//设置画笔的粗细
graphicsQRCode.setStroke(new BasicStroke(3f));
//画到画布
graphicsQRCode.draw(shape);
//释放资源
graphicsQRCode.dispose();
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
insertLogo方法可在创建普通二维码时调用
/**
* 用zxing创建普通二维码
* @param width
* @param height
* @param format
* @param content
* @param path
* @param logoPath
* @return
*/
public static BufferedImage createImage(int width, int height, String format, String content, String path , InputStream logoPath) {
HashMap map = new HashMap();
//设置容错等级
map.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
//定义字符集,我们设置为utf-8
map.put(EncodeHintType.CHARACTER_SET, \"UTF-8\");
//设置边距,二维码边距空白宽度为0
map.put(EncodeHintType.MARGIN, 2);
BufferedImage image = null;
try {
//生成二维码对象
BitMatrix bitMatrix = new MultiFormatWriter()
.encode(content, BarcodeFormat.QR_CODE, width, height, map);
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, bitMatrix.get(x, y) ? 0xFF000000 : 0XFFFFFFFF);
}
}
if(!StringUtils.isEmpty(logoPath)){
insertLogo(image,logoPath);
}
Path file = new File(path).toPath();
ImageIO.write(image, format, file.toFile());
} catch (WriterException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
public static void main(String[] args) {
File file = new File(\"D:\\\\QRCode\\\\logo.png\");
try {
InputStream in = new FileInputStream(file);
createImage(300, 300, \"png\", \"用zxing创建带logo二维码\", \"D:\\\\QRCode\\\\zxingLogo.png\",in);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
来源于一个开源项目中一部分,qrcode-plugin 在开源二维码处理库zxing的基础上,重写了二维码渲染的逻辑,以支持更灵活、更个性化的二维码生成规则,封装了二维码的生成和解析,深度定制了二维码的生成,支持各种酷炫二维码的产生。
com.github.liuyueyi.media
qrcode-plugin
2.5.2
/**
* 用qrcode-plugin实现普通二维码
* @param content
* @param format
* @param path
* @return
*/
public static BufferedImage QrCode_Normal(String content ,String format ,String path) {
BufferedImage image = null;
try {
image = QrCodeGenWrapper.of(content).asBufferedImage();
Path file = new File(path).toPath();
ImageIO.write(image, format, file.toFile());
} catch (IOException e) {
e.printStackTrace();
} catch (WriterException e) {
e.printStackTrace();
}
return image;
}
public static void main(String[] args) {
QrCode_Normal(\"用qrcode-plugin创建普通二维码\",\"png\",\"D:\\\\QRCode\\\\qrcodePluginNormal.png\");
}
/**
* 用QrCode生成带logo的二维码
* @param content
* @param logo
* @return
*/
public static BufferedImage QrCode_Logo(String content, String format, String path, InputStream logo) {
BufferedImage image = null;
try {
image = QrCodeGenWrapper.of(content).setLogo(logo)
.setLogoRate(7) //设置比例
.setLogoStyle(QrCodeOptions.LogoStyle.ROUND) //设置四个角的样式
.asBufferedImage();
Path file = new File(path).toPath();
ImageIO.write(image, format, file.toFile());
} catch (IOException e) {
e.printStackTrace();
} catch (WriterException e) {
e.printStackTrace();
}
return image;
}
main方法
public static void main(String[] args) {
File file = new File(\"D:\\\\QRCode\\\\logo.png\");
try {
InputStream in = new FileInputStream(file);
QrCode_Logo(\"用qrcode-plugin创建带logo二维码\", \"png\", \"D:\\\\QRCode\\\\qrcodePluginLogo.png\", in);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
/**
* QrCode生成彩色的二维码
* @param content
* @return
*/
public static BufferedImage QrCode_Color(String content,String format ,String path) {
BufferedImage image = null;
try {
image = QrCodeGenWrapper.of(content)
.setDrawPreColor(Color.RED) //画的着色点 也就是二维码的黑色设置为其他颜色
.asBufferedImage();
Path file = new File(path).toPath();
ImageIO.write(image, format, file.toFile());
} catch (IOException e) {
e.printStackTrace();
} catch (WriterException e) {
e.printStackTrace();
}
return image;
}
public static void main(String[] args) {
QrCode_Color(\"用qrcode-plugin创建彩色二维码\",\"png\",\"D:\\\\QRCode\\\\qrcodePluginColor.png\");
}
/**
* QrCode实现背景图片的二维码
* @param content
* @param bgImage
* @return
*/
public static BufferedImage QrCode_Baground(String content, InputStream bgImage ,String format ,String path) {
BufferedImage image = null;
try {
image = QrCodeGenWrapper.of(content)
.setBgImg(bgImage) //默认是背景全覆盖二维码
.setBgOpacity(0.5f) //设置透明度
.asBufferedImage();
Path file = new File(path).toPath();
ImageIO.write(image, format, file.toFile());
} catch (IOException e) {
e.printStackTrace();
} catch (WriterException e) {
e.printStackTrace();
}
return image;
}
public static void main(String[] args) {
File file = new File(\"D:\\\\QRCode\\\\background.png\");
try {
InputStream in = new FileInputStream(file);
QrCode_Baground(\"用qrcode-plugin创建带背景二维码\",in,\"png\",\"D:\\\\QRCode\\\\qrcodePluginBaground.png\");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
/**
* QrCode实现特殊形状的二维码
* @param content
* @param format
* @param path
* @return
*/
public static BufferedImage QrCode_Shape(String content ,String format ,String path) {
BufferedImage image = null;
try {
image = QrCodeGenWrapper.of(content)
.setDrawEnableScale(true)
//黑色方块变原点
.setDrawStyle(QrCodeOptions.DrawStyle.CIRCLE)
.asBufferedImage();
Path file = new File(path).toPath();
ImageIO.write(image, format, file.toFile());
} catch (IOException e) {
e.printStackTrace();
} catch (WriterException e) {
e.printStackTrace();
}
return image;
}
public static void main(String[] args) {
QrCode_Shape(\"用qrcode-plugin创建特殊形状的二维码\",\"png\",\"D:\\\\QRCode\\\\qrcodePluginShape.png\");
}
/**
* QrCode实现用图片取代方块填充二维码,用小图标
* @param content
* @param tcImage
* @param format
* @param path
* @return
*/
public static BufferedImage QrCode_imgTC(String content, InputStream tcImage ,String format ,String path) {
BufferedImage image = null;
try {
image = QrCodeGenWrapper.of(content)
.setDrawEnableScale(true)
//黑色方块变图片
.setDrawStyle(QrCodeOptions.DrawStyle.IMAGE)
//设置精度
.setErrorCorrection(ErrorCorrectionLevel.H)
//设置一个坐标 从哪开始
.addImg(1, 1, tcImage)
.asBufferedImage();
Path file = new File(path).toPath();
ImageIO.write(image, format, file.toFile());
} catch (IOException e) {
e.printStackTrace();
} catch (WriterException e) {
e.printStackTrace();
}
return image;
}
main方法
public static void main(String[] args) {
File file = new File(\"D:\\\\QRCode\\\\logo.png\");
InputStream in = null;
try {
in = new FileInputStream(file);
QrCode_imgTC(\"用qrcode-plugin创建用图片取代方块填充二维码\",in,\"png\",\"D:\\\\QRCode\\\\qrcodePluginTcImg.png\");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
这里我用logo图片来取代方块
如果二维码需要显示到前端页面,需要先把二维码转换为字符串传给前端,然后前端把返回的数据再回显二维码展示在页面上。
public static String imageToString(BufferedImage image) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
ImageIO.write(image, \"png\", os);
} catch (IOException e) {
e.printStackTrace();
}
//转base64的字符串
return Base64.encodeBase64String(os.toByteArray());
}