📄 qrcodesymbol.java
字号:
package jp.sourceforge.qrcode.data;import java.util.Vector;import jp.sourceforge.qrcode.ecc.BCH15_5;import jp.sourceforge.qrcode.geom.*;import jp.sourceforge.qrcode.pattern.LogicalSeed;public class QRCodeSymbol { int version; int errorCollectionLevel; int maskPattern; int dataCapacity; boolean[][] moduleMatrix; int width, height; Point[][] alignmentPattern; final int[][] numErrorCollectionCode = { { 7,10,13,17 }, { 10,16,22,28 }, { 15,26,36,44 }, { 20,36,52,64 }, { 26,48,72,88 }, { 36,64,96,112 }, { 40,72,108,130 }, { 48,88,132,156 }, { 60,110,160,192 }, { 72,130,192,224 }, { 80,150,224,264 }, { 96,176,260,308 }, { 104,198,288,352 }, { 120,216,320,384 }, { 132,240,360,432 }, { 144,280,408,480 }, { 168,308,448,532 }, { 180,338,504,588 }, { 196,364,546,650 }, { 224,416,600,700 }, { 224,442,644,750 }, { 252,476,690,816 }, { 270,504,750,900 }, { 300,560,810,960 }, { 312,588,870,1050 }, { 336,644,952,1110 }, { 360,700,1020,1200 }, { 390,728,1050,1260 }, { 420,784,1140,1350 }, { 450,812,1200,1440 }, { 480,868,1290,1530 }, { 510,924,1350,1620 }, { 540,980,1440,1710 }, { 570,1036,1530,1800 }, { 570,1064,1590,1890 }, { 600,1120,1680,1980 }, { 630,1204,1770,2100 }, { 660,1260,1860,2220 }, { 720,1316,1950,2310 }, { 750,1372,2040,2430 } }; final int[][] numRSBlocks = { { 1,1,1,1 }, { 1,1,1,1 }, { 1,1,2,2 }, { 1,2,2,4 }, { 1,2,4,4 }, { 2,4,4,4 }, { 2,4,6,5 }, { 2,4,6,6 }, { 2,5,8,8 }, { 4,5,8,8 }, { 4,5,8,11 }, { 4,8,10,11 }, { 4,9,12,16 }, { 4,9,16,16 }, { 6,10,12,18 }, { 6,10,17,16 }, { 6,11,16,19 }, { 6,13,18,21 }, { 7,14,21,25 }, { 8,16,20,25 }, { 8,17,23,25 }, { 9,17,23,34 }, { 9,18,25,30 }, { 10,20,27,32 }, { 12,21,29,35 }, {12,23,34,37 }, { 12,25,34,40 }, { 13,26,35,42 }, { 14,28,38,45 }, { 15,29,40,48 }, { 16,31,43,51 }, { 17,33,45,54 }, { 18,35,48,57 }, { 19,37,51,60 }, { 19,38,53,63 }, { 20,40,56,66 }, { 21,43,59,70 }, { 22,45,62,74 }, { 24,47,65,77 }, { 25,49,68,81 } }; public boolean getElement(int x, int y) { return moduleMatrix[x][y]; } public int getNumErrorCollectionCode() { return numErrorCollectionCode[version - 1][errorCollectionLevel]; } public int getNumRSBlocks() { return numRSBlocks[version - 1][errorCollectionLevel]; } public QRCodeSymbol(boolean[][] moduleMatrix) { this.moduleMatrix = moduleMatrix; width = moduleMatrix.length; height = moduleMatrix[0].length; initialize(); } void initialize() { //calculate version by number of side modules version = (width - 17) / 4; Point[][] alignmentPattern = new Point[1][1]; int[] logicalSeeds = new int[1];/* //create "row coordinates" be based on relative coordinates if (version >= 2 && version <= 6) { logicalSeeds = new int[2]; logicalSeeds[0] = 6; logicalSeeds[1] = 10 + 4 * version; alignmentPattern = new Point[logicalSeeds.length][logicalSeeds.length]; } else if (version >= 7 && version <= 13) { logicalSeeds = new int[3]; logicalSeeds[0] = 6; logicalSeeds[1] = 8 + 2 * version; logicalSeeds[2] = 10 + 4 * version; alignmentPattern = new Point[logicalSeeds.length][logicalSeeds.length]; }*/ if (version>=2 && version <=40) { //int sqrtCenters = (version / 7) + 2; //logicalSeeds = new int[sqrtCenters]; //for(int i=0 ; i<sqrtCenters ; i++) { // logicalSeeds[i] = 6 + i * (4 + 4 * version) / (sqrtCenters - 1); // logicalSeeds[i] -= (logicalSeeds[i] - 2) % 4; //} logicalSeeds = LogicalSeed.getSeed(version); alignmentPattern = new Point[logicalSeeds.length][logicalSeeds.length]; } //obtain alignment pattern's center coordintates by logical seeds for (int col = 0; col < logicalSeeds.length; col++) { //列 for (int row = 0; row < logicalSeeds.length; row++) { //行 alignmentPattern[row][col] = new Point(logicalSeeds[row], logicalSeeds[col]); } } this.alignmentPattern = alignmentPattern; dataCapacity = calcDataCapacity(); boolean[] formatInformation = readFormatInformation(); decodeFormatInformation(formatInformation); unmask(); } public int getVersion() { return version; } public String getVersionReference() { final char[] versionReferenceCharacter = {'L', 'M', 'Q', 'H'}; return Integer.toString(version)+ "-" + versionReferenceCharacter[errorCollectionLevel]; } public Point[][] getAlignmentPattern() { return alignmentPattern; } boolean[] readFormatInformation() { boolean[] modules = new boolean[15]; //obtain format information from symbol for (int i = 0; i <= 5; i++) modules[i] = getElement(8, i); modules[6] = getElement(8, 7); modules[7] = getElement(8, 8); modules[8] = getElement(7, 8); for (int i = 9; i <= 14; i++) modules[i] = getElement(14 - i, 8); //unmask Format Information's with given mask pattern. (JIS-X-0510(2004), p65) int maskPattern = 0x5412; for (int i = 0; i <= 14; i++) { boolean xorBit = false; if (((maskPattern >>> i) & 1) == 1) xorBit = true; else xorBit = false; // get unmasked format information with bit shift if (modules[i] == xorBit) modules[i] = false; else modules[i] = true; } 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() { boolean[][] maskPattern = generateMaskPattern(); int size = getWidth(); for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { if (maskPattern[x][y] == true) { reverseElement(x, y); } } } } boolean[][] generateMaskPattern() { int maskPatternReferer = getMaskPatternReferer(); int width = getWidth(); int height = getHeight(); boolean[][] maskPattern = new boolean[width][height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (isInFunctionPattern(x, y)) continue; switch (maskPatternReferer) { case 0: // 000 if ((y + x) % 2 == 0) maskPattern[x][y] = true; break; case 1: // 001 if (y % 2 == 0) maskPattern[x][y] = true; break; case 2: // 010 if (x % 3 == 0) maskPattern[x][y] = true; break; case 3: // 011 if ((y + x) % 3 == 0) maskPattern[x][y] = true; break; case 4: // 100 if ((y / 2 + x / 3) % 2 == 0) maskPattern[x][y] = true; break; case 5: // 101 if ((y * x) % 2 + (y * x) % 3 == 0) maskPattern[x][y] = true; break; case 6: // 110 if (((y * x) % 2 + (y * x) % 3) % 2 == 0) maskPattern[x][y] = true; break; case 7: // 111 if (((y * x) % 3 + (y + x) % 2) % 2 == 0) maskPattern[x][y] = true; break; } } } return maskPattern; } private int calcDataCapacity() { int numFunctionPatternModule = 0; int numFormatAndVersionInfoModule = 0; int version = this.getVersion(); //System.out.println("Version:" + String.valueOf(version)); if (version <= 6) numFormatAndVersionInfoModule = 31; else numFormatAndVersionInfoModule = 67; // the number of finter patterns : int sqrtCenters = (version / 7) + 2; // the number of modules left when we remove the patterns modules // 3*64 for the 3 big ones, // sqrtCenters*sqrtCenters)-3)*25 for the small ones int modulesLeft = (version==1?192:192+((sqrtCenters*sqrtCenters)-3)*25); // Don't ask me how I found that one... // numFunctionPatternModule = modulesLeft +8 * version + 2 - (sqrtCenters-2)*10; int dataCapacity = (width * width - numFunctionPatternModule - numFormatAndVersionInfoModule) / 8; return dataCapacity; } public int getDataCapacity() { return this.dataCapacity; } void decodeFormatInformation(boolean[] formatInformation) { if (formatInformation[4] == false) if (formatInformation[3] == true) errorCollectionLevel = 0; else errorCollectionLevel = 1; else if (formatInformation[3] == true) errorCollectionLevel = 2; else errorCollectionLevel = 3; for (int i = 2; i >= 0; i--) if (formatInformation[i] == true) maskPattern += 1 << i; } public int getErrorCollectionLevel() { return errorCollectionLevel; } public int getMaskPatternReferer() { return maskPattern; } // for debug public String getMaskPatternRefererAsString() { String maskPattern = Integer.toString(getMaskPatternReferer() ,2); int length = maskPattern.length(); for (int i = 0; i < 3 - length; i++) maskPattern = "0" + maskPattern; return maskPattern; } public int getWidth() { return width; } public int getHeight() { return height; } public int[] getBlocks() { int width = getWidth(); //System.out.println("SymbolWidth:" + Integer.toString(symbol.getWidth())); //System.out.println("SymbolHeight:" + Integer.toString(symbol.getHeight())); int height = getHeight(); int x = width - 1; int y = height - 1; Vector codeBits = new Vector(); Vector codeWords = new Vector(); int tempWord = 0; int figure = 7; int isNearFinish = 0; final boolean READ_UP = true; final boolean READ_DOWN = false; boolean direction = READ_UP; do { //canvas.drawPoint(new Point(x * 4 +8 , y * 4 + 47), Color.RED); codeBits.addElement(new Boolean(getElement(x, y))); //System.out.println(Integer.toString(codeBits.size())); //int ratio = canvas.getWidth() / symbol.getWidth(); //int offsetX = (canvas.getWidth() - symbol.getWidth() * ratio) / 2; //int offsetY = (canvas.getHeight() - symbol.getHeight() * ratio) / 2; //canvas.drawPoint(new Point(offsetX + x * ratio + 3, offsetY + y * ratio + 3), 0xFF0000); if (getElement(x, y) == true) { tempWord += 1 << figure; } //System.out.println(new Point(x, y).toString() + " " + symbol.getElement(x, y)); figure--; if (figure == -1) { codeWords.addElement(new Integer(tempWord)); //System.out.print(codeWords.size() + ": "); //System.out.println(tempWord); figure = 7; tempWord = 0; } // determine module that read next do { if (direction == READ_UP) { if ((x + isNearFinish) % 2 == 0) //if right side of two column x--; // to left else { if (y > 0) { //be able to move upper side x++; y--; } else { //can't move upper side x--; //change direction if (x == 6){ x--; isNearFinish=1; // after through horizontal Timing Pattern, move pattern is changed } direction = READ_DOWN; } } } else { if ((x + isNearFinish) % 2 == 0) //if left side of two column x--; else { if (y < height - 1) { x++; y++; } else { x--; if (x == 6){ x--; isNearFinish=1; } direction = READ_UP; } } } } while (isInFunctionPattern(x, y)); } while (x != -1); int[] gotWords = new int[codeWords.size()]; for (int i = 0; i < codeWords.size(); i++) { Integer temp = (Integer)codeWords.elementAt(i); gotWords[i] = temp.intValue(); } return gotWords; } public void reverseElement(int x, int y) { moduleMatrix[x][y] = !moduleMatrix[x][y]; } public boolean isInFunctionPattern(int targetX, int targetY) { if (targetX < 9 && targetY < 9) //in Left-Up Finder Pattern or function patterns around it return true; if (targetX > getWidth() - 9 && targetY < 9) //in Right-up Finder Pattern or function patterns around it return true; if (targetX < 9 && targetY > getHeight() - 9) //in Left-bottom Finder Pattern or function patterns around it return true; if (version >= 7) { if (targetX > getWidth() - 12 && targetY < 6) return true; if (targetX < 6 && targetY > getHeight() - 12) return true; } // in timing pattern if (targetX == 6 || targetY == 6) return true; // in alignment pattern. Point[][] alignmentPattern = getAlignmentPattern(); int sideLength = alignmentPattern.length; for (int y = 0; y < sideLength; y++) { for (int x = 0; x < sideLength; x++) { if (!(x == 0 && y == 0) && !(x == sideLength - 1 && y == 0) && !(x == 0 && y == sideLength - 1)) if (Math.abs(alignmentPattern[x][y].getX() - targetX) < 3 && Math.abs(alignmentPattern[x][y].getY() - targetY) < 3) return true; } } return false; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -