簡體   English   中英

使用 zxing 編碼和解碼隨機字節數組

[英]Encoding and decoding random byte array with zxing

我正在嘗試使用二維碼傳輸字節數組,因此為了測試,我決定生成一個隨機字節數組,將其編碼為二維碼,然后對其進行解碼。 我使用 ISO-8859-1 將字節數組轉換為字符串 st 它在傳輸時不會丟失數據:

對於編碼器端:

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

如果你運行這個,你可以很容易地看到你最終可以得到完全相同的數組。 我對此沒有任何問題。

更新 3 :我也嘗試使用 UTF-8 對其進行編碼,但它會丟失數據,因此無法在編碼器中使用。

更新 4 :剛剛添加:

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

在解碼器中,仍然拋出異常。

嘗試PURE_BARCODE模式作為檢測提示。 奇怪的是,當圖像只是純合成圖像時,發現者模式的誤報檢測是一個更大的問題。 啟發式假設一張照片,它沒有這些問題。 在這種替代模式下,它可以利用知道它是純圖像而不是照片的優勢,並且速度更快,永遠不會出錯。

要將二進制數據存儲在二維碼中,您必須克服兩個問題。

  1. ISO-8859-1 不允許 00-1F 和 7F-9F 范圍內的字節。 由於您使用的是隨機生成器,因此您只需檢查隨機生成的字節是否適合該值並重新生成它,直到獲得適合該范圍的隨機字節。 如果仍然需要對這些字節進行編碼,則可以將數組編碼為 Base-64 字符串或十六進制字符串。 如果是十六進制字符串,它將以字母數字模式而不是 8 位模式存儲在二維碼中。

  2. 由於您嘗試在二維碼中存儲二進制數據,因此您只能依靠自己的掃描儀來處理這些二進制數據,並且您需要確保您的掃描儀不會使用啟發式算法來自動確定字符編碼,等等. 大多數 QR 解碼器使用啟發式方法來檢測使用的字符集。 這些啟發式方法可能會檢測到 ISO-8859-1 以外的字符集,因此無法正確顯示您的二進制數據。 一些掃描器使用啟發式方法來檢測字符集,即使字符集是由 QR 碼內的 ECI 可選擴展明確給出的。

因此,僅使用 US-ASCII(例如,在將二進制數據傳遞給 QR 碼生成器之前以 Base64 編碼的二進制數據)是對抗試探法的 QR 碼最安全的選擇。 這還將克服另一個復雜問題:ISO-8859-1 不是 2000 年發布的早期二維碼標准 (ISO/IEC 18004:2000) 中的默認編碼。 該標准確實指定了符合 JIS X 0201(JIS8 也稱為 ISO-2022-JP)的 8 位拉丁文/假名字符集作為 8 位模式的默認編碼,而 2005 年發布的更新標准確實將默認值更改為ISO-8859-1。

如果您將緩沖區存儲為 QR 碼中的十六進制字符串,這肯定會禁用所有啟發式方法,並且不應生成比 Base-64 更大的 QR 碼,因為字母數字模式中的每個字符在 QR 碼流中僅占 6 位.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM