Zxing 生成二维码和条形码去掉白边
源码下载:
https://github.com/AndroidZmm123/ZxingApplication
需求:根据输入内容,生成条形码或者二维码。
我们大多数会选择Zxing。因为jar包较小。且使用简单。根据内容生成二维码的工具类也是一搜一大堆。上面的源码里面也提供了一个。但是我们仔细看了下。会发现。不管生成的是条形码还是二维码都会有一部分的白边。如图:
我们可以看到周围有白边。那我们怎么去掉呢。
我们先把zxing的源码下载下来。然后看下这个白边是如果产生的。
首先是二维码的。
BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, widthPix,
heightPix, hints);
这是根据我们输入的内容。产生一个矩阵。我们可以看到QRCodeWriter的encode()方法里面的最后两行:
QRCode code = Encoder.encode(contents, errorCorrectionLevel, hints);
return renderResult(code, width, height, quietZone);
第一句是将我们输入的内容转换成code.不涉及宽高。
第二句是将code转换成矩阵。加入白边的代码就在这里面。
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 qrWidth = inputWidth;
int qrHeight = inputHeight;
int outputWidth = Math.max(width, qrWidth);
int outputHeight = Math.max(height, qrHeight);
int multiple = Math.min(outputWidth / qrWidth, outputHeight / qrHeight);
// 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;
//修改--》去掉间距
int leftPadding = 0;
int topPadding = 0;
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;
}
这样就二维码的白边就去掉了。
效果图:
再来看条形码的。条形码的修改稍微麻烦点。
条形码的解析类是:Code128Writer。进去同样可以找到encode()。调用的是父类的encode()。
int sidesMargin = getDefaultMargin();
if (hints != null && hints.containsKey(EncodeHintType.MARGIN)) {
sidesMargin = Integer.parseInt(hints.get(EncodeHintType.MARGIN).toString());
}
boolean[] code = encode(contents);
return renderResult(code, width, height, sidesMargin);
这里有个sideMargin..emmm。看着像是白边的大小的样子。我试着先把这个值修改为0.默认是10.修改以后。运行起来可以发现。还是有白边。看来这不是全部。看下renderResult()方法。
/**
* @return a byte array of horizontal pixels (0 = white, 1 = black)
*/
private static BitMatrix renderResult(boolean[] code, int width, int height, int sidesMargin) {
int inputWidth = code.length;
// Add quiet zone on both sides.
int fullWidth = inputWidth + sidesMargin;
int outputWidth = Math.max(width, fullWidth);
int outputHeight = Math.max(1, height);
int multiple = outputWidth / fullWidth;
Log.e("zmm", outputWidth + "renderResult-->" + inputWidth + "--->" + multiple);
int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
Log.e("zmm", "间距----------->" + leftPadding);
BitMatrix output = new BitMatrix(outputWidth, outputHeight);
for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX +=
multiple) {
if (code[inputX]) {
output.setRegion(outputX, 0, multiple, outputHeight);
}
}
return output;
}
我们可以看到leftPadding。我试着把这个值修改为0.发现还是不行,有白边。
仔细看下。这个规则。我们的宽度是700px.我们刚刚已经把sideMargin修改成0了。所以
fullWidth=700;
inputWidth:是根据我们的内容根据128编码生成的一个数组的长度。我们输入1234567890:这里的inputWidth:90
multiple=700/90=7.77777;但是这里是int。所以multiple=7;这就产生了误差。multiple看成是竖线之间的增量。也就是,第一个竖线坐标是0,第二个竖线就应该在0+multiple的位置,以此类推。总共有90个竖线。那90*7<700.那还剩下的70.就只能平分当做左右的白边。
leftPadding=(outputWidth - (inputWidth * multiple)) / 2;也就是(700-90*7)/2=35.所以我们算出白边应该是35。
这样一下来我们就知道该怎么修改这个长度了。我们值修改leftPadding=0的话。那就会剩下70的空白。所以。不行。我们要做的事修改原始的图片大小。故修改成:
/**
* @return a byte array of horizontal pixels (0 = white, 1 = black)
*/
private static BitMatrix renderResult(boolean[] code, int width, int height, int sidesMargin) {
int inputWidth = code.length;
// Add quiet zone on both sides.
int fullWidth = inputWidth + sidesMargin;
int outputWidth = Math.max(width, fullWidth);
int outputHeight = Math.max(1, height);
int multiple = outputWidth / fullWidth;
//先判断是不是可以整除。如果可以整除。那leftPadding肯定为0,就不需要修改。
// 如果不能整除。需要把原始的大小修改成outputWidth = multiple * fullWidth;这样以后。leftPadding也就为0了。
if (outputHeight % fullWidth != 0) {
outputWidth = multiple * fullWidth;
}
Log.e("zmm", outputWidth + "renderResult-->" + inputWidth + "--->" + multiple);
int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
Log.e("zmm", "间距----------->" + leftPadding);
BitMatrix output = new BitMatrix(outputWidth, outputHeight);
for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX +=
multiple) {
if (code[inputX]) {
output.setRegion(outputX, 0, multiple, outputHeight);
}
}
return output;
}
这样以后。我们还需要在生成条形码那里把真实大小修改成我们改过以后的。也就是:
/**
* 绘制条形码
*
* @param content 要生成条形码包含的内容
* @param widthPix 条形码的宽度
* @param heightPix 条形码的高度
* @param isShowContent 否则显示条形码包含的内容
* @return 返回生成条形的位图
*/
public static Bitmap createBarcode(String content, int widthPix, int heightPix, boolean isShowContent) {
if (TextUtils.isEmpty(content)) {
return null;
}
//配置参数
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
// 容错级别 这里选择最高H级别
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
MultiFormatWriter writer = new MultiFormatWriter();
try {
// 图像数据转换,使用了矩阵转换 参数顺序分别为:编码内容,编码类型,生成图片宽度,生成图片高度,设置参数
BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.CODE_128, widthPix, heightPix, hints);
//增加:把宽度修改我们修改过后的真实的宽度
widthPix = bitMatrix.getWidth();
// Log.e("zmm", "---------->" + widthPix + "--->" + height);
int[] pixels = new int[widthPix * heightPix];
// 下面这里按照条形码的算法,逐个生成条形码的图片,
// 两个for循环是图片横列扫描的结果
for (int y = 0; y < heightPix; y++) {
for (int x = 0; x < widthPix; x++) {
if (bitMatrix.get(x, y)) {
pixels[y * widthPix + x] = 0xff000000; // 黑色
} else {
pixels[y * widthPix + x] = 0xffffffff;// 白色
}
}
}
Bitmap bitmap = Bitmap.createBitmap(widthPix, heightPix, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, widthPix, 0, 0, widthPix, heightPix);
if (isShowContent) {
bitmap = showContent(bitmap, content);
}
return bitmap;
} catch (WriterException e) {
e.printStackTrace();
}
return null;
}
运行看下效果:
至此百边就去掉了。当然这样不好看。你也可以。自己来定一个固定的白边的宽度。我觉得还是不要去掉的比较好。因为。毕竟zxing这样设计肯定有一定的原因。
每日语录:
看到一个故事叫“刻舟求剑”,心里觉得这个人好傻,世上怎么会有这样的人,难道不知道剑在江*掉下了水,跑到江边是找不到的?然而长大后发现,在这条岁月的长河里,很多人在某个节点遗失的东西,之后一次又一次返回寻找,却不知道自己只是站在船边徘徊,江*已经回不去了。看到一个故事叫“掩耳盗铃”,心里想,这又是一个傻瓜,捂着耳朵偷东西骗的了谁?然而长大后发现,自己和同学一起逃课、一起抄作业、一起考试作弊,一起做许多明知道不应该做却克制不住自己的事情。没有被抓到就沾沾自喜,其实警告的铃声早已响起,只是自己捂着耳朵假装听不到。看到一个故事叫“朝三暮四”,心里偷笑,这群猴子怎么如此好骗,明明就是七个栗子,早晨三个晚上四个变成早晨四个晚上三个就一个个被哄得服服帖帖。然而长大后发现,女孩儿被渣男伤害,对面一个道歉就还是原谅了他;商家使个小小的心眼儿,几块钱红包就引得全国人趋之若鹜……我们不比猴子聪明多少。看到一个故事叫“削足适履”,心里哀叹,怎么会有这样的蠢人,居然会蠢到砍自己的脚去适应鞋子,换一双鞋子就那么难吗?然而长大后发现,明明知道自己的权益被损害,明明知道这样的环境和体系并不科学,然而在这其中的每个人却都默不作声,甘心忍受。看到一个故事叫“邯郸学步”,心里崩溃,为什么成语故事里的人一个比一个傻?别人走路姿势好看就去模仿,到了最后居然忘了自己怎么走路?然而长大后却发现,这个世界的确被一股股潮流所带领,今天“假装生活”,明天“佛系青年”;今天都在比拼“跳一跳”,明天都在晒“养青蛙”。现在谁能想象,自己扔掉手机生活的样子?原来,成语中那些傻事儿可能没有人会去干,但是,成语里那些傻瓜,却是真实地存在着 ---------------------------------来自知乎(作者:雾雨之灵)
单曲循环《曾经的你》第一次找工作那段时间天天听。。因为太迷茫了。太惶恐了。听着这首歌。沿着一条路。一直走。一直走。想把以后的路想明白,想清楚。其实。。根本毫无用处。路都是走着走着就明白了。愿看到这段话的你。可以少些苦恼。少些惶恐。加油!!!
上一篇: MySQL连接Java
下一篇: java连接mysql