Issue 183: Adds support for detecting multiple barcodes, and simplifies ResultPoint abstraction

git-svn-id: https://zxing.googlecode.com/svn/trunk@918 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2009-04-28 17:35:33 +00:00
parent cfff716c6c
commit 29d7d6443e
17 changed files with 352 additions and 201 deletions

View file

@ -0,0 +1,95 @@
/*
* Copyright 2009 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.zxing;
import com.google.zxing.common.BitArray;
/**
* Encapulates a cropped region, a subset, of another {@link MonochromeBitmapSource}.
*
* @author Sean Owen
*/
public final class CroppedMonochromeBitmapSource implements MonochromeBitmapSource {
private final MonochromeBitmapSource delegate;
private final int left;
private final int top;
private final int right;
private final int bottom;
/**
* Creates an instance that uses only a region of the given image as a source of pixels to decode.
*
* @param delegate image to decode a region of
* @param left x coordinate of leftmost pixels to decode
* @param top y coordinate of topmost pixels to decode
* @param right one more than the x coordinate of rightmost pixels to decode, i.e. we will decode
* pixels whose x coordinate is in [left,right)
* @param bottom likewise, one more than the y coordinate of the bottommost pixels to decode
*/
public CroppedMonochromeBitmapSource(MonochromeBitmapSource delegate,
int left, int top, int right, int bottom) {
this.delegate = delegate;
this.left = left;
this.top = top;
this.right = right;
this.bottom = bottom;
}
public boolean isBlack(int x, int y) {
return delegate.isBlack(left + x, top + y);
}
public BitArray getBlackRow(int y, BitArray row, int startX, int getWidth) {
return delegate.getBlackRow(top + y, row, left + startX, getWidth);
}
public BitArray getBlackColumn(int x, BitArray column, int startY, int getHeight) {
return delegate.getBlackColumn(left + x, column, top + startY, getHeight);
}
public int getHeight() {
return bottom - top;
}
public int getWidth() {
return right - left;
}
public void estimateBlackPoint(BlackPointEstimationMethod method, int argument) throws ReaderException {
// Hmm, the delegate will probably base this on the whole image though...
delegate.estimateBlackPoint(method, argument);
}
public BlackPointEstimationMethod getLastEstimationMethod() {
return delegate.getLastEstimationMethod();
}
public MonochromeBitmapSource rotateCounterClockwise() {
MonochromeBitmapSource rotated = delegate.rotateCounterClockwise();
return new CroppedMonochromeBitmapSource(rotated,
top,
delegate.getWidth() - right,
delegate.getHeight() - bottom,
left);
}
public boolean isRotateSupported() {
return delegate.isRotateSupported();
}
}

View file

@ -0,0 +1,111 @@
/*
* Copyright 2009 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.zxing;
import java.util.Hashtable;
import java.util.Vector;
/**
* Attempts to locate multiple barcodes in an image by repeatedly decoding portion of the image.
* After one barcode is found, the areas left, above, right and below the barcode's {@link ResultPoint}s
* are scanned, recursively.
*
* @author Sean Owen
*/
public final class MultipleBarcodeReader {
private final Reader delegate;
public MultipleBarcodeReader(Reader delegate) {
this.delegate = delegate;
}
public Result[] decodeMultiple(MonochromeBitmapSource image) throws ReaderException {
return decodeMultiple(image, null);
}
public Result[] decodeMultiple(MonochromeBitmapSource image, Hashtable hints) throws ReaderException {
Vector results = new Vector();
doDecodeMultiple(image, hints, results, 0, 0);
if (results.isEmpty()) {
throw ReaderException.getInstance();
}
int numResults = results.size();
Result[] resultArray = new Result[numResults];
for (int i = 0; i < numResults; i++) {
resultArray[i] = (Result) results.elementAt(i);
}
return resultArray;
}
private void doDecodeMultiple(MonochromeBitmapSource image, Hashtable hints, Vector results, int xOffset, int yOffset) {
Result result;
try {
result = delegate.decode(image, hints);
} catch (ReaderException re) {
return;
}
results.addElement(translateResultPoints(result, xOffset, yOffset));
ResultPoint[] resultPoints = result.getResultPoints();
if (resultPoints == null || resultPoints.length == 0) {
return;
}
int width = image.getWidth();
int height = image.getHeight();
float minX = width;
float minY = height;
float maxX = 0.0f;
float maxY = 0.0f;
for (int i = 0; i < resultPoints.length; i++) {
ResultPoint point = resultPoints[i];
float x = point.getX();
float y = point.getY();
if (x < minX) {
minX = x;
}
if (y < minY) {
minY = y;
}
if (x > maxX) {
maxX = x;
}
if (y > maxY) {
maxY = y;
}
}
doDecodeMultiple(new CroppedMonochromeBitmapSource(image, 0, 0, (int) minX, height),
hints, results, 0, 0);
doDecodeMultiple(new CroppedMonochromeBitmapSource(image, 0, 0, width, (int) minY),
hints, results, 0, 0);
doDecodeMultiple(new CroppedMonochromeBitmapSource(image, (int) maxX, 0, width, height),
hints, results, (int) maxX, 0);
doDecodeMultiple(new CroppedMonochromeBitmapSource(image, 0, (int) maxY, width, height),
hints, results, 0, (int) maxY);
}
private static Result translateResultPoints(Result result, int xOffset, int yOffset) {
ResultPoint[] oldResultPoints = result.getResultPoints();
ResultPoint[] newResultPoints = new ResultPoint[oldResultPoints.length];
for (int i = 0; i < oldResultPoints.length; i++) {
ResultPoint oldPoint = oldResultPoints[i];
newResultPoints[i] = new ResultPoint(oldPoint.getX() + xOffset, oldPoint.getY() + yOffset);
}
return new Result(result.getText(), result.getRawBytes(), newResultPoints, result.getBarcodeFormat());
}
}

View file

@ -22,10 +22,106 @@ package com.google.zxing;
*
* @author Sean Owen
*/
public interface ResultPoint {
public class ResultPoint {
float getX();
private final float x;
private final float y;
public ResultPoint(float x, float y) {
this.x = x;
this.y = y;
}
public final float getX() {
return x;
}
public final float getY() {
return y;
}
public boolean equals(Object other) {
if (other instanceof ResultPoint) {
ResultPoint otherPoint = (ResultPoint) other;
return x == otherPoint.x && y == otherPoint.y;
}
return false;
}
public int hashCode() {
return 31 * Float.floatToIntBits(x) + Float.floatToIntBits(y);
}
public String toString() {
StringBuffer result = new StringBuffer(25);
result.append('(');
result.append(x);
result.append(',');
result.append(y);
result.append(')');
return result.toString();
}
/**
* <p>Orders an array of three ResultPoints in an order [A,B,C] such that AB < AC and
* BC < AC and the angle between BC and BA is less than 180 degrees.
*/
public static void orderBestPatterns(ResultPoint[] patterns) {
// Find distances between pattern centers
float zeroOneDistance = distance(patterns[0], patterns[1]);
float oneTwoDistance = distance(patterns[1], patterns[2]);
float zeroTwoDistance = distance(patterns[0], patterns[2]);
ResultPoint pointA, pointB, pointC;
// Assume one closest to other two is B; A and C will just be guesses at first
if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance) {
pointB = patterns[0];
pointA = patterns[1];
pointC = patterns[2];
} else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance) {
pointB = patterns[1];
pointA = patterns[0];
pointC = patterns[2];
} else {
pointB = patterns[2];
pointA = patterns[0];
pointC = patterns[1];
}
// Use cross product to figure out whether A and C are correct or flipped.
// This asks whether BC x BA has a positive z component, which is the arrangement
// we want for A, B, C. If it's negative, then we've got it flipped around and
// should swap A and C.
if (crossProductZ(pointA, pointB, pointC) < 0.0f) {
ResultPoint temp = pointA;
pointA = pointC;
pointC = temp;
}
patterns[0] = pointA;
patterns[1] = pointB;
patterns[2] = pointC;
}
/**
* @return distance between two points
*/
public static float distance(ResultPoint pattern1, ResultPoint pattern2) {
float xDiff = pattern1.getX() - pattern2.getX();
float yDiff = pattern1.getY() - pattern2.getY();
return (float) Math.sqrt((double) (xDiff * xDiff + yDiff * yDiff));
}
/**
* Returns the z component of the cross product between vectors BC and BA.
*/
public static float crossProductZ(ResultPoint pointA, ResultPoint pointB, ResultPoint pointC) {
float bX = pointB.x;
float bY = pointB.y;
return ((pointC.x - bX) * (pointA.y - bY)) - ((pointC.y - bY) * (pointA.x - bX));
}
float getY();
}

View file

@ -1,128 +0,0 @@
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.zxing.common;
import com.google.zxing.ResultPoint;
/**
* <p>Simple implementation of {@link ResultPoint} for applications that don't need
* to use anything more complex.</p>
*
* @author dswitkin@google.com (Daniel Switkin)
*/
public final class GenericResultPoint implements ResultPoint {
private final float posX;
private final float posY;
public GenericResultPoint(float posX, float posY) {
this.posX = posX;
this.posY = posY;
}
public float getX() {
return posX;
}
public float getY() {
return posY;
}
public String toString() {
StringBuffer result = new StringBuffer(25);
result.append('(');
result.append(posX);
result.append(',');
result.append(posY);
result.append(')');
return result.toString();
}
public boolean equals(Object other) {
if (other instanceof GenericResultPoint) {
GenericResultPoint otherPoint = (GenericResultPoint) other;
return posX == otherPoint.posX && posY == otherPoint.posY;
}
return false;
}
public int hashCode() {
return 31 * Float.floatToIntBits(posX) + Float.floatToIntBits(posY);
}
/**
* <p>Orders an array of three ResultPoints in an order [A,B,C] such that AB < AC and
* BC < AC and the angle between BC and BA is less than 180 degrees.
*/
public static void orderBestPatterns(ResultPoint[] patterns) {
// Find distances between pattern centers
float zeroOneDistance = distance(patterns[0], patterns[1]);
float oneTwoDistance = distance(patterns[1], patterns[2]);
float zeroTwoDistance = distance(patterns[0], patterns[2]);
ResultPoint pointA, pointB, pointC;
// Assume one closest to other two is B; A and C will just be guesses at first
if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance) {
pointB = patterns[0];
pointA = patterns[1];
pointC = patterns[2];
} else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance) {
pointB = patterns[1];
pointA = patterns[0];
pointC = patterns[2];
} else {
pointB = patterns[2];
pointA = patterns[0];
pointC = patterns[1];
}
// Use cross product to figure out whether A and C are correct or flipped.
// This asks whether BC x BA has a positive z component, which is the arrangement
// we want for A, B, C. If it's negative, then we've got it flipped around and
// should swap A and C.
if (crossProductZ(pointA, pointB, pointC) < 0.0f) {
ResultPoint temp = pointA;
pointA = pointC;
pointC = temp;
}
patterns[0] = pointA;
patterns[1] = pointB;
patterns[2] = pointC;
}
/**
* @return distance between two points
*/
public static float distance(ResultPoint pattern1, ResultPoint pattern2) {
float xDiff = pattern1.getX() - pattern2.getX();
float yDiff = pattern1.getY() - pattern2.getY();
return (float) Math.sqrt((double) (xDiff * xDiff + yDiff * yDiff));
}
/**
* Returns the z component of the cross product between vectors BC and BA.
*/
public static float crossProductZ(ResultPoint pointA, ResultPoint pointB, ResultPoint pointC) {
float bX = pointB.getX();
float bY = pointB.getY();
return ((pointC.getX() - bX) * (pointA.getY() - bY)) - ((pointC.getY() - bY) * (pointA.getX() - bX));
}
}

View file

@ -21,7 +21,6 @@ import com.google.zxing.ReaderException;
import com.google.zxing.ResultPoint;
import com.google.zxing.BlackPointEstimationMethod;
import com.google.zxing.common.BitArray;
import com.google.zxing.common.GenericResultPoint;
/**
* <p>A somewhat generic detector that looks for a barcode-like rectangular region within an image.
@ -122,21 +121,21 @@ public final class MonochromeRectangleDetector {
if (lastRange[0] < centerJ) {
if (lastRange[1] > centerJ) {
// straddle, choose one or the other based on direction
return new GenericResultPoint(di > 0 ? lastRange[0] : lastRange[1], lastI);
return new ResultPoint(di > 0 ? lastRange[0] : lastRange[1], lastI);
}
return new GenericResultPoint(lastRange[0], lastI);
return new ResultPoint(lastRange[0], lastI);
} else {
return new GenericResultPoint(lastRange[1], lastI);
return new ResultPoint(lastRange[1], lastI);
}
} else {
int lastJ = j - dj;
if (lastRange[0] < centerI) {
if (lastRange[1] > centerI) {
return new GenericResultPoint(lastJ, dj < 0 ? lastRange[0] : lastRange[1]);
return new ResultPoint(lastJ, dj < 0 ? lastRange[0] : lastRange[1]);
}
return new GenericResultPoint(lastJ, lastRange[0]);
return new ResultPoint(lastJ, lastRange[0]);
} else {
return new GenericResultPoint(lastJ, lastRange[1]);
return new ResultPoint(lastJ, lastRange[1]);
}
}
}

View file

@ -23,7 +23,6 @@ import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.Collections;
import com.google.zxing.common.Comparator;
import com.google.zxing.common.DetectorResult;
import com.google.zxing.common.GenericResultPoint;
import com.google.zxing.common.GridSampler;
import com.google.zxing.common.detector.MonochromeRectangleDetector;
@ -39,7 +38,7 @@ import java.util.Vector;
*/
public final class Detector {
private static final int MAX_MODULES = 32;
//private static final int MAX_MODULES = 32;
// Trick to avoid creating new Integer objects below -- a sort of crude copy of
// the Integer.valueOf(int) optimization added in Java 5, not in J2ME
@ -117,7 +116,7 @@ public final class Detector {
// Bottom left is correct but top left and bottom right might be switched
ResultPoint[] corners = { maybeTopLeft, bottomLeft, maybeBottomRight };
// Use the dot product trick to sort them out
GenericResultPoint.orderBestPatterns(corners);
ResultPoint.orderBestPatterns(corners);
// Now we know which is which:
ResultPoint bottomRight = corners[0];

View file

@ -24,7 +24,6 @@ import com.google.zxing.Result;
import com.google.zxing.ResultMetadataType;
import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray;
import com.google.zxing.common.GenericResultPoint;
import java.util.Hashtable;
@ -130,8 +129,8 @@ public abstract class AbstractOneDReader implements OneDReader {
result.putMetadata(ResultMetadataType.ORIENTATION, new Integer(180));
// And remember to flip the result points horizontally.
ResultPoint[] points = result.getResultPoints();
points[0] = new GenericResultPoint(width - points[0].getX() - 1, points[0].getY());
points[1] = new GenericResultPoint(width - points[1].getX() - 1, points[1].getY());
points[0] = new ResultPoint(width - points[0].getX() - 1, points[0].getY());
points[1] = new ResultPoint(width - points[1].getX() - 1, points[1].getY());
}
return result;
} catch (ReaderException re) {

View file

@ -21,7 +21,6 @@ import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray;
import com.google.zxing.common.GenericResultPoint;
import java.util.Hashtable;
@ -137,8 +136,8 @@ public abstract class AbstractUPCEANReader extends AbstractOneDReader implements
return new Result(resultString,
null, // no natural byte representation for these barcodes
new ResultPoint[]{
new GenericResultPoint(left, (float) rowNumber),
new GenericResultPoint(right, (float) rowNumber)},
new ResultPoint(left, (float) rowNumber),
new ResultPoint(right, (float) rowNumber)},
getBarcodeFormat());
}

View file

@ -21,7 +21,6 @@ import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray;
import com.google.zxing.common.GenericResultPoint;
import java.util.Hashtable;
@ -461,8 +460,8 @@ public final class Code128Reader extends AbstractOneDReader {
resultString,
null,
new ResultPoint[]{
new GenericResultPoint(left, (float) rowNumber),
new GenericResultPoint(right, (float) rowNumber)},
new ResultPoint(left, (float) rowNumber),
new ResultPoint(right, (float) rowNumber)},
BarcodeFormat.CODE_128);
}

View file

@ -21,7 +21,6 @@ import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray;
import com.google.zxing.common.GenericResultPoint;
import java.util.Hashtable;
@ -160,8 +159,8 @@ public final class Code39Reader extends AbstractOneDReader {
resultString,
null,
new ResultPoint[]{
new GenericResultPoint(left, (float) rowNumber),
new GenericResultPoint(right, (float) rowNumber)},
new ResultPoint(left, (float) rowNumber),
new ResultPoint(right, (float) rowNumber)},
BarcodeFormat.CODE_39);
}

View file

@ -22,7 +22,6 @@ import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
import com.google.zxing.DecodeHintType;
import com.google.zxing.common.BitArray;
import com.google.zxing.common.GenericResultPoint;
import java.util.Hashtable;
@ -115,8 +114,8 @@ public final class ITFReader extends AbstractOneDReader {
return new Result(
resultString,
null, // no natural byte representation for these barcodes
new ResultPoint[] { new GenericResultPoint(startRange[1], (float) rowNumber),
new GenericResultPoint(endRange[0], (float) rowNumber)},
new ResultPoint[] { new ResultPoint(startRange[1], (float) rowNumber),
new ResultPoint(endRange[0], (float) rowNumber)},
BarcodeFormat.ITF);
}

View file

@ -24,32 +24,21 @@ import com.google.zxing.ResultPoint;
*
* @author Sean Owen
*/
public final class AlignmentPattern implements ResultPoint {
public final class AlignmentPattern extends ResultPoint {
private final float posX;
private final float posY;
private final float estimatedModuleSize;
AlignmentPattern(float posX, float posY, float estimatedModuleSize) {
this.posX = posX;
this.posY = posY;
super(posX, posY);
this.estimatedModuleSize = estimatedModuleSize;
}
public float getX() {
return posX;
}
public float getY() {
return posY;
}
/**
* <p>Determines if this alignment pattern "about equals" an alignment pattern at the stated
* position and size -- meaning, it is at nearly the same center with nearly the same size.</p>
*/
boolean aboutEquals(float moduleSize, float i, float j) {
if (Math.abs(i - posY) <= moduleSize && Math.abs(j - posX) <= moduleSize) {
if (Math.abs(i - getY()) <= moduleSize && Math.abs(j - getX()) <= moduleSize) {
float moduleSizeDiff = Math.abs(moduleSize - estimatedModuleSize);
return moduleSizeDiff <= 1.0f || moduleSizeDiff / estimatedModuleSize <= 1.0f;
}

View file

@ -22,7 +22,6 @@ import com.google.zxing.ReaderException;
import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.DetectorResult;
import com.google.zxing.common.GenericResultPoint;
import com.google.zxing.common.GridSampler;
import com.google.zxing.qrcode.decoder.Version;
@ -176,8 +175,8 @@ public final class Detector {
ResultPoint topRight,
ResultPoint bottomLeft,
float moduleSize) throws ReaderException {
int tltrCentersDimension = round(GenericResultPoint.distance(topLeft, topRight) / moduleSize);
int tlblCentersDimension = round(GenericResultPoint.distance(topLeft, bottomLeft) / moduleSize);
int tltrCentersDimension = round(ResultPoint.distance(topLeft, topRight) / moduleSize);
int tlblCentersDimension = round(ResultPoint.distance(topLeft, bottomLeft) / moduleSize);
int dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7;
switch (dimension & 0x03) { // mod 4
case 0:

View file

@ -25,28 +25,17 @@ import com.google.zxing.ResultPoint;
*
* @author Sean Owen
*/
public final class FinderPattern implements ResultPoint {
public final class FinderPattern extends ResultPoint {
private final float posX;
private final float posY;
private final float estimatedModuleSize;
private int count;
FinderPattern(float posX, float posY, float estimatedModuleSize) {
this.posX = posX;
this.posY = posY;
super(posX, posY);
this.estimatedModuleSize = estimatedModuleSize;
this.count = 1;
}
public float getX() {
return posX;
}
public float getY() {
return posY;
}
float getEstimatedModuleSize() {
return estimatedModuleSize;
}
@ -64,7 +53,7 @@ public final class FinderPattern implements ResultPoint {
* position and size -- meaning, it is at nearly the same center with nearly the same size.</p>
*/
boolean aboutEquals(float moduleSize, float i, float j) {
if (Math.abs(i - posY) <= moduleSize && Math.abs(j - posX) <= moduleSize) {
if (Math.abs(i - getY()) <= moduleSize && Math.abs(j - getX()) <= moduleSize) {
float moduleSizeDiff = Math.abs(moduleSize - estimatedModuleSize);
return moduleSizeDiff <= 1.0f || moduleSizeDiff / estimatedModuleSize <= 1.0f;
}

View file

@ -19,10 +19,10 @@ package com.google.zxing.qrcode.detector;
import com.google.zxing.DecodeHintType;
import com.google.zxing.MonochromeBitmapSource;
import com.google.zxing.ReaderException;
import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray;
import com.google.zxing.common.Collections;
import com.google.zxing.common.Comparator;
import com.google.zxing.common.GenericResultPoint;
import java.util.Hashtable;
import java.util.Vector;
@ -162,7 +162,7 @@ final class FinderPatternFinder {
}
FinderPattern[] patternInfo = selectBestPatterns();
GenericResultPoint.orderBestPatterns(patternInfo);
ResultPoint.orderBestPatterns(patternInfo);
return new FinderPatternInfo(patternInfo);
}

View file

@ -108,7 +108,7 @@ public final class Encoder {
}
// Step 1: Choose the mode (encoding).
Mode mode = chooseMode(content);
Mode mode = chooseMode(content, encoding);
// Step 2: Append "bytes" into "dataBits" in appropriate encoding.
BitVector dataBits = new BitVector();
@ -121,17 +121,17 @@ public final class Encoder {
BitVector headerAndDataBits = new BitVector();
// Step 4.5: Append ECI message if applicable
// TODO: Why is this commented out?
/*
if (mode == Mode.BYTE && !DEFAULT_BYTE_MODE_ENCODING.equals(encoding)) {
CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByName(encoding);
if (eci != null) {
appendECI(eci, headerAndDataBits);
}
}
*/
appendModeInfo(mode, headerAndDataBits);
appendLengthInfo(content.length(), qrCode.getVersion(), mode, headerAndDataBits);
int numLetters = mode.equals(Mode.BYTE) ? dataBits.sizeInBytes() : content.length();
appendLengthInfo(numLetters, qrCode.getVersion(), mode, headerAndDataBits);
headerAndDataBits.appendBitVector(dataBits);
// Step 5: Terminate the bits properly.
@ -168,14 +168,18 @@ public final class Encoder {
return -1;
}
/**
* Choose the best mode by examining the content.
*
* Note that this function does not return MODE_KANJI, as we cannot distinguish Shift_JIS from
* other encodings such as ISO-8859-1, from data bytes alone. For example "\xE0\xE0" can be
* interpreted as one character in Shift_JIS, but also two characters in ISO-8859-1.
*/
public static Mode chooseMode(String content) {
return chooseMode(content, null);
}
/**
* Choose the best mode by examining the content. Note that 'encoding' is used as a hint;
* if it is Shift_JIS then we assume the input is Kanji and return {@link Mode#KANJI}.
*/
public static Mode chooseMode(String content, String encoding) {
if ("Shift_JIS".equals(encoding)) {
return Mode.KANJI;
}
boolean hasNumeric = false;
boolean hasAlphanumeric = false;
for (int i = 0; i < content.length(); ++i) {

View file

@ -60,7 +60,10 @@ public final class BufferedImageMonochromeBitmapSource extends BaseMonochromeBit
* @param right one more than the x coordinate of rightmost pixels to decode, i.e. we will decode
* pixels whose x coordinate is in [left,right)
* @param bottom likewise, one more than the y coordinate of the bottommost pixels to decode
* @deprecated use
* {@link com.google.zxing.CroppedMonochromeBitmapSource#CroppedMonochromeBitmapSource(MonochromeBitmapSource, int, int, int, int)}
*/
@Deprecated
public BufferedImageMonochromeBitmapSource(BufferedImage image, int left, int top, int right,
int bottom) {
super(right - left, bottom - top);