zxing generates QR code to add pictures and text

 Go directly to the code, and add a description later when there is time

The basic information of the QR code, including the text to be included in the QR code, the embedded picture, and the text added to the bottom of the QR code

/**
 *
 */
package com.tong.util.code;

import java.io.File;

/**
 * @author zxm
 *
 */
public class CodeModel {
	private String contents;
	private int width = 400;
	private int height = 400;
	private String format = "gif";
	private String character_set = "utf-8";
	private int fontSize = 12;
	private File logoFile;
	private float logoRatio = 0.20f;
	private String desc;
	private int whiteWidth;//The width of the white border
	private int[] bottomStart;//Start coordinates of the bottom of the QR code
	private int[] bottomEnd;//The end coordinate of the bottom of the QR code

	public String getContents() {
		return contents;
	}

	public void setContents(String contents) {
		this.contents = contents;
	}

	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 String getCharacter_set() {
		return character_set;
	}

	public void setCharacter_set(String character_set) {
		this.character_set = character_set;
	}

	public int getFontSize() {
		return fontSize;
	}

	public void setFontSize(int fontSize) {
		this.fontSize = fontSize;
	}

	public File getLogoFile() {
		return logoFile;
	}

	public void setLogoFile(File logoFile) {
		this.logoFile = logoFile;
	}

	public float getLogoRatio() {
		return logoRatio;
	}

	public void setLogoRatio(float logoRatio) {
		this.logoRatio = logoRatio;
	}

	public String getDesc() {
		return desc;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}

	public int getWhiteWidth() {
		return whiteWidth;
	}

	public void setWhiteWidth(int whiteWidth) {
		this.whiteWidth = whiteWidth;
	}

	public int[] getBottomStart() {
		return bottomStart;
	}

	public void setBottomStart(int[] bottomStart) {
		this.bottomStart = bottomStart;
	}

	public int[] getBottomEnd() {
		return bottomEnd;
	}

	public void setBottomEnd(int[] bottomEnd) {
		this.bottomEnd = bottomEnd;
	}
}

 Generate QR code

/**
 *
 */
package com.tong.util.code;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import org.springframework.util.StringUtils;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

/**
 * @author zxm
 *
 */
public class CodeCreator {
	private static int BLACK = 0x000000;
	private static int WHITE = 0xFFFFFF;
	
	private BufferedImage createCodeImage(CodeModel info){
		String contents = info.getContents();
		int width = info.getWidth();
		int height = info.getHeight();
		Map<EncodeHintType, Object> hint = new HashMap<>();
		hint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
		hint.put(EncodeHintType.CHARACTER_SET, info.getCharacter_set());
		hint.put(EncodeHintType.MARGIN, 0);
		MultiFormatWriter writer = new MultiFormatWriter();
		BufferedImage img = null;
		try {
			BitMatrix bm = writer.encode(contents, BarcodeFormat.QR_CODE, width, height, hint);
			int[] locationTopLeft = bm.getTopLeftOnBit();
			int[] locationBottomRight = bm.getBottomRightOnBit();
			info.setBottomStart(new int[]{locationTopLeft[0], locationBottomRight[1]});
			info.setBottomEnd(locationBottomRight);
			int w = bm.getWidth();
			int h = bm.getHeight();
			img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
			for(int x=0;x<w;x++){
				for(int y=0;y<h;y++){
					img.setRGB(x, y, bm.get(x, y) ? BLACK : WHITE);
				}
			}
		} catch (WriterException e) {
			e.printStackTrace ();
		}
		return img;
	}
	
	public void createCodeImage(CodeModel info, OutputStream output){
		BufferedImage bm = createCodeImage(info);
		File logoFile = info.getLogoFile();
		if(logoFile!=null && logoFile.exists()){
			try{
			BufferedImage logoImg = ImageIO.read(logoFile);
			int logoWidth = logoImg.getWidth();
			int logoHeight = logoImg.getHeight();
			int width = bm.getWidth();
			int height = bm.getHeight();
			float ratio = info.getLogoRatio();
			if(ratio>0){
				logoWidth = logoWidth>width*ratio ? (int)(width*ratio) : logoWidth;
				logoHeight = logoHeight> height * ratio? (int) (height * ratio): logoHeight;
			}
			int x = (width-logoWidth)/2;
			int y = (height-logoHeight)/2;
			Graphics g = bm.getGraphics();
			g.drawImage(logoImg, x, y, logoWidth, logoHeight, null);
			String desc = info.getDesc();
			//int whiteWidth = 8;
			if(!StringUtils.isEmpty(desc)){
				int whiteWidth = info.getHeight()-info.getBottomEnd()[1];
//				width = info.getBottomEnd()[0]-info.getBottomStart()[0];
//				height = info.getBottomEnd()[1]+1;
				Font font = new Font("Bold", Font.BOLD, info.getFontSize());
				int fontHeight = g.getFontMetrics (font) .getHeight ();
				// Calculate how many lines are needed
				int lineNum = 1;
				int currentLineLen = 0;
				for(int i=0;i<desc.length();i++){
					char c = desc.charAt(i);
					int charWidth = g.getFontMetrics(font).charWidth(c);
					if(currentLineLen+charWidth>width){
						lineNum++;
						currentLineLen = 0;
						continue;
					}
					currentLineLen += charWidth;
				}
				int totalFontHeight = fontHeight*lineNum;
				int wordTopMargin = 4;
				BufferedImage bm1 = new BufferedImage(width, height+totalFontHeight+wordTopMargin-whiteWidth, BufferedImage.TYPE_INT_RGB);
				Graphics g1 = bm1.getGraphics();
				if(totalFontHeight+wordTopMargin-whiteWidth>0){
				g1.setColor(Color.WHITE);
				g1.fillRect(0, height, width, totalFontHeight+wordTopMargin-whiteWidth);
				}
				g1.setColor(new Color(BLACK));
				g1.setFont(font);
				g1.drawImage(bm, 0, 0, null);
				width = info.getBottomEnd()[0]-info.getBottomStart()[0];
				height = info.getBottomEnd()[1]+1;
				currentLineLen = 0;
				int currentLineIndex = 0;
				int baseLo = g1.getFontMetrics().getAscent();
				for(int i=0;i<desc.length();i++){
					String c = desc.substring(i, i+1);
					int charWidth = g.getFontMetrics(font).stringWidth(c);
					if(currentLineLen+charWidth>width){
						currentLineIndex++;
						currentLineLen = 0;
						g1.drawString(c, currentLineLen + whiteWidth, height+baseLo+fontHeight*(currentLineIndex)+wordTopMargin);
						currentLineLen = charWidth;
						continue;
					}
					g1.drawString(c, currentLineLen+whiteWidth, height+baseLo+fontHeight*(currentLineIndex) + wordTopMargin);
					currentLineLen += charWidth;
				}
				g1.dispose();
				bm = bm1;
			}
			}catch(Exception e){
				e.printStackTrace ();
			}
		}
		try{
			ImageIO.write(bm, StringUtils.isEmpty(info.getFormat()) ? info.getFormat() : info.getFormat(), output);
		}catch(Exception e){
			e.printStackTrace ();
		}
	}
	
	public void createCodeImage(CodeModel info, File file){
		File parent = file.getParentFile();
		if(!parent.exists())parent.mkdirs();
		OutputStream output = null;
		try{
			output = new BufferedOutputStream(new FileOutputStream(file));
			createCodeImage(info, output);
			output.flush();
		}catch(Exception e){
			e.printStackTrace ();
		}finally{
			try {
				output.close();
			} catch (IOException e) {
				e.printStackTrace ();
			}
		}
	}
	
	public void createCodeImage(CodeModel info, String filePath){
		createCodeImage(info, new File(filePath));
	}
}

 QR code reading

/**
 *
 */
package com.tong.util.code;

import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;

/**
 * @author zxm
 *
 */
public class CodeDecoder {
	public String decode(InputStream input){
		Map<DecodeHintType, Object> hint = new HashMap<DecodeHintType, Object>();
		hint.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
		String result = "";
		try{
		BufferedImage img = ImageIO.read(input);
		int[] pixels = img.getRGB(0, 0, img.getWidth(), img.getHeight(), null, 0, img.getWidth());
		LuminanceSource source = new RGBLuminanceSource(img.getWidth(), img.getHeight(), pixels);
		BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
		QRCodeReader reader = new QRCodeReader();
		Result r = reader.decode(bitmap, hint);
		result = r.getText();
		}catch(Exception e){
			result="read error";
		}
		return result;
	}
}

 

test code

 

/**
 *
 */
package com.tong.util;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.tong.util.code.CodeCreator;
import com.tong.util.code.CodeDecoder;
import com.tong.util.code.CodeModel;

/**
 * @author zxm
 *
 */
public class QRCodeMain{
	private static void encode() {
		CodeCreator creator = new CodeCreator();
		CodeModel info = new CodeModel();
		info.setWidth(400);
		info.setHeight(400);
		info.setFontSize(24);
		info.setContents("<a href='http://www.sohu.com'>Life is hard work</a>");
		//info.setContents("http://www.sohu.com");
		info.setContents("Thousands of waters and thousands of mountains are only leisurely\nThe sharp corners of Xiaohecai Building\nWhose new swallow is pecking the spring mud\nThe boundless scene is new for a while\nThousands of waters and thousands of mountains are only leisurely\nThe sharp corners of Xiaohecailou\nWho is new Swallows pecking the spring mud\nBoundless scenery is new for a while\nThousands of waters and thousands of mountains are just waiting for you\nXiaohecai's tower is sharp and sharp\nWhose new Yan is pecking the spring mud\nThe boundless scenery is new for a while\nThousands of waters and thousands of mountains are just waiting for time\nXiaohecai's building is sharp and sharp Corner\nWhose new swallow is pecking the spring mud\nThe boundless scene is new for a while\nThousands of waters and thousands of mountains are just waiting for you\nThe sharp corner of Xiaohe Cailou\nWhose new swallow is pecking the spring mud\nThe boundless scene is new for a while\nThe waters and thousands of mountains are just waiting for you\n Xiaohe Cailou has sharp corners\nWhose new swallow is pecking the spring mud\nThe boundless scene is new for a while\nThousands of waters and thousands of mountains are just waiting for time\nThe Xiaohe Cailou is sharp and sharp\nWhose new swallow is pecking the spring mud\nThe boundless scene is momentarily new\ nThousands of waters and thousands of mountains are only idle\nThe sharp corners of Xiaohecai Building\nWhose new swallow is pecking the spring mud\nThe boundless scene is new for a while\nThe thousands of waters and thousands of mountains are only idle\nThe sharp corners of Xiaohecailou\nWhose new swallow is pecking at the spring mud\ nBoundless scenery is new for a while\nThousands of waters and thousands of mountains are just waiting for time\nXiaohecai Building has sharp corners\nWhose new swallow is pecking at the spring mud\nBoundless scenery is changing for a while\nThousands of waters and thousands of mountains are just waiting for you\nThe sharp corners of Xiaohecai Building\nWho A new swallow pecks the spring mud\nThe boundless scene is new for a while\nThousands of waters and thousands of mountains are just waiting for you\nThe sharp corners of the Xiaohecai Building\nWhose new swallow is pecking the spring mud\nThe boundless scene is new for a while\nThe thousands of waters and thousands of mountains are just waiting for you\nThe Xiaohecai Building Sharp corners\nWhose new swallow pecks the spring mud\nThe boundless scene is new for a while\nThousands of waters and thousands of mountains are just waiting for time\nThe sharp corner of Xiaohecailou\nWhose new swallow is pecking the spring mud\nThe boundless scene is new for a while");
		info.setLogoFile(new File("D:/workspaces/workspace1/tong3/WebContent/img/girl3.jpg"));
		info.setDesc("How do you know my suffering, I am a lonely boat, drifting in the world asdfsaf33333abCD1234567890");
		//info.setLogoDesc("A leaf of duckweed returns to the sea, where adsasfbhtjg will never meet in life");
		//info.setLogoDesc("One Leaf Duckweed");
		creator.createCodeImage(info, "D:/2Dcode/dest." + info.getFormat());
	}
	
	static public void decode(InputStream input){
		CodeDecoder decoder = new CodeDecoder();
		String result = decoder.decode(input);
		System.out.println(result);
	}
	
	public static void main(String[] args) throws Exception{
		encode();
		//decode(new FileInputStream(new File("D:/2Dcode/dest.gif")));
	}
}
 

 

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326968159&siteId=291194637