频道栏目
首页 > 资讯 > Java > 正文

二维码的功能、特点及使用Java生成带logo的二维码

16-07-15        来源:[db:作者]  
收藏   我要投稿

二维条码/二维码(2-dimensional bar code)是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的;在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实现信息自动处理:它具有条码技术的一些共性:每种码制有其特定的字符集;每个字符占有一定的宽度;具有一定的校验功能等。同时还具有对不同行的信息自动识别功能、及处理图形旋转变化点。

 

1. 二维码主要特点

二维条码是一种高密度、高信息含量的便携式数据文件,是实现证件及卡片等大容量、高可靠性信息自动存储、携带并可用机器自动识读的理想手段。二维条码具有如下特点:

1、信息容量大根据不同的条空比例每平方英寸可以容纳250到1100个字符。在国际标准的证卡有效面积上(相当于信用卡面积的2/3,约500个汉字信息。这种二维条码比普通条码信息容量高几十倍,也高于磁卡。

2、编码范围广二维条码可以将照片、指纹、掌纹、签字、声音、文字等凡可数字化的信息进行编码。

3、保密、防伪性能好二维条码具有信息不可改写等多重防伪特性,它可以采用密码防伪、软件加密及利用所包含的信息如指纹、照片等进行防伪,因此具有较强的保密防伪性能。

4、译码可靠性高普通条码的译码错误率约为百分之二左右,而二维条码的误码率不超过千万分之一,译码可靠性极高。

5、修正错误能力强二维条码采用了世界上最先进的数字纠错理论,如果破损面积不超过50%,条码由于沾污、破损等所丢失的信息,可以照常被破译出。

6、容易制作且成本很低利用现有的点阵、激光、喷墨、热敏/热转印、制卡机等打印技术,即可在纸张、卡片、PVC、甚至金属表面上印出二维条码。由此所增加的费用仅是油墨的成本。

7、条码符号的形状可变同样的信息量,二维条码形状可以根据载体面积及美工设计等进行自我调整。

 

2. QRcode

QR(Quick-Response) code是被广泛使用的一种二维码,解码速度快。它可以存储多用类型。如下图时一个qrcode的基本结构,其中:

I.测图形、位置探测图形分隔符、定位图形:用于对二维码的定位,对每个QR码来说,位置都是固定存在的,只是大小规格会有所差异;

II.校正图形:规格确定,校正图形的数量和位置也就确定了;

III.格式信息:表示改二维码的纠错级别,分为L、M、Q、H;

IV.版本信息:即二维码的规格,QR码符号共有40种规格的矩阵(一般为黑白色),从21x21(版本1),到177x177(版本40),每一版本符号比前一版本 每边增加4个模块。

V. 数据和纠错码字:实际保存的二维码信息,和纠错码字(用于修正二维码损坏带来的错误)。

 

3. 带中心logo图片的二维码生成

使用先导入google开源的zxing和j2se的jar包

(1) 二维码的数据模型

package com.Lin;

public class Qrcode {
	private String content;    	//二维码内容    
	private String filePath;   	//文件存放路径
	private String fileName;   	//文件名称
	private int width;         	//图像宽度  
	private int height;  	   	//图像高度  
	private String format;     	//图像类型,eg:png
	private int onColor = 0xFF000000;  //默认为黑
	private int offColor = 0xFFFFFFFF; //背景颜色,默认为白
	
	//无参的构造函数
	public Qrcode(){}
	
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public String getFilePath() {
		return filePath;
	}
	public void setFilePath(String filePath) {
		this.filePath = filePath;
	}
	public String getFileName() {
		return fileName;
	}
	public void setFileName(String fileName) {
		this.fileName = fileName;
	}
	public int getWidth() {
		return width;
	}
	public void setWidth(int width) {
		this.width = width;
	}
	public int getHeight() {
		return height;
	}
	public void setHeight(int height) {
		this.height = height;
	}
	public String getFormat() {
		return format;
	}
	public void setFormat(String format) {
		this.format = format;
	}

	public int getOnColor() {
		return onColor;
	}

	public void setOnColor(int onColor) {
		this.onColor = onColor;
	}

	public int getOffColor() {
		return offColor;
	}

	public void setOffColor(int offColor) {
		this.offColor = offColor;
	}
	
	

}

 

 

(2) 生成二维码图像

	/**
	 * 生成二维码图像
	 * @param q          二维码模型
	 * @param logoPath   中心logo的存储路径,为null时没中心logo
	 * @throws WriterException
	 * @throws IOException
	 */
	public void encode(Qrcode q, String logoPath) throws WriterException, IOException {	
        BitMatrix bitMatrix;    

        Hashtable hints = new Hashtable<>();  
        hints.put(EncodeHintType.MARGIN, 1); //设置二维码空白边框的大小 1-4,1是最小 4是默认的国标

        //生成矩阵
        bitMatrix = new MultiFormatWriter().encode(new String(q.getContent().getBytes("UTF-8"),"iso-8859-1"),    
                BarcodeFormat.QR_CODE, q.getWidth(), q.getHeight(), hints);  

        //存储路径
        Path path = FileSystems.getDefault().getPath(q.getFilePath(), q.getFileName()); 
        
        //矩阵颜色设置
        MatrixToImageConfig config = new MatrixToImageConfig(q.getOnColor(), q.getOffColor());
        
        BufferedImage image = MatrixToImageWriter.toBufferedImage(bitMatrix, config);
        
        if(null == logoPath){   //不需要中心logo
        	ImageIO.write(image, q.getFormat(), new File(path.toString()));
        }else{
        	this.overlapImage(image, path.toString(), logoPath, q.getFormat());
        }

        System.out.println("success");
   
    }

 

(3) 在二维码中心加入logo

	/**
	 * 对生成的二维码添加中心图形
	 * @param image
	 * @param imgSavePath
	 * @param logoPath
	 * @param format
	 */
	public void overlapImage(BufferedImage image, String imgSavePath, String logoPath, String format) {
		try {
			BufferedImage logo = scale(logoPath, image.getWidth() / 5,
					image.getHeight() / 5, true);
			Graphics2D g = image.createGraphics();
			//logo宽高
			int width = image.getWidth() / 5;
			int height = image.getHeight() / 5;
			//logo起始位置,此目的是为logo居中显示
			int x = (image.getWidth() - width) / 2;
			int y = (image.getHeight() - height) / 2;
			g.drawImage(logo, x, y, width, height, null);
			g.dispose();
			ImageIO.write(image, format, new File(imgSavePath));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

 

(4) 将原始图像缩放至合适尺寸

	/**
	 * 把传入的原始图像按高度和宽度进行缩放,生成符合要求的图标
	 * @param srcImageFile  源文件地址
	 * @param height        目标高度
	 * @param width         目标宽度
	 * @param hasFiller     比例不对时是否需要补白:true为补白; false为不补白;
	 * @throws IOException
	 */
	private static BufferedImage scale(String srcImageFile, int height,
			int width, boolean hasFiller) throws IOException {
		double ratio = 0.0; // 缩放比例
		File file = new File(srcImageFile);
		BufferedImage srcImage = ImageIO.read(file);
		Image destImage = srcImage.getScaledInstance(width, height,
				BufferedImage.SCALE_SMOOTH);
		// 计算比例
		if ((srcImage.getHeight() > height) || (srcImage.getWidth() > width)) {
			if (srcImage.getHeight() > srcImage.getWidth()) {
				ratio = (new Integer(height)).doubleValue()
						/ srcImage.getHeight();
			} else {
				ratio = (new Integer(width)).doubleValue()
						/ srcImage.getWidth();
			}
			AffineTransformOp op = new AffineTransformOp(
					AffineTransform.getScaleInstance(ratio, ratio), null);
			destImage = op.filter(srcImage, null);
		}
		if (hasFiller) {// 补白
			BufferedImage image = new BufferedImage(width, height,
					BufferedImage.TYPE_INT_RGB);
			Graphics2D graphic = image.createGraphics();
			graphic.setColor(Color.white);
			graphic.fillRect(0, 0, width, height);
			if (width == destImage.getWidth(null))
				graphic.drawImage(destImage, 0,
						(height - destImage.getHeight(null)) / 2,
						destImage.getWidth(null), destImage.getHeight(null),
						Color.white, null);
			else
				graphic.drawImage(destImage,
						(width - destImage.getWidth(null)) / 2, 0,
						destImage.getWidth(null), destImage.getHeight(null),
						Color.white, null);
			graphic.dispose();
			destImage = image;
		}
		return (BufferedImage) destImage;
	}


 

4. 二维码的解码

 

	 /** 
	 * 解析图像
	 * @param  filePath  二维码存放路径
	 * @throws IOException 
	 * @throws NotFoundException 
	 */  
	 public void decode(String filePath) throws IOException, NotFoundException {
	     BufferedImage image;
	     
	     image = ImageIO.read(new File(filePath));  
         LuminanceSource source = new BufferedImageLuminanceSource(image);  
         Binarizer binarizer = new HybridBinarizer(source);  
         BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);  
         Map hints = new HashMap();  
         hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");  
         Result result = new MultiFormatReader().decode(binaryBitmap, hints);// 对图像进行解码  

         System.out.println("图片中内容:  ");  
         System.out.println(result.getText()); 
     }

 

5. 生成二维码的示例

 

package com.Lin;

import java.io.IOException;

import com.google.zxing.NotFoundException;
import com.google.zxing.WriterException;

public class Test {
	
	public static void main(String[] args) throws WriterException, IOException, NotFoundException {
		TestQrcode t = new TestQrcode();
		
		//二维码数据的封装,便于以后数据与业务逻辑的分离
		Qrcode q = new Qrcode();
		q.setContent("我多么想和你见一面");
		q.setFilePath("D://");
		q.setFileName("1.png");
		q.setHeight(200);
		q.setWidth(200);
		q.setFormat("png");
		q.setOnColor(0xFF4169E1);   //Royal blue
		String logoPath = "D://1.jpg";
		
		t.encode(q, logoPath);
//		t.decode("D://1.png");
	}

}

Zxing和j2se的jar包、项目代码及应用例子在github

生成的二维码效果:

 


 

相关TAG标签
上一篇:VMware安装CentOS以及CentOS的一些配置
下一篇:动态规划-面试题
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站