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

📄 qrcodedecoder.java

📁 QRcode二维码生成源代码,一个做条形码的代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * 嶌惉擔丗 2004/09/12
 *
 * TODO 偙偺惗惉偝傟偨僼傽僀儖偺僥儞僾儗乕僩傪曄峏偡傞偵偼師傪嶲徠丅
 * 僂傿儞僪僂 亜 愝掕 亜 Java 亜 僐乕僪丒僗僞僀儖 亜 僐乕僪丒僥儞僾儗乕僩
 */
package jp.sourceforge.qrcode.codec;

import java.util.Vector;

import jp.sourceforge.qrcode.codec.data.QRCodeSymbol;
import jp.sourceforge.qrcode.codec.ecc.BCH15_5;
import jp.sourceforge.qrcode.codec.ecc.ReedSolomon;
import jp.sourceforge.qrcode.codec.exception.AlignmentPatternEdgeNotFoundException;
import jp.sourceforge.qrcode.codec.exception.DecodingFailedException;
import jp.sourceforge.qrcode.codec.exception.FinderPatternNotFoundException;
import jp.sourceforge.qrcode.codec.exception.IllegalDataBlockException;
import jp.sourceforge.qrcode.codec.exception.SymbolNotFoundException;
import jp.sourceforge.qrcode.codec.exception.VersionInformationException;
import jp.sourceforge.qrcode.codec.reader.QRCodeDataBlockReader;
import jp.sourceforge.qrcode.codec.reader.QRCodeImageReader;
import jp.sourceforge.qrcode.codec.util.DebugCanvas;

/**
 * @author Owner
 *
 * TODO 偙偺惗惉偝傟偨宆僐儊儞僩偺僥儞僾儗乕僩傪曄峏偡傞偵偼師傪嶲徠丅
 * 僂傿儞僪僂 亜 愝掕 亜 Java 亜 僐乕僪丒僗僞僀儖 亜 僐乕僪丒僥儞僾儗乕僩
 */
public class QRCodeDecoder {
	//QRCodeImageReader reader;
	int internalScale;
	QRCodeSymbol symbol;
	DebugCanvas canvas;
	//僨僐乕僟杮懱
	public QRCodeDecoder() {
		internalScale = 2;
		canvas = DebugCanvas.getCanvas();
	}
	
	public String decode(int[][] image) throws DecodingFailedException{
		canvas.println("Decoding started.");
		try {
			symbol = getQRCodeSymbol(image);
		} catch (SymbolNotFoundException e) {
			e.printStackTrace();
			throw new DecodingFailedException();
		}
		canvas.println("Created QRCode symbol.");
		//int ratio = canvas.getWidth() / symbol.getWidth();
		//canvas.drawMatrix(symbol , ratio);
		canvas.println("Reading symbol.");
		boolean[] formatInformation = getFormatInformation(symbol);
		symbol.setFormatInformation(formatInformation);
		canvas.println("Version: " + symbol.getVersionReference());
		String maskPattern = Integer.toString(symbol.getMaskPatternReferer() ,2);
		int length = maskPattern.length();
		for (int i = 0; i < 3 - length; i++)
			maskPattern = "0" + maskPattern;
		
		canvas.println("Mask pattern: " + maskPattern);
		canvas.println("Unmasking.");
		unmask(symbol);
		//canvas.drawMatrix(symbol, 4);
		int[] blocks = getBlocks(symbol);
		canvas.println("Correcting data errors.");
		int[] dataBlocks = getCorrectedDataBlocks(blocks);
		String decodedString = "";
		try {
			decodedString = getDecodedString(dataBlocks, symbol.getVersion());
		} catch (IllegalDataBlockException e) {
			e.printStackTrace();
			throw new DecodingFailedException();
		}
//		return new QRCodeContent(decodedString);
		canvas.println("Decoding finished.");
		return decodedString;
	}
	
	boolean[][] processImage(int[][] image) {
		imageToGrayScale(image);
		boolean[][] bitmap = grayScaleToBitmap(image);
		//boolean[][] bitmapEx = extendBitmap(bitmap, internalScale);
		return bitmap;
	}
	
	void imageToGrayScale(int[][] image) {
		for (int y = 0; y < image[0].length; y++) {
			for (int x = 0; x < image.length; x++) {
				int r = image[x][y] >> 16 & 0xFF;
				int g = image[x][y] >> 8 & 0xFF;
				int b = image[x][y] & 0xFF;
				int m = (r * 30 + g * 59 + b * 11) / 100;
				image[x][y] = m;
			}
		}
	}
	
	boolean[][] grayScaleToBitmap_(int[][] grayScale) {
		int[][] middle = findAreaMiddle(grayScale);
		int[] minmax = findMinMax(grayScale);
		boolean[][] bitmap = new boolean[grayScale.length][grayScale[0].length];
		int halftone = (minmax[0] + minmax[1]) / 2;

		for (int y = 0; y < grayScale[0].length; y++) {
			for (int x = 0; x < grayScale.length; x++) {
				bitmap[x][y] = (grayScale[x][y] < halftone) ? true : false;
			}
		}
		
		return bitmap;
	}
	boolean[][] grayScaleToBitmap(int[][] grayScale) {
		int[][] middle = findAreaMiddle(grayScale);
		int sqrtNumArea = middle.length;
		int areaWidth = grayScale.length / sqrtNumArea;
		int areaHeight = grayScale[0].length / sqrtNumArea;
		boolean[][] bitmap = new boolean[grayScale.length][grayScale[0].length];

		for (int ay = 0; ay < sqrtNumArea; ay++) {
			for (int ax = 0; ax < sqrtNumArea; ax++) {
				for (int dy = 0; dy < areaHeight; dy++) {
					for (int dx = 0; dx < areaWidth; dx++) {
						bitmap[areaWidth * ax + dx][areaHeight * ay + dy] = (grayScale[areaWidth * ax + dx][areaHeight * ay + dy] < middle[ax][ay]) ? true : false;
					}
				}
			}
		}
		return bitmap;
	}
	
	int[] findMinMax(int[][] image) {
		int tempMin = Integer.MAX_VALUE;
		int tempMax = Integer.MIN_VALUE;
		for (int y = 0; y < image[0].length; y++) {
			for (int x = 0; x < image.length; x++) {
				if (image[x][y] < tempMin)
					tempMin = image[x][y];
				else if (image[x][y] > tempMax)
					tempMax = image[x][y];
			}
		}
		return new int[] {tempMin, tempMax};
	}
	
	int[][] findAreaMiddle(int[][] image) {
		final int numSqrtArea = 4;
		//4x4偺僄儕傾偛偲偺柧傞偝偺拞娫抣((min + max) / 2)傪弌偡
		int areaWidth = image.length / numSqrtArea;
		int areaHeight = image[0].length / numSqrtArea;
		int[][][] minmax = new int[numSqrtArea][numSqrtArea][2];
		for (int ay = 0; ay < numSqrtArea; ay++) {
			for (int ax = 0; ax < numSqrtArea; ax++) {
				minmax[ax][ay][0] = 0xFF;
				for (int dy = 0; dy < areaHeight; dy++) {
					for (int dx = 0; dx < areaWidth; dx++) {
						int target = image[areaWidth * ax + dx][areaHeight * ay + dy];
						if (target < minmax[ax][ay][0]) minmax[ax][ay][0] = target;
						if (target > minmax[ax][ay][1]) minmax[ax][ay][1] = target;
					}
				}
				//minmax[ax][ay][0] = (minmax[ax][ay][0] + minmax[ax][ay][1]) / 2;
			}
		}
		int[][] middle =  new int[numSqrtArea][numSqrtArea];
		for (int ay = 0; ay < numSqrtArea; ay++) {
			for (int ax = 0; ax < numSqrtArea; ax++) {
				middle[ax][ay] = (minmax[ax][ay][0] + minmax[ax][ay][1]) / 2;
				//System.out.print(middle[ax][ay] + ",");
			}
			//System.out.println("");
		}
		//System.out.println("");

		return middle;
	}
	
	boolean[][] extendBitmap(boolean[][] bitmap, int scale) {
		boolean[][] bitmap2x = new boolean[bitmap.length * 2][bitmap[0].length * 2];
		for (int y = 0; y < bitmap[0].length; y++) {
			for (int x = 0; x < bitmap.length; x++) {
				if (bitmap[x][y] == true) {
					for (int sx = 0; sx < scale; sx++)
						for (int sy = 0; sy < scale; sy++)
							bitmap2x[x * scale + sx][y * scale + sy] = true;
				}
					
			}
		}
		return bitmap2x;
	}

	QRCodeSymbol getQRCodeSymbol(int[][] image) throws SymbolNotFoundException {

		//canvas.println("Creating binary matrix.");
 		//BinaryMatrix binaryImage = new BinaryMatrix(imageData);
		//canvas.println("Drawing matrix.");
 		//canvas.drawMatrix(binaryImage);
 		//canvas.println("Reading matrix");
 		canvas.println("Creating bitmap.");
		boolean[][] bitmap = processImage(image);
		QRCodeImageReader reader = new QRCodeImageReader();

		QRCodeSymbol symbol = null;
		try {
			symbol = reader.getQRCodeSymbol(bitmap, internalScale);
		} catch (FinderPatternNotFoundException e) {
			throw new SymbolNotFoundException();
		} catch (VersionInformationException e2) {
			throw new SymbolNotFoundException();
		} catch (AlignmentPatternEdgeNotFoundException e3) {
			throw new SymbolNotFoundException();
		}
		return symbol;
	}
	
	boolean[] getFormatInformation(QRCodeSymbol qRCodeMatrix) {
		boolean[] modules = new boolean[15];

		//儅僩儕僢僋僗偐傜宍幃忣曬晹暘庢傝弌偟
		for (int i = 0; i <= 5; i++)
			modules[i] = qRCodeMatrix.getElement(8, i);
		
		modules[6] = qRCodeMatrix.getElement(8, 7);
		modules[7] = qRCodeMatrix.getElement(8, 8);
		modules[8] = qRCodeMatrix.getElement(7, 8);
		
		for (int i = 9; i <= 14; i++)
			modules[i] = qRCodeMatrix.getElement(14 - i, 8);
		
		//XOR墘嶼偱儅僗僋張棟
		int maskPattern = 0x5412;
		
		for (int i = 0; i <= 14; i++) {
			boolean xorBit = false;
			if (((maskPattern >>> i) & 1) == 1)
				xorBit = true;
			else
				xorBit = false;
			
			if (modules[i] == xorBit) //價僢僩僔僼僩偟偨屻偺堦寘栚傪尒傞
				modules[i] = false;
			else
				modules[i] = true;
		}
		//int a[] = {0,1,2,4,8,3,6,12,11,5,10,7,14,15,13,9,1};
		//System.out.println("debug");
		//printBit("formatInfo", modules);
		
		//僄儔乕掶惓
		BCH15_5 corrector = new BCH15_5(modules);
		boolean[] output = corrector.correct();
		int numError = corrector.getNumCorrectedError();
		if (numError > 0)
			canvas.println(String.valueOf(numError) + " format errors corrected.");
		boolean[] formatInformation = new boolean[5];
		for (int i = 0; i < 5; i++)
			formatInformation[i] = output[10 + i];
		
		return formatInformation;
		
	}
	
	void unmask(QRCodeSymbol symbol) {
		int maskPatternReferer = symbol.getMaskPatternReferer();
		
		//儅僗僋僷僞乕儞惗惉
		boolean[][] maskPattern = generateMaskPattern(symbol);

		int size = symbol.getWidth();
		
		for (int y = 0; y < size; y++) {
			for (int x = 0; x < size; x++) {
				if (maskPattern[x][y] == true) {
					symbol.reverseElement(x, y);
				}
			}
		}
	}
	
	boolean[][] generateMaskPattern(QRCodeSymbol symbol) {
		int maskPatternReferer = symbol.getMaskPatternReferer();
		
		//儅僗僋僷僞乕儞惗惉
		int width = symbol.getWidth();
		int height = symbol.getHeight();
		boolean[][] maskPattern = new boolean[width][height];
		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				if (symbol.isInFunctionPattern(x, y))
					continue;
				switch (maskPatternReferer) {
				case 0: // 000
					if ((x + y) % 2 == 0)
						maskPattern[x][y] = true;
					break;
				case 1: // 001
					if (y % 2 == 0)
						maskPattern[x][y] = true;
					break;
				case 2: // 010

⌨️ 快捷键说明

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