Created
May 31, 2014 19:02
-
-
Save creswick/17808161de1f37a94415 to your computer and use it in GitHub Desktop.
Property-based Junit test to check that zxing barcodes will round-trip with PURE_BARCODE
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.galois.qrstream.qrpipe; | |
import static org.junit.Assert.assertEquals; | |
import static org.junit.Assert.fail; | |
import java.awt.image.BufferedImage; | |
import java.io.File; | |
import java.io.IOException; | |
import java.util.Collection; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Random; | |
import javax.imageio.ImageIO; | |
import org.junit.Test; | |
import org.junit.runner.RunWith; | |
import org.junit.runners.Parameterized; | |
import org.junit.runners.Parameterized.Parameters; | |
import com.google.common.base.Charsets; | |
import com.google.common.collect.Lists; | |
import com.google.common.collect.Maps; | |
import com.google.zxing.BarcodeFormat; | |
import com.google.zxing.BinaryBitmap; | |
import com.google.zxing.ChecksumException; | |
import com.google.zxing.DecodeHintType; | |
import com.google.zxing.EncodeHintType; | |
import com.google.zxing.FormatException; | |
import com.google.zxing.LuminanceSource; | |
import com.google.zxing.NotFoundException; | |
import com.google.zxing.Result; | |
import com.google.zxing.WriterException; | |
import com.google.zxing.client.j2se.BufferedImageLuminanceSource; | |
import com.google.zxing.client.j2se.MatrixToImageWriter; | |
import com.google.zxing.common.BitMatrix; | |
import com.google.zxing.common.HybridBinarizer; | |
import com.google.zxing.qrcode.QRCodeReader; | |
import com.google.zxing.qrcode.QRCodeWriter; | |
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; | |
/** | |
* Property-based test to confirm that PURE_BARCODE can correctly decode any | |
* machine-generated qr codes. | |
* | |
* @author creswick | |
* | |
*/ | |
@RunWith(Parameterized.class) | |
public class QRCodePureBarcodeRoundTripTest { | |
private static final int COUNT = 30; | |
@Parameters(name = "{0}") | |
public static Collection<Object[]> setup() { | |
List<Object[]> qrcodes = Lists.newArrayList(); | |
long seed = System.currentTimeMillis(); | |
Random rand = new Random(seed); | |
for(int i = 0; i < COUNT; i++ ){ | |
byte[] bytes = new byte[1 + nextNatural(rand) % 768]; | |
rand.nextBytes(bytes); | |
int height = 200;// + (nextNatural(rand) % 7) * 100; | |
int width = 200;// + (nextNatural(rand) % 7) * 100; | |
String data = new String(bytes, Charsets.ISO_8859_1); | |
qrcodes.add(new Object[] { "seed: "+ seed + ": "+i | |
, data, height, width | |
}); | |
} | |
return qrcodes; | |
} | |
public static int nextNatural(Random r) { | |
return Math.abs(r.nextInt()); | |
} | |
private static BufferedImage encodeQRCode(String data, int height, int width) | |
throws WriterException { | |
QRCodeWriter writer = new QRCodeWriter(); | |
Map<EncodeHintType, Object> hints = Maps.newHashMap(); | |
hints.put(EncodeHintType.CHARACTER_SET, "ISO-8859-1"); | |
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); | |
BitMatrix bMat = writer.encode(data, BarcodeFormat.QR_CODE, | |
width, height, hints); | |
BufferedImage newCode = MatrixToImageWriter.toBufferedImage(bMat); | |
return newCode; | |
} | |
private static Result decodeQRcode(BufferedImage image) throws NotFoundException, | |
ChecksumException, FormatException { | |
LuminanceSource source = new BufferedImageLuminanceSource(image); | |
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); | |
Map<DecodeHintType, Object> hints = Maps.newHashMap(); | |
hints.put(DecodeHintType.CHARACTER_SET, "ISO-8859-1"); | |
hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE); | |
// decode the barcode | |
QRCodeReader reader = new QRCodeReader(); | |
Result res = reader.decode(bitmap, hints); | |
//return getRawData(res); | |
return res; | |
} | |
private String expected; | |
private int height; | |
private int width; | |
public QRCodePureBarcodeRoundTripTest(String name, String data, int height, int width) { | |
super(); | |
this.expected = data; | |
this.height = height; | |
this.width = width; | |
} | |
@Test | |
public void test() throws WriterException, ChecksumException, FormatException, IOException { | |
BufferedImage image = encodeQRCode(expected, height, width); | |
Result res = null; | |
try { | |
res = decodeQRcode(image); | |
} catch (NotFoundException e) { | |
String dest = saveImage(image, "not-found-"); | |
fail("Could not locate QR Code in image: " + dest); | |
} | |
String actual = res.getText(); | |
if ( !actual.equals(expected) ) { | |
String dest = saveImage(image, "failed-roundtrip-"); | |
assertEquals("Data did not roundtrip via image: " + dest, | |
expected, actual); | |
} | |
} | |
private String saveImage(BufferedImage image, String prefix) throws IOException { | |
File outputFile = File.createTempFile(prefix, ".png"); | |
ImageIO.write(image, "png", outputFile); | |
return outputFile.getAbsolutePath(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment