Skip to content

Commit

Permalink
BoofMiscOps
Browse files Browse the repository at this point in the history
- Added md5sum function
QrCode
- Renamed "raw" to "binary" since it is more commonly referred to as binary data
  • Loading branch information
lessthanoptimal committed Jan 24, 2022
1 parent 22eb1fa commit ac90ca3
Show file tree
Hide file tree
Showing 9 changed files with 47 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package boofcv.examples.fiducial;

import boofcv.abst.fiducial.QrCodeDetector;
import boofcv.alg.fiducial.qrcode.EciEncoding;
import boofcv.alg.fiducial.qrcode.QrCode;
import boofcv.alg.fiducial.qrcode.QrCodeEncoder;
import boofcv.alg.fiducial.qrcode.QrCodeGeneratorImage;
Expand All @@ -33,11 +34,11 @@
* 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 "raw".
* how illegal characters are encoded. To be safe you can force the encoding to be "binary".
*
* @author Peter Abeles
*/
public class ExampleQrCodeRawData {
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];
Expand All @@ -51,9 +52,9 @@ public static void main( String[] args ) throws UnsupportedEncodingException {

// Let's detect and then decode the image
var config = new ConfigQrCode();
// If you force the encoding to "raw" then you turn off auto encoding you know the bit values will not
// 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 = "raw";
config.forceEncoding = EciEncoding.BINARY;
QrCodeDetector<GrayU8> detector = FactoryFiducial.qrcode(config, GrayU8.class);
detector.process(gray);

Expand All @@ -62,10 +63,10 @@ public static void main( String[] args ) throws UnsupportedEncodingException {
if (qr.mode != QrCode.Mode.BYTE)
continue;

// Convert the message from a String to byte data. This only works if the 'raw' encoding is used
// Convert the message from a String to byte data. This only works if the 'binary' encoding is used
byte[] data;
if (qr.byteEncoding.equals("raw")) {
data = BoofMiscOps.stringRawToByteArray(qr.message);
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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
* @author Peter Abeles
*/
public class EciEncoding {
// BINARY is specific to BoofCV and is used to indicate that there should be no encoding done
public static final String BINARY = "binary";

// Standard QR Code string encodings
public static final String UTF8 = "UTF8";
public static final String ISO8859_1 = "ISO8859_1";
public static final String JIS = "JIS";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ public int decodeByte( PackedBits8 data, int bitLocation, int lengthBits ) {

selectedByteEncoding = selectByteEncoding(rawdata);
try {
if (selectedByteEncoding.equalsIgnoreCase("raw")) {
if (selectedByteEncoding.equalsIgnoreCase(EciEncoding.BINARY)) {
// Handle raw mode where there is no encoding which could change the character's value.
// This is what the QR code specifications says you should use, but most ignore it
workString.ensureCapacity(workString.length() + rawdata.length);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public class ConfigMicroQrCode implements Configuration {
/**
* If not null, then when decoding BYTE mode data it will always use this encoding. This can be desirable
* if the automatic encoding detection is making a mistake or if you know the data is binary. For binary
* data you should set this to "raw".
* data you should set this to {@link EciEncoding#BINARY}.
*/
public @Nullable String forceEncoding = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class ConfigQrCode implements Configuration {
/**
* If not null, then when decoding BYTE mode data it will always use this encoding. This can be desirable
* if the automatic encoding detection is making a mistake or if you know the data is binary. For binary
* data you should set this to "raw".
* data you should set this to {@link EciEncoding#BINARY}.
*/
public @Nullable String forceEncoding = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,18 @@ public class TestQrCodeCodecBitsUtils extends BoofStandardJUnit {
}

/** Tell it to encode a raw byte array and see if it does it correctly. No hints */
@Test void rawBytesAutoEncoding() {
checkRawBytes(255, null);
@Test void binaryAutoEncoding() {
checkBinaryBytes(255, null);
}

/** Tell it that it should use raw bytes */
@Test void rawBytesHint() {
@Test void binaryBytesHint() {
// reduce the number of values so that UTF-8 is still an option, and it will modify the byte
// values unless you force it into raw mode
checkRawBytes(150, "raw");
checkBinaryBytes(150, EciEncoding.BINARY);
}

void checkRawBytes( int length, @Nullable String forceEncoding ) {
void checkBinaryBytes( int length, @Nullable String forceEncoding ) {
// encode fewer values so that it could possibly be UTF-8 without the hint
byte[] data = new byte[length];
for (int i = 0; i < data.length; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class TestQrCodeDecoderBits extends BoofStandardJUnit {
@Test public void applyErrorCorrection() {
QrCode qr = new QrCodeEncoder().addNumeric("923492348985").fixate();

var alg = new QrCodeDecoderBits(EciEncoding.UTF8, "raw");
var alg = new QrCodeDecoderBits(EciEncoding.UTF8, EciEncoding.BINARY);

byte[] original = new byte[qr.rawbits.length];
System.arraycopy(qr.rawbits, 0, original, 0, original.length);
Expand Down Expand Up @@ -71,7 +71,7 @@ public class TestQrCodeDecoderBits extends BoofStandardJUnit {
@Test public void checkPaddingBytes() {
QrCode qr = new QrCodeEncoder().addNumeric("923492348985").fixate();

var alg = new QrCodeDecoderBits(EciEncoding.UTF8, "raw");
var alg = new QrCodeDecoderBits(EciEncoding.UTF8, EciEncoding.BINARY);

qr.corrected = new byte[50];

Expand Down Expand Up @@ -102,7 +102,7 @@ public class TestQrCodeDecoderBits extends BoofStandardJUnit {
// ECI Assignment number
bits.append(0b00001001, 8, false);

var alg = new QrCodeDecoderBits(EciEncoding.UTF8, "raw");
var alg = new QrCodeDecoderBits(EciEncoding.UTF8, EciEncoding.BINARY);

int newBit = alg.decodeEci(bits, 0);
assertEquals("ISO8859_7", alg.encodingEci);
Expand Down
25 changes: 23 additions & 2 deletions main/boofcv-types/src/main/java/boofcv/misc/BoofMiscOps.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

import java.io.*;
import java.lang.reflect.Method;
import java.security.MessageDigest;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
Expand All @@ -45,7 +46,7 @@
*
* @author Peter Abeles
*/
@SuppressWarnings("rawtypes")
@SuppressWarnings({"rawtypes", "ForLoopReplaceableByForEach"})
public class BoofMiscOps {

/**
Expand Down Expand Up @@ -1019,11 +1020,31 @@ public static int getJavaVersion() {
* @param message String with raw bytes encoded inside of it.
* @return byte array conversion of the string.
*/
public static byte[] stringRawToByteArray( String message ) {
public static byte[] castStringToByteArray( String message ) {
byte[] data = new byte[message.length()];
for (int i = 0; i < message.length(); i++) {
data[i] = (byte)message.charAt(i);
}
return data;
}

/**
* Computes MD5SUM of byte data as a string
*/
public static String md5sum( byte[] data ) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
return byteArrayToHex(md.digest(data));
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public static String byteArrayToHex(byte[] array) {
var sb = new StringBuilder(array.length * 2);
for (int i = 0; i < array.length; i++) {
sb.append(String.format("%02X", array[i]));
}
return sb.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ void containsDuplicates() {
builder.append((char)i);
}

byte[] found = BoofMiscOps.stringRawToByteArray(builder.toString());
byte[] found = BoofMiscOps.castStringToByteArray(builder.toString());
for (int i = 0; i < N; i++) {
assertEquals(i & 0xFF, found[i] & 0xFF);
}
Expand Down

0 comments on commit ac90ca3

Please sign in to comment.