?? qrcodedecoder.java
字號:
/*
* 嶌惉擔丗 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 + -