{"action":"created","issue":{"url":"https://api.github.com/repos/zxing/zxing/issues/642","repository_url":"https://api.github.com/repos/zxing/zxing","labels_url":"https://api.github.com/repos/zxing/zxing/issues/642/labels{/name}","comments_url":"https://api.github.com/repos/zxing/zxing/issues/642/comments","events_url":"https://api.github.com/repos/zxing/zxing/issues/642/events","html_url":"https://github.com/zxing/zxing/issues/642","id":168678901,"number":642,"title":"Aztec decoding: incorrect decoding of codes with U/S B/S","user":{"login":"fgrieu","id":7809433,"avatar_url":"https://avatars.githubusercontent.com/u/7809433?v=3","gravatar_id":"","url":"https://api.github.com/users/fgrieu","html_url":"https://github.com/fgrieu","followers_url":"https://api.github.com/users/fgrieu/followers","following_url":"https://api.github.com/users/fgrieu/following{/other_user}","gists_url":"https://api.github.com/users/fgrieu/gists{/gist_id}","starred_url":"https://api.github.com/users/fgrieu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fgrieu/subscriptions","organizations_url":"https://api.github.com/users/fgrieu/orgs","repos_url":"https://api.github.com/users/fgrieu/repos","events_url":"https://api.github.com/users/fgrieu/events{/privacy}","received_events_url":"https://api.github.com/users/fgrieu/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2016-08-01T15:50:06Z","updated_at":"2016-08-01T21:38:11Z","closed_at":null,"body":"ZXing (as of July 25, 2016) decodes the following Aztec code as 3333h3i3j33333, when that should I believe be 3333h3i3jITIT per a literal reading of the ISO/IEC 24778:2008 standard, and is what I get with at least one popular decoder independent of ZXing (NeoReader).\r\n![dlusbs.png](https://cloud.githubusercontent.com/assets/7809433/17298916/4fe36296-580c-11e6-8345-6ba524b7d232.png)\r\n\r\n\r\nThe binary sequence in that code, before applying the process of _14.5.2 Interpreting the bit stream_ in the standard, is the bit sequence 11110010101010101010111111111100101011010000011001101101001001100110110101001010101010101010101 which parses to\r\n```\r\n  per ZXing             per the standard and Neoreader\r\n11110    (D/L)             11110    (D/L)\r\n0101      3                0101      3\r\n0101      3                0101      3\r\n0101      3                0101      3\r\n0101      3                0101      3\r\n1111      (U/S)            1111      (U/S)\r\n11111     (B/S)            11111     (B/S)\r\n00101     [5]              00101     [5]\r\n01101000  h                01101000  h\r\n00110011  3                00110011  3\r\n01101001  i                01101001  i\r\n00110011  3                00110011  3\r\n01101010  j                01101010  j\r\n0101      3                01010     I\r\n0101      3                10101     T\r\n0101      3                01010     I\r\n0101      3                10101     T\r\n0101      3\r\n```\r\nThe discrepancy boils down to diverging interpretation of :\r\n> Byte Shift (B/S) is a special case, shifting into a run length-controlled string of literal 8-bit bytes. Following a B/S is a 5-bit binary value: if non-zero, it encodes the number of bytes (1 to 31) that follow, but if zero then the next 11 bits encode the number of bytes less 31. Byte Shift can thus encode either isolated extended ASCII or control characters or long strings of byte data, possibly filling the whole symbol. At the end of the byte string, **encoding returns to the _mode_ from which B/S was invoked**.\r\n\r\nThe closest thing to a definition of _mode_ would be\r\n> The Upper and Lower code sets contain upper and lowercase alphabetic characters respectively; Mixed contains a mixture of ASCII control and punctuation characters; Punctuation contains common punctuation characters and combinations; and Digit contains the numerals plus some punctuation (..)<br>Message encoding starts in the Upper code set, and can be latched (semi-permanently, via U/L, L/L, M/L, P/L, or D/L) or shifted (for one character only, via U/S or P/S) into the other _modes_ as needed.\r\n\r\nIn a literal interpretation, _mode_ means one of Upper, Lower, Mixed, Punctuation, and Digit; we are in Upper mode after U/S (even though that's only until the next character); thus \"the _mode_ from which B/S was invoked\" is Upper; thus we return to the Upper mode at the end of the Byte Shift sequence; and further, since there has been at least one character ( h ) in the Byte Shift sequence, the temporary Upper Shift has ceased to be in effect when the decoder _returns to the mode from which B/S was invoked_.\r\n\r\nThe interpretation made by ZXing could to be that _the next character_ after U/S is B/S, and that ends the Upper sequence and brings back to Digit, and that's the mode in which B/S is invoked; however that is paradoxical since B/S does not appear in the codes of Digit mode; and requires to treat B/S as a character, while the _character set_ is defined as \"all 8-bit values\" plus \"two non-data characters\" (FNC1 and ECI), which does not include B/S. The only thing weakly in support of ZXing's interpretation is that annex H, table LatLen, counts 14 bits to go from Digit to Binary _and back_ including 5-bit length (when that would require 19 bits per the above literal interpretation). However annex H similarly miscounts how many bits it takes to go from Punctuation to Binary and back (as 15 bits rather than the unambiguous 20 bits); is a general mess; and is informative only, thus can not override normative parts of the standard.\r\n\r\nI believe (not tested) that the problem would be fixed with no negative side effect by inserting\r\n```\r\n          latchTable = shiftTable;  // after U/S B/S, return to Upper mode\r\n```\r\nbetween the two lines 133/134 of [core/src/main/java/com/google/zxing/aztec/decoder/Decoder.java](https://github.com/zxing/zxing/blob/master/core/src/main/java/com/google/zxing/aztec/decoder/Decoder.java#L133) currently reading\r\n```\r\n          // Table changes\r\n          if (str.charAt(6) == 'L') {\r\n```\r\nOf course a test case should be added in [core/src/test/resources/blackbox/aztec-1](https://github.com/zxing/zxing/tree/master/core/src/test/resources/blackbox/aztec-1), with dlusbs.png and the expected dlusbs.txt, as enclosed in this zip: \r\n[dlusbs.zip](https://github.com/zxing/zxing/files/394203/dlusbs.zip)\r\n\r\nThe problem was detected by encoding test input 3333h3i3j33333 with a tentative direct implementation of the encoding algorithm in annex H, written on the assumption that it is optimal (it's stated goal) at least in the case of letters and digits. Decoding worked fine with ZXing, not with NeoReader. The root cause of the issue seems to be the messy annex H and ZXing's implementation of the decoder."},"comment":{"url":"https://api.github.com/repos/zxing/zxing/issues/comments/236716096","html_url":"https://github.com/zxing/zxing/issues/642#issuecomment-236716096","issue_url":"https://api.github.com/repos/zxing/zxing/issues/642","id":236716096,"user":{"login":"srowen","id":822522,"avatar_url":"https://avatars.githubusercontent.com/u/822522?v=3","gravatar_id":"","url":"https://api.github.com/users/srowen","html_url":"https://github.com/srowen","followers_url":"https://api.github.com/users/srowen/followers","following_url":"https://api.github.com/users/srowen/following{/other_user}","gists_url":"https://api.github.com/users/srowen/gists{/gist_id}","starred_url":"https://api.github.com/users/srowen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/srowen/subscriptions","organizations_url":"https://api.github.com/users/srowen/orgs","repos_url":"https://api.github.com/users/srowen/repos","events_url":"https://api.github.com/users/srowen/events{/privacy}","received_events_url":"https://api.github.com/users/srowen/received_events","type":"User","site_admin":false},"created_at":"2016-08-01T21:38:11Z","updated_at":"2016-08-01T21:38:11Z","body":"Sure, sounds like you have looked into this thoroughly! thank you. Feel free to open a pull request with your change so we can test it (ideally with your test case thrown in). If it all passes, I'll merge it."}}
{"actor":{"display_login":"srowen"}}