论坛: English (Thread #10668)

Problem with big images (2006-03-31 21:24 by 匿名 #20946)

Hi !

Qrcode is a wonderful library, Bravo, but it does'nt seem to be able to work with "big" images (28-L).

I get an ArrayIndexOutOfBoundsException here :
in jp.sourceforge.qrcode.codec.reader.pattern.AlignmentPattern.findAlignmentPattern()

int logicalDistance = logicalCenters[1][0].getX() - logicalCenters[0][0].getX();


Any idea how this could be fixed ?

Is there a new version planned to be release any time ?

Regards,
Benjamin.

____
$java jp.sourceforge.qrcode.example.QRCodeDecoderSampleCUI bigimage.jpg

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)

回复到 #20946×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) 登录

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;

}
回复到 #20946

回复到 #21037×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) 登录

Finding logical centers... (2006-04-06 07:58 by benjaminbellamy #21041)

I found the logical centers.
But I still have at jp.sourceforge.qrcode.codec.reader.pattern.AlignmentPattern.getCenter()

Could anyone translate this for me please ? (I don't read japanese at all.) I think it might be useful...
//型番7~13の中央上の位置合せパターン

Benjamin.


Finding logical centers (not the cleverest way...)
//各位置合せパターンの論理座標を得る
static Point[][] getLogicalCenter(FinderPattern finderPattern)
throws UnsupportedVersionException{
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[0] + logicalSeeds[2]) / 2
logicalSeeds[2] = 10 + 4 * version;
logicalCenters = new Point[logicalSeeds.length][logicalSeeds.length];
}
else if (version >= 14 && version <= 20) {
logicalSeeds = new int[4];
logicalSeeds[0] = 6;
logicalSeeds[1] = 6 + 1 * (4 + 4 * version) / 3; logicalSeeds[1] -= (logicalSeeds[1] - 2) % 4;
logicalSeeds[2] = 6 + 2 * (4 + 4 * version) / 3; logicalSeeds[2] -= (logicalSeeds[2] - 2) % 4;
logicalSeeds[3] = 10 + 4 * version;
logicalCenters = new Point[logicalSeeds.length][logicalSeeds.length];
}
else if (version >= 21 && version <= 27) {
logicalSeeds = new int[5];
logicalSeeds[0] = 6;
logicalSeeds[1] = 6 + 1 * (4 + 4 * version) / 4;
logicalSeeds[2] = 6 + 2 * (4 + 4 * version) / 4;
logicalSeeds[3] = 6 + 3 * (4 + 4 * version) / 4;
logicalSeeds[4] = 10 + 4 * version;
logicalCenters = new Point[logicalSeeds.length][logicalSeeds.length];
}
else if (version >= 28 && version <= 34) {
logicalSeeds = new int[6];
logicalSeeds[0] = 6;
logicalSeeds[1] = 6 + 1 * (4 + 4 * version) / 5; logicalSeeds[1] -= (logicalSeeds[1] - 2) % 4;
logicalSeeds[2] = 6 + 2 * (4 + 4 * version) / 5; logicalSeeds[2] -= (logicalSeeds[2] - 2) % 4;
logicalSeeds[3] = 6 + 3 * (4 + 4 * version) / 5; logicalSeeds[3] -= (logicalSeeds[3] - 2) % 4;
logicalSeeds[4] = 6 + 4 * (4 + 4 * version) / 5; logicalSeeds[4] -= (logicalSeeds[4] - 2) % 4;
logicalSeeds[5] = 10 + 4 * version;
logicalCenters = new Point[logicalSeeds.length][logicalSeeds.length];
}
else if (version >= 35 && version <= 40) {
logicalSeeds = new int[7];
logicalSeeds[0] = 6;
logicalSeeds[1] = 6 + 1 * (4 + 4 * version) / 6; logicalSeeds[1] -= (logicalSeeds[1] - 2) % 4;
logicalSeeds[2] = 6 + 2 * (4 + 4 * version) / 6; logicalSeeds[2] -= (logicalSeeds[2] - 2) % 4;
logicalSeeds[3] = 6 + 3 * (4 + 4 * version) / 6; logicalSeeds[3] -= (logicalSeeds[3] - 2) % 4;
logicalSeeds[4] = 6 + 4 * (4 + 4 * version) / 6; logicalSeeds[4] -= (logicalSeeds[4] - 2) % 4;
logicalSeeds[5] = 6 + 5 * (4 + 4 * version) / 6; logicalSeeds[5] -= (logicalSeeds[5] - 2) % 4;
logicalSeeds[6] = 10 + 4 * version;
logicalCenters = new Point[logicalSeeds.length][logicalSeeds.length];
}
else {
System.out.println("UnsupportedVersionException");
throw new UnsupportedVersionException();
}

//実際の相対座標の作成
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]);
}
}
return logicalCenters;
}
回复到 #20946

回复到 #21041×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) 登录

Almost there... (2006-04-07 08:29 by benjaminbellamy #21066)

I finally got the centers...
I still have to modify QRCodeImageReader...

Benjamin.

package jp.sourceforge.qrcode.codec.reader.pattern;

import jp.sourceforge.qrcode.codec.reader.*;
import jp.sourceforge.qrcode.codec.exception.AlignmentPatternEdgeNotFoundException;
import jp.sourceforge.qrcode.codec.exception.UnsupportedVersionException;
import jp.sourceforge.qrcode.codec.geom.*;
import jp.sourceforge.qrcode.codec.util.*;

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;
}

public static AlignmentPattern findAlignmentPattern(boolean[][] image, FinderPattern finderPattern)
throws AlignmentPatternEdgeNotFoundException, UnsupportedVersionException {

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];

axis.setOrigin(finderPattern.getCenter(FinderPattern.UL));
centers[0][0] = axis.translate(3, 3);

//centers[0][0] = finderPattern.getCenter(FinderPattern.UL);
axis.setOrigin(finderPattern.getCenter(FinderPattern.UR));
centers[sqrtCenters - 1][0] = axis.translate(-3, 3);

//centers[sqrtCenters - 1][0] = finderPattern.getCenter(FinderPattern.UR);
axis.setOrigin(finderPattern.getCenter(FinderPattern.DL));
centers[0][sqrtCenters - 1] = axis.translate(3, -3);

//centers[0][sqrtCenters - 1] = finderPattern.getCenter(FinderPattern.DL);

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;

}

}
回复到 #20946

回复到 #21066×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) 登录

RE: Almost there... (2006-04-11 12:10 by drhu00 #21163)

where is your method
Point.getBarycenter?

And also when you think you can get QRCodeImageReader done?
回复到 #21066

回复到 #21163×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) 登录

Barycenter (2006-04-11 15:45 by benjaminbellamy #21169)

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.)

Regards,
Benjamin.
回复到 #21163

回复到 #21169×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) 登录