zoukankan      html  css  js  c++  java
  • ZXing生成条形码、二维码、带logo二维码

    采用的是开源的ZXing,Maven配置如下,jar包下载地址,自己选择版本下载,顺便推荐下Maven Repository 

    <!-- https://mvnrepository.com/artifact/com.google.zxing/core -->
    <dependency>
    	<groupId>com.google.zxing</groupId>
    	<artifactId>core</artifactId>
    	<version>3.3.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.google.zxing/javase -->
    <dependency>
    	<groupId>com.google.zxing</groupId>
    	<artifactId>javase</artifactId>
    	<version>3.3.0</version>
    </dependency>

    参考了不少文章,感谢分享

    一、条形码

    EAN码是国际物品编码协会制定的一种商品用条码,通用于全世界。EAN码符号有标准版(EAN-13)和缩短版(EAN-8)两种。标准版表示13位数字,又称为EAN13码,缩短版表示8位数字,又称EAN8。两种条码的最后一位为校验位,由前面的12位或7位数字计算得出,所以这个码不是随便瞎写的。

    package com.phil.common.util;
    
    import java.awt.image.BufferedImage;
    import java.io.File;
    
    import javax.imageio.ImageIO;
    
    import com.google.zxing.BarcodeFormat;
    import com.google.zxing.BinaryBitmap;
    import com.google.zxing.LuminanceSource;
    import com.google.zxing.MultiFormatReader;
    import com.google.zxing.MultiFormatWriter;
    import com.google.zxing.Result;
    import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
    import com.google.zxing.client.j2se.MatrixToImageWriter;
    import com.google.zxing.common.BitMatrix;
    import com.google.zxing.common.HybridBinarizer;
    
    /**
     * ZXing条形码编码/解码
     * 
     * @author phil
     * @date 2017年8月30日
     */
    public class ZxingCode {
    
    	/**
    	 * 条形码编码
    	 * 
    	 * @param contents
    	 * @param width
    	 * @param height
    	 * @param imgPath
    	 */
    	public static void encode(String contents, int width, int height, String imgPath) {
    		int codeWidth = 3 + // start guard
    				(7 * 6) + // left bars
    				5 + // middle guard
    				(7 * 6) + // right bars
    				3; // end guard
    		codeWidth = Math.max(codeWidth, width);
    		try {
    			BitMatrix bitMatrix = new MultiFormatWriter().encode(contents,BarcodeFormat.EAN_13, codeWidth, height, null);
    			MatrixToImageWriter.writeToFile(bitMatrix, "png", new File(imgPath));
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    	/**
    	 * 条形码解码
    	 * 
    	 * @param imgPath
    	 * @return String
    	 */
    	public static String decode(String imgPath) {
    		BufferedImage image = null;
    		Result result = null;
    		try {
    			image = ImageIO.read(new File(imgPath));
    			if (image == null) {
    				System.out.println("the decode image may be not exit.");
    			}
    			LuminanceSource source = new BufferedImageLuminanceSource(image);
    			BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
    			result = new MultiFormatReader().decode(bitmap, null);
    			return result.getText();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
    	
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		String imgPath = "F:/zxing_EAN-13.png";
    		String contents = "6926557300360";
    		int width = 105, height = 50;
    		encode(contents, width, height, imgPath);
    		System.out.println("finished zxing EAN-13 encode.");
    		String decodeContent = decode(imgPath);
    		System.out.println("解码内容如下:" + decodeContent);
    		System.out.println("finished zxing EAN-13 decode.");
    	}
    }
    执行结果:
    finished zxing EAN-13 encode.
    解码内容如下:6926557300360
    finished zxing EAN-13 decode.

    二、二维码

    二维码就不多介绍了,现在各种各样的二维码,网址、名片、付款码、商品二维码、优惠券、会员信息。。。
    package com.phil.common.util;
    
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics2D;
    import java.awt.image.BufferedImage;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.util.Arrays;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.imageio.ImageIO;
    
    import org.apache.commons.codec.binary.Base64;
    import org.apache.commons.io.IOUtils;
    import org.apache.commons.lang.StringUtils;
    
    import com.google.zxing.BarcodeFormat;
    import com.google.zxing.BinaryBitmap;
    import com.google.zxing.DecodeHintType;
    import com.google.zxing.EncodeHintType;
    import com.google.zxing.LuminanceSource;
    import com.google.zxing.MultiFormatReader;
    import com.google.zxing.MultiFormatWriter;
    import com.google.zxing.Result;
    import com.google.zxing.WriterException;
    import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
    import com.google.zxing.client.j2se.MatrixToImageConfig;
    import com.google.zxing.common.BitMatrix;
    import com.google.zxing.common.HybridBinarizer;
    import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
    
    /**
     * ZXing二维码生成/解码
     * @author phil
     * @date 2017年8月30日
     *
     */
    public class ZXingCode {
    
    	public static void main(String[] args) throws WriterException {
    		try {
    			String logoPath = "F:/logo.jpg";
    			String logo_savePath = "F:/" + new Date().getTime() + ".png";
    			String str = toQRCode("http://blog.csdn.net/phil_jing", logoPath, logo_savePath,  "CSDN博客");
    			System.out.println("finished zxing QRcode encode.");
    			System.out.println(Arrays.toString(Base64.decodeBase64(str)));
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	/**
    	 * 生成二维码图片
    	 * @param content
    	 * @param logoPath
    	 * @param savePath
    	 * @param remark
    	 * @return
    	 */
    	public static String toQRCode(String content, String logoPath, String savePath, String remark) {
    		int width = 400, height = 400;
    		try {
    			BufferedImage bim = toBufferedImage(content, BarcodeFormat.QR_CODE, width, height, toDecodeHintType());
    			return encode(bim, logoPath, savePath, new LogoConfig(), remark);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
    
    	/**
    	 * 是否需要给二维码图片添加Logo
    	 * @param bim
    	 * @param logoPath
    	 * @param savePath
    	 * @param logoConfig
    	 * @param remark
    	 * @return
    	 */
    	private static String encode(BufferedImage bim, String logoPath, String savePath, LogoConfig logoConfig, String remark) {
    		ByteArrayOutputStream baos = null;
    		try {
    			/**
    			 * 读取二维码图片
    			 */
    			BufferedImage image = bim;
    			if(StringUtils.isBlank(logoPath)){ //不需要添加logo
    				baos = new ByteArrayOutputStream();
    				baos.flush();
    				ImageIO.write(image, "png", baos);//流输出
    				//ImageIO.write(bim, "png", new File(savePath));//直接写入某路径,本地测试加上
    				return Base64.encodeBase64URLSafeString(baos.toByteArray());//Encodes binary data using a URL-safe variation of the base64 algorithm
    			}
    			/**
    			 * 构建绘图对象
    			 */
    			Graphics2D g = image.createGraphics();
    			/**
    			 * 读取Logo图片
    			 */
    			BufferedImage logo = ImageIO.read(new File(logoPath));
    			/**
    			 * 设置logo的大小,设置为二维码图片的20%,因为过大会盖掉二维码
    			 */
    			int widthLogo = logo.getWidth(null) > image.getWidth() * 3 / 10 ? (image.getWidth() * 3 / 10)
    					: logo.getWidth(null),
    					heightLogo = logo.getHeight(null) > image.getHeight() * 3 / 10 ? (image.getHeight() * 3 / 10)
    							: logo.getWidth(null);
    			/**
    			 * logo放在中心
    			 */
    			int x = (image.getWidth() - widthLogo) / 2;
    			int y = (image.getHeight() - heightLogo) / 2;
    			/**
    			 * logo放在右下角 int x = (image.getWidth() - widthLogo); int y = (image.getHeight() - heightLogo);
    			 */
    			// 开始绘制图片
    			g.drawImage(logo, x, y, widthLogo, heightLogo, null);
    			// g.drawRoundRect(x, y, widthLogo, heightLogo, 15, 15);
    			// g.setStroke(new BasicStroke(logoConfig.getBorder()));
    			// g.setColor(logoConfig.getBorderColor());
    			// g.drawRect(x, y, widthLogo, heightLogo);
    			g.dispose();
    			// 把备注添加上去,备注不要太长超过两行会自动截取
    			if (  StringUtils.isNotBlank(remark)){
    				// 新的图片,把带logo的二维码下面加上文字
    				BufferedImage outImage = new BufferedImage(400, 445, BufferedImage.TYPE_4BYTE_ABGR);
    				Graphics2D outg = outImage.createGraphics();
    				// 画二维码到新的面板
    				outg.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
    				// 画文字到新的面板
    				outg.setColor(Color.BLACK);
    				outg.setFont(new Font("微软雅黑", Font.BOLD, 30)); // 字体、字型、字号
    				int strWidth = outg.getFontMetrics().stringWidth(remark);
    				if (strWidth > 399) {
    					// //长度过长就截取前面部分
    					// outg.drawString(productName, 0, image.getHeight() +
    					// (outImage.getHeight() - image.getHeight())/2 + 5 ); //画文字
    					String productName1 = remark.substring(0, remark.length() / 2);
    					String productName2 = remark.substring(remark.length() / 2, remark.length());
    					int strWidth1 = outg.getFontMetrics().stringWidth(productName1);
    					int strWidth2 = outg.getFontMetrics().stringWidth(productName2);
    					outg.drawString(productName1, 200 - strWidth1 / 2, image.getHeight() + (outImage.getHeight() - image.getHeight()) / 2 + 12);
    					BufferedImage outImage2 = new BufferedImage(400, 485, BufferedImage.TYPE_4BYTE_ABGR);
    					Graphics2D outg2 = outImage2.createGraphics();
    					outg2.drawImage(outImage, 0, 0, outImage.getWidth(), outImage.getHeight(), null);
    					outg2.setColor(Color.BLACK);
    					outg2.setFont(new Font("微软雅黑", Font.BOLD, 30)); // 字体、字型、字号
    					outg2.drawString(productName2, 200 - strWidth2 / 2, outImage.getHeight() + (outImage2.getHeight() - outImage.getHeight()) / 2 + 5);
    					outg2.dispose();
    					outImage2.flush();
    					outImage = outImage2;
    				} else {
    					outg.drawString(remark, 200 - strWidth / 2, image.getHeight() + (outImage.getHeight() - image.getHeight()) / 2 + 12); // 画文字
    				}
    				outg.dispose();
    				outImage.flush();
    				image = outImage;
    			}
    			logo.flush();
    			image.flush();
    			baos = new ByteArrayOutputStream();
    			baos.flush();
    			ImageIO.write(image, "png", baos); //不用MatrixToImageWriter
    			//ImageIO.write(image, "png", new File(savePath));//直接写入某路径
    			return Base64.encodeBase64URLSafeString(baos.toByteArray());
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			IOUtils.closeQuietly(baos);
    		}
    		return null;
    	}
    
    	/**
    	 * 生成二维码bufferedImage图片
    	 * @param content 编码内容
    	 * @param barcodeFormat 编码类型
    	 * @param width 图片宽度
    	 * @param height 图片高度
    	 * @param hints 设置参数
    	 * @return
    	 */
    	private static BufferedImage toBufferedImage(String content, BarcodeFormat barcodeFormat, int width, int height,
    			Map<EncodeHintType, ?> hints) {
    		MultiFormatWriter multiFormatWriter = null;
    		BitMatrix bitMatrix = null;
    		BufferedImage image = null;
    		try {
    			multiFormatWriter = new MultiFormatWriter();
    			// 参数顺序分别为:编码内容,编码类型,生成图片宽度,生成图片高度,设置参数
    			bitMatrix = multiFormatWriter.encode(content, barcodeFormat, width, height, hints);
    			int w = bitMatrix.getWidth();
    			int h = bitMatrix.getHeight();
    			image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
    			// 开始利用二维码数据创建Bitmap图片,分别设为黑(0xFFFFFFFF)白(0xFF000000)两色
    			for (int x = 0; x < w; x++) {
    				for (int y = 0; y < h; y++) {
    					image.setRGB(x, y, bitMatrix.get(x, y) ? MatrixToImageConfig.BLACK : MatrixToImageConfig.WHITE);
    				}
    			}
    		} catch (WriterException e) {
    			e.printStackTrace();
    		}
    		return image;
    	}
    
    	/**
    	 * 设置二维码的格式参数
    	 * @return
    	 */
    	private static Map<EncodeHintType, Object> toDecodeHintType() {
    		// 用于设置QR二维码参数
    		Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
    		// 设置QR二维码的纠错级别(H为最高级别)具体级别信息
    		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
    		// 设置编码方式
    		hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
    		hints.put(EncodeHintType.MARGIN, 0);
    		//hints.put(EncodeHintType.MAX_SIZE, 350);//Only applicable to Data Matrix now
    		//hints.put(EncodeHintType.MIN_SIZE, 100);//Only applicable to Data Matrix now
    		return hints;
    	}
    	
    	/**
    	 * 二维码解码
    	 * 
    	 * @param imgPath
    	 * @return 
    	 */
    	public static String decode(String imgPath) {
    		BufferedImage image = null;
    		Result result = null;
    		try {
    			File file = new File(imgPath);
    			image = ImageIO.read(file);
    			if (image == null) {
    				System.out.println("the decode image may be not exit.");
    			}
    			LuminanceSource source = new BufferedImageLuminanceSource(image);
    			BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
    			Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
    			hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
    			result = new MultiFormatReader().decode(bitmap, hints);
    			return result.getText();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
    }
    /**
     * Logo图片配置
     * @author phil
     * @date 2017年8月30日
     *
     */
    class LogoConfig {
    	// logo默认边框颜色
    	public static final Color DEFAULT_BORDERCOLOR = Color.WHITE;
    	// logo默认边框宽度
    	public static final int DEFAULT_BORDER = 2;
    	// logo大小默认为照片的1/5
    	public static final int DEFAULT_LOGOPART = 5;
    
    	private final int border = DEFAULT_BORDER;
    	private final Color borderColor;
    	private final int logoPart;
    
    	/**
    	 * Creates a default config with on color {@link #BLACK} and off color
    	 * {@link #WHITE}, generating normal black-on-white barcodes.
    	 */
    	public LogoConfig() {
    		this(DEFAULT_BORDERCOLOR, DEFAULT_LOGOPART);
    	}
    
    	public LogoConfig(Color borderColor, int logoPart) {
    		this.borderColor = borderColor;
    		this.logoPart = logoPart;
    	}
    
    	public Color getBorderColor() {
    		return borderColor;
    	}
    
    	public int getBorder() {
    		return border;
    	}
    
    	public int getLogoPart() {
    		return logoPart;
    	}
    }

    效果图,扫扫有惊喜

      


    本文为Phil Jing原创文章,未经博主允许不得转载,如有问题请直接回复或者加群。
  • 相关阅读:
    poj3613 Cow Relays【好题】【最短路】【快速幂】【离散化】
    poj1734 Sightseeing trip【最小环】
    poj1094 Sorting It All Out【floyd】【传递闭包】【拓扑序】
    BZOJ2200 道路和航线【好题】【dfs】【最短路】【缩点】
    CH6101 最优贸易【最短路】
    poj3662 Telephone Lines【最短路】【二分】
    codeforces#514 Div2---1059ABCD
    进阶指南---基本算法【阅读笔记】
    hdu5954 Do not pour out【积分】【二分】【待补.....】
    mariadb yum安装
  • 原文地址:https://www.cnblogs.com/phil_jing/p/15615861.html
Copyright © 2011-2022 走看看