Android利用zxing生成二维码,识别二维码,中间填充图片超详细、超简易教程

https://blog.csdn.net/mountain_hua/article/details/80646089

gayhub上的zxing可用于生成二维码,识别二维码
gayhub地址:https://github.com/zxing/zxing
此文只是简易教程,文末附有完整代码和demo下载地址,进入正题:

(1)下载并导入zxing.jar包

下载:

zxing.jar下载地址,只需要1积分,方便大家学习下载。

把下载好的zxing.jar放在app的libs文件夹内,如图

导入:

进入project structure.如图

点进去之后,依次进入app——Dependencies——jar dependency:

选择zxing.jar,导入

 

(2)生成二维码:

生成二维码的函数:

 
  1. public void createQRcodeImage(String url)

  2. {

  3. im1=(ImageView)findViewById(R.id.imageView);

  4. w=im1.getWidth();

  5. h=im1.getHeight();

  6. try

  7. {

  8. //判断URL合法性

  9. if (url == null || "".equals(url) || url.length() < 1)

  10. {

  11. return;

  12. }

  13. Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();

  14. hints.put(EncodeHintType.CHARACTER_SET, "utf-8");

  15. //图像数据转换,使用了矩阵转换

  16. BitMatrix bitMatrix = new QRCodeWriter().encode(url, BarcodeFormat.QR_CODE, w, h, hints);

  17. int[] pixels = new int[w * h];

  18. //下面这里按照二维码的算法,逐个生成二维码的图片,

  19. //两个for循环是图片横列扫描的结果

  20. for (int y = 0; y < h; y++)

  21. {

  22. for (int x = 0; x < w; x++)

  23. {

  24. if (bitMatrix.get(x, y))

  25. {

  26. pixels[y * w + x] = 0xff000000;

  27. }

  28. else

  29. {

  30. pixels[y * w + x] = 0xffffffff;

  31. }

  32. }

  33. }

  34. //生成二维码图片的格式,使用ARGB_8888

  35. Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);

  36. bitmap.setPixels(pixels, 0, w, 0, 0, w, h);

  37. //显示到我们的ImageView上面

  38. im1.setImageBitmap(bitmap);

  39. }

  40. catch (WriterException e)

  41. {

  42. e.printStackTrace();

  43. }

  44. }

设置两种转换方式,默认转换/自定义转换:

 
  1.         Button bt=(Button)findViewById(R.id.button);

  2. bt.setOnClickListener(new View.OnClickListener() {

  3. @Override

  4. public void onClick(View v) {

  5. createQRcodeImage("https://blog.csdn.net/mountain_hua");//url为我的csdn博客地址

  6. }

  7. });

  8.  
  9. Button bt2=(Button)findViewById(R.id.button2);

  10. bt2.setOnClickListener(new View.OnClickListener() {

  11. @Override

  12. public void onClick(View v) {

  13. EditText editText=(EditText)findViewById(R.id.editText);

  14. createQRcodeImage(editText.getText().toString());//自定义转换内容

  15. }

  16. });

默认转换为我的博客:                                                    自定义转换:

二维码转换出来了,可以拿手机扫一扫试一试。

 

(3)识别二维码

识别二维码需要一个RGBLuminanceSource类:

 
  1. //识别图片所需要的RGBLuminanceSource类

  2. public class RGBLuminanceSource extends LuminanceSource {

  3.  
  4. private byte bitmapPixels[];

  5.  
  6. protected RGBLuminanceSource(Bitmap bitmap) {

  7. super(bitmap.getWidth(), bitmap.getHeight());

  8.  
  9. // 首先,要取得该图片的像素数组内容

  10. int[] data = new int[bitmap.getWidth() * bitmap.getHeight()];

  11. this.bitmapPixels = new byte[bitmap.getWidth() * bitmap.getHeight()];

  12. bitmap.getPixels(data, 0, getWidth(), 0, 0, getWidth(), getHeight());

  13.  
  14. // 将int数组转换为byte数组,也就是取像素值中蓝色值部分作为辨析内容

  15. for (int i = 0; i < data.length; i++) {

  16. this.bitmapPixels[i] = (byte) data[i];

  17. }

  18. }

  19.  
  20. @Override

  21. public byte[] getMatrix() {

  22. // 返回我们生成好的像素数据

  23. return bitmapPixels;

  24. }

  25.  
  26. @Override

  27. public byte[] getRow(int y, byte[] row) {

  28. // 这里要得到指定行的像素数据

  29. System.arraycopy(bitmapPixels, y * getWidth(), row, 0, getWidth());

  30. return row;

  31. }

  32. }

  33.  

识别二维码的函数:

 
  1.      //识别二维码的函数

  2. public void recogQRcode(ImageView imageView){

  3. Bitmap QRbmp = ((BitmapDrawable) (imageView).getDrawable()).getBitmap(); //将图片bitmap化

  4. int width = QRbmp.getWidth();

  5. int height = QRbmp.getHeight();

  6. int[] data = new int[width * height];

  7. QRbmp.getPixels(data, 0, width, 0, 0, width, height); //得到像素

  8. RGBLuminanceSource source = new RGBLuminanceSource(QRbmp); //RGBLuminanceSource对象

  9. BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));

  10. QRCodeReader reader = new QRCodeReader();

  11. Result re = null;

  12. try {

  13. //得到结果

  14. re = reader.decode(bitmap1);

  15. } catch (NotFoundException e) {

  16. e.printStackTrace();

  17. } catch (ChecksumException e) {

  18. e.printStackTrace();

  19. } catch (FormatException e) {

  20. e.printStackTrace();

  21. }

  22. //Toast出内容

  23. Toast.makeText(MainActivity.this,re.getText(),Toast.LENGTH_SHORT).show();

  24.  
  25. //利用正则表达式判断内容是否是URL,是的话则打开网页

  26. String regex = "(((https|http)?://)?([a-z0-9]+[.])|(www.))"

  27. + "\\w+[.|\\/]([a-z0-9]{0,})?[[.]([a-z0-9]{0,})]+((/[\\S&&[^,;\u4E00-\u9FA5]]+)+)?([.][a-z0-9]{0,}+|/?)";//设置正则表达式

  28.  
  29. Pattern pat = Pattern.compile(regex.trim());//比对

  30. Matcher mat = pat.matcher(re.getText().trim());

  31. if (mat.matches()){

  32. Uri uri = Uri.parse(re.getText());

  33. Intent intent = new Intent(Intent.ACTION_VIEW, uri);//打开浏览器

  34. startActivity(intent);

  35. }

  36.  
  37. }

下面看识别效果:

这是识别URL的结果:                                        这是识别一般文字的结果:

 

(4)完整代码:

Mainactivity:

 
  1. package mountain_hua.learn_zxing;

  2.  
  3. import android.content.Intent;

  4. import android.graphics.Bitmap;

  5. import android.graphics.drawable.BitmapDrawable;

  6. import android.net.Uri;

  7. import android.support.v7.app.AppCompatActivity;

  8. import android.os.Bundle;

  9. import android.view.View;

  10. import android.widget.Button;

  11. import android.widget.EditText;

  12. import android.widget.ImageView;

  13. import android.widget.Toast;

  14.  
  15. import com.google.zxing.BarcodeFormat;

  16. import com.google.zxing.BinaryBitmap;

  17. import com.google.zxing.ChecksumException;

  18. import com.google.zxing.EncodeHintType;

  19. import com.google.zxing.FormatException;

  20. import com.google.zxing.LuminanceSource;

  21. import com.google.zxing.NotFoundException;

  22. import com.google.zxing.Result;

  23. import com.google.zxing.WriterException;

  24. import com.google.zxing.common.BitMatrix;

  25. import com.google.zxing.common.HybridBinarizer;

  26. import com.google.zxing.qrcode.QRCodeReader;

  27. import com.google.zxing.qrcode.QRCodeWriter;

  28.  
  29. import java.util.Hashtable;

  30. import java.util.regex.Matcher;

  31. import java.util.regex.Pattern;

  32.  
  33. public class MainActivity extends AppCompatActivity {

  34.  
  35. private ImageView im1; //imageview图片

  36. private int w,h; //图片宽度w,高度h

  37. @Override

  38. protected void onCreate(Bundle savedInstanceState) {

  39. super.onCreate(savedInstanceState);

  40. setContentView(R.layout.activity_main);

  41.  
  42. Button bt=(Button)findViewById(R.id.button);

  43. bt.setOnClickListener(new View.OnClickListener() {

  44. @Override

  45. public void onClick(View v) {

  46. createQRcodeImage("https://blog.csdn.net/mountain_hua");//url为我的csdn博客地址

  47. }

  48. });

  49.  
  50. Button bt2=(Button)findViewById(R.id.button2);

  51. bt2.setOnClickListener(new View.OnClickListener() {

  52. @Override

  53. public void onClick(View v) {

  54. EditText editText=(EditText)findViewById(R.id.editText);

  55. createQRcodeImage(editText.getText().toString());//自定义转换内容

  56. }

  57. });

  58.  
  59. Button bt3=(Button)findViewById(R.id.button3);

  60. bt3.setOnClickListener(new View.OnClickListener() {

  61. @Override

  62. public void onClick(View v) {

  63. im1=(ImageView)findViewById(R.id.imageView);

  64. recogQRcode(im1);

  65. }

  66. });

  67.  
  68. }

  69.  
  70. //转换成二维码QRcode的函数。参数为一个字符串

  71. public void createQRcodeImage(String url)

  72. {

  73. im1=(ImageView)findViewById(R.id.imageView);

  74. w=im1.getWidth();

  75. h=im1.getHeight();

  76. try

  77. {

  78. //判断URL合法性

  79. if (url == null || "".equals(url) || url.length() < 1)

  80. {

  81. return;

  82. }

  83. Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();

  84. hints.put(EncodeHintType.CHARACTER_SET, "utf-8");

  85. //图像数据转换,使用了矩阵转换

  86. BitMatrix bitMatrix = new QRCodeWriter().encode(url, BarcodeFormat.QR_CODE, w, h, hints);

  87. int[] pixels = new int[w * h];

  88. //下面这里按照二维码的算法,逐个生成二维码的图片,

  89. //两个for循环是图片横列扫描的结果

  90. for (int y = 0; y < h; y++)

  91. {

  92. for (int x = 0; x < w; x++)

  93. {

  94. if (bitMatrix.get(x, y))

  95. {

  96. pixels[y * w + x] = 0xff000000;

  97. }

  98. else

  99. {

  100. pixels[y * w + x] = 0xffffffff;

  101. }

  102. }

  103. }

  104. //生成二维码图片的格式,使用ARGB_8888

  105. Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);

  106. bitmap.setPixels(pixels, 0, w, 0, 0, w, h);

  107. //显示到我们的ImageView上面

  108. im1.setImageBitmap(bitmap);

  109. }

  110. catch (WriterException e)

  111. {

  112. e.printStackTrace();

  113. }

  114. }

  115.  
  116. //识别二维码的函数

  117. public void recogQRcode(ImageView imageView){

  118. Bitmap QRbmp = ((BitmapDrawable) (imageView).getDrawable()).getBitmap(); //将图片bitmap化

  119. int width = QRbmp.getWidth();

  120. int height = QRbmp.getHeight();

  121. int[] data = new int[width * height];

  122. QRbmp.getPixels(data, 0, width, 0, 0, width, height); //得到像素

  123. RGBLuminanceSource source = new RGBLuminanceSource(QRbmp); //RGBLuminanceSource对象

  124. BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));

  125. QRCodeReader reader = new QRCodeReader();

  126. Result re = null;

  127. try {

  128. //得到结果

  129. re = reader.decode(bitmap1);

  130. } catch (NotFoundException e) {

  131. e.printStackTrace();

  132. } catch (ChecksumException e) {

  133. e.printStackTrace();

  134. } catch (FormatException e) {

  135. e.printStackTrace();

  136. }

  137. //Toast出内容

  138. Toast.makeText(MainActivity.this,re.getText(),Toast.LENGTH_SHORT).show();

  139.  
  140. //利用正则表达式判断内容是否是URL,是的话则打开网页

  141. String regex = "(((https|http)?://)?([a-z0-9]+[.])|(www.))"

  142. + "\\w+[.|\\/]([a-z0-9]{0,})?[[.]([a-z0-9]{0,})]+((/[\\S&&[^,;\u4E00-\u9FA5]]+)+)?([.][a-z0-9]{0,}+|/?)";//设置正则表达式

  143.  
  144. Pattern pat = Pattern.compile(regex.trim());//比对

  145. Matcher mat = pat.matcher(re.getText().trim());

  146. if (mat.matches()){

  147. Uri uri = Uri.parse(re.getText());

  148. Intent intent = new Intent(Intent.ACTION_VIEW, uri);//打开浏览器

  149. startActivity(intent);

  150. }

  151.  
  152. }

  153.  
  154. //识别图片所需要的RGBLuminanceSource类

  155. public class RGBLuminanceSource extends LuminanceSource {

  156.  
  157. private byte bitmapPixels[];

  158.  
  159. protected RGBLuminanceSource(Bitmap bitmap) {

  160. super(bitmap.getWidth(), bitmap.getHeight());

  161.  
  162. // 首先,要取得该图片的像素数组内容

  163. int[] data = new int[bitmap.getWidth() * bitmap.getHeight()];

  164. this.bitmapPixels = new byte[bitmap.getWidth() * bitmap.getHeight()];

  165. bitmap.getPixels(data, 0, getWidth(), 0, 0, getWidth(), getHeight());

  166.  
  167. // 将int数组转换为byte数组,也就是取像素值中蓝色值部分作为辨析内容

  168. for (int i = 0; i < data.length; i++) {

  169. this.bitmapPixels[i] = (byte) data[i];

  170. }

  171. }

  172.  
  173. @Override

  174. public byte[] getMatrix() {

  175. // 返回我们生成好的像素数据

  176. return bitmapPixels;

  177. }

  178.  
  179. @Override

  180. public byte[] getRow(int y, byte[] row) {

  181. // 这里要得到指定行的像素数据

  182. System.arraycopy(bitmapPixels, y * getWidth(), row, 0, getWidth());

  183. return row;

  184. }

  185. }

  186.  
  187. }

布局文件activity_main:

 
  1. <?xml version="1.0" encoding="utf-8"?>

  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

  3. xmlns:app="http://schemas.android.com/apk/res-auto"

  4. android:orientation="vertical" android:layout_width="match_parent"

  5. android:layout_height="match_parent">

  6.  
  7. <ImageView

  8. android:id="@+id/imageView"

  9. android:layout_width="300dp"

  10. android:layout_height="300dp"

  11. app:srcCompat="@android:color/background_light" />

  12.  
  13. <Button

  14. android:id="@+id/button"

  15. android:layout_width="match_parent"

  16. android:layout_height="wrap_content"

  17. android:textAllCaps="false"

  18. android:text="转换成二维码(mountain_hua的博客)" />

  19.  
  20. <EditText

  21. android:id="@+id/editText"

  22. android:layout_width="match_parent"

  23. android:layout_height="wrap_content"

  24. android:ems="10"

  25. android:hint="输入要转换的内容"

  26. android:inputType="textPersonName" />

  27.  
  28. <Button

  29. android:id="@+id/button2"

  30. android:layout_width="match_parent"

  31. android:layout_height="wrap_content"

  32. android:text="自定义转换" />

  33.  
  34. <Button

  35. android:id="@+id/button3"

  36. android:layout_width="match_parent"

  37. android:layout_height="wrap_content"

  38. android:text="识别二维码" />

  39. </LinearLayout>

demo下载地址:https://download.csdn.net/download/mountain_hua/10471127

本文参考:

https://www.jianshu.com/p/20db116b6279

https://blog.csdn.net/qq_29634351/article/details/78688315

http://www.cnblogs.com/mythou/p/3280023.html

https://www.2cto.com/kf/201603/495847.html

 

续:在二维码中间填充图片logo

首先说明,二维码是有一定的纠错功能的,二维条码因穿孔、污损等引起局部损坏时,照样可以正确得到识读,损毁面积达30%仍可恢复信息。但三个角上的“回”字及周围的底色不要改变,这是用于二维码定位的,最好是填充图片在中间,越小越好。

下面进入正题:

填充图片函数:

 
  1. //给二维码添加图片

  2. //第一个参数为原二维码,第二个参数为添加的logo

  3. private static Bitmap addLogo(Bitmap src, Bitmap logo) {

  4. //如果原二维码为空,返回空

  5. if (src ==null ) {

  6. return null;

  7. }

  8. //如果logo为空,返回原二维码

  9. if (src ==null ||logo ==null) {

  10. return src;

  11. }

  12.  
  13. //这里得到原二维码bitmap的数据

  14. int srcWidth = src.getWidth();

  15. int srcHeight = src.getHeight();

  16. //logo的Width和Height

  17. int logoWidth = logo.getWidth();

  18. int logoHeight = logo.getHeight();

  19.  
  20. //同样如果为空,返回空

  21. if (srcWidth == 0 || srcHeight == 0) {

  22. return null;

  23. }

  24. //同样logo大小为0,返回原二维码

  25. if (logoWidth == 0 || logoHeight == 0) {

  26. return src;

  27. }

  28.  
  29. //logo大小为二维码整体大小的1/5,也可以自定义多大,越小越好

  30. //二维码有一定的纠错功能,中间图片越小,越容易纠错

  31. float scaleFactor = srcWidth * 1.0f / 5 / logoWidth;

  32. Bitmap bitmap = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888);

  33. try {

  34. Canvas canvas = new Canvas(bitmap);

  35. canvas.drawBitmap(src, 0, 0, null);

  36. canvas.scale(scaleFactor, scaleFactor, srcWidth / 2, srcHeight / 2);

  37. canvas.drawBitmap(logo, (srcWidth - logoWidth) / 2, (srcHeight - logoHeight) / 2,null );

  38.  
  39. canvas.save(Canvas.ALL_SAVE_FLAG);

  40. canvas.restore();

  41. } catch (Exception e) {

  42. bitmap = null;

  43. e.getStackTrace();

  44. }

  45.  
  46. return bitmap;

  47. }

然后在button中设置监听:

 
  1. Button bt4=(Button)findViewById(R.id.button4);

  2. bt4.setOnClickListener(new View.OnClickListener() {

  3. @Override

  4. public void onClick(View v) {

  5. im1=(ImageView)findViewById(R.id.imageView);

  6. Bitmap QRbmp = ((BitmapDrawable) (im1).getDrawable()).getBitmap(); //将图片bitmap化

  7. //将drawable里面的图片bitmap化

  8. Bitmap logo = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);

  9. im1.setImageBitmap(addLogo(QRbmp,logo));

  10. }

  11. });

效果如下:

附完整版demo(带填充图片):https://download.csdn.net/download/mountain_hua/10473011

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值