討論區: English (Thread #11056)

several suggestion (2006-05-14 03:09 by drhu00 #21856)

1) reedSolomon.java, correct method after hasError = true; add break;
2) I don't think need the duplicate code to handle getDecodedByteArray/getDecodedString, getDataByte/getDataString. Instead we can modify the old original method get8biteByteString as following to handle UTF-8

String get8bitByteString(int dataLength) throws ArrayIndexOutOfBoundsException {
int length = dataLength;
int intData = 0;
ByteArrayOutputStream output=new ByteArrayOutputStream();

boolean flag = true;
do {
intData = getNextBits(8);
if (intData == 0) {
flag = false;
} else {
if (debug) System.out.print(intData + " ");
output.write((byte)intData);
}
length--;
if (length == 0) flag = false;
} while (flag);
if (debug) System.out.println("");

String strData = "";
try {
strData = new String(output.toByteArray(), "UTF-8");
} catch (Exception e) {
if (debug) e.printStackTrace();
strData = new String(output.toByteArray());
}

return strData;
}

3) Why we need the package level codec? I think that jp.sourceforge.qrcode is good enough.

4) Create some standard testing decode image suite to test each new release.

回覆 #21856×

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: several suggestion (2006-05-15 12:19 by yanbe #21893)

Yes. It's error comes with
回覆: #21856

回覆 #21893×

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: several suggestion  (2006-05-15 12:28 by yanbe #21897)

Thank you for your four suggestion.
I agree with you mostly.

1) Yes. It seems bug and let's fix it. This class comes from RSCODE(http://sourceforge.net/project/rscode). And I will report about this bug to Henry Minsky, a original author of C version.

2) This modification seems good, but it possible incompatibility of specification. So please time for me to re-confirm the JIS0510X specification.

3) I think package level codec is verbose now, too. I was not experienced enough when I created this package hierarchy. (it was about 1.5 years ago). Then, let's modify it.

4) Yes. For long time, I think that testing decode image suite is very important for stable release. Let's prepare it until next release.
回覆: #21856

回覆 #21897×

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: several suggestion (2006-05-18 02:27 by umbalaconmeogia #21960)

The code that takes most running time is the FinderPattern.findLineAcross(). I changed the algorithm and it becomes very fast.

I believe that the garbage collection process makes the program becomes slow on J2ME. The FinderPattern.findLineCross() runs fast but the system always calls GC after it. I feel that the implementation of findLineCross() is not good and want to rewrite it, but I don't understand it so much. There isn't any comment.

Who can explain what it does for me? I will try to rewrite it.

I will post the code after complete them.
回覆: #21856

回覆 #21960×

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: several suggestion (2006-05-21 01:03 by 匿名 #22134)

I rewrite the findLineAcross(), checkPattern(), findLineCross() like the following:

/*
* 位置要素検出パターンを検出するために、(暗:明:暗:明:暗)=(1:1:3:1:1)の
* パターンに一致する区間を線分として抽出する。
* 注意:位置要素パターンを横切らない部分が抽出されることもある
*/
static Line[] findLineAcross(boolean[][] image) {
final boolean[] nextSectionElement = {false,
QRCodeImageReader.POINT_LIGHT,
QRCodeImageReader.POINT_DARK,
QRCodeImageReader.POINT_LIGHT,
QRCodeImageReader.POINT_DARK,
QRCodeImageReader.POINT_LIGHT};

int imageWidth = image.length;
int imageHeight = image[0].length;
int currentX, currentY;

Vector lineAcross = new Vector();

// 直近の、同じ色で連続した要素の長さ
int[] lengthBuffer = new int[5];
int bufferPointer;
int nsection;
boolean currentElement, lastElement;

// Read horizontal
for (currentY = 0; currentY < imageHeight; currentY++) {

lengthBuffer[bufferPointer = 0] = 0;
nsection = 1;
lastElement = QRCodeImageReader.POINT_LIGHT;

for (currentX = 0; currentX < imageWidth; currentX++) {
currentElement = image[currentX][currentY];
if (currentElement == lastElement) { //前回の要素と同じ
lengthBuffer[bufferPointer]++;
} else { //前回の要素と違う
if (currentElement == nextSectionElement[nsection]) {
while (nsection > 2) {
// Check with current secsions.
if (checkPattern(lengthBuffer, bufferPointer, nsection)) {
// The rate of the secsions' length is OK.
if (nsection == 5) {
// Add this pattern into lineAcross.
int x1, y1, x2, y2;
// パターン候補の両端のx座標を求める
// 左端は現在の要素のx座標とバッファの長さの和から算出
x1 = currentX;
for (int j = 0; j < 5; j++) {
x1 -= lengthBuffer[j];
}
x2 = currentX - 1; // 右端は直前の要素のx座標
y1 = y2 = currentY;
lineAcross.addElement(new Line(x1, y1, x2, y2));

// Continue checking, so that we may reduce the nsection.
nsection -= 2;
} else {
// The rate is OK, but the number of the sections is not 5,
// so read in the next section.
break;
}
} else {
// The rate is not OK, so continue checking to cut
// out the unnecessary sections.
nsection -= 2;
}
} // of while
} else {
// The nsection == 1, but its color is white, so it can be the section no.1 in the 5 sections.
nsection--;
}
nsection++;
bufferPointer = (bufferPointer + 1) % 5;
lengthBuffer[bufferPointer] = 1;
lastElement = !lastElement;
}
}
}

// Read vertical
for (currentX = 0; currentX < imageWidth; currentX++) {

lengthBuffer[bufferPointer = 0] = 0;
nsection = 1;
lastElement = QRCodeImageReader.POINT_LIGHT;

for (currentY = 0; currentY < imageHeight; currentY++) {
currentElement = image[currentX][currentY];
if (currentElement == lastElement) { //前回の要素と同じ
lengthBuffer[bufferPointer]++;
} else { //前回の要素と違う
if (currentElement == nextSectionElement[nsection]) {
while (nsection > 2) {
// Check with current secsions.
if (checkPattern(lengthBuffer, bufferPointer, nsection)) {
// The rate of the secsions' length is OK.
if (nsection == 5) {
// Add this pattern into lineAcross.
int x1, y1, x2, y2;
x1 = x2 = currentX;
// パターン候補の両端のy座標を求める
// 左端は現在の要素のy座標とバッファの長さの和から算出
y1 = currentY;
for (int j = 0; j < 5; j++) {
y1 -= lengthBuffer[j];
}
y2 = currentY - 1; // 右端は直前の要素のy座標
lineAcross.addElement(new Line(x1, y1, x2, y2));

// Continue checking, so that we may reduce the nsection.
nsection -= 2;
} else {
// The rate is OK, but the number of the sections is not 5,
// so read in the next section.
break;
}
} else {
// The rate is not OK, so continue checking to cut
// out the unnecessary sections.
nsection -= 2;
}
} // of while
} else {
// The nsection == 1, but its color is white, so it can be the section no.1 in the 5 sections.
nsection--;
}
nsection++;
bufferPointer = (bufferPointer + 1) % 5;
lengthBuffer[bufferPointer] = 1;
lastElement = !lastElement;
}
}
}

Line[] foundLines = new Line[lineAcross.size()];

for (int i = 0; i < foundLines.length; i++)
foundLines[i] = (Line) lineAcross.elementAt(i);

return foundLines;
}

static boolean checkPattern(int[] buffer, int pointer, int nsection) {
final int[] modelRatio = {1, 1, 3, 1, 1};
final int[] modelPart = {1, 2, 5, 6, 7};

int nsection_1 = nsection - 1;
int i;
int baselength = 0;
for (i = 0; i < nsection; i++) {
baselength += buffer[(pointer + 5 - nsection_1 + i) % 5];
}
baselength <<= QRCodeImageReader.DECIMAL_POINT; //丸め誤差を減らすために4098倍する
baselength /= modelPart[nsection_1];

for (i = 0; i < nsection; i++) {
int leastlength = baselength * modelRatio[i] - baselength / 2;
int mostlength = baselength * modelRatio[i] + baselength / 2;

//試験的に条件を甘くする
leastlength -= baselength / 8;
mostlength += baselength / 8;

int targetlength = buffer[(pointer + 5 - nsection_1 + i) % 5] << QRCodeImageReader.DECIMAL_POINT;
if (targetlength < leastlength || targetlength > mostlength) {
return false;
}
}
return true;
}

/**
* Scan lines received from findLIneAcross() and detemine where are center(s) of three Finder Patterns.
* @param lineAcross
* @return The center lines (in normal, be 6 lines).
*/
static Line[] findLineCross(Line[] lineAcross) {
int numLineCandidate = lineAcross.length;
int numLineCandidate_1 = numLineCandidate - 1;
int[] lineNeighborIndex = new int[numLineCandidate];
int numLineNeighborIndex;
int[] crossLineIndex = new int[numLineCandidate];
int numCrossLineIndex = 0;
boolean[] removedOfIndex = new boolean[numLineCandidate];

for (int i = 0; i < numLineCandidate_1; i++) {
if (!removedOfIndex[i]) {
// Start finding pattern from line[i].

// Start the list of neighbor lines.
numLineNeighborIndex = 0;
lineNeighborIndex[numLineNeighborIndex++] = i;
int lastNeighborIndex = i;

// Search for the next lines.
for (int j = i + 1; j < numLineCandidate; j++) {
if (!removedOfIndex[j]) {
if (Line.isNeighbor(lineAcross[lastNeighborIndex], lineAcross[j])) {
// Add line[j] to the list of neighbor lines.
lastNeighborIndex = lineNeighborIndex[numLineNeighborIndex++] = j;

// Check if reach to the last line of lineAcross.
if (j == numLineCandidate_1
&& numLineNeighborIndex * 5 > lineAcross[lastNeighborIndex].getLength()) {
// Get the center line of this neighbor lines.
crossLineIndex[numCrossLineIndex++] = lineNeighborIndex[numLineNeighborIndex / 2];

// Mark all neighbor lines are removed.
for (int k = 0; k < numLineNeighborIndex; k++) {
removedOfIndex[lineNeighborIndex[k]] = true;
}
}
}
// Terminate comparision if there are no possibility for found neighbor lines.
else if (j == numLineCandidate_1
||cantNeighbor(lineAcross[lastNeighborIndex], lineAcross[j])) {
// Determine lines across Finder Patterns when number of neightbor lines are
// bigger than 1/6 length of theirselves.
if (numLineNeighborIndex * 6 > lineAcross[lastNeighborIndex].getLength()) {
// Get the center line of this neighbor lines.
crossLineIndex[numCrossLineIndex++] = lineNeighborIndex[numLineNeighborIndex / 2];

// Mark all neighbor lines are removed.
for (int k = 0; k < numLineNeighborIndex; k++) {
removedOfIndex[lineNeighborIndex[k]] = true;
}
}
break;
}
}
}
}
}

Line[] foundLines = new Line[numCrossLineIndex];
for (int i = 0; i < numCrossLineIndex; i++) {
Line line = lineAcross[crossLineIndex[i]];
foundLines[i] = new Line(line.x1, line.y1, line.x2, line.y2);
}
return foundLines;
}
回覆: #21960

回覆 #22134×

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: several suggestion (2006-05-21 05:21 by drhu00 #22138)

Your method works. The speed only increase a little.
回覆: #22134

回覆 #22138×

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: several suggestion (2006-05-21 10:27 by drhu00 #22140)

Now the code that takes most running time is processImage. For example, to decode a 640x480 pixels, 5 sec on processImage and 1 sec on other methods. A total 6 secs.
回覆: #22138

回覆 #22140×

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: several suggestion (2006-05-22 01:50 by 匿名 #22179)

What environment do you use to get this result? On the mobile phone or on the emulator?
回覆: #22140

回覆 #22179×

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: several suggestion (2006-05-22 02:29 by drhu00 #22180)

emulator
回覆: #22179

回覆 #22180×

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

I explain findLineCross() (2006-05-18 09:32 by yanbe #21968)

I wrote findLineCross(). So I explain about it.

First, I expect that you are using version 0.5 source from package "qrcode". If yes, please check latest CVS source. Because it has English comments substitute of Japanese one, I think this is more helpful to understand.

findLineCross() method scan lines recieved from findLineAcross(). And it determines where are center(s) of three Finder Patterns.

To determine where are centers, the method collects "neighbor lines", which places side by side each other. when Size of collection reached to threshold, method determines that the middle point of collection is the FinderPattern's center.

This approach is based on "Near place of the finderPattern has many crossLines" hypothesis.

Finally, this method returns these determined FinderPattern centers.

As you say, I think FinderPattern-related methods are slow and need to be fixed too. Thank you for your suggestion.
回覆: #21856

回覆 #21968×

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: I explain findLineCross() (2006-05-18 10:26 by yanbe #21971)

> This approach is based on "Near place of the finderPattern has many crossLines" hypothesis.

Sorry, I mistyped. and please let me correct.

This approach is based on "Near place of the finderPattern has many across lines" hypothesis.
回覆: #21968

回覆 #21971×

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