使用zxing和php qrcode生成二维码的二维码为什么不一样

BGAQRCode-Android项目地址:简介:ZXing生成二维码ZXing扫描二维码ZXing识别图库中的二维码图片可以控制闪光灯,方便夜间使用可以定制各式各样的扫描框ZBar扫描二维码「扫描中文会有乱码,如果对中文有要求,请使用ZXing」更多:&&&&&&&&&标签:目录
根据的产品需求,参考
改的,希望能帮助到有生成二维码、扫描二维码、识别图片二维码等需求的猿友。修改幅度较大,也就没准备针对
库提交 PR。
[x] ZXing 生成可自定义颜色、带 logo 的二维码
[x] ZXing 扫描二维码
[x] ZXing 识别图库中的二维码图片
[x] 可以设置用前置摄像头扫描
[x] 可以控制闪光灯,方便夜间使用
[x] 可以定制各式各样的扫描框
[x] 可定制全屏扫描或只识别扫描框区域内的二维码
[x] ZBar 扫描二维码「扫描中文会有乱码,如果对中文有要求,请使用 ZXing」
1.宽高一定要填充除了状态栏以外的其余部分
android:layout_width=&match_parent&
android:layout_height=&match_parent&
2.Gradle 依赖时提示找不到 cn.bingoogolapple:bga-libraryname:「latestVersion」@aar
「latestVersion」指的是左边这个 maven-central 徽章后面的「数字」,请自行替换。请不要再来问我「latestVersion」是什么了
3.ZBar 混淆规则
-keep class net.sourceforge.zbar.** { *; }
-keep interface net.sourceforge.zbar.** { *; }
-dontwarn net.sourceforge.zbar.**
效果图与示例 apk
或扫描下面的二维码安装
或扫描下面的二维码安装
Gradle 依赖
「latestVersion」指的是左边这个 maven-central 徽章后面的「数字」,请自行替换。
dependencies {
compile 'com.google.zxing:core:3.2.1'
compile 'cn.bingoogolapple:bga-qrcodecore:latestVersion@aar'
compile 'cn.bingoogolapple:bga-zxing:latestVersion@aar'
dependencies {
compile 'cn.bingoogolapple:bga-qrcodecore:latestVersion@aar'
compile 'cn.bingoogolapple:bga-zbar:latestVersion@aar'
&cn.bingoogolapple.qrcode.zxing.ZXingView
android:id=&@+id/zxingview&
style=&@style/MatchMatch&
app:qrcv_animTime=&1000&
app:qrcv_borderColor=&@android:color/white&
app:qrcv_borderSize=&1dp&
app:qrcv_cornerColor=&@color/colorPrimaryDark&
app:qrcv_cornerLength=&20dp&
app:qrcv_cornerSize=&3dp&
app:qrcv_maskColor=&#33FFFFFF&
app:qrcv_rectWidth=&200dp&
app:qrcv_scanLineColor=&@color/colorPrimaryDark&
app:qrcv_scanLineSize=&1dp&
app:qrcv_topOffset=&90dp& /&
&cn.bingoogolapple.qrcode.zbar.ZBarView
android:id=&@+id/zbarview&
style=&@style/MatchMatch&
app:qrcv_animTime=&1000&
app:qrcv_borderColor=&@android:color/white&
app:qrcv_borderSize=&1dp&
app:qrcv_cornerColor=&@color/colorPrimaryDark&
app:qrcv_cornerLength=&20dp&
app:qrcv_cornerSize=&3dp&
app:qrcv_isShowDefaultScanLineDrawable=&true&
app:qrcv_maskColor=&#33FFFFFF&
app:qrcv_rectWidth=&200dp&
app:qrcv_scanLineColor=&@color/colorPrimaryDark&
app:qrcv_topOffset=&90dp& /&
自定义属性说明
qrcv_topOffset
扫描框距离 toolbar 底部的距离
qrcv_cornerSize
扫描框边角线的宽度
qrcv_cornerLength
扫描框边角线的长度
qrcv_cornerColor
扫描框边角线的颜色
@android:color/white
qrcv_rectWidth
扫描框的宽度
qrcv_barcodeRectHeight
条码扫样式描框的高度
qrcv_maskColor
除去扫描框,其余部分阴影颜色
qrcv_scanLineSize
扫描线的宽度
qrcv_scanLineColor
扫描线的颜色「扫描线和默认的扫描线图片的颜色」
@android:color/white
qrcv_scanLineMargin
扫描线距离上下或者左右边框的间距
qrcv_isShowDefaultScanLineDrawable
是否显示默认的图片扫描线「设置该属性后 qrcv_scanLineSize 将失效,可以通过 qrcv_scanLineColor 设置扫描线的颜色,避免让你公司的 UI 单独给你出特定颜色的扫描线图片」
qrcv_customScanLineDrawable
扫描线的图片资源「默认的扫描线图片样式不能满足你的需求时使用,设置该属性后 qrcv_isShowDefaultScanLineDrawable、qrcv_scanLineSize、qrcv_scanLineColor 将失效」
qrcv_borderSize
扫描边框的宽度
qrcv_borderColor
扫描边框的颜色
@android:color/white
qrcv_animTime
扫描线从顶部移动到底部的动画时间「单位为毫秒」
qrcv_isCenterVertical
扫描框是否垂直居中,该属性为 true 时会忽略 qrcv_topOffset 属性
qrcv_toolbarHeight
Toolbar 的高度,通过该属性来修正由 Toolbar 导致扫描框在垂直方向上的偏差
qrcv_isBarcode
是否是扫条形码
qrcv_tipText
qrcv_tipTextSize
提示文案字体大小
qrcv_tipTextColor
提示文案颜色
@android:color/white
qrcv_isTipTextBelowRect
提示文案是否在扫描框的底部
qrcv_tipTextMargin
提示文案与扫描框之间的间距
qrcv_isShowTipTextAsSingleLine
是否把提示文案作为单行显示
qrcv_isShowTipBackground
是否显示提示文案的背景
qrcv_tipBackgroundColor
提示文案的背景色
qrcv_isScanLineReverse
扫描线是否来回移动
qrcv_isShowDefaultGridScanLineDrawable
是否显示默认的网格图片扫描线
qrcv_customGridScanLineDrawable
扫描线的网格图片资源
qrcv_isOnlyDecodeScanBoxArea
是否只识别扫描框区域的二维码
QRCodeView
* 设置扫描二维码的代理
* @param delegate 扫描二维码的代理
public void setDelegate(Delegate delegate)
* 显示扫描框
public void showScanRect()
* 隐藏扫描框
public void hiddenScanRect()
* 打开后置摄像头开始预览,但是并未开始识别
public void startCamera()
* 打开指定摄像头开始预览,但是并未开始识别
* @param cameraFacing
Camera.CameraInfo.CAMERA_FACING_BACK or Camera.CameraInfo.CAMERA_FACING_FRONT
public void startCamera(int cameraFacing)
* 关闭摄像头预览,并且隐藏扫描框
public void stopCamera()
* 延迟 1.5 秒后开始识别
public void startSpot()
* 延迟 delay 毫秒后开始识别
* @param delay
public void startSpotDelay(int delay)
* 停止识别
public void stopSpot()
* 停止识别,并且隐藏扫描框
public void stopSpotAndHiddenRect()
* 显示扫描框,并且延迟 1.5 秒后开始识别
public void startSpotAndShowRect()
* 打开闪光灯
public void openFlashlight()
* 关闭散光灯
public void closeFlashlight()
QRCodeView.Delegate
扫描二维码的代理
* 处理扫描结果
* @param result
void onScanQRCodeSuccess(String result)
* 处理打开相机出错
void onScanQRCodeOpenCameraError()
QRCodeDecoder
解析二维码图片。几个重载方法都是耗时操作,请在子线程中调用。
* 同步解析本地图片二维码。该方法是耗时操作,请在子线程中调用。
* @param picturePath 要解析的二维码图片本地路径
* @return 返回二维码图片里的内容 或 null
public static String syncDecodeQRCode(String picturePath)
* 同步解析 bitmap 二维码。该方法是耗时操作,请在子线程中调用。
* @param bitmap 要解析的二维码图片
* @return 返回二维码图片里的内容 或 null
public static String syncDecodeQRCode(Bitmap bitmap)
QRCodeEncoder
创建二维码图片。几个重载方法都是耗时操作,请在子线程中调用。
* 同步创建黑色前景色、白色背景色的二维码图片。该方法是耗时操作,请在子线程中调用。
* @param content 要生成的二维码图片内容
* @param size
图片宽高,单位为 px
public static Bitmap syncEncodeQRCode(String content, int size)
* 同步创建指定前景色、白色背景色的二维码图片。该方法是耗时操作,请在子线程中调用。
* @param content
要生成的二维码图片内容
* @param size
图片宽高,单位为 px
* @param foregroundColor 二维码图片的前景色
public static Bitmap syncEncodeQRCode(String content, int size, int foregroundColor)
* 同步创建指定前景色、白色背景色、带 logo 的二维码图片。该方法是耗时操作,请在子线程中调用。
* @param content
要生成的二维码图片内容
* @param size
图片宽高,单位为 px
* @param foregroundColor 二维码图片的前景色
* @param logo
二维码图片的 logo
public static Bitmap syncEncodeQRCode(String content, int size, int foregroundColor, Bitmap logo)
* 同步创建指定前景色、指定背景色、带 logo 的二维码图片。该方法是耗时操作,请在子线程中调用。
* @param content
要生成的二维码图片内容
* @param size
图片宽高,单位为 px
* @param foregroundColor 二维码图片的前景色
* @param backgroundColor 二维码图片的背景色
* @param logo
二维码图片的 logo
public static Bitmap syncEncodeQRCode(String content, int size, int foregroundColor, int backgroundColor, Bitmap logo)
详细用法请查看:feet:
详细用法请查看:feet:
BGA 系列开源库 QQ 群
如果觉得 BGA 系列开源库对您有用,请随意打赏。
loading自己记录、分享给好友:17794人阅读
二维码相关(6)
首先下载对应的jar包,本实例用的是Zxing2.2jar
下载地址:
Zxing是Google提供的关于条码(一维码、二维码)的解析工具,提供了二维码的生成与解析的方法,
下面看Zxing实例
package com.zxing.
import java.awt.image.BufferedI
import java.io.F
import java.io.IOE
import java.util.HashM
import java.util.M
import javax.imageio.ImageIO;
import com.google.zxing.BarcodeF
import com.google.zxing.B
import com.google.zxing.BinaryB
import com.google.zxing.EncodeHintT
import com.google.zxing.LuminanceS
import com.google.zxing.MultiFormatR
import com.google.zxing.MultiFormatW
import com.google.zxing.R
import com.google.zxing.WriterE
import com.mon.BitM
import com.mon.HybridB
import com.util.BufferedImageLuminanceS
* @Description: (普通二维码生成)
* @author:Relieved
* @date: 下午04:42:35
public class CreateParseCode {
public static void
main(String [] args) throws IOException, WriterException{
CreateParseCode cpCode = new CreateParseCode();
生成二维码
cpCode.createCode();
解析二维码
cpCode.parseCode(new File(&D:/二维码生成/TDC-test.png&));
* 二维码的生成
public void createCode(){
String text = &http://blog.csdn.net/gao36951&;
int width = 300;
int height = 300;
// 二维码的图片格式
String format = &png&;
* 设置二维码的参数
HashMap hints = new HashMap();
// 内容所使用编码
hints.put(EncodeHintType.CHARACTER_SET, &utf-8&);
BitMatrix bitMatrix = new MultiFormatWriter().encode(text,BarcodeFormat.QR_CODE,width,height,hints);
// 生成二维码
File outputFile = new File(&D:&+ File.separator +&二维码生成& + File.separator + &TDC-test.png&);
MatrixToImageWriter.writeToFile(bitMatrix, format, outputFile);
} catch (Exception e) {
e.printStackTrace();
* 二维码的解析
* @param file
public void parseCode(File file)
MultiFormatReader formatReader = new MultiFormatReader();
if (!file.exists())
BufferedImage image = ImageIO.read(file);
LuminanceSource source = new BufferedImageLuminanceSource(image);
Binarizer binarizer = new HybridBinarizer(source);
BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
Map hints = new HashMap();
hints.put(EncodeHintType.CHARACTER_SET, &UTF-8&);
Result result = formatReader.decode(binaryBitmap, hints);
System.out.println(&解析结果 = & + result.toString());
System.out.println(&二维码格式类型 = & + result.getBarcodeFormat());
System.out.println(&二维码文本内容 = & + result.getText());
catch (Exception e)
e.printStackTrace();
生成和解析相关工具类代码:
import com.mon.BitM
import javax.imageio.ImageIO;
import java.io.F
import java.io.OutputS
import java.io.IOE
import java.awt.image.BufferedI
public final class MatrixToImageWriter {
private static final int BLACK = 0xFF000000;
private static final int WHITE = 0xFFFFFFFF;
private MatrixToImageWriter() {}
public static BufferedImage toBufferedImage(BitMatrix matrix) {
int width = matrix.getWidth();
int height = matrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x & x++) {
for (int y = 0; y & y++) {
image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
public static void writeToFile(BitMatrix matrix, String format, File file)
throws IOException {
BufferedImage image = toBufferedImage(matrix);
if (!ImageIO.write(image, format, file)) {
throw new IOException(&Could not write an image of format & + format + & to & + file);
public static void writeToStream(BitMatrix matrix, String format, OutputStream stream)
throws IOException {
BufferedImage image = toBufferedImage(matrix);
if (!ImageIO.write(image, format, stream)) {
throw new IOException(&Could not write an image of format & + format);
package com.
import com.google.zxing.LuminanceS
import java.awt.Graphics2D;
import java.awt.geom.AffineT
import java.awt.image.BufferedI
public final class BufferedImageLuminanceSource extends LuminanceSource {
private final BufferedI
public BufferedImageLuminanceSource(BufferedImage image) {
this(image, 0, 0, image.getWidth(), image.getHeight());
public BufferedImageLuminanceSource(BufferedImage image, int left, int top, int width, int height) {
super(width, height);
int sourceWidth = image.getWidth();
int sourceHeight = image.getHeight();
if (left + width & sourceWidth || top + height & sourceHeight) {
throw new IllegalArgumentException(&Crop rectangle does not fit within image data.&);
for (int y = y & top + y++) {
for (int x = x & left + x++) {
if ((image.getRGB(x, y) & 0xFF000000) == 0) {
image.setRGB(x, y, 0xFFFFFFFF); // = white
this.image = new BufferedImage(sourceWidth, sourceHeight, BufferedImage.TYPE_BYTE_GRAY);
this.image.getGraphics().drawImage(image, 0, 0, null);
this.left =
this.top =
public byte[] getRow(int y, byte[] row) {
if (y & 0 || y &= getHeight()) {
throw new IllegalArgumentException(&Requested row is outside the image: & + y);
int width = getWidth();
if (row == null || row.length & width) {
row = new byte[width];
image.getRaster().getDataElements(left, top + y, width, 1, row);
public byte[] getMatrix() {
int width = getWidth();
int height = getHeight();
int area = width *
byte[] matrix = new byte[area];
image.getRaster().getDataElements(left, top, width, height, matrix);
public boolean isCropSupported() {
public LuminanceSource crop(int left, int top, int width, int height) {
return new BufferedImageLuminanceSource(image, this.left + left, this.top + top, width, height);
public boolean isRotateSupported() {
public LuminanceSource rotateCounterClockwise() {
int sourceWidth = image.getWidth();
int sourceHeight = image.getHeight();
AffineTransform transform = new AffineTransform(0.0, -1.0, 1.0, 0.0, 0.0, sourceWidth);
BufferedImage rotatedImage = new BufferedImage(sourceHeight, sourceWidth, BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g = rotatedImage.createGraphics();
g.drawImage(image, transform, null);
g.dispose();
int width = getWidth();
return new BufferedImageLuminanceSource(rotatedImage, top, sourceWidth - (left + width), getHeight(), width);
生成的二维码如下图:
解析结果如下:
下面看QR CODE实例
package com.qrcode.
* @创建日期
(利用QrCode生成二维码)
* @版本 V 1.0
import java.awt.C
import java.awt.Graphics2D;
import java.awt.image.BufferedI
import java.io.F
import javax.imageio.ImageIO;
import com.swetake.util.Q
* 二维码生成器
public class QRCodeEncoderHandler {
* 生成二维码(QRCode)图片
* @param content
* @param imgPath
public void encoderQRCode(String content, String imgPath,int version) {
Qrcode qrcodeHandler = new Qrcode();
//设置二维码排错率,可选L(7%)、M(15%)、Q(25%)、H(30%),排错率越高可存储的信息越少,但对二维码清晰度的要求越小
qrcodeHandler.setQrcodeErrorCorrect('M');
//N代表数字,A代表字符a-Z,B代表其他字符
qrcodeHandler.setQrcodeEncodeMode('B');
//版本1为21*21矩阵,版本每增1,二维码的两个边长都增4;所以版本7为45*45的矩阵;最高版本为是40,是177*177的矩阵
qrcodeHandler.setQrcodeVersion(version);
int imgSize = 67 + 12 * (version- 1) ;
System.out.println(content);
byte[] contentBytes = content.getBytes(&gb2312&);
BufferedImage bufImg = new BufferedImage(imgSize , imgSize ,BufferedImage.TYPE_INT_RGB);
Graphics2D gs = bufImg.createGraphics();
gs.setBackground(Color.WHITE);
gs.clearRect(0, 0, imgSize , imgSize );
// 设定图像颜色 & BLACK
gs.setColor(Color.BLACK);
// 设置偏移量 不设置可能导致解析出错
int pixoff = 2;
// 输出内容 & 二维码
System.out.println(contentBytes.length);
if (contentBytes.length & 0 && contentBytes.length & 130) {
boolean[][] codeOut = qrcodeHandler.calQrcode(contentBytes);
for (int i = 0; i & codeOut. i++) {
for (int j = 0; j & codeOut. j++) {
if (codeOut[j][i]) {
gs.fillRect(j * 3 + pixoff, i * 3 + pixoff, 3, 3);
System.err.println(&QRCode content bytes length = &
+ contentBytes.length + & not in [ 0,130 ]. &);
gs.dispose();
bufImg.flush();
File imgFile = new File(imgPath);
// 生成二维码QRCode图片
ImageIO.write(bufImg, &png&, imgFile);
} catch (Exception e) {
e.printStackTrace();
* @param args the command line arguments
public static void main(String[] args) {
String imgPath = &D:/二维码生成/Relieved_QRCode.png&;
String content = &http://blog.csdn.net/gao36951&;
QRCodeEncoderHandler handler = new QRCodeEncoderHandler();
handler.encoderQRCode(content, imgPath,8);
System.out.println(&encoder QRcode success&);
生成二维码如下图
解析代码如下:
package com.qrcode.create.
* @创建日期
(解析QrCode二维码)
* @版本 V 1.0
import java.awt.image.BufferedI
import java.io.F
import java.io.IOE
import javax.imageio.ImageIO;
import jp.sourceforge.qrcode.QRCodeD
import jp.sourceforge.qrcode.data.QRCodeI
import jp.sourceforge.qrcode.exception.DecodingFailedE
public class QRCodeDecoderHandler {
* 解码二维码
* @param imgPath
* @return String
public String decoderQRCode(String imgPath) {
// QRCode 二维码图片的文件
File imageFile = new File(imgPath);
BufferedImage bufImg =
String decodedData =
bufImg = ImageIO.read(imageFile);
QRCodeDecoder decoder = new QRCodeDecoder();
decodedData = new String(decoder.decode(new J2SEImage(bufImg)),&gb2312&);
} catch (IOException e) {
System.out.println(&Error: & + e.getMessage());
e.printStackTrace();
} catch (DecodingFailedException dfe) {
System.out.println(&Error: & + dfe.getMessage());
dfe.printStackTrace();
return decodedD
* @param args the command line arguments
public static void main(String[] args) {
QRCodeDecoderHandler handler = new QRCodeDecoderHandler();
String imgPath = &D:/二维码生成/Relieved_QRCode.png&;
String decoderContent = handler.decoderQRCode(imgPath);
System.out.println(&解析结果如下:&);
System.out.println(decoderContent);
System.out.println(&========decoder success!!!&);
class J2SEImage implements QRCodeImage {
BufferedImage bufI
public J2SEImage(BufferedImage bufImg) {
this.bufImg = bufI
public int getWidth() {
return bufImg.getWidth();
public int getHeight() {
return bufImg.getHeight();
public int getPixel(int x, int y) {
return bufImg.getRGB(x, y);
解析结果如下图:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:164187次
积分:2454
积分:2454
排名:第11189名
原创:96篇
转载:33篇
评论:104条
文章:10篇
阅读:2249
阅读:46722
阅读:5104
(4)(4)(4)(5)(4)(4)(6)(5)(4)(4)(4)(4)(4)(4)(4)(4)(4)(5)(5)(2)(6)(13)(11)(3)(6)(6)(1)(1)使用zxing和qrcode生成的二维码为什么不一样_百度知道再见ZXing 使用系统原生代码处理QRCode - 简书
下载简书移动应用
写了31406字,被1174人关注,获得了312个喜欢
再见ZXing 使用系统原生代码处理QRCode
二维码每个人都一定不陌生 尤其是在支付宝和微信的努力下 相信每个人都或多或少的使用过"扫一扫"这个功能而作为开发者 大家都应该有过二维码的开发经验 不管是练习还是研究 或者是公司的项目(尤其是社交类的APP 基本都有扫一扫加好友这个功能吧?)
说到二维码 其实我们现在生活中接触到的都是 --由日本人在上个世纪末用于汽车工业的一项发明 如今在移动互联网发光发亮而实际上 除了QRCode 还有很多二维码的类型 最出名的应该就是了 而在4,5年前 一度还有很多QRCode的竞争对手出现 比如微软推出的 还有个人觉得很有意思的 可是在这几年的发展过程中 还是QRCode笑到了最后 所以现在我们一般提起二维码 就指的是QRCode 下面我们就用QRCode来代替二维码
对于开发人员来说 熟悉的第三方QRCode库有:
Google出品并开源 一直到现在都还有专人维护 是世界上使用最广的二维码库 iOS上比较稳定的移植版是
功能上与ZXing不相伯仲 可惜的是项目在2012年之后就不维护了 虽然代码到现在还可以使用
而我从开始到现在一直是ZXing的忠实用户 除了Google的光环之外 那时候的ZXing资料也比ZBar多很多 不过随着iOS7的发布 苹果推出了内建的二维码扫描功能 这让这些第三方库多少显得有点尴尬了
回到今天的主题上 为什么说要跟ZXing说再见呢? 其实我目前做的项目使用的也是ZXing 不过在开发过程中发现了一些很严重而且绕不过去的问题 比如下面这张图
此处输入图片的描述
如果使用相册读取QRCode的功能 ZXing是无法识别的 不信大家可以去 我也去Github 不过作者也没有给出有效的解决办法 所以只能跟ZXing说88了(不过ZBar是可以扫描出来的哟!)
先分析一下 我们使用QRCode一般都是要做如下几种场景的操作
扫描比如 微信的"扫一扫"加好友
读取比如 微信中长按图片 会弹出"识别图中二维码"这个功能
生成比如 微信的"我的二维码"功能
接下来我们就分三个部分分别来介绍一下如何实现对应的功能(要注意的是 "读取图片"这个功能只有在iOS8以上的系统才能支持 iOS7的话 建议还是使用ZXing或者ZBar)
扫描主要使用的是AVFoundation 使用起来也非常的简单 正常的初始化流程如下
@interface Example1Controller()
AVCaptureMetadataOutputObjectsDelegate,
UIAlertViewDelegate
@property (nonatomic, strong) UIView *scanRectV
@property (strong, nonatomic) AVCaptureDevice
@property (strong, nonatomic) AVCaptureDeviceInput
@property (strong, nonatomic) AVCaptureMetadataOutput
@property (strong, nonatomic) AVCaptureSession
@property (strong, nonatomic) AVCaptureVideoPreviewLayer *
@implementation Example1Controller
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
self.output = [[AVCaptureMetadataOutput alloc]init];
[self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
self.session = [[AVCaptureSession alloc]init];
[self.session setSessionPreset:([UIScreen mainScreen].bounds.size.height&500)?AVCaptureSessionPreset640x480:AVCaptureSessionPresetHigh];
[self.session addInput:self.input];
[self.session addOutput:self.output];
self.output.metadataObjectTypes=@[AVMetadataObjectTypeQRCode];
self.output.rectOfInterest = scanR
self.preview = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
self.preview.videoGravity = AVLayerVideoGravityResizeAspectF
self.preview.frame = [UIScreen mainScreen].
[self.view.layer insertSublayer:self.preview atIndex:0];
//开始捕获
[self.session startRunning];
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
if ( (metadataObjects.count==0) )
if (metadataObjects.count&0) {
[self.session stopRunning];
AVMetadataMachineReadableCodeObject *metadataObject = metadataObjects.firstO
//输出扫描字符串
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:metadataObject.stringValue message:@"" delegate:self cancelButtonTitle:@"ok" otherButtonTitles: nil];
[alert show];
- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
[self.session startRunning];
AVFoundation的部分我就不多介绍了 只要按照上面的代码初始化 即可实现二维码扫描的功能 是不是很简单?
不过这里还不能完全满足我们的要求 因为如果运行以后你会发现 现在是全屏扫描 而不是像我们印象中的那种在屏幕中间有个框 只有在框中的二维码才会被扫描到 不过其实改起来也很简单 AVCaptureMetadataOutput有个属性rectOfInterest就是做这个事情的
@interface AVCaptureMetadataOutput : AVCaptureOutput
@property rectOfInterest
Specifies a rectangle of interest for limiting the search area for visual metadata.
@discussion
The value of this property is a CGRect that determines the receiver's rectangle of interest for each frame of video.
The rectangle's origin is top left and is relative to the coordinate space of the device providing the metadata.
Specifying
a rectOfInterest may improve detection performance for certain types of metadata. The default value of this property is the
value CGRectMake(0, 0, 1, 1).
Metadata objects whose bounds do not intersect with the rectOfInterest will not be returned.
@property(nonatomic) CGRect rectOfInterest NS_AVAILABLE_IOS(7_0);
可以看到 rectOfInterest的值的范围都是0-1 是按比例取值而不是实际尺寸 不过其实也很简单 只要换算一下就好了 接下来我们添加取景框
CGSize windowSize = [UIScreen mainScreen].bounds.
CGSize scanSize = CGSizeMake(windowSize.width*3/4, windowSize.width*3/4);
CGRect scanRect = CGRectMake((windowSize.width-scanSize.width)/2, (windowSize.height-scanSize.height)/2, scanSize.width, scanSize.height);
//计算rectOfInterest 注意x,y交换位置
scanRect = CGRectMake(scanRect.origin.y/windowSize.height, scanRect.origin.x/windowSize.width, scanRect.size.height/windowSize.height,scanRect.size.width/windowSize.width);
self.output.rectOfInterest = scanR
self.scanRectView = [UIView new];
[self.view addSubview:self.scanRectView];
self.scanRectView.frame = CGRectMake(0, 0, scanSize.width, scanSize.height);
self.scanRectView.center = CGPointMake(CGRectGetMidX([UIScreen mainScreen].bounds), CGRectGetMidY([UIScreen mainScreen].bounds));
self.scanRectView.layer.borderColor = [UIColor redColor].CGC
self.scanRectView.layer.borderWidth = 1;
这里唯一要注意的一点是 rectOfInterest 都是按照横屏来计算的 所以当竖屏的情况下 x轴和y轴要交换一下
看看实际效果
读取主要用到CoreImage 不过要强调的是读取二维码的功能只有在iOS8之后才支持读取的代码实现就更简单了
UIImage * srcImage = qrcodeI
CIContext *context = [CIContext contextWithOptions:nil];
CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:context options:@{CIDetectorAccuracy:CIDetectorAccuracyHigh}];
CIImage *image = [CIImage imageWithCGImage:srcImage.CGImage];
NSArray *features = [detector featuresInImage:image];
CIQRCodeFeature *feature = [features firstObject];
NSString *result = feature.messageS
看看实际效果
生成也是用到CoreImage 其步骤稍微多一点 代码如下
NSString *text = self.tfCode.
NSData *stringData = [text dataUsingEncoding: NSUTF8StringEncoding];
CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
[qrFilter setValue:stringData forKey:@"inputMessage"];
[qrFilter setValue:@"M" forKey:@"inputCorrectionLevel"];
UIColor *onColor = [UIColor redColor];
UIColor *offColor = [UIColor blueColor];
CIFilter *colorFilter = [CIFilter filterWithName:@"CIFalseColor"
keysAndValues:
@"inputImage",qrFilter.outputImage,
@"inputColor0",[CIColor colorWithCGColor:onColor.CGColor],
@"inputColor1",[CIColor colorWithCGColor:offColor.CGColor],
CIImage *qrImage = colorFilter.outputI
CGSize size = CGSizeMake(300, 300);
CGImageRef cgImage = [[CIContext contextWithOptions:nil] createCGImage:qrImage fromRect:qrImage.extent];
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetInterpolationQuality(context, kCGInterpolationNone);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage);
UIImage *codeImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGImageRelease(cgImage);
首先通过[CIFilter filterWithName:@"CIQRCodeGenerator"]生成QRCode
然后通过[CIFilter filterWithName:@"CIFalseColor"]上色(当然这一步不是必须的 如果仅仅需要白底黑块的QRCode 可以跳过这一步)
最后无损放大并绘制QRCode (上面两步生成的QRCode很小 大概是31*31 如果不放大 就会很模糊)
这里要注意的是 在最后一步一定要使用CGContextScaleCTM(context, 1.0, -1.0)来翻转一下图片 不然生成的QRCode就是上下颠倒的哦
看看实际效果
源码和Demo请点
如果不需要对QRCode进行深入的探索的话 相信各位看完本文后 绝大多数的关于QRCode的使用问题 应该都可以迎刃而解了 如果需要进一步了解QRCode的原理 我推荐陈皓的这篇
最后 祝大家国庆愉快 不要加班哟~~~
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
被以下专题收入,发现更多相似内容:
· 7087人关注
· 2045人关注
纪录开发的点点滴滴,相互学习,共同进步~
专题内容主要包括Object-C、Swift等开发技巧以及学习过程的内容
· 2030人关注
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
选择支付方式:

我要回帖

更多关于 ios qrcode生成二维码 的文章

 

随机推荐