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

📄 qrcodeimagereader.java

📁 qrcode的java开源版本
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
package jp.sourceforge.qrcode.codec.reader;


import java.util.Vector;

import jp.sourceforge.qrcode.codec.QRCodeDecoder;
import jp.sourceforge.qrcode.codec.data.*;
import jp.sourceforge.qrcode.codec.exception.AlignmentPatternNotFoundException;
import jp.sourceforge.qrcode.codec.exception.FinderPatternNotFoundException;
import jp.sourceforge.qrcode.codec.exception.SymbolNotFoundException;
import jp.sourceforge.qrcode.codec.exception.InvalidVersionException;
import jp.sourceforge.qrcode.codec.exception.VersionInformationException;
import jp.sourceforge.qrcode.codec.geom.*;
import jp.sourceforge.qrcode.codec.reader.pattern.*;
import jp.sourceforge.qrcode.codec.util.*;

public class QRCodeImageReader {
	DebugCanvas canvas;
	//boolean[][] image;
	//DP = 
	//23 ...side pixels of image will be limited maximum 255 (8 bits)
	//22 .. side pixels of image will be limited maximum 511 (9 bits)
	//21 .. side pixels of image will be limited maximum 1023 (10 bits)
	
	//I think it's good idea to use DECIMAL_POINT with type "long" too.
	
	public static int DECIMAL_POINT = 21;
	public static final boolean POINT_DARK = true;
	public static final boolean POINT_LIGHT = false;
	SamplingGrid samplingGrid;
	boolean[][] bitmap;
	//int numModuleAtSide; //デコード対象のシンボルにおける一辺のモジュールの数

	
	public QRCodeImageReader() {
		this.canvas = QRCodeDecoder.getCanvas();
	}
	// local class for module pitch
	private class ModulePitch
	{
		public int top;
		public int left;
		public int bottom;
		public int right;
	};


	boolean[][] applyMedianFilter(boolean[][] image, int threshold) {
		boolean[][] filteredMatrix = new boolean[image.length][image[0].length];
		//filtering noise in image with median filter
		int numPointDark;
		for (int y = 1; y < image[0].length - 1; y++) {
			for (int x = 1; x < image.length - 1; x++) {
			//if (image[x][y] == true) {
			numPointDark = 0;
			for (int fy = -1; fy < 2; fy++) {
				for (int fx = -1; fx < 2; fx++) {
					if (image[x + fx][y + fy] == true) {
						numPointDark++;
					}
				}
			}
			if (numPointDark > threshold) 
				filteredMatrix[x][y] = POINT_DARK;
			}
		}
		
		return filteredMatrix;
	}
	boolean[][] applyCrossMaskingMedianFilter(boolean[][] image, int threshold) {
		boolean[][] filteredMatrix = new boolean[image.length][image[0].length];
		//filtering noise in image with median filter
		int numPointDark;
		for (int y = 2; y < image[0].length - 2; y++) {
			for (int x = 2; x < image.length - 2; x++) {
			//if (image[x][y] == true) {
			numPointDark = 0;
			for (int f = -2; f < 3; f++) {
				if (image[x+f][y] == true)
					numPointDark++;
				
				if (image[x][y+f] == true)
					numPointDark++;
			}
			
			if (numPointDark > threshold) 
				filteredMatrix[x][y] = POINT_DARK;
			}
		}
		
		return filteredMatrix;
	}	
	boolean[][] filterImage(int[][] image) {
		imageToGrayScale(image);
		boolean[][] bitmap = grayScaleToBitmap(image);
		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 = getMiddleBrightnessPerArea(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[][] getMiddleBrightnessPerArea(int[][] image) {
		final int numSqrtArea = 4;
		//obtain middle brightness((min + max) / 2) per area
		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;
	}
	
	public QRCodeSymbol getQRCodeSymbol(int[][] image) 
			throws SymbolNotFoundException {
		int longSide = (image.length < image[0].length) ? image[0].length : image.length;
		QRCodeImageReader.DECIMAL_POINT = 23 - QRCodeUtility.sqrt(longSide / 256);
		bitmap = filterImage(image);			
		canvas.println("Drawing matrix.");
		canvas.drawMatrix(bitmap);

		canvas.println("Scanning Finder Pattern.");
		FinderPattern finderPattern = null;
		try {
			finderPattern = FinderPattern.findFinderPattern(bitmap);
		} catch (FinderPatternNotFoundException e) {
			canvas.println("Not found, now retrying...");
			bitmap = applyCrossMaskingMedianFilter(bitmap, 5);
			canvas.drawMatrix(bitmap);
			for (int i=0; i< 1000000000;i++);
			try {
				finderPattern = FinderPattern.findFinderPattern(bitmap);
			} catch (FinderPatternNotFoundException e2) {
				throw new SymbolNotFoundException(e2.getMessage());
			} catch (VersionInformationException e2) {
				throw new SymbolNotFoundException(e2.getMessage());
			}
		} catch (VersionInformationException e) {
			throw new SymbolNotFoundException(e.getMessage());
		}


		canvas.println("FinderPattern at");
		String finderPatternCoordinates = 
			finderPattern.getCenter(FinderPattern.UL).toString() + 
			finderPattern.getCenter(FinderPattern.UR).toString() +
			finderPattern.getCenter(FinderPattern.DL).toString();
		canvas.println(finderPatternCoordinates);
 		int[] sincos = finderPattern.getAngle();
		canvas.println("Angle*4098: Sin " + Integer.toString(sincos[0]) + "  " + "Cos " + Integer.toString(sincos[1]));

		int version = finderPattern.getVersion();
		canvas.println("Version: " + Integer.toString(version));
		if (version < 1 || version > 40)
			throw new InvalidVersionException("Invalid version: " + version);
		
		AlignmentPattern alignmentPattern = null;
		try {
			alignmentPattern = AlignmentPattern.findAlignmentPattern(bitmap, finderPattern);
		} catch (AlignmentPatternNotFoundException e) {
			throw new SymbolNotFoundException(e.getMessage());
		}
		
		int matrixLength = alignmentPattern.getCenter().length;
		canvas.println("AlignmentPatterns at");
		for (int y = 0; y < matrixLength; y++) {
			String alignmentPatternCoordinates = "";
			for (int x = 0; x < matrixLength; x++) {
				alignmentPatternCoordinates += alignmentPattern.getCenter()[x][y].toString();
			}
			canvas.println(alignmentPatternCoordinates);
		}
		//for(int i = 0; i < 500000; i++) System.out.println("");

		canvas.println("Creating sampling grid.");
		//[TODO] need all-purpose method
		//samplingGrid = getSamplingGrid2_6(finderPattern, alignmentPattern);
		samplingGrid = getSamplingGrid(finderPattern, alignmentPattern);
		canvas.println("Reading grid.");
		boolean[][] qRCodeMatrix = null;
		try {
			qRCodeMatrix = getQRCodeMatrix(bitmap, samplingGrid);
		} catch (ArrayIndexOutOfBoundsException e) {
			throw new SymbolNotFoundException("Sampling grid exceeded image boundary");
		}
		//canvas.drawMatrix(qRCodeMatrix);
		return new QRCodeSymbol(qRCodeMatrix);
	}
	
	public QRCodeSymbol getQRCodeSymbolWithAdjustedGrid(Point adjust)
		throws IllegalStateException, SymbolNotFoundException {
		if (bitmap == null || samplingGrid == null) {
			throw new IllegalStateException("This method must be called after QRCodeImageReader.getQRCodeSymbol() called");
		}
		samplingGrid.adjust(adjust);
		canvas.println("Sampling grid adjusted d("+adjust.getX()+","+adjust.getY()+")");

		boolean[][] qRCodeMatrix = null;
		try { 
			qRCodeMatrix = getQRCodeMatrix(bitmap, samplingGrid);
		} catch (ArrayIndexOutOfBoundsException e) {
			throw new SymbolNotFoundException("Sampling grid exceeded image boundary");			
		}
		return new QRCodeSymbol(qRCodeMatrix);
	}
	
	// For only version 1 which has no Alignement Patterns
/*	SamplingGrid getSamplingGrid1(FinderPattern finderPattern) {
		int sqrtNumArea = 1;
		int sqrtNumModules = finderPattern.getSqrtNumModules(); //get nummber of modules at side
		int sqrtNumAreaModules = sqrtNumModules / sqrtNumArea;
		Point[] centers = finderPattern.getCenter();
		int logicalDistance = 14;
		SamplingGrid samplingGrid = new SamplingGrid(sqrtNumArea);
		Line baseLineX, baseLineY, gridLineX, gridLineY;

		
		ModulePitch modulePitch = new ModulePitch(); //store (up,left) order
		modulePitch.top = getAreaModulePitch(centers[0], centers[1], logicalDistance);
		modulePitch.left = getAreaModulePitch(centers[0], centers[2], logicalDistance);

		//X軸に垂直の基線(一般に縦)
		baseLineX = new Line(
				finderPattern.getCenter(FinderPattern.UL), 
				finderPattern.getCenter(FinderPattern.DL));

		Axis axis = new Axis(finderPattern.getAngle(), modulePitch.top);
		axis.setOrigin(baseLineX.getP1());
		baseLineX.setP1(axis.translate(-3, -3));

		axis.setModulePitch(modulePitch.left);
		axis.setOrigin(baseLineX.getP2());
		baseLineX.setP2(axis.translate(-3, 3));

		//Y軸に垂直の基線(一般に横)
	  baseLineY =
			new Line(finderPattern.getCenter(FinderPattern.UL),
					finderPattern.getCenter(FinderPattern.UR));
	  

⌨️ 快捷键说明

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