📄 qrcodeimagereader.java
字号:
package jp.sourceforge.qrcode.reader;import java.util.Vector;import jp.sourceforge.qrcode.QRCodeDecoder;import jp.sourceforge.qrcode.data.*;import jp.sourceforge.qrcode.exception.AlignmentPatternNotFoundException;import jp.sourceforge.qrcode.exception.FinderPatternNotFoundException;import jp.sourceforge.qrcode.exception.SymbolNotFoundException;import jp.sourceforge.qrcode.exception.InvalidVersionException;import jp.sourceforge.qrcode.exception.VersionInformationException;import jp.sourceforge.qrcode.geom.*;import jp.sourceforge.qrcode.pattern.*;import jp.sourceforge.qrcode.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 protected 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); 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 Alignment Patterns/* SamplingGrid getSamplingGrid1(FinderPattern finderPattern) { int sqrtNumArea = 1; int sqrtNumModules = finderPattern.getSqrtNumModules(); //get number 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)); axis.setModulePitch(modulePitch.left);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -