去除zxing生成二维码的白色边距

您所在的位置:网站首页 pdf删除白边距后留一部分 去除zxing生成二维码的白色边距

去除zxing生成二维码的白色边距

2024-07-07 13:26:01| 来源: 网络整理| 查看: 265

1.背景介绍

最近在做一些期刊类的素材时使用到了生成二维码的功能,实际在8-9年以前就实践过二维码的生成,当时还做了一个在线生成的示例,可以自定义宽度、高度、内容、logo小图标(小图标有多种位置可选),本次拿来使用时发现以前的二维码确实还有一个白边问题存在,时隔多年发现这种问题搜索起来一大片,实际能起到作用的却是非常少,所以本次记录一下解决的方式,采用修改源码的方式,将源代码拷贝至项目中(保持包路径名称与jar中一致),利用IDE优先加载项目中的class的特点来覆盖jar中class文件的特性,起到更改源码生效的目的。(PS:若使用启动脚本来运行的程序,比如java -cp时指定的classpath同样是支持优先加载顺序的,详见本站提供的Spring Boot应用程序打包篇)

回归主题,本篇文章主要是解决使用zxing组件生成二维码时的白边问题,所谓白边则是指生成的二维码图片的大小并不是实际设置的大小,会留有一定尺寸的白色边距。本次实践在编码过程中发现设置的参数“EncodeHintType.MARGIN”为0时并不生效,许多专业文章也给出了解释是为了优先保证二维码的图形质量所采取的图形横纵比例。也有的文章使用的方式是先生成带白边距的图片,再使用图片放大技术将二维码图片进行一定比例的缩放(放大),虽然一定程度会出现图片的模糊,但可解决白边问题,也是网上很多资料文章中所采取的优先解决方式。

2.实现过程

本次选取的方式是比较简单的一种,直接修改源码,判断当前是否设置了“EncodeHintType.MARGIN”为0,若未设置则不发生任何动作,设置了则使修改的源码生效,参考修改后的源码如下:

2.1 pom.xml坐标 com.google.zxing core 3.5.1 com.google.zxing javase 3.5.1 2.2 源码类QRCodeWriter /* * Copyright 2008 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.zxing.qrcode; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.Writer; import com.google.zxing.WriterException; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.encoder.ByteMatrix; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import com.google.zxing.qrcode.encoder.Encoder; import com.google.zxing.qrcode.encoder.QRCode; import java.util.Map; /** * This object renders a QR Code as a BitMatrix 2D array of greyscale values. * * @author [email protected] (Daniel Switkin) */ public final class QRCodeWriter implements Writer { private static final int QUIET_ZONE_SIZE = 4; @Override public BitMatrix encode(String contents, BarcodeFormat format, int width, int height) throws WriterException { return encode(contents, format, width, height, null); } @Override public BitMatrix encode(String contents, BarcodeFormat format, int width, int height, Map hints) throws WriterException { if (contents.isEmpty()) { throw new IllegalArgumentException("Found empty contents"); } if (format != BarcodeFormat.QR_CODE) { throw new IllegalArgumentException("Can only encode QR_CODE, but got " + format); } if (width < 0 || height < 0) { throw new IllegalArgumentException("Requested dimensions are too small: " + width + 'x' + height); } ErrorCorrectionLevel errorCorrectionLevel = ErrorCorrectionLevel.L; int quietZone = QUIET_ZONE_SIZE; if (hints != null) { if (hints.containsKey(EncodeHintType.ERROR_CORRECTION)) { errorCorrectionLevel = ErrorCorrectionLevel.valueOf(hints.get(EncodeHintType.ERROR_CORRECTION).toString()); } if (hints.containsKey(EncodeHintType.MARGIN)) { quietZone = Integer.parseInt(hints.get(EncodeHintType.MARGIN).toString()); } } QRCode code = Encoder.encode(contents, errorCorrectionLevel, hints); return renderResult(code, width, height, quietZone); } // Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses // 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap). 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); /**1.改动点begin**/ if (quietZone == 0) { outputWidth = qrWidth * multiple; outputHeight = qrWidth * multiple; } /**1.改动点end**/ // Padding includes both the quiet zone and the extra white pixels to accommodate the requested // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone. // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will // handle all the padding from 100x100 (the actual QR) up to 200x160. int leftPadding = (outputWidth - (inputWidth * multiple)) / 2; int topPadding = (outputHeight - (inputHeight * multiple)) / 2; /**2.改动点begin**/ if (quietZone == 0) { leftPadding = 0 ; topPadding = 0; } /**2.改动点end**/ BitMatrix output = new BitMatrix(outputWidth, outputHeight); for (int inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) { // Write the contents of this row of the barcode for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) { if (input.get(inputX, inputY) == 1) { output.setRegion(outputX, outputY, multiple, multiple); } } } return output; } }

说明:源码中修改共涉及两个位置,可参见注释,主要逻辑就是判断传递的MARGIN值是否为0,为0则重设左上角的坐标。

2.3 简单工具类 package cn.chendd.core.utils.zxing; /** * 二维码生成工具类 * * @author chendd * @date 2014/06/06 10:20 */ import com.google.zxing.*; import com.google.zxing.client.j2se.BufferedImageLuminanceSource; import com.google.zxing.client.j2se.ImageReader; import com.google.zxing.client.j2se.MatrixToImageConfig; import com.google.zxing.client.j2se.MatrixToImageWriter; import com.google.zxing.common.BitMatrix; import com.google.zxing.common.HybridBinarizer; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import org.apache.commons.compress.utils.CharsetNames; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; public class BarCodeUtil { /** * * * 对已存在的文件地址进行解码,Copy to 下载的源码中的例子 * * * * @param file 文件路径 * @return 解码后的字符串 * @author chendd, 2014-6-6 上午11:03:01 */ private static String getDecodeText(Path file) { BufferedImage image; try { image = ImageReader.readImage(file.toUri()); } catch (IOException ioe) { return ioe.toString(); } LuminanceSource source = new BufferedImageLuminanceSource(image); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); Result result; try { result = new MultiFormatReader().decode(bitmap); } catch (ReaderException re) { re.printStackTrace(); return re.toString(); } return String.valueOf(result.getText()); } /** * * * 根据文件路径和类型(条形码/二维码等)写入相关文件 * * * * @param contents 写入类型 * @param type 写入的图片类型,如二维码、条形码等等 * @param format 图片格式 * @param width 图片宽度 * @param height 图片高度 * @param writeFile 写入文件 * @throws Exception 抛出异常的爱 * @author chendd, 2014-6-6 下午3:50:39 */ public static void writeToFile(String contents, BarcodeFormat type, String format, int width, int height, File writeFile) throws Exception { BitMatrix matrix = new MultiFormatWriter().encode(contents, type, width, height); MatrixToImageWriter.writeToPath(matrix, format, writeFile.toPath()); } public static void writeToStream(String contents, BarcodeFormat type, String format, int width, int height, OutputStream os) throws Exception { Map mapConfig = new HashMap(); // 用于设置QR二维码参数 // 设置QR二维码的纠错级别(H为最高级别)具体级别信息 mapConfig.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 设置编码方式 mapConfig.put(EncodeHintType.CHARACTER_SET, CharsetNames.UTF_8); mapConfig.put(EncodeHintType.MARGIN, 0); BitMatrix matrix = new MultiFormatWriter().encode(contents, type, width, height , mapConfig); MatrixToImageWriter.writeToStream(matrix, format, os); } /** * 定制二维码输出 * @param content 内容 * @param os 输出流 * @throws Exception 异常处理 */ public static void writeToStream(String content , OutputStream os) throws Exception { BarCodeUtil.writeToStream(content, BarcodeFormat.QR_CODE, "png", 200, 200, os); } } 3.测试验证

PS:虽无白色边距,但是输出的图片大小要比实际设置的图片大小小一圈,这一点现在看来觉得问题不大。

【其它说明】

更多个人经验分享可转至个人博客站点:https://www.chendd.cn

站内文章地址:https://www.chendd.cn/blog/article/1633047307104395266.html



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭