Java—二维码生成与识别(一)

一、二维码生成

思路:将字符串中的每个字符转为二进制码字符串,保存在二进制码字符串数组中。对二进制码字符串数组中的每个二进制码字符串进行字符遍历,若是‘0’,则设置画笔颜色为白色,若是‘1’,则设置画笔颜色为黑色。最后绘制图片。

例如,生成字符串"http://bilibili.com"的二维码

1、将字符串中的每个字符转为二进码字符串

String str="http://bilibili.com";
for(int i=0;i<str.length();i++) {
			char c=str.charAt(i);//获取字符串中的每个字符
			String binarystring=Integer.toBinaryString(c);//将字符转为而二进码字符串

此时我们打印输出二进码字符串,会发现输出的二进制数不规则,有7bit也有8bit的。所以我们需要对不足8bit的二进数前面补‘0’,使得到的二进数都是8bit的,然后再将其保存到数组中。

//补码 在二进制数不足8个bit的前面补0
			while(binarystring.length()<8) {
				binarystring=0+binarystring;	
			}

2、保存在二进制码字符串数组中

String[] Binarystring=new String[str.length()];//定义一个一维数组
for(int j=0;j<str.length();j++) {
				Binarystring[i]=binarystring;
			}

3、遍历二进制码字符串中的字符,设置画笔颜色,绘制图片

for(int i=0;i<binarystring.length;i++) {
			String str=binarystring[i];
			for(int j=0;j<str.length();j++) {
				char c=str.charAt(j);
				if(c=='0') {
					g.setColor(Color.white);
				}else {
					g.setColor(Color.black);
				}
				g.fillRect(200+i*10, 100+j*10, 10, 10);
			}
		}
		
	}

 4、完整代码

QRcode类:将字符串转换为二进码字符串,创建保存二进码字符串数组

public class QRcode {
	String str="http://bilibili.com";
	String[] Binarystring=new String[str.length()];//定义一个一维数组
	public String[] tobinarystring() {
		for(int i=0;i<str.length();i++) {
			char c=str.charAt(i);//获取字符串中的每个字符
			String binarystring=Integer.toBinaryString(c);//字符转为二进制码字符串
			//System.out.println(binarystring);//输出的二进制不规则 有7个bit也有8个bit
			//补码 在二进制数不足8个bit的前面补0
			while(binarystring.length()<8) {
				binarystring=0+binarystring;	
			}
			//此时二进制数都是8个bit 需将这些二进数存储到数组中
			for(int j=0;j<str.length();j++) {
				Binarystring[i]=binarystring;
			}
		}
		return Binarystring;
	}	

}

QRcodeUI类:二维码窗体界面类,用来绘制二维码(二值化图片)

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
public class QRcodeUI extends JFrame {
	private static final long serialVersionUID = 1L;
	QRcode qrcode=new QRcode();
	String[] binarystring=qrcode.tobinarystring();//调用QRcode类中创建二进制码字符串数组的方法
	//创建窗体界面
	public void init() {
		setTitle("二维码");
		setSize(800,600);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);
		Graphics g=getGraphics();
		paint(g);
	}
	//创建绘图方法
	public void paint(Graphics g) {
		super.paint(g);
		//遍历二进制码字符串中的字符
		for(int i=0;i<binarystring.length;i++) {
			String str=binarystring[i];
			for(int j=0;j<str.length();j++) {
				char c=str.charAt(j);
				//设置画笔颜色
				if(c=='0') {
					g.setColor(Color.white);
				}else {
					g.setColor(Color.black);
				}
				//绘制图片
				g.fillRect(200+i*10, 100+j*10, 10, 10);
			}
		}
		
	}
	public static void main(String[]args) {
		QRcodeUI qrdcodeui=new QRcodeUI();
		qrdcodeui.init();
	}
		
}
	


5、效果图

5

二、二维码识别

思路:将获得的二维码图片转为int类型的二维数组,保存该图片的像素点。根据图片的宽度和方向进行取值,并设置灰度值,若灰度值大于100,则取二进制码0,否则则取1,从而获得二进码字符串。将获得的二进制码字符串先转为整数,再强制转为字符。然后将获得的字符保存到字符数组中,最后遍历输出字符数组中的字符。

1、将二维码图片转为int类型的二维数组

public int[][] getpixelarray(String imgpath){
		BufferedImage img=null;
		try {
			img=ImageIO.read(new File(imgpath));//根据路径生成图片
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//获取图片的宽和高
		int w=img.getWidth();
		int h=img.getHeight();
		
		int[][] imgarr=new int[w][h];
		for(int i=0;i<w;i++) {
			for(int j=0;j<h;j++) {
				imgarr[i][j]=img.getRGB(i, j);
			}
		}
		return imgarr;
	}

2、设置灰度值,根据灰度值进行判断,获得二进码字符串

int[][] imgarr= getpixelarray("C:\\Users\\011\\Pictures\\Saved Pictures\\QRcode1.png");
int w=imgarr.length;
int width=w/20;//格子宽度
//考虑到可能会取到边界,所以需要改变起点,i、j不是从0取起,从每个矩形中点取起
for(int i=width/2;i<imgarr.length;i+=width) {
	String str="";//声明字符串
	for(int j=width/2;j<width*8;j+=width) {//每隔一个格子来取rgb值
		int rgb=imgarr[i][j];
		Color color=new Color(rgb);
		int gray=(color.getRed()+color.getBlue()+color.getGreen())/3;//引入灰度值来判断取0还是1
		if(gray>150) {
		    str+="0";//格子颜色为黑色就取0
		}else {
			str+="1";
		}
	}
}

3、将获得的二进码字符串进行类型转换

int in=Integer.parseInt(str, 2);
char c=(char)+in;

4、将获得的字符保存到字符数组中,最后遍历输出字符数组中的字符

char[] ch=new char[20];//声明一个字符型数组,用来保存转换好的字符
int t=0;//数组下标
for(int i=width/2;i<imgarr.length;i+=width) {
	String str="";//声明字符串
	for(int j=width/2;j<width*8;j+=width) {//每隔一个格子来取rgb值
		int rgb=imgarr[i][j];
		Color color=new Color(rgb);
		int gray=(color.getRed()+color.getBlue()+color.getGreen())/3;//引入灰度值来判断取0还是1
		if(gray>150) {
			str+="0";//格子颜色为黑色就取0
		}else {
			str+="1";
		}
	}
	int in=Integer.parseInt(str, 2);
	char c=(char)+in;
	ch[t]=c;
	t++;//每保存一个字符,下标下移
}
for(int k=0;k<ch.length;k++) {
	System.out.print(ch[k]);//输出保存好的字符
}

5完整代码

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class QRcodedefi {
	//将二维码图片转为int类型的二维数组
	public int[][] getpixelarray(String imgpath){
		BufferedImage img=null;
		try {
			img=ImageIO.read(new File(imgpath));//根据路径生成图片
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//获取图片的宽和高
		int w=img.getWidth();
		int h=img.getHeight();
		
		int[][] imgarr=new int[w][h];
		for(int i=0;i<w;i++) {
			for(int j=0;j<h;j++) {
				imgarr[i][j]=img.getRGB(i, j);
			}
		}
		return imgarr;
	}
	//将获取的二维数组中保存的像素值转为二进制码
	public void tobinary() {
		int[][] imgarr= getpixelarray("C:\\Users\\011\\Pictures\\Saved Pictures\\QRcode1.png");
		int w=imgarr.length;
		int width=w/20;//格子宽度
		char[] ch=new char[20];//声明一个字符型数组,用来保存转换好的字符(将得到的二进制码字符串先转为整数再转为字符)
		int t=0;//数组下标
		//考虑到可能会取到边界,所以需要改变起点,i、j不是从0取起,从每个矩形中点取起
		for(int i=width/2;i<imgarr.length;i+=width) {
			String str="";//声明字符串
			for(int j=width/2;j<width*8;j+=width) {//每隔一个格子来取rgb值
				int rgb=imgarr[i][j];
				Color color=new Color(rgb);
				int gray=(color.getRed()+color.getBlue()+color.getGreen())/3;//引入灰度值来判断取0还是1
				if(gray>150) {
					str+="0";//格子颜色为黑色就取0
				}else {
					str+="1";
				}
			}
			int in=Integer.parseInt(str, 2);
			char c=(char)+in;
			ch[t]=c;
			t++;//每保存一个字符,下标下移
			System.out.println(str+"---"+(char)+in);
		}
		for(int k=0;k<ch.length;k++) {
			System.out.print(ch[k]);//输出保存好的字符
		}
	}
		
	public static void main(String[]args) {
		QRcodedefi qrcodedefi=new QRcodedefi();
		qrcodedefi.tobinary();	
		
	}
}

6、效果图

 

 


版权声明:本文为qq_57082071原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。