mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -08:00
Ported and rewrote the Renderer unit test to test QRCodeWriter. We encode several barcodes looking for good behavior, and several others which are compared pixel by pixel to golden results stored in PNGs. I'm happy to say we nail the three images Satoru created to the dot!
Along the way, I added support for encoder hints, and no longer hardcode the error correction level. git-svn-id: https://zxing.googlecode.com/svn/trunk@752 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
6d7d507e27
commit
0f648cd1be
34
core/src/com/google/zxing/EncodeHintType.java
Normal file
34
core/src/com/google/zxing/EncodeHintType.java
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* These are a set of hints that you may pass to Writers to specify their behavior.
|
||||
*
|
||||
* @author dswitkin@google.com (Daniel Switkin)
|
||||
*/
|
||||
public final class EncodeHintType {
|
||||
|
||||
/**
|
||||
* Specifies what degree of error correction to use, for example in QR Codes (type Integer).
|
||||
*/
|
||||
public static final EncodeHintType ERROR_CORRECTION = new EncodeHintType();
|
||||
|
||||
private EncodeHintType() {
|
||||
}
|
||||
|
||||
}
|
|
@ -17,10 +17,11 @@
|
|||
package com.google.zxing.qrcode;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.Writer;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.ByteMatrix;
|
||||
import com.google.zxing.common.ByteArray;
|
||||
import com.google.zxing.common.ByteMatrix;
|
||||
import com.google.zxing.qrcode.encoder.Encoder;
|
||||
import com.google.zxing.qrcode.encoder.QRCode;
|
||||
|
||||
|
@ -57,8 +58,14 @@ public final class QRCodeWriter implements Writer {
|
|||
height);
|
||||
}
|
||||
|
||||
// TODO: Check hints for error correction level instead of hardcoding
|
||||
int errorCorrectionLevel = QRCode.EC_LEVEL_L;
|
||||
if (hints != null) {
|
||||
Integer requestedECLevel = (Integer) hints.get(EncodeHintType.ERROR_CORRECTION);
|
||||
if (requestedECLevel != null) {
|
||||
errorCorrectionLevel = requestedECLevel.intValue();
|
||||
}
|
||||
}
|
||||
|
||||
QRCode code = new QRCode();
|
||||
Encoder.Encode(new ByteArray(contents), errorCorrectionLevel, code);
|
||||
return renderResult(code, width, height);
|
||||
|
|
Before Width: | Height: | Size: 287 B After Width: | Height: | Size: 287 B |
Before Width: | Height: | Size: 189 B After Width: | Height: | Size: 189 B |
Before Width: | Height: | Size: 280 B After Width: | Height: | Size: 280 B |
139
core/test/src/com/google/zxing/qrcode/QRCodeWriterTestCase.java
Normal file
139
core/test/src/com/google/zxing/qrcode/QRCodeWriterTestCase.java
Normal file
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* 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.qrcode;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.ByteMatrix;
|
||||
import com.google.zxing.qrcode.encoder.QRCode;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
* @author satorux@google.com (Satoru Takabayashi) - creator
|
||||
* @author dswitkin@google.com (Daniel Switkin) - ported and expanded from C++
|
||||
*/
|
||||
public final class QRCodeWriterTestCase extends TestCase {
|
||||
|
||||
private static final String BASE_IMAGE_PATH = "test/data/golden/qrcode/";
|
||||
|
||||
private static BufferedImage loadImage(String fileName) {
|
||||
try {
|
||||
File file = new File(BASE_IMAGE_PATH + fileName);
|
||||
assertTrue("Please run from the 'core' directory", file.exists());
|
||||
return ImageIO.read(file);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// In case the golden images are not monochromatic, convert the RGB values to greyscale.
|
||||
private static ByteMatrix createMatrixFromImage(BufferedImage image) {
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
int[] pixels = new int[width * height];
|
||||
image.getRGB(0, 0, width, height, pixels, 0, width);
|
||||
|
||||
ByteMatrix matrix = new ByteMatrix(height, width);
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int pixel = pixels[y * width + x];
|
||||
int luminance = (306 * ((pixel >> 16) & 0xFF) +
|
||||
601 * ((pixel >> 8) & 0xFF) +
|
||||
117 * (pixel & 0xFF)) >> 10;
|
||||
matrix.set(y, x, luminance);
|
||||
}
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
public void testQRCodeWriter() throws WriterException {
|
||||
// The QR should be multiplied up to fit, with extra padding if necessary
|
||||
final int bigEnough = 256;
|
||||
QRCodeWriter writer = new QRCodeWriter();
|
||||
ByteMatrix matrix = writer.encode("http://www.google.com/", BarcodeFormat.QR_CODE, bigEnough,
|
||||
bigEnough, null);
|
||||
assertTrue(matrix != null);
|
||||
assertEquals(bigEnough, matrix.width());
|
||||
assertEquals(bigEnough, matrix.height());
|
||||
|
||||
// The QR will not fit in this size, so the matrix should come back bigger
|
||||
final int tooSmall = 20;
|
||||
matrix = writer.encode("http://www.google.com/", BarcodeFormat.QR_CODE, tooSmall,
|
||||
tooSmall, null);
|
||||
assertTrue(matrix != null);
|
||||
assertTrue(tooSmall < matrix.width());
|
||||
assertTrue(tooSmall < matrix.height());
|
||||
|
||||
// We should also be able to handle non-square requests by padding them
|
||||
final int strangeWidth = 500;
|
||||
final int strangeHeight = 100;
|
||||
matrix = writer.encode("http://www.google.com/", BarcodeFormat.QR_CODE, strangeWidth,
|
||||
strangeHeight, null);
|
||||
assertTrue(matrix != null);
|
||||
assertEquals(strangeWidth, matrix.width());
|
||||
assertEquals(strangeHeight, matrix.height());
|
||||
}
|
||||
|
||||
private static boolean compareToGoldenFile(final String contents, final int ecLevel,
|
||||
final int resolution, final String fileName) throws WriterException {
|
||||
|
||||
BufferedImage image = loadImage(fileName);
|
||||
assertNotNull(image);
|
||||
ByteMatrix goldenResult = createMatrixFromImage(image);
|
||||
assertNotNull(goldenResult);
|
||||
|
||||
QRCodeWriter writer = new QRCodeWriter();
|
||||
Hashtable hints = new Hashtable();
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, new Integer(ecLevel));
|
||||
ByteMatrix generatedResult = writer.encode(contents, BarcodeFormat.QR_CODE, resolution,
|
||||
resolution, hints);
|
||||
|
||||
assertEquals("Width should be " + resolution + ", but was " + generatedResult.width(),
|
||||
resolution, generatedResult.width());
|
||||
assertEquals("Height should be " + resolution + ", but was " + generatedResult.height(),
|
||||
resolution, generatedResult.height());
|
||||
assertTrue("Expected " + goldenResult.toString() + " but got " + generatedResult.toString(),
|
||||
Arrays.deepEquals(goldenResult.getArray(), generatedResult.getArray()));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Golden images are generated with "qrcode_sample.cc". The images are checked with both eye balls
|
||||
// and cell phones. We expect pixel-perfect results, because the error correction level is known,
|
||||
// and the pixel dimensions matches exactly.
|
||||
public void testRegressionTest() throws WriterException {
|
||||
assertTrue(compareToGoldenFile("http://www.google.com/", QRCode.EC_LEVEL_M, 99,
|
||||
"renderer-test-01.png"));
|
||||
|
||||
assertTrue(compareToGoldenFile("12345", QRCode.EC_LEVEL_L, 58, "renderer-test-02.png"));
|
||||
|
||||
// Test in Katakana in Shift_JIS.
|
||||
final byte[] KATAKANA_INPUT = {
|
||||
(byte)0x83, 0x65, (byte)0x83, 0x58, (byte)0x83, 0x67
|
||||
};
|
||||
assertTrue(compareToGoldenFile(new String(KATAKANA_INPUT), QRCode.EC_LEVEL_H, 145,
|
||||
"renderer-test-03.png"));
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue