【问题标题】:Encoding and decoding random byte array with zxing用 zxing 编码和解码随机字节数组
【发布时间】:2013-01-16 20:01:38
【问题描述】:

我正在尝试使用 QR 码传输字节数组,因此为了测试,我决定生成一个随机字节数组,将其编码为 QR 码,然后对其进行解码。我使用 ISO-8859-1 将字节数组转换为字符串 s.t 它在传输时不会丢失数据:

编码器端:

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();
    }

这样我已经将字节数组转换为二维码,没有问题。 但是对于接收方:

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();
}

我试图解码生成的二维码,但它抛出了 NotFoundException。 有人可以帮我解决这个问题吗?

更新 1:我确认解码器与普通 QR 完美配合,我还添加了 DecodeHintType.try_harder 但仍然不行。

更新 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));

如果你运行这个,你可以很容易地看到你最终可以得到完全相同的数组。我对此没有任何问题。

Update 3:我也尝试过使用 UTF-8 对其进行编码,但它会丢失数据,因此不能用于编码器。

更新 4:刚刚添加:

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

在解码器中,仍然抛出异常。

【问题讨论】:

  • 我使用 ISO-8859-1 将字节数组转换为字符串,因此在传输时不会丢失数据。抱歉,这没有任何意义。
  • 对不起,我的意思是我可以将随机字节数组转换为字符串,然后再转换回来,我仍然可以获得相同的字节数组。我的更新#2 显示了详细信息
  • 您说过它在一条消息中有效。您还没有发布任何失败的二维码。有什么问题?
  • 如果你像我的更新 2 那样生成一个随机字节数组,那么它肯定会失败。但是,如果我只输入一个字符串并进行编码,它就可以正常工作。
  • 这已经正确解码了。但是尝试 PURE_BARCODE 模式

标签: java android qr-code zxing


【解决方案1】:

尝试PURE_BARCODE 模式作为检测提示。奇怪的是,当图像只是一个纯合成图像时,发现者模式的误报检测是一个更大的问题。启发式假设一张照片没有这些问题。在这种替代模式下,它可以利用知道它是纯图像而不是照片的优势,并且速度更快,并且永远不会出错。

【讨论】:

  • 谢谢,notfoundexception已经消失了。。但是现在解码器出现formatexception,你能告诉我这是为什么吗?
  • 我的解码器现在和我的更新7一样,图片还是我贴的截图。
  • 现在我的问题是,什么样的解码提示组合才能成功解码这张图片?谢谢
  • 我尝试了所有可能的提示组合,但仍然抛出未找到和校验和异常:(
  • 我自己解决了这个问题,我在解码之前不小心篡改了YUV数据,很抱歉给您带来麻烦。
【解决方案2】:

在二维码中存储二进制数据需要克服两个问题。

  1. ISO-8859-1 不允许 00-1F 和 7F-9F 范围内的字节。由于您使用的是随机生成器,因此您只需检查随机生成的字节是否适合此值并重新生成它,直到您获得适合此范围的随机字节。如果你 尽管如此,无论如何都需要对这些字节进行编码,您可以将数组编码为 Base-64 字符串或十六进制字符串。如果是十六进制字符串,它将以字母数字模式存储在 QR 码中,而不是 8 位模式。

  2. 由于您尝试将二进制数据存储在 QR 码中,因此您必须 仅依靠您自己的扫描仪来处理此二进制数据,并且您需要确保您的扫描仪不使用启发式算法来自动确定字符编码等等。大多数 QR 解码器使用启发式方法来检测字符 设置使用。这些启发式可能会检测到一个字符集,而不是 ISO-8859-1,因此无法正确显示您的二进制数据。一些 扫描仪使用启发式方法来检测字符集,即使 字符集由二维码内的 ECI 可选扩展明确给出。

因此,仅使用 US-ASCII(例如,在将其传递给 QR 码生成器之前以 Base64 编码的二进制数据)是针对启发式的 QR 码的最安全选择。这也将克服另一个复杂性:ISO-8859-1 不是 2000 年发布的早期 QR 码标准 (ISO/IEC 18004:2000) 中的默认编码。该标准确实根据 JIS X 0201(JIS8 也称为 ISO-2022-JP)指定了 8 位拉丁/假名字符集作为 8 位模式的默认编码,而 2005 年发布的更新标准确实将默认设置更改为ISO-8859-1。

如果您将缓冲区作为十六进制字符串存储在 QR 码中,这肯定会禁用所有启发式算法,并且不会产生比 Base-64 更大的 QR 码,因为字母数字模式下的每个字符在二维码流。

【讨论】:

    猜你喜欢
    • 2012-06-19
    • 2011-10-04
    • 2013-05-11
    • 2013-05-25
    • 2012-03-25
    • 1970-01-01
    • 1970-01-01
    • 2010-10-27
    • 2011-01-30
    相关资源
    最近更新 更多