Decoding started.
Creating bitmap.
Drawing matrix.
Scanning Finder Pattern.
(19,19)
(385,19)
(19,385)
3
FinderPattern at
(19,19)(385,19)(19,385)
Angle*4098: Sin 0 Cos 4194304
Version: 28
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at jp.sourceforge.qrcode.codec.reader.pattern.AlignmentPattern.findAlignmentPattern(AlignmentPattern.java:28)
at jp.sourceforge.qrcode.codec.reader.QRCodeImageReader.getQRCodeSymbol(QRCodeImageReader.java:135)
at jp.sourceforge.qrcode.codec.QRCodeDecoder.getQRCodeSymbol(QRCodeDecoder.java:206)
at jp.sourceforge.qrcode.codec.QRCodeDecoder.decode(QRCodeDecoder.java:44)
at jp.sourceforge.qrcode.example.QRCodeDecoderSampleCUI.main(QRCodeDecoderSampleCUI.java:32)
RE: Problem with big images (2006-04-05 23:09 by 匿名 #21037)
I found out that it cannot work with this kind of image (28-L) since it works only for version 13 and less.
Does somebody plan to implement it ?
Regards,
Benjamin.
in package jp.sourceforge.qrcode.codec.reader.pattern
//各位置合せパターンの論理座標を得る
static Point[][] getLogicalCenter(FinderPattern finderPattern) {
int version = finderPattern.getVersion();
Point[][] logicalCenters = new Point[1][1];
int[] logicalSeeds = new int[1];
//相対座標の元になる列座標,行座標の作成
if (version == 1)
return null;
else if (version >= 2 && version <= 6) {
logicalSeeds = new int[2];
logicalSeeds[0] = 6;
logicalSeeds[1] = 10 + 4 * version;
logicalCenters = 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;
logicalCenters = new Point[logicalSeeds.length][logicalSeeds.length];
}
// else if (version >= 14 && version <= 20) {
// //canvas.println("logical center v14-20");
// logicalSeeds = new int[4];
// logicalSeeds[0] = 6;
// logicalSeeds[1] = 26 + ((version - 14) / 3) * 4;
// logicalSeeds[2] = 18 + 2 * version;
// logicalSeeds[3] = 10 + 4 * version;
// logicalCenters = new Point[logicalSeeds.length][logicalSeeds.length];
// }
//実際の相対座標の作成
for (int col = 0; col < logicalCenters.length; col++) { //列
for (int row = 0; row < logicalCenters.length; row++) { //行
logicalCenters[row][col] = new Point(logicalSeeds[row], logicalSeeds[col]);
//System.out.print(logicalCenters[row][col]);
}
}
return logicalCenters;
public class AlignmentPattern {
static final int RIGHT = 1;
static final int BOTTOM = 2;
static final int LEFT = 3;
static final int TOP = 4;
static DebugCanvas canvas = DebugCanvas.getCanvas();
Point[][] center;
//int sqrtCenters; //位置合せパターンの1辺当たりの数 ///The number per 1 sides of alignment pattern
int patternDistance;
AlignmentPattern(Point[][] center, int patternDistance) {
this.center = center;
this.patternDistance = patternDistance;
}
Point[][] logicalCenters = getLogicalCenter(finderPattern);
int logicalDistance = logicalCenters[1][0].getX() - logicalCenters[0][0].getX();
//FinderPatternをAlignmentPatternと同様に扱うために変換する ///With it converts in order to handle in the same way
Point[][] centers = null;
try {
centers = getCenter(image, finderPattern, logicalCenters);
} catch (AlignmentPatternEdgeNotFoundException e) {
e.printStackTrace();
throw e;
}
return new AlignmentPattern(centers, logicalDistance);
}
public Point[][] getCenter() {
return center;
}
public int getLogicalDistance() {
return patternDistance;
}
static Point[][] getCenter(boolean[][] image, FinderPattern finderPattern, Point[][] logicalCenters)
throws AlignmentPatternEdgeNotFoundException {
int moduleSize = finderPattern.getModuleSize();
int sin = finderPattern.getAngle()[0];
int cos = finderPattern.getAngle()[1];
Axis axis = new Axis(sin, cos, moduleSize);
int sqrtCenters = logicalCenters.length;
Point[][] centers = new Point[sqrtCenters][sqrtCenters];
for (int y = 0; y < sqrtCenters; y++) {
for (int x = 0; x < sqrtCenters; x++) {
if (x >= 1 && x<(sqrtCenters-1) && y == 0 && sqrtCenters >= 3) {
//型番7~13の中央上の位置合せパターン ///Type turn 7~13 Alignment pattern on center
// Modified to go beyond version 13
centers[x][y] = Point.getBarycenter(centers[0][0], centers[sqrtCenters - 1][0], ((float)x)/(sqrtCenters-1));
}
else if (x == 0 && y<(sqrtCenters-1) && y >= 1 && sqrtCenters >= 3) {
//型番7~13の左中央の位置合せパターン ///Type turn 7~13 Alignment pattern on center
// Modified to go beyond version 13
centers[x][y] = Point.getBarycenter(centers[0][0], centers[0][sqrtCenters - 1], ((float)y)/(sqrtCenters-1));
}
else if (x >= 1 && y >= 1){
Line[] additionalLines = {
new Line(centers[x - 1][y - 1], centers[x][y - 1]),
new Line(centers[x - 1][y - 1], centers[x - 1][y])};
int dx = centers[x - 1][y].getX() - centers[x - 1][y - 1].getX();
int dy = centers[x - 1][y].getY() - centers[x - 1][y - 1].getY();
additionalLines[0].translate(dx,dy);
dx = centers[x][y - 1].getX() - centers[x - 1][y - 1].getX();
dy = centers[x][y - 1].getY() - centers[x - 1][y - 1].getY();
additionalLines[1].translate(dx,dy);
centers[x][y] = Point.getCenter(additionalLines[0].getP2(), additionalLines[1].getP2());
}
else // dummy alignment pattern (source is finder pattern)
continue;
try {
centers[x][y] = getPrecisionCenter(image, centers[x][y]);
} catch (AlignmentPatternEdgeNotFoundException e) {
e.printStackTrace();
throw e;
}
canvas.drawCross(centers[x][y], java.awt.Color.MAGENTA);
}
//System.out.println("");
}
return centers;
}
static Point getPrecisionCenter(boolean[][] image, Point targetPoint)
throws AlignmentPatternEdgeNotFoundException {
if (image[targetPoint.getX()][targetPoint.getY()] == QRCodeImageReader.POINT_LIGHT) {
int scope = 0;
boolean notFound = true;
while (notFound) {
scope++;
for (int dy = scope; dy > -scope; dy--) {
for (int dx = scope; dx > -scope; dx--) {
if (image[targetPoint.getX() + dx][targetPoint.getY() + dy] == QRCodeImageReader.POINT_DARK) {
targetPoint = new Point(targetPoint.getX() + dx,targetPoint.getY() + dy);
notFound = false;
}
}
}
}
}
int x, lx, rx, y, uy, dy;
x = lx = rx = targetPoint.getX();
y = uy = dy = targetPoint.getY();
while (!isEdge(image, lx, y, lx - 1, y) && lx >= 0)
lx--;
while (!isEdge(image, rx, y, rx + 1, y) && lx < image.length)
rx++;
while (!isEdge(image, x, uy, x, uy - 1) && uy >= 0)
uy--;
while (!isEdge(image, x, dy, x, dy + 1) && dy < image[0].length)
dy++;
return new Point((lx + rx + 1) / 2, (uy + dy + 1) / 2);
}
static boolean isEdge(boolean[][] image, int x, int y, int nx, int ny) {
if (image[x][y] == QRCodeImageReader.POINT_LIGHT &&
image[nx][ny] == QRCodeImageReader.POINT_DARK)
return true;
else
return false;
}
//各位置合せパターンの論理座標を得る ///Logical coordinate of everyone position adjusting pattern is obtained
static Point[][] getLogicalCenter(FinderPattern finderPattern)
throws UnsupportedVersionException{
int version = finderPattern.getVersion();
Point[][] logicalCenters = new Point[1][1];
int[] logicalSeeds = new int[1];
//相対座標の元になる列座標,行座標の作成 ///The presence mark which becomes the cause in relative coordinate, compilation in line coordinate
if (version == 1)
return null;
else if (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;
}
logicalCenters = new Point[logicalSeeds.length][logicalSeeds.length];
}
else {
throw new UnsupportedVersionException();
}
//実際の相対座標の作成 ///Compilation in actually relative coordinate
for (int col = 0; col < logicalCenters.length; col++) { //列 ///Line
for (int row = 0; row < logicalCenters.length; row++) { //行 ///Line
logicalCenters[row][col] = new Point(logicalSeeds[row], logicalSeeds[col]);
}
}
return logicalCenters;
I had to create a new "Barycenter" function to the Point class :
public static Point getBarycenter(Point p1, Point p2, float ratio) {
return new Point(
(int)(p1.getX() + ( p2.getX() - p1.getX() ) * ratio),
(int)(p1.getY() + ( p2.getY() - p1.getY() ) * ratio)
);
}
But don't try to use this source code, it still contains several bugs.
I think I'll have QRCodeImageReader done by the end of the week. (Unfortunately, there are several functions that don't work at all anymore on version 14 and beyond.)