⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qrcodedecoder.java

📁 QR Code码的解码程序
💻 JAVA
字号:
/* * created 2004/09/12 */package jp.sourceforge.qrcode;import java.util.Vector;import jp.sourceforge.qrcode.data.QRCodeImage;import jp.sourceforge.qrcode.data.QRCodeSymbol;import jp.sourceforge.qrcode.exception.DecodingFailedException;import jp.sourceforge.qrcode.exception.InvalidDataBlockException;import jp.sourceforge.qrcode.exception.SymbolNotFoundException;import jp.sourceforge.qrcode.geom.Point;//import jp.sourceforge.qrcode.ecc.ReedSolomon;import jp.sourceforge.qrcode.util.DebugCanvas;import jp.sourceforge.qrcode.util.DebugCanvasAdapter;import jp.sourceforge.qrcode.reader.QRCodeDataBlockReader;import jp.sourceforge.qrcode.reader.QRCodeImageReader;import jp.sourceforge.reedsolomon.RsDecode;public class QRCodeDecoder {	int numTryDecode;	QRCodeSymbol qrCodeSymbol;	Vector results;	Vector lastResults = new Vector();	static DebugCanvas canvas;	QRCodeImageReader imageReader;	int numLastCorrectionFailures;	class DecodeResult {		int numCorrectionFailures;		byte[] decodedBytes;		public DecodeResult(byte[] decodedBytes,int numCorrectionFailures) {			this.decodedBytes = decodedBytes;			this.numCorrectionFailures = numCorrectionFailures;		}		public byte[] getDecodedBytes() {			return decodedBytes;		}		public int getNumCorrectuionFailures() {			return numCorrectionFailures;		}		public boolean isCorrectionSucceeded() {			return numLastCorrectionFailures == 0;		}	}		public static void setCanvas(DebugCanvas canvas) {		QRCodeDecoder.canvas = canvas;	}	public static DebugCanvas getCanvas() {		return QRCodeDecoder.canvas;	}	public QRCodeDecoder() {		numTryDecode = 0;		results = new Vector();		QRCodeDecoder.canvas = new DebugCanvasAdapter();	}		public byte[] decode(QRCodeImage qrCodeImage) throws DecodingFailedException {		Point[] adjusts = getAdjustPoints();		Vector results = new Vector();    numTryDecode = 0;		while (numTryDecode < adjusts.length) {			try {				DecodeResult result = decode(qrCodeImage, adjusts[numTryDecode]);				if (result.isCorrectionSucceeded()) {					return result.getDecodedBytes();				}				else {					results.addElement(result);					canvas.println("Decoding succeeded but could not correct");					canvas.println("all errors. Retrying..");				}			} catch (DecodingFailedException dfe) {				if (dfe.getMessage().indexOf("Finder Pattern") >= 0)					throw dfe;			} finally {				numTryDecode += 1;			}		}				if (results.size() == 0)			throw new DecodingFailedException("Give up decoding");				int minErrorIndex = -1;		int minError = Integer.MAX_VALUE;		for (int i = 0; i < results.size(); i++) {			DecodeResult result = (DecodeResult)results.elementAt(i);			if (result.getNumCorrectuionFailures() < minError) {				minError = result.getNumCorrectuionFailures();				minErrorIndex = i;			}		}		canvas.println("All trials need for correct error");		canvas.println("Reporting #" + (minErrorIndex)+" that,");		canvas.println("corrected minimum errors (" +minError + ")");		canvas.println("Decoding finished.");		return ((DecodeResult)results.elementAt(minErrorIndex)).getDecodedBytes();	}		Point[] getAdjustPoints() {		// note that adjusts affect dependently		// i.e. below means (0,0), (2,3), (3,4), (1,2), (2,1), (1,1), (-1,-1)		//		Point[] adjusts = {new Point(0,0), new Point(2,3), new Point(1,1), //				new Point(-2,-2), new Point(1,-1), new Point(-1,0), new Point(-2,-2)};		Vector adjustPoints = new Vector();		for (int d = 0; d < 4; d++)			adjustPoints.addElement(new Point(1, 1));		int lastX = 0, lastY = 0;		for (int y = 0; y > -4; y--) {			for (int x = 0; x > -4; x--) {				if (x != y && ((x+y) % 2 == 0)) {					adjustPoints.addElement(new Point(x-lastX, y-lastY));					lastX = x;					lastY = y;				}			}		}		Point[] adjusts = new Point[adjustPoints.size()];		for (int i = 0; i < adjusts.length; i++)			adjusts[i] = (Point)adjustPoints.elementAt(i);		return adjusts;	}		DecodeResult decode(QRCodeImage qrCodeImage, Point adjust) 		throws DecodingFailedException {		try {			if (numTryDecode == 0) {				canvas.println("Decoding started");				int[][] intImage = imageToIntArray(qrCodeImage);				imageReader = new QRCodeImageReader();				qrCodeSymbol = imageReader.getQRCodeSymbol(intImage);			} else {				canvas.println("--");				canvas.println("Decoding restarted #" + (numTryDecode));				qrCodeSymbol = imageReader.getQRCodeSymbolWithAdjustedGrid(adjust);			}		} catch (SymbolNotFoundException e) {			throw new DecodingFailedException(e.getMessage());		}		canvas.println("Created QRCode symbol.");		canvas.println("Reading symbol.");		canvas.println("Version: " + qrCodeSymbol.getVersionReference());				canvas.println("Mask pattern: " + qrCodeSymbol.getMaskPatternRefererAsString());		// blocks contains all (data and RS) blocks in QR Code symbol		int[] blocks = qrCodeSymbol.getBlocks();		canvas.println("Correcting data errors.");		// now blocks turn to data blocks (corrected and extracted from original blocks)    blocks = correctDataBlocks(blocks);		try {			byte[] decodedByteArray = 				getDecodedByteArray(blocks, qrCodeSymbol.getVersion(), qrCodeSymbol.getNumErrorCollectionCode());			return new DecodeResult(decodedByteArray, numLastCorrectionFailures);		} catch (InvalidDataBlockException e) {			canvas.println(e.getMessage());			throw new DecodingFailedException(e.getMessage());		}	}			int[][] imageToIntArray(QRCodeImage image) {		int width = image.getWidth();		int height = image.getHeight();		int[][] intImage = new int[width][height];		for (int y = 0; y < height; y++) {			for (int x = 0; x < width; x++) {				intImage[x][y] = image.getPixel(x,y);			}		}		return intImage;	}		int[] correctDataBlocks(int[] blocks) {		int numSucceededCorrections = 0;    int numCorrectionFailures = 0;		int dataCapacity = qrCodeSymbol.getDataCapacity();		int[] dataBlocks = new int[dataCapacity];		int numErrorCollectionCode = qrCodeSymbol.getNumErrorCollectionCode();		int numRSBlocks = qrCodeSymbol.getNumRSBlocks();		int eccPerRSBlock = numErrorCollectionCode / numRSBlocks;		if (numRSBlocks == 1) {      RsDecode corrector = new RsDecode(eccPerRSBlock / 2);      int ret = corrector.decode(blocks);      if (ret > 0)        numSucceededCorrections += ret;      else if (ret < 0)        numCorrectionFailures++;			return blocks;		}		else  { //we have to interleave data blocks because symbol has 2 or more RS blocks			int numLongerRSBlocks = dataCapacity % numRSBlocks;			if (numLongerRSBlocks == 0) { //symbol has only 1 type of RS block				int lengthRSBlock = dataCapacity / numRSBlocks;				int[][] RSBlocks = new int[numRSBlocks][lengthRSBlock];				//obtain RS blocks				for (int i = 0; i < numRSBlocks; i++) {					for (int j = 0; j < lengthRSBlock; j++) {						RSBlocks[i][j] = blocks[j * numRSBlocks + i];					}          canvas.println("eccPerRSBlock=" + eccPerRSBlock );          RsDecode corrector = new RsDecode(eccPerRSBlock / 2);          int ret = corrector.decode(RSBlocks[i]);          if (ret > 0)            numSucceededCorrections += ret;          else if (ret < 0)            numCorrectionFailures++;				}				//obtain only data part				int p = 0;				for (int i = 0; i < numRSBlocks; i++) {					for (int j = 0; j < lengthRSBlock - eccPerRSBlock; j++) {						dataBlocks[p++] = RSBlocks[i][j];					}				}			}			else { //symbol has 2 types of RS blocks				int lengthShorterRSBlock = dataCapacity / numRSBlocks;				int lengthLongerRSBlock = dataCapacity / numRSBlocks + 1;				int numShorterRSBlocks = numRSBlocks - numLongerRSBlocks;				int[][] shorterRSBlocks = new int[numShorterRSBlocks][lengthShorterRSBlock];				int[][] longerRSBlocks = new int[numLongerRSBlocks][lengthLongerRSBlock];				for (int i = 0; i < numRSBlocks; i++) {					if (i < numShorterRSBlocks) { //get shorter RS Block(s)						int mod = 0;						for (int j = 0; j < lengthShorterRSBlock; j++) {							if (j == lengthShorterRSBlock - eccPerRSBlock) mod = numLongerRSBlocks;							shorterRSBlocks[i][j] = blocks[j * numRSBlocks + i + mod];						}            canvas.println("eccPerRSBlock(shorter)=" + eccPerRSBlock );            RsDecode corrector = new RsDecode(eccPerRSBlock / 2);            int ret = corrector.decode(shorterRSBlocks[i]);            if (ret > 0)              numSucceededCorrections += ret;            else if (ret < 0)              numCorrectionFailures++;					}					else { 	//get longer RS Blocks						int mod = 0;						for (int j = 0; j < lengthLongerRSBlock; j++) {							if (j == lengthShorterRSBlock - eccPerRSBlock) mod = numShorterRSBlocks;							longerRSBlocks[i - numShorterRSBlocks][j] = blocks[j * numRSBlocks + i - mod];						}            canvas.println("eccPerRSBlock(longer)=" + eccPerRSBlock );            RsDecode corrector = new RsDecode(eccPerRSBlock / 2);            int ret = corrector.decode(longerRSBlocks[i - numShorterRSBlocks]);            if (ret > 0)              numSucceededCorrections += ret;            else if (ret < 0)              numCorrectionFailures++;					}				}				int p = 0;				for (int i = 0; i < numRSBlocks; i++) {					if (i < numShorterRSBlocks) {						for (int j = 0; j < lengthShorterRSBlock - eccPerRSBlock; j++) {							dataBlocks[p++] = shorterRSBlocks[i][j];						}					}					else {						for (int j = 0; j < lengthLongerRSBlock - eccPerRSBlock; j++) {							dataBlocks[p++] = longerRSBlocks[i - numShorterRSBlocks][j];						}					}				}			}			if (numSucceededCorrections > 0)				canvas.println(String.valueOf(numSucceededCorrections) + " data errors corrected successfully.");			else				canvas.println("No errors found.");					numLastCorrectionFailures = numCorrectionFailures;			return dataBlocks;		}	}		byte[] getDecodedByteArray(int[] blocks, int version, int numErrorCorrectionCode) throws InvalidDataBlockException {		byte[] byteArray;		QRCodeDataBlockReader reader = new QRCodeDataBlockReader(blocks, version, numErrorCorrectionCode);		try {			byteArray = reader.getDataByte();		} catch (InvalidDataBlockException e) {			throw e;		}		return byteArray;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -