- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
一段时间以来,我一直在为 Deutsche Bahn(德国铁路)使用的一种特殊条形码开发 iOS 阅读器应用程序。它是连接 DSA 签名字符串和 zlib 压缩负载的 Aztec 条形码的变体。
当我得知 AVMetadataMachineReadableCodeObject
没有用于读取条形码中包含的原始字节的公共(public)方法并且字符串方法总是使 zlib 压缩数据出现乱码时,我陷入了困境。
幸运的是,this answer 让我朝着正确的方向前进。可以使用 KVO 访问(私有(private))字节,因为我目前不希望在 App Store 上分发该应用程序,所以这是完美的。
尽管我几乎不存在 Swift
和 Objective-C
知识,但我设法让它工作,正如您在示例代码中看到的那样。但是存储在 NSData
中的条形码中的字节与预期结果不匹配!我怀疑我使用的 zlib 库( DeflateSwift )不起作用,所以我构建了一个测试用例,它运行良好。
我的问题是:我做错了什么?我是否需要进一步处理原始字节以获得预期结果(见下文)? AVMetadataMachineReadableCodeObject
中存储的字节到底有多原始?谁能指出我正确的方向?任何帮助表示赞赏。
这是我的代码(这是 Swift
和 Objective-C
的可悲混搭)
if let metadataObject = metadataObjects.first {
let readableObject = metadataObject as! AVMetadataMachineReadableCodeObject;
let rawReadableObject = readableObject.valueForKeyPath("_internal.basicDescriptor")!["BarcodeRawData"] as? NSData;
if let rawBytes = rawReadableObject {
let barcodeData = rawBytes; // or use testData instead
let barcodeSplit:Int = 68;
let barcodeLength:Int = barcodeData.length;
let barcodeHeader:NSData = barcodeData.subdataWithRange(NSRange(location: 0, length: barcodeSplit))
let barcodeZlibContent:NSData = barcodeData.subdataWithRange(NSRange(location: barcodeSplit, length: (barcodeLength-barcodeSplit)))
let count = barcodeZlibContent.length / sizeof(UInt8)
var array = [UInt8](count: count, repeatedValue: 0)
barcodeZlibContent.getBytes(&array, length:count * sizeof(UInt8))
print("\(barcodeLength)kb")
print(barcodeHeader)
print(barcodeZlibContent)
var inflater = InflateStream()
var (inflated, err) = inflater.write(array, flush: true)
if err != nil{
fatalError("\(err!)")
}
if let ticketString = String(bytes: inflated, encoding: NSUTF8StringEncoding) {
print(ticketString)
} else {
print("not a valid UTF-8 sequence")
}
}
}
AVMetadataMachineReadableCodeObject
返回的字节是
40 B4 FA 88 89 8A 88 88 98 E6 3E 20 09 10 0A 0E EF 25 ED AC DE C8 80 5A 6F 9D 21 9F 4A 6D 61 33 19 F3 12 10 8A 80 2B F0 C2 7C CE E0 AB 83 46 AF A6 42 79 FD E8 35 D4 8B 0B 00 00 00 00 03 13 3B A3 47 8E A9 C2 B4 DC 30 03 C2 89 32 8D A3 B0 D4 E6 2B 35 5B 7B 08 88 12 A0 AA A2 00 8E 22 20 31 95 10 1C 21 2A FF 78 2C BE 31 1B A2 12 B5 CF A3 87 9B 9B 59 EF 7B BC AC AE CA 88 C8 1C 02 E8 D2 B5 87 76 0D 93 77 8B FB 04 A2 B5 D1 F8 9A 67 D5 55 15 DA 61 13 91 EC 08 60 2D 9B 86 E1 94 35 C3 D8 A9 49 41 5B 3A 7C 59 A5 FD 9A E3 FE F8 3C 9F 3F 7B B2 59 DC 98 E3 5E 92 CC C0 21 11 EC AF BA D7 F4 5D DB FC BD A5 CA AF 99 08 28 E3 02 30 06 20 A8 00 88 43 8E A2 58 2D 87 24 33 40 18 C1 AE 50 04 08 91 7E 59 E1 F6 9B 87 E7 8A 67 AA 1B 3E FF FE EF 79 46 18 5A 23 03 B4 E9 1A 4F 2F 15 EA DC 46 F5 A9 67 AE B8 F7 16 0B F2 38 8B B3 96 35 34 AB D3 A6 0E 6C 77 9D 72 D5 85 7E 58 0B E0 25 69 2C AC 42 9C 13 0F 27 4F 13 72 4A 90 CB 1C ED 78 B3 60 F4 AD 4C FE 2B F4 51 A8 0D 60 CC DF 78 C7 65 78 CC E6 63 02 45 B1 F3 1F A8 ED 9E FE 63 00 00 00 00
23 55 54 30 31 30 30 38 30 30 30 30 30 31 30 2C 02 14 1C 3D E9 2D CD 5E C4 C0 56 BD AE 61 3E 54 AD A1 B3 26 33 D2 02 14 40 75 03 D0 CF 9C C1 F5 70 58 BD 59 50 A7 AF C5 EB 0A F4 74 00 00 00 00 30 32 37 31 78 9C 65 50 CB 4E C3 30 10 E4 53 2C 71 43 4A D9 F5 2B 36 B7 84 04 52 01 55 51 40 1C 51 01 23 2A 42 0E 21 15 3F C7 8D 1F 63 36 11 52 2B 7C F1 78 76 76 66 BD F7 8F 4D 5D 54 C4 44 CE 10 05 D2 EB 78 5B AC 32 7B B4 77 C8 11 6B 62 C7 D6 79 AA EA AA 16 E1 B2 22 4D C4 01 AD 36 58 61 CA 6B 30 C6 E5 64 A0 B6 97 0F A6 A9 6F D6 71 DF C7 CF 3E 7F 37 93 66 8E C6 71 DE 92 4C C0 E1 22 0D FD 57 7A CB EE B6 CF EF 69 54 FD 66 44 05 31 D0 03 18 01 05 40 04 70 9C 51 46 AD 38 49 33 00 86 20 DD 42 88 04 22 5F A6 A1 DB F6 78 79 D4 79 95 76 1F 3F DF FD E7 98 86 16 B1 30 0B 65 D6 3C BD 2A 15 CE D8 AB E5 79 9D 47 7B DA 34 13 C7 34 73 5A 6B 0B 35 72 D9 5C 0D BB AE 53 AA E8 5F 86 B4 01 E9 25 8D 0D 50 8E 72 3C 39 3C B2 13 94 82 74 CE 2D C7 B3 41 8B ED 4C 9F F5 0B E2 85 6C 01 8C FE C7 B8 E9 87 8C D9 F1 90 28 A3 73 FE 05 6D DE 5F F1
78 9C
) 开始一个有效的 zlib 流。如果您在此处拆分数据并膨胀 zlib 数据,它会返回如下字符串:
U_HEAD01005300802P9QAN-40501201514560DEDE0080ID0200180104840080BL020357031204GW3HEMP906012015060120151021193517S0010018Fernweh-Ticket natS00200012S0030001AS00900051-0-0S01200010S0140002S2S0150006BerlinS0160011NeumünsterS0210038B-Hbf 8:16 ICE794/HH-Hbf 10:16 IC2224S0230013Krull AndreaS026000213S0270019***************0484S0280013Andrea#Krull S031001006.01.2015S032001006.01.2015S035000511160S0360003271
let testArray = [UInt8](arrayLiteral: 0x23, 0x55, 0x54, 0x30, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x2C, 0x02, 0x14, 0x1C, 0x3D, 0xE9, 0x2D, 0xCD, 0x5E, 0xC4, 0xC0, 0x56, 0xBD, 0xAE, 0x61, 0x3E, 0x54, 0xAD, 0xA1, 0xB3, 0x26, 0x33, 0xD2, 0x02, 0x14, 0x40, 0x75, 0x03, 0xD0, 0xCF, 0x9C, 0xC1, 0xF5, 0x70, 0x58, 0xBD, 0x59, 0x50, 0xA7, 0xAF, 0xC5, 0xEB, 0x0A, 0xF4, 0x74, 0x00, 0x00, 0x00, 0x00, 0x30, 0x32, 0x37, 0x31, 0x78, 0x9C, 0x65, 0x50, 0xCB, 0x4E, 0xC3, 0x30, 0x10, 0xE4, 0x53, 0x2C, 0x71, 0x43, 0x4A, 0xD9, 0xF5, 0x2B, 0x36, 0xB7, 0x84, 0x04, 0x52, 0x01, 0x55, 0x51, 0x40, 0x1C, 0x51, 0x01, 0x23, 0x2A, 0x42, 0x0E, 0x21, 0x15, 0x3F, 0xC7, 0x8D, 0x1F, 0x63, 0x36, 0x11, 0x52, 0x2B, 0x7C, 0xF1, 0x78, 0x76, 0x76, 0x66, 0xBD, 0xF7, 0x8F, 0x4D, 0x5D, 0x54, 0xC4, 0x44, 0xCE, 0x10, 0x05, 0xD2, 0xEB, 0x78, 0x5B, 0xAC, 0x32, 0x7B, 0xB4, 0x77, 0xC8, 0x11, 0x6B, 0x62, 0xC7, 0xD6, 0x79, 0xAA, 0xEA, 0xAA, 0x16, 0xE1, 0xB2, 0x22, 0x4D, 0xC4, 0x01, 0xAD, 0x36, 0x58, 0x61, 0xCA, 0x6B, 0x30, 0xC6, 0xE5, 0x64, 0xA0, 0xB6, 0x97, 0x0F, 0xA6, 0xA9, 0x6F, 0xD6, 0x71, 0xDF, 0xC7, 0xCF, 0x3E, 0x7F, 0x37, 0x93, 0x66, 0x8E, 0xC6, 0x71, 0xDE, 0x92, 0x4C, 0xC0, 0xE1, 0x22, 0x0D, 0xFD, 0x57, 0x7A, 0xCB, 0xEE, 0xB6, 0xCF, 0xEF, 0x69, 0x54, 0xFD, 0x66, 0x44, 0x05, 0x31, 0xD0, 0x03, 0x18, 0x01, 0x05, 0x40, 0x04, 0x70, 0x9C, 0x51, 0x46, 0xAD, 0x38, 0x49, 0x33, 0x00, 0x86, 0x20, 0xDD, 0x42, 0x88, 0x04, 0x22, 0x5F, 0xA6, 0xA1, 0xDB, 0xF6, 0x78, 0x79, 0xD4, 0x79, 0x95, 0x76, 0x1F, 0x3F, 0xDF, 0xFD, 0xE7, 0x98, 0x86, 0x16, 0xB1, 0x30, 0x0B, 0x65, 0xD6, 0x3C, 0xBD, 0x2A, 0x15, 0xCE, 0xD8, 0xAB, 0xE5, 0x79, 0x9D, 0x47, 0x7B, 0xDA, 0x34, 0x13, 0xC7, 0x34, 0x73, 0x5A, 0x6B, 0x0B, 0x35, 0x72, 0xD9, 0x5C, 0x0D, 0xBB, 0xAE, 0x53, 0xAA, 0xE8, 0x5F, 0x86, 0xB4, 0x01, 0xE9, 0x25, 0x8D, 0x0D, 0x50, 0x8E, 0x72, 0x3C, 0x39, 0x3C, 0xB2, 0x13, 0x94, 0x82, 0x74, 0xCE, 0x2D, 0xC7, 0xB3, 0x41, 0x8B, 0xED, 0x4C, 0x9F, 0xF5, 0x0B, 0xE2, 0x85, 0x6C, 0x01, 0x8C, 0xFE, 0xC7, 0xB8, 0xE9, 0x87, 0x8C, 0xD9, 0xF1, 0x90, 0x28, 0xA3, 0x73, 0xFE, 0x05, 0x6D, 0xDE, 0x5F, 0xF1)
let testData = NSData(bytes: testArray, length: testArray.count)
最佳答案
我前段时间在 Xamarin/C# 中解决了这个问题,但这个想法对于 Swift 也是一样的。 encodedData
和 ReadCode
方法取自 ZXing lib。希望能帮助到你。
它适用于读取和解码“小”和“大”票代码,但 iOS SDK 中默认的 Aztec 阅读器不够好,所以最后我们继续使用 Manateeworks 的阅读器。我现在可以看到 iOS 10 SDK 并没有变得更好。
public override void DidOutputMetadataObjects (AVCaptureMetadataOutput captureOutput, AVMetadataObject[] metadataObjects, AVCaptureConnection connection)
{
foreach (AVMetadataMachineReadableCodeObject metadata in metadataObjects) {
var d1 = (metadata.ValueForKey ((NSString)"_internal"));
var d2 = (d1.ValueForKey ((NSString)"basicDescriptor"));
var data = (d2.ValueForKey ((NSString)"BarcodeRawData"));
var str = data.ToString ().Trim ().Trim (new [] { '<', '>' }).Replace (" ", "");
var bitarray = new bool[str.Length * 4];
for (var i = 0; i < str.Length / 2; i++) {
int value = Convert.ToInt32 (str.Substring (i * 2, 2), 16);
bitarray [i * 8 + 0] = (value & 1) > 0;
bitarray [i * 8 + 1] = (value & 2) > 0;
bitarray [i * 8 + 2] = (value & 4) > 0;
bitarray [i * 8 + 3] = (value & 8) > 0;
bitarray [i * 8 + 4] = (value & 16) > 0;
bitarray [i * 8 + 5] = (value & 32) > 0;
bitarray [i * 8 + 6] = (value & 64) > 0;
bitarray [i * 8 + 7] = (value & 128) > 0;
}
var pabData = encodedData (bitarray);
parent.scanFinished (true, pabData);
}
}
enum ZXAztecTable
{
ZXAztecTableUpper,
ZXAztecTableBinary,
ZXAztecTableDigit
};
public byte[] encodedData (bool[] bitArray)
{
var result = new List<byte> ();
int endIndex = bitArray.Length;
ZXAztecTable latchTable = ZXAztecTable.ZXAztecTableUpper; // table most recently latched to
ZXAztecTable shiftTable = ZXAztecTable.ZXAztecTableUpper; // table to use for the next read
int index = 0;
while (index < endIndex) {
if (shiftTable == ZXAztecTable.ZXAztecTableBinary) {
if (endIndex - index < 5) {
break;
}
int length = ReadCode (bitArray, index, 5);
index += 5;
if (length == 0) {
if (endIndex - index < 11) {
break;
}
length = ReadCode (bitArray, index, 11) + 31;
index += 11;
}
for (int charCount = 0; charCount < length; charCount++) {
if (endIndex - index < 8) {
index = endIndex; // Force outer loop to exit
break;
}
byte code = (byte)ReadCode (bitArray, index, 8);
result.Add (code);
index += 8;
}
// Go back to whatever mode we had been in
shiftTable = latchTable;
} else {
int size = shiftTable == ZXAztecTable.ZXAztecTableDigit ? 4 : 5;
if (endIndex - index < size) {
break;
}
ReadCode (bitArray, index, size);
index += size;
latchTable = shiftTable;
shiftTable = ZXAztecTable.ZXAztecTableBinary;
}
}
return result.ToArray ();
}
public int ReadCode (bool[] bitArray, int startIndex, int length)
{
int res = 0;
for (int i = startIndex; i < startIndex + length; i++) {
res <<= 1;
if (bitArray [i]) {
res |= 0x01;
}
}
return res;
}
关于ios - 通过 AVMetadataMachineReadableCodeObject 从 Aztec 条码读取原始字节会产生意外结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37225276/
我在尝试用 Swift 保存 AVMetadataMachineReadableCodeObject 时遇到了一些严重的问题。 我正在使用这个库:https://github.com/yeahdong
看起来 AVMetadataMachineReadableCodeObject 的“corners”属性在使用 Xcode 12 时不知何故丢失了。 它仍然在文档中提到,但编译器失败了 "Value
好的,我明白了,Read binary QR Code with AVFoundation 可能重复但我会尝试从不同的角度解决这个问题。 我正在尝试在我的 swift 应用程序中扫描条形码(在本例中为
一段时间以来,我一直在为 Deutsche Bahn(德国铁路)使用的一种特殊条形码开发 iOS 阅读器应用程序。它是连接 DSA 签名字符串和 zlib 压缩负载的 Aztec 条形码的变体。 当我
我是一名优秀的程序员,十分优秀!