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、效果图

 

 

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值