blob: a5d9739ce686c01898bfaa90a3ad724b1adac136 [file] [log] [blame]
/*
* 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.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.junit.Assert;
import org.junit.Test;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.EnumMap;
import java.util.Map;
/**
* @author satorux@google.com (Satoru Takabayashi) - creator
* @author dswitkin@google.com (Daniel Switkin) - ported and expanded from C++
*/
public final class QRCodeWriterTestCase extends Assert {
private static final String BASE_IMAGE_PATH = "test/data/golden/qrcode/";
private static BufferedImage loadImage(String fileName) throws IOException {
File file = new File(BASE_IMAGE_PATH + fileName);
if (!file.exists()) {
// try starting with 'core' since the test base is often given as the project root
file = new File("core/" + BASE_IMAGE_PATH + fileName);
}
assertTrue("Please download and install test images, and run from the 'core' directory", file.exists());
return ImageIO.read(file);
}
// In case the golden images are not monochromatic, convert the RGB values to greyscale.
private static BitMatrix 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);
BitMatrix matrix = new BitMatrix(width, height);
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;
if (luminance <= 0x7F) {
matrix.set(x, y);
}
}
}
return matrix;
}
@Test
public void testQRCodeWriter() throws WriterException {
// The QR should be multiplied up to fit, with extra padding if necessary
int bigEnough = 256;
QRCodeWriter writer = new QRCodeWriter();
BitMatrix matrix = writer.encode("http://www.google.com/", BarcodeFormat.QR_CODE, bigEnough,
bigEnough, null);
assertNotNull(matrix);
assertEquals(bigEnough, matrix.getWidth());
assertEquals(bigEnough, matrix.getHeight());
// The QR will not fit in this size, so the matrix should come back bigger
int tooSmall = 20;
matrix = writer.encode("http://www.google.com/", BarcodeFormat.QR_CODE, tooSmall,
tooSmall, null);
assertNotNull(matrix);
assertTrue(tooSmall < matrix.getWidth());
assertTrue(tooSmall < matrix.getHeight());
// We should also be able to handle non-square requests by padding them
int strangeWidth = 500;
int strangeHeight = 100;
matrix = writer.encode("http://www.google.com/", BarcodeFormat.QR_CODE, strangeWidth,
strangeHeight, null);
assertNotNull(matrix);
assertEquals(strangeWidth, matrix.getWidth());
assertEquals(strangeHeight, matrix.getHeight());
}
private static void compareToGoldenFile(String contents,
ErrorCorrectionLevel ecLevel,
int resolution,
String fileName) throws WriterException, IOException {
BufferedImage image = loadImage(fileName);
assertNotNull(image);
BitMatrix goldenResult = createMatrixFromImage(image);
assertNotNull(goldenResult);
Map<EncodeHintType,Object> hints = new EnumMap<EncodeHintType,Object>(EncodeHintType.class);
hints.put(EncodeHintType.ERROR_CORRECTION, ecLevel);
QRCodeWriter writer = new QRCodeWriter();
BitMatrix generatedResult = writer.encode(contents, BarcodeFormat.QR_CODE, resolution,
resolution, hints);
assertEquals(resolution, generatedResult.getWidth());
assertEquals(resolution, generatedResult.getHeight());
assertEquals(goldenResult, generatedResult);
}
// 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.
@Test
public void testRegressionTest() throws Exception {
compareToGoldenFile("http://www.google.com/", ErrorCorrectionLevel.M, 99,
"renderer-test-01.png");
compareToGoldenFile("12345", ErrorCorrectionLevel.L, 58, "renderer-test-02.png");
// Test in Katakana in Shift_JIS.
// TODO: this test is bogus now that byte mode has been basically fixed to assuming ISO-8859-1 encoding
// The real solution is to implement Kanji mode, in which case the golden file will be wrong again
/*
compareToGoldenFile(
new String(new byte[] {(byte)0x83, 0x65, (byte)0x83, 0x58, (byte)0x83, 0x67}, "Shift_JIS"),
ErrorCorrectionLevel.H, 145,
"renderer-test-03.png");
*/
}
}