文章目录
- 引言
- 二维码基本原理
- 1、二维码概述
- 2、QR Code结构
- 3、错误纠正级别
- QR Code生成技术
- 1、ZXing库
- 2、生成二维码的步骤
- 图像处理技术
- 1、嵌入Logo
- 2. 去除白边
- 阿里云OSS基本概念
- 1、OSS概述
- 2. 主要功能
- 3. 基本概念
- 实战演示
- 1、依赖库
- 2、类结构
- 3、生成普通二维码
- 4. 去除白边
- 5、普通二维码增加Logo
- 6. 上传到阿里云OSS
- 完整工具类
- 总结
引言
在现代应用中,二维码因其高效的信息编码能力而被广泛应用。为了提升二维码的视觉效果和品牌识别度,通常会在二维码中嵌入Logo。本文将详细介绍使用ZXing库生成带有Logo的二维码图片,去除白边,并将生成的二维码上传到阿里云OSS。此外,本文还将介绍二维码的基本原理、QR Code的结构、图像处理技术以及阿里云OSS的基本概念。
二维码基本原理
1、二维码概述
二维码(QR Code)是一种二维条码,可以存储大量的数据,如URL、文本、数字等。与一维条码相比,二维码可以在两个维度上存储信息,因此具有更高的信息密度和更强的容错能力。
2、QR Code结构
QR Code由以下部分组成:
定位图案:位于二维码的三个角,用于帮助扫描设备定位二维码。
校正图案:用于纠正扫描过程中可能出现的错误。
数据区域:存储实际的数据信息。
格式信息:存储二维码的版本、错误纠正级别等信息。
版本信息:指示二维码的版本号,版本号越高,可以存储的数据量越大。
静区:二维码周围的空白区域,用于防止二维码与其他图案混淆。
3、错误纠正级别
QR Code支持四种错误纠正级别:
L(Low):约7%的错误纠正能力。
M(Medium):约15%的错误纠正能力。
Q(Quartile):约25%的错误纠正能力。
H(High):约30%的错误纠正能力。
QR Code生成技术
1、ZXing库
ZXing(Zebra Crossing)是一个开源的、多格式的1D/2D条码图像处理库。它支持多种条码格式,包括QR Code、Code 128、EAN-13等。在本文中,我们将使用ZXing库来生成二维码。
2、生成二维码的步骤
创建QRCodeWriter实例:用于生成二维码。
设置编码提示:如字符集、错误纠正级别等。
生成BitMatrix:将输入数据编码为BitMatrix对象。
转换为BufferedImage:将BitMatrix对象转换为BufferedImage对象。
去除白边:去除二维码周围的白边,使二维码更加紧凑。
嵌入Logo:在二维码中嵌入Logo图像。
图像处理技术
1、嵌入Logo
在二维码中嵌入Logo图像可以提升视觉效果。嵌入Logo的步骤如下:
读取Logo图像:从指定路径读取Logo图像。
调整Logo大小:根据二维码的大小调整Logo的尺寸。
绘制Logo:将调整后的Logo绘制到二维码的中心位置。
添加圆角:为Logo添加圆角,使其更加美观。
2. 去除白边
去除二维码周围的白边可以减少图像的大小,提升视觉效果。去除白边的步骤如下:
遍历图像:遍历二维码图像,找到非白色像素的边界。
裁剪图像:根据找到的边界裁剪图像,去除白边。
阿里云OSS基本概念
1、OSS概述
阿里云对象存储服务(Object Storage Service,简称OSS)是阿里云提供的海量、安全、低成本、高可靠的云存储服务。OSS适合存放任意类型的文件,如图片、音视频、日志文件、备份文件等。
2. 主要功能
存储和分发:提供高可用性和持久性的存储服务。
权限管理:支持细粒度的访问控制。
数据处理:提供图像处理、视频处理等增值服务。
监控和日志:提供详细的监控和日志记录。
3. 基本概念
Bucket:存储空间,用于存放文件。
Object:存储在Bucket中的文件。
Endpoint:访问OSS的域名。
Access Key ID 和 Access Key Secret:用于身份验证的密钥对。
实战演示
1、依赖库
为了实现二维码生成和图像处理功能,QRCodeWithLogoUtil 使用了以下依赖库:
ZXing (Zebra Crossing):一个开源的、多格式的1D/2D条码图像处理库。
Apache Commons Imaging:用于图像处理和操作。
阿里云OSS SDK:用于上传文件到阿里云OSS。
在 pom.xml 中添加以下依赖:
<!--安装OSS SDK-->
<dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.16.3</version>
</dependency>
<!-- ZXing core -->
<dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.3</version>
</dependency>
<!-- ZXing javase -->
<dependency><groupId>com.google.zxing</groupId><artifactId>javase</artifactId><version>3.5.3</version>
</dependency>
2、类结构
3、生成普通二维码
generateQRCodeImage(String text, int width, int height) 方法用于生成带有Logo的二维码。
4. 去除白边
deleteWhite(BitMatrix matrix,int qrWidth,int qrHeight)
方法用于去除二维码周围的白边,使二维码更加紧凑,去除白边后对二维码图片进行拉伸满足业务要求。
5、普通二维码增加Logo
addLogoToQrCode(BufferedImage qrCodeImage, BufferedImage logoImage,int loginWidth,int loginHeight) 方法在原始的 二维码基础上增加logo。
6. 上传到阿里云OSS
generateQrCodeImageAndUploadToOss(String qrText, int width, int height,String logoName,int loginWidth,int loginHeight,String objectName) 方法作为调用入口,将二维码创建完成后并将生成的二维码上传到阿里云OS。
完整工具类
/*** QRCodeWithLogoUtil* @author senfel* @version 1.0* @date 2025/2/25 14:31*/
@Component
@Slf4j
public class QRCodeWithLogoUtil {private static final String ENDPOINT = "https://oss-cn-shanghai.aliyuncs.com";private static final String ACCESS_KEY_ID = "LTAI5tB91wtXft75XXXX";private static final String ACCESS_KEY_SECRET = "ecgR2ZCAb9uXXXXXX";private static final String BUCKET_NAME = "cn-sh-dev-csa-oss-01";private static OSS OSS_CLIENT = null;static {// 创建OSSClient实例。OSS_CLIENT = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);}public static void main(String[] args) throws Exception {// 二维码内容String qrText = "https://XXXXX/code/mp?scene=dp&dpsource=scancode&b=fdzInN0FwUuL4a5E";// logo图片名称,放置在resourceString logoName = "inchanel-logo.png";String objectName = "moi/fdzInN0FwUuL4a5E222.png";int width = 100;int height = 100;int loginWidth = 26;int loginHeight = 26;String s = generateQrCodeImageAndUploadToOss(qrText, width, height, logoName, loginWidth, loginHeight, objectName);System.err.println(s);}/*** generateQrCodeImageAndUploadToOss* @param qrText* @param width* @param height* @param logoName* @param loginWidth* @param loginHeight* @param objectName* @author senfel* @date 2025/2/26 10:01* @return java.lang.String*/public static String generateQrCodeImageAndUploadToOss(String qrText, int width, int height,String logoName,int loginWidth,int loginHeight,String objectName) throws Exception {try {BufferedImage qrImage = generateQRCodeImage(qrText, width, height);BufferedImage logoImage = ImageIO.read(Objects.requireNonNull(QRCodeWithLogoUtil.class.getClassLoader().getResource(logoName)));BufferedImage finalImage = addLogoToQrCode(qrImage, logoImage,loginWidth,loginHeight);ByteArrayOutputStream os = new ByteArrayOutputStream();ImageIO.write(finalImage, "PNG", os);// 将图片保存在内存中,imageBytes即为二维码图片的字节流byte[] imageBytes = os.toByteArray();//保存本地//ImageIO.write(finalImage, "PNG", new File("D:\\blank\\fdzInN0FwUuL4a5E22.png"));//将图片上传到oss//将imageBytes转为输入流ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME, objectName, inputStream);OSS_CLIENT.putObject(putObjectRequest);VoidResult voidResult = OSS_CLIENT.setObjectAcl(BUCKET_NAME, objectName, CannedAccessControlList.PublicRead);if( 200 != voidResult.getResponse().getStatusCode()){log.error("QRCodeWithLogoUtil上传图片到OSS失败,响应信息为:{}", voidResult.getResponse());throw new RuntimeException("QRCodeWithLogoUtil上传图片到OSS失败");}return voidResult.getResponse().getUri().substring(0,voidResult.getResponse().getUri().indexOf("?"));} catch (Exception e) {log.error("QRCodeWithLogoUtil生成二维码失败,异常信息为:{}", e.getMessage(),e);throw new RuntimeException("QRCodeWithLogoUtil生成二维码失败");}}/*** generateQRCodeImage* @param text* @param width* @param height* @author senfel* @date 2025/2/25 19:00* @return java.awt.image.BufferedImage*/private static BufferedImage generateQRCodeImage(String text, int width, int height) throws WriterException {Map<EncodeHintType, Object> hints = new HashMap<>();hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints);return deleteWhite(bitMatrix,width,height);}/*** deleteWhite* @param matrix* @param qrWidth* @param qrHeight* @author senfel* @date 2025/2/25 19:00* @return java.awt.image.BufferedImage*/private static BufferedImage deleteWhite(BitMatrix matrix,int qrWidth,int qrHeight) {int[] rec = matrix.getEnclosingRectangle();int resWidth = rec[2];int resHeight = rec[3];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);}}//生成二维码BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(resMatrix);// 若二维码的实际宽高和预期的宽高不一致, 则缩放if (qrWidth != width || qrHeight != height) {BufferedImage tmp = new BufferedImage(qrWidth, qrHeight, BufferedImage.TYPE_INT_RGB);tmp.getGraphics().drawImage(bufferedImage.getScaledInstance(qrWidth, qrHeight,Image.SCALE_SMOOTH), 0, 0, null);bufferedImage = tmp;}return bufferedImage;}/*** addLogoToQrCode* @param qrCodeImage* @param logoImage* @param loginWidth* @param loginHeight* @author senfel* @date 2025/2/26 17:42* @return java.awt.image.BufferedImage*/private static BufferedImage addLogoToQrCode(BufferedImage qrCodeImage, BufferedImage logoImage,int loginWidth,int loginHeight) {Graphics2D graphics = qrCodeImage.createGraphics();// Logo图片左上角的x坐标,可根据需要调整位置int x = (qrCodeImage.getWidth() - loginWidth) / 2;// Logo图片左上角的y坐标,可根据需要调整位置int y = (qrCodeImage.getHeight() - loginHeight) / 2;// 设置抗锯齿graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);// 绘制Logo图片到二维码上graphics.drawImage(logoImage, x, y, loginWidth, loginHeight, null);// 释放资源graphics.dispose();// 返回带有Logo的二维码图片对象return qrCodeImage;}
}
效果展示
总结
通过本文的介绍,你已经了解了使用ZXing库生成带有Logo的二维码图片,去除白边,并将生成的二维码上传到阿里云OSS。此外,本文还介绍了二维码的基本原理、QR Code的结构、图像处理技术以及阿里云OSS的基本概念。这个工具类可以广泛应用于各种需要生成二维码的场景,提升用户体验和品牌识别度。