Reading raw bytes from an Aztec barcode via AVMetadataMachineReadableCodeObject yields unexpected result

[亡魂溺海] 提交于 2019-11-29 01:43:07

I solved this some time ago in Xamarin/C#, but the idea is the same for Swift too. The encodedData and ReadCode methods are taken form ZXing lib. Hope it helps.

It works well for reading and decoding both "small" and "large" ticket codes, but the default Aztec reader in iOS SDK is not good enough, so in the end we went on with the reader from Manateeworks. I can see now that it did not get any better with 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;
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!