简体   繁体   English

使用 zxing 编码和解码随机字节数组

[英]Encoding and decoding random byte array with zxing

I'm trying to transfer a byte array with QR code, so for testing, I decided to generate a random byte array, encode it as QR code, then decode it.我正在尝试使用二维码传输字节数组,因此为了测试,我决定生成一个随机字节数组,将其编码为二维码,然后对其进行解码。 I used ISO-8859-1 to convert byte array to string st it does not lose data while transmission:我使用 ISO-8859-1 将字节数组转换为字符串 st 它在传输时不会丢失数据:

For encoder side:对于编码器端:

byte []buffer = new byte[11];
com.google.zxing.Writer writer = new QRCodeWriter();
Random randomGenerator = new Random();
    for(int i=0;i<=10;i++){
        buffer[i]=(byte) randomGenerator.nextInt(254);
    }
   // Log.i("time1","original: "+Arrays.toString(buffer));
    String decoded = null;
    try {
        decoded = new String(buffer, "ISO-8859-1");
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    try {
        result=writer.encode(decoded, BarcodeFormat.QR_CODE, 500, 500);
    } catch (WriterException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

In this way I have converted byte array to QR code, it has no problem.这样我已经将字节数组转换为二维码,没有问题。 But for the receiver side:但对于接收方:

LuminanceSource source = new PlanarYUVLuminanceSource(data,640,480,0,0,640,480,false);
bmtobedecoded = new BinaryBitmap(new HybridBinarizer(source));
Map<DecodeHintType,Object> mp=new HashMap<DecodeHintType, Object>();

mp.put(DecodeHintType.TRY_HARDER, true);
try {
    result= qrr.decode(bmtobedecoded,mp);
} catch (NotFoundException e) {
    Log.i("123","not found");
    e.printStackTrace();
} catch (ChecksumException e) {
    Log.i("123","checksum");
    e.printStackTrace();
} catch (FormatException e) {
    Log.i("123","format");
    e.printStackTrace();
}

I tried to decode the generated QR code, but it throws out NotFoundException.我试图解码生成的二维码,但它抛出了 NotFoundException。 Can someone help me with this issue?有人可以帮我解决这个问题吗?

Update 1 : I confirmed that the decoder works perfectly with the normal QR, I also added DecodeHintType.try_harder but still no good.更新 1 :我确认解码器与普通 QR 完美配合,我还添加了 DecodeHintType.try_harder 但仍然不好。

Update 2 : To clarify, below is what I did to convert between byte array and string:更新 2 :为了澄清,下面是我在字节数组和字符串之间进行转换的操作:

Random randomGenerator = new Random();
for(int i=0;i<=10;i++){
    buffer[i]=(byte) randomGenerator.nextInt(254);
}
Log.i("time1","original: "+Arrays.toString(buffer));
String decoded = null;
try {
    decoded = new String(buffer, "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
Log.i("time1","encoded string:" + decoded);
BitMatrix result=null;
try {
    result=qw.encode(decoded, BarcodeFormat.QR_CODE, 500, 500);
} catch (WriterException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}
iv.setImageBitmap(encodematrix(result));
byte[] encoded = null;
try {
    encoded = decoded.getBytes("ISO-8859-1");
} catch (UnsupportedEncodingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} 
Log.i("time1","result byte array:" + java.util.Arrays.toString(encoded));

If you run this, you can easily see that you can get exactly the same array in the end.如果你运行这个,你可以很容易地看到你最终可以得到完全相同的数组。 I have no problem with this.我对此没有任何问题。

Update 3 : I also tried encoding it using UTF-8, but it loses data, so it cannot be the used in encoder.更新 3 :我也尝试使用 UTF-8 对其进行编码,但它会丢失数据,因此无法在编码器中使用。

Update 4 : Just added:更新 4 :刚刚添加:

Map<DecodeHintType,Object> mp=new HashMap<DecodeHintType, Object>();
mp.put(DecodeHintType.CHARACTER_SET, "ISO-8859-1");

in the decoder, still throwing out exception.在解码器中,仍然抛出异常。

Try PURE_BARCODE mode as a detection hint.尝试PURE_BARCODE模式作为检测提示。 Strangely, false positive detection of finder patterns is a much bigger problem when the image is just a pure synthetic image.奇怪的是,当图像只是纯合成图像时,发现者模式的误报检测是一个更大的问题。 The heuristics assume a photo, which doesn't have these problems.启发式假设一张照片,它没有这些问题。 In this alternate mode it can take advantage of knowing it's a pure image and not a photo and be much faster and never get the detection wrong.在这种替代模式下,它可以利用知道它是纯图像而不是照片的优势,并且速度更快,永远不会出错。

There are two issues that you have to overcome to store binary data in QR codes.要将二进制数据存储在二维码中,您必须克服两个问题。

  1. ISO-8859-1 does not allow bytes in ranges of 00-1F and 7F-9F. ISO-8859-1 不允许 00-1F 和 7F-9F 范围内的字节。 Since you are using a random generator, you can just check whether a randomly generated byte fits this value and re-generate it until you get a random byte that fits this range.由于您使用的是随机生成器,因此您只需检查随机生成的字节是否适合该值并重新生成它,直到获得适合该范围的随机字节。 If you nevertheless need to encode these bytes anyway, you may encode the array as a Base-64 string or as a hexadecimal string.如果仍然需要对这些字节进行编码,则可以将数组编码为 Base-64 字符串或十六进制字符串。 In case of a hexadecimal string, it will be stored in the QR code in the alphanumeric mode, not in 8-bit mode.如果是十六进制字符串,它将以字母数字模式而不是 8 位模式存储在二维码中。

  2. Since you are trying to store binary data in QR codes, you have to rely only on your own scanner that will handle this binary data, and you need to make sure that your scanner does not use heuristics to automatically determine character encoding, and so on.由于您尝试在二维码中存储二进制数据,因此您只能依靠自己的扫描仪来处理这些二进制数据,并且您需要确保您的扫描仪不会使用启发式算法来自动确定字符编码,等等. Most QR decoders use heuristics to detect the character set used.大多数 QR 解码器使用启发式方法来检测使用的字符集。 These heuristics may detect a character set other than ISO-8859-1 and thus fail to properly display your binary data.这些启发式方法可能会检测到 ISO-8859-1 以外的字符集,因此无法正确显示您的二进制数据。 Some scanners use heuristics to detect a character set even if the character set is explicitly given by the ECI optional extension inside the QR Code.一些扫描器使用启发式方法来检测字符集,即使字符集是由 QR 码内的 ECI 可选扩展明确给出的。

So, using US-ASCII only (eg, binary data encoded in Base64 before passing it to a QR Code generator) is the safest choice for QR code against the heuristics.因此,仅使用 US-ASCII(例如,在将二进制数据传递给 QR 码生成器之前以 Base64 编码的二进制数据)是对抗试探法的 QR 码最安全的选择。 This will also overcome another complication: that ISO-8859-1 was not the default encoding in earlier QR code standard published in 2000 (ISO/IEC 18004:2000).这还将克服另一个复杂问题:ISO-8859-1 不是 2000 年发布的早期二维码标准 (ISO/IEC 18004:2000) 中的默认编码。 That standard did specify 8-bit Latin/Kana character set in accordance with JIS X 0201 (JIS8 also known as ISO-2022-JP) as default encoding for 8-bit mode, while the updated standard published in 2005 did change the default to ISO-8859-1.该标准确实指定了符合 JIS X 0201(JIS8 也称为 ISO-2022-JP)的 8 位拉丁文/假名字符集作为 8 位模式的默认编码,而 2005 年发布的更新标准确实将默认值更改为ISO-8859-1。

If you store your buffer as a hexadecimal string in your QR code, this will disable all heuristics for sure and should not produce larger QR Code than with Base-64, because each character in the alphanumeric mode takes only 6 bits in the QR code stream.如果您将缓冲区存储为 QR 码中的十六进制字符串,这肯定会禁用所有启发式方法,并且不应生成比 Base-64 更大的 QR 码,因为字母数字模式中的每个字符在 QR 码流中仅占 6 位.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM