Example QR Code Binary Data

From BoofCV
Revision as of 12:11, 24 January 2022 by Peter (talk | contribs) (Created page with "As is explained below, things are a bit tricky when you encode binary data inside a QR code. This example shows you multiple ways to decode the binary data without corrupting...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

As is explained below, things are a bit tricky when you encode binary data inside a QR code. This example shows you multiple ways to decode the binary data without corrupting it. Hopefully the person who created the QR Code knew what they were doing and didn't corrupt the data either...

Example Code:

Concepts:

  • QR Codes
  • Binaries

Relevant Examples/Tutorials:

Example Code

/**
 * When dealing with binary data embedded in a QR code things do get more complicated. You will need to convert
 * the string message into a byte array. By default, it's assumed that BYTE data is a text string and it will
 * encode it into a string. In general the conversion to a string will not modify the data but it's not defined
 * how illegal characters are encoded. To be safe you can force the encoding to be "binary".
 *
 * @author Peter Abeles
 */
public class ExampleQrCodeBinaryData {
	public static void main( String[] args ) throws UnsupportedEncodingException {
		// Let's generate some random data. In the real world this could be a zip file or similar
		byte[] originalData = new byte[500];
		for (int i = 0; i < originalData.length; i++) {
			originalData[i] = (byte)i;
		}

		// Generate a marking that's encoded with this raw data
		QrCode original = new QrCodeEncoder().addBytes(originalData).fixate();
		var gray = new QrCodeGeneratorImage(/* pixel per module */ 5).render(original).getGray();

		// Let's detect and then decode the image
		var config = new ConfigQrCode();
		// If you force the encoding to "binary" then you turn off auto encoding you know the bit values will not
		// be modified. It's undefined how illegal values are handled in different encodings, but often still work.
		config.forceEncoding = EciEncoding.BINARY;
		QrCodeDetector<GrayU8> detector = FactoryFiducial.qrcode(config, GrayU8.class);
		detector.process(gray);

		for (QrCode qr : detector.getDetections()) {
			// Only consider QR codes that are encoded with BYTE data
			if (qr.mode != QrCode.Mode.BYTE)
				continue;

			// Convert the message from a String to byte data. This only works if the 'binary' encoding is used
			byte[] data;
			if (qr.byteEncoding.equals(EciEncoding.BINARY)) {
				data = BoofMiscOps.castStringToByteArray(qr.message);
			} else {
				// If it thought the byte data was UTF-8 you need to decode with UTF-8 because a single character
				// can be multiple bytes.
				data = qr.message.getBytes(qr.byteEncoding);
			}

			// See if the data got corrupted or not
			boolean perfectMatch = data.length == originalData.length;
			for (int i = 0; i < data.length; i++) {
				perfectMatch &= data[i] == originalData[i];
			}

			// Print the results
			System.out.println("Encoding: '" + qr.byteEncoding + "' Matched: " + perfectMatch);
		}
	}
}