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

📄 qrcodedatablockreader.java

📁 qrcode的java开源版本
💻 JAVA
字号:
/*
 * created: 2004/10/04
 */
package jp.sourceforge.qrcode.codec.reader;

import jp.sourceforge.qrcode.codec.QRCodeDecoder;
import jp.sourceforge.qrcode.codec.exception.InvalidDataBlockException;
import jp.sourceforge.qrcode.codec.util.DebugCanvas;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class QRCodeDataBlockReader {
	int[] blocks;
	int dataLengthMode;
	int blockPointer;
	int bitPointer;
	int dataLength;
	int numErrorCorrectionCode;
	DebugCanvas canvas;
	final int MODE_NUMBER = 1;
	final int MODE_ROMAN_AND_NUMBER = 2;
	final int MODE_8BIT_BYTE = 4;
	final int MODE_KANJI = 8;
	// this constant come from p16, JIS-X-0510(2004) 
	final int[][] sizeOfDataLengthInfo = {
		{10, 9, 8, 8}, {12, 11, 16, 10}, {14, 13, 16, 12}
	};

	public QRCodeDataBlockReader(int[] blocks, int version, int numErrorCorrectionCode) {
		blockPointer = 0;
		bitPointer = 7;
		dataLength = 0;
		this.blocks = blocks;
		this.numErrorCorrectionCode = numErrorCorrectionCode;
		if (version <= 9) dataLengthMode = 0;
		else if (version >= 10 && version <= 26) dataLengthMode = 1;
		else if (version >= 27 && version <= 40) dataLengthMode = 2;
		canvas = QRCodeDecoder.getCanvas();
	}
	
	int getNextBits(int numBits) throws ArrayIndexOutOfBoundsException {
//		System.out.println("numBits:" + String.valueOf(numBits));
//		System.out.println("blockPointer:" + String.valueOf(blockPointer));
//		System.out.println("bitPointer:" + String.valueOf(bitPointer));
		int bits = 0;
		if (numBits < bitPointer + 1) { // next word fits into current data block
			int mask = 0;
			for (int i = 0; i < numBits; i++) {
				mask += 1 << i;
			}
			mask <<= (bitPointer - numBits + 1);
			
			bits = (blocks[blockPointer] & mask) >> (bitPointer - numBits + 1);
			bitPointer -= numBits;
			return bits;
		}
		else if (numBits < bitPointer + 1 + 8) { // next word crosses 2 data blocks
			int mask1 = 0;
			for (int i = 0; i < bitPointer + 1; i++) {
				mask1 += 1 << i;
			}
			bits = (blocks[blockPointer] & mask1) << (numBits - (bitPointer + 1));
			blockPointer++;
			bits += (blocks[blockPointer]) >> (8 - (numBits - (bitPointer + 1)));

			bitPointer = bitPointer - numBits % 8;
			if (bitPointer < 0) {
				bitPointer = 8 + bitPointer;
			}
			return bits;	
		}
		else if (numBits < bitPointer + 1 + 16) { // next word crosses 3 data blocks
			int mask1 = 0; // mask of first block
			int mask3 = 0; // mask of 3rd block
			//bitPointer + 1 : number of bits of the 1st block
			//8 : number of the 2nd block (note that use already 8bits because next word uses 3 data blocks)
			//numBits - (bitPointer + 1 + 8) : number of bits of the 3rd block 
			for (int i = 0; i < bitPointer + 1; i++) {
				mask1 += 1 << i;
			}
			int bitsFirstBlock = (blocks[blockPointer] & mask1) << (numBits - (bitPointer + 1));
			blockPointer++;

			int bitsSecondBlock = blocks[blockPointer] << (numBits - (bitPointer + 1 + 8));
			blockPointer++;
			
			for (int i = 0; i < numBits - (bitPointer + 1 + 8); i++) {
				mask3 += 1 << i;
			}
			mask3 <<= 8 - (numBits - (bitPointer + 1 + 8));
			int bitsThirdBlock = (blocks[blockPointer] & mask3) >> (8 - (numBits - (bitPointer + 1 + 8)));
			
			bits = bitsFirstBlock + bitsSecondBlock + bitsThirdBlock;
			bitPointer = bitPointer - (numBits - 8) % 8;
			if (bitPointer < 0) {
				bitPointer = 8 + bitPointer;
			}
			return bits;
		}
		else {
			System.out.println("ERROR!");
			return 0;
		}
	}	
	
	int getNextMode() throws ArrayIndexOutOfBoundsException {
		//canvas.println("data blocks:"+ (blocks.length - numErrorCorrectionCode));
		if ((blockPointer > blocks.length - numErrorCorrectionCode -2))
			return 0;
		else
			return getNextBits(4);
	}
	
	int guessMode(int mode) {
		//correct modes: 0001 0010 0100 1000
		//possible data: 0000 0011 0101 1001 0110 1010 1100
		//               0111 1101 1011 1110 1111
//		MODE_NUMBER = 1;
//		MODE_ROMAN_AND_NUMBER = 2;
//		MODE_8BIT_BYTE = 4;
//		MODE_KANJI = 8;
		switch (mode) {
		case 3:
			return MODE_NUMBER;
		case 5:
			return MODE_8BIT_BYTE;
		case 6:
			return MODE_8BIT_BYTE;
		case 7:
			return MODE_8BIT_BYTE;
		case 9:
			return MODE_KANJI;
		case 10:
			return MODE_KANJI;
		case 11:
			return MODE_KANJI;
		case 12:
			return MODE_8BIT_BYTE;
		case 13:
			return MODE_8BIT_BYTE;
		case 14:
			return MODE_8BIT_BYTE;
		case 15:
			return MODE_8BIT_BYTE;
		default:
			return MODE_KANJI;
		}
	}

	int getDataLength(int modeIndicator) throws ArrayIndexOutOfBoundsException {
		int index = 0;
		while(true) {
			if ((modeIndicator >> index) == 1)
				break;
			index++;
		}
		
		return getNextBits(sizeOfDataLengthInfo[dataLengthMode][index]);
	}

	public byte[] getDataByte() throws InvalidDataBlockException {
		canvas.println("Reading data blocks.");
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		
		try {
			do {
				int mode = getNextMode();
				//canvas.println("mode: " + mode);
				if (mode == 0) {
					if (output.size() > 0)
						break;
					else
						throw new InvalidDataBlockException("Empty data block");
				}
				//if (mode != 1 && mode != 2 && mode != 4 && mode != 8)
				//	break;
				//}
				if (mode != MODE_NUMBER && mode != MODE_ROMAN_AND_NUMBER &&
						mode != MODE_8BIT_BYTE && mode != MODE_KANJI) {
/*					canvas.println("Invalid mode: " + mode);
					mode = guessMode(mode);
					canvas.println("Guessed mode: " + mode); */
					throw new InvalidDataBlockException("Invalid mode: " + mode + " in (block:"+blockPointer+" bit:"+bitPointer+")");
				}
				dataLength = getDataLength(mode);
				if (dataLength < 1)
					throw new InvalidDataBlockException("Invalid data length: " + dataLength);
				//canvas.println("length: " + dataLength);
				switch (mode) {
				case MODE_NUMBER:
					//canvas.println("Mode: Figure");
					output.write(getFigureString(dataLength).getBytes());
					break;
				case MODE_ROMAN_AND_NUMBER:
					//canvas.println("Mode: Roman&Figure");
					output.write(getRomanAndFigureString(dataLength).getBytes());
					break;
				case MODE_8BIT_BYTE:
					//canvas.println("Mode: 8bit Byte");
					output.write(get8bitByteArray(dataLength));
					break;
				case MODE_KANJI:
					//canvas.println("Mode: Kanji");
					output.write(getKanjiString(dataLength).getBytes());
					break;
				}
	//			
				//canvas.println("DataLength: " + dataLength);
				//System.out.println(dataString);
			} while (true);
		} catch (ArrayIndexOutOfBoundsException e) {
			e.printStackTrace();
			throw new InvalidDataBlockException("Data Block Error in (block:"+blockPointer+" bit:"+bitPointer+")");
		} catch (IOException e) {
			throw new InvalidDataBlockException(e.getMessage());
		}
		return output.toByteArray();
	}
	
	public String getDataString() throws ArrayIndexOutOfBoundsException {
		canvas.println("Reading data blocks...");
		String dataString = "";
		do {
			int mode = getNextMode();
			canvas.println("mode: " + mode);
			if (mode == 0)
				break;
			//if (mode != 1 && mode != 2 && mode != 4 && mode != 8)
			//	break;
			//}
			if (mode != MODE_NUMBER && mode != MODE_ROMAN_AND_NUMBER &&
					mode != MODE_8BIT_BYTE && mode != MODE_KANJI) {
				// mode = guessMode(mode);
				// do not guesswork
				//System.out.println("guessed mode: " + mode);

			}
				
			dataLength = getDataLength(mode);
			canvas.println(Integer.toString(blocks[blockPointer]));
			System.out.println("length: " + dataLength);
			switch (mode) {
			case MODE_NUMBER: 
				//canvas.println("Mode: Figure");
				dataString += getFigureString(dataLength);
				break;
			case MODE_ROMAN_AND_NUMBER:
				//canvas.println("Mode: Roman&Figure");
				dataString += getRomanAndFigureString(dataLength);
				break;
			case MODE_8BIT_BYTE:
				//canvas.println("Mode: 8bit Byte");
				dataString += get8bitByteString(dataLength);
				break;
			case MODE_KANJI:
				//canvas.println("Mode: Kanji");
				dataString += getKanjiString(dataLength);
				break;
			}
			//canvas.println("DataLength: " + dataLength);
			//System.out.println(dataString);
		} while (true);
		System.out.println("");
		return dataString;
	}
	
	
	String getFigureString(int dataLength) throws ArrayIndexOutOfBoundsException {
		int length = dataLength;
		int intData = 0;
		String strData = "";
		do {
			if (length >= 3) {
				intData = getNextBits(10);
				if (intData < 100) strData += "0";
				if (intData < 10) strData += "0";
				length -= 3;
			}
			else if (length == 2) {
				intData = getNextBits(7);
				if (intData < 10) strData += "0";
				length -= 2;
			}
			else if (length == 1) {
				intData = getNextBits(4);
				length -= 1;
			}				
			strData += Integer.toString(intData);
		} while (length > 0);
		
		return strData;
	}
	
	String getRomanAndFigureString(int dataLength) throws ArrayIndexOutOfBoundsException  {
		int length = dataLength;
		int intData = 0;
		String strData = "";
		final char[] tableRomanAndFigure = {
			 '0', '1', '2', '3', '4', '5',
	 		 '6', '7', '8', '9', 'A', 'B',
			 'C', 'D', 'E', 'F', 'G', 'H',
			 'I', 'J', 'K', 'L', 'M', 'N',
			 'O', 'P', 'Q', 'R', 'S', 'T',
			 'U', 'V', 'W', 'X', 'Y', 'Z',
			 ' ', '$', '%', '*', '+', '-',
			 '.', '/', ':'
			 };
		do {
			if (length > 1) {
				intData = getNextBits(11);
				int firstLetter = intData / 45;
				int secondLetter = intData % 45;
				strData += String.valueOf(tableRomanAndFigure[firstLetter]);
				strData += String.valueOf(tableRomanAndFigure[secondLetter]);
				length -= 2;
			}
			else if (length == 1) {
				intData = getNextBits(6);
				strData += String.valueOf(tableRomanAndFigure[intData]);
				length -= 1;
			}
		} while (length > 0);
		
		return strData;
	}
	
	public byte[] get8bitByteArray(int dataLength) throws ArrayIndexOutOfBoundsException  {
		int length = dataLength;
		int intData = 0;
		ByteArrayOutputStream output=new ByteArrayOutputStream();

		do {
			intData = getNextBits(8);
			output.write((byte)intData);
			length--;
		} while (length > 0);
		return output.toByteArray();
	}

	String get8bitByteString(int dataLength) throws ArrayIndexOutOfBoundsException  {
		int length = dataLength;
		int intData = 0;
		String strData = "";
		do {
			intData = getNextBits(8);
			strData+=(char)intData;
			length--;
		} while (length > 0);
		return strData;
	}

	String getKanjiString(int dataLength) throws ArrayIndexOutOfBoundsException {
		int length = dataLength;
		int intData = 0;
		String unicodeString = "";
		do {
			intData = getNextBits(13);
			int lowerByte = intData % 0xC0;
			int higherByte = intData / 0xC0;

			int tempWord = (higherByte << 8) + lowerByte;
			int shiftjisWord = 0;
			if (tempWord + 0x8140 <= 0x9FFC) { // between 8140 - 9FFC on Shift_JIS character set
				shiftjisWord = tempWord + 0x8140;
			}
			else { // between E040 - EBBF on Shift_JIS character set
				shiftjisWord = tempWord + 0xC140;
			}

			byte[] tempByte = new byte[2];
			tempByte[0] = (byte)(shiftjisWord >> 8);
			tempByte[1] = (byte)(shiftjisWord & 0xFF);
			unicodeString += new String(tempByte);
			length--;
		} while (length > 0);

			
		return unicodeString;
	}
	
}

⌨️ 快捷键说明

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