def test_split_into_blocks(): # <http://www.thonky.com/qr-code-tutorial/error-correction-coding> # HELLO WORLD as a 5-Q code s = '01000011 01010101 01000110 10000110 01010111 00100110 01010101 ' \ '11000010 01110111 00110010 00000110 00010010 00000110 01100111 ' \ '00100110 11110110 11110110 01000010 00000111 01110110 10000110 ' \ '11110010 00000111 00100110 01010110 00010110 11000110 11000111 ' \ '10010010 00000110 10110110 11100110 11110111 01110111 00110010 ' \ '00000111 01110110 10000110 01010111 00100110 01010010 00000110 ' \ '10000110 10010111 00110010 00000111 01000110 11110111 01110110 ' \ '01010110 11000010 00000110 10010111 00110010 11100000 11101100 ' \ '00010001 11101100 00010001 11101100 00010001 11101100' data = bits(s) buff = Buffer(data) codewords = list(buff.toints()) assert 62 == len(codewords) ec_infos = consts.ECC[5][consts.ERROR_LEVEL_Q] assert ec_infos assert 2 == len(ec_infos) blocks, error_blocks = encoder.make_blocks(ec_infos, buff) assert 4 == len(blocks) assert 15 == len(blocks[0]) assert bytearray(codewords[:15]) == blocks[0] assert 15 == len(blocks[1]) assert 16 == len(blocks[2]) assert 16 == len(blocks[3])
def test_write_padding_bits_iso_i3(): # See ISO/IEC 18004:2006(E) -- I.3 Encoding a Micro QR Code symbol (page 96) data = bits('0 1000 0000001100 0101011001 1000011 00000') buff = Buffer(data) version = consts.VERSION_M2 encoder.write_padding_bits(buff, version, len(buff)) assert bits('01000000 00011000 10101100 11000011 00000000') == buff.getbits()
def test_binary_sequence_to_integers(): # <http://www.thonky.com/qr-code-tutorial/error-correction-coding> # HELLO WORLD as a 1-M code data = bits('00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 01000000 11101100 00010001 11101100 00010001 11101100 00010001') expected = [32, 91, 11, 120, 209, 114, 220, 77, 67, 64, 236, 17, 236, 17, 236, 17] assert len(data) // 8 == len(Buffer(data).toints()) assert expected == Buffer(data).toints()
def test_write_padding_bits_iso_i2(): # See ISO/IEC 18004:2006(E) -- I.2 Encoding a QR Code symbol (page 94) data = bits('0001 0000001000 0000001100 0101011001 1000011 0000') buff = Buffer(data) version = 1 encoder.write_padding_bits(buff, version, len(buff)) assert bits('00010000 00100000 00001100 01010110 01100001 10000000') == buff.getbits()
def test_write_padding_bits_thonky(): # <http://www.thonky.com/qr-code-tutorial/data-encoding> data = bits('00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 010000') buff = Buffer(data) version = 1 encoder.write_padding_bits(buff, version, len(buff)) assert bits('00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 01000000') == buff.getbits()
def test_write_terminator_standard_value_i3(): # See ISO/IEC 18004:2006(E) -- I.3 Encoding a Micro QR Code symbol (page 96) data = bits('01000000000110001010110011000011') buff = Buffer(data) version = consts.VERSION_M2 capacity = consts.SYMBOL_CAPACITY[version][consts.ERROR_LEVEL_L] encoder.write_terminator(buff, capacity, version, len(data)) assert data + bits('00000') == buff.getbits()
def test_write_segment_alphanumeric_standard_value_example(eci): # See ISO/IEC 18004:2006(E) -- 6.4.3 Numeric mode - EXAMPLE (page 26) s = b'AC-42' seg = encoder.make_segment(s, consts.MODE_ALPHANUMERIC) buff = Buffer() v, vrange = None, consts.VERSION_RANGE_01_09 encoder.write_segment(buff, seg, v, vrange, eci=eci) assert bits('00100000001010011100111011100111001000010') == buff.getbits()
def test_write_segment_alphanumeric_thonky(eci): # <http://www.thonky.com/qr-code-tutorial/data-encoding/#step-3-encode-using-the-selected-mode> s = b'HELLO WORLD' seg = encoder.make_segment(s, consts.MODE_ALPHANUMERIC, None) buff = Buffer() v, vrange = None, consts.VERSION_RANGE_01_09 encoder.write_segment(buff, seg, v, vrange, eci) assert bits('00100000010110110000101101111000110100010111001011011100010011010100001101') == buff.getbits()
def test_write_segment_numeric_standard_value_example2(eci): # See ISO/IEC 18004:2006(E) -- 6.4.3 Numeric mode - EXAMPLE 2 (page 25) s = b'0123456789012345' seg = encoder.make_segment(s, consts.MODE_NUMERIC) buff = Buffer() v, vrange = consts.VERSION_M3, consts.VERSION_M3 encoder.write_segment(buff, seg, v, vrange, eci=eci) assert bits('0010000000000110001010110011010100110111000010100111010100101') == buff.getbits()
def test_write_segment_numeric_standard_value_i3(eci): # See ISO/IEC 18004:2006(E) -- I.3 Encoding a Micro QR Code symbol (page 96) s = b'01234567' seg = encoder.make_segment(s, consts.MODE_NUMERIC) buff = Buffer() v, vrange = consts.VERSION_M2, consts.VERSION_M2 encoder.write_segment(buff, seg, v, vrange, eci=eci) assert bits('01000000000110001010110011000011') == buff.getbits()
def test_write_terminator_standard_value_i2(): # See ISO/IEC 18004:2006(E) -- I.2 Encoding a QR Code symbol (page 94) data = bits('000100000010000000001100010101100110000110000') buff = Buffer(data) version = 1 v = None capacity = consts.SYMBOL_CAPACITY[version][consts.ERROR_LEVEL_M] encoder.write_terminator(buff, capacity, v, len(data)) assert data + bits('0000') == buff.getbits()
def test_write_terminator_thonky(): # <http://www.thonky.com/qr-code-tutorial/data-encoding/#add-a-terminator-of-0s-if-necessary> data = bits('00100000010110110000101101111000110100010111001011011100010011010100001101') buff = Buffer(data) version = 1 v = None capacity = consts.SYMBOL_CAPACITY[version][consts.ERROR_LEVEL_Q] encoder.write_terminator(buff, capacity, v, len(data)) assert data + bits('0000') == buff.getbits()
def test_write_pad_codewords_standard_value_i3(): # See ISO/IEC 18004:2006(E) -- I.3 Encoding a Micro QR Code symbol (page 96) data = bits('0100000000011000101011001100001100000000') buff = Buffer(data) version = consts.VERSION_M2 error = consts.ERROR_LEVEL_L capacity = consts.SYMBOL_CAPACITY[version][error] encoder.write_pad_codewords(buff, version, capacity, len(buff)) assert data == buff.getbits()
def test_write_pad_codewords_standard_value_i2(): # See ISO/IEC 18004:2006(E) -- I.2 Encoding a QR Code symbol (page 94) data = bits('00010000 00100000 00001100 01010110 01100001 10000000') buff = Buffer(data) version = 1 error = consts.ERROR_LEVEL_M capacity = consts.SYMBOL_CAPACITY[version][error] encoder.write_pad_codewords(buff, version, capacity, len(buff)) assert data + bits('11101100000100011110110000010001111011000001000111101100000100011110110000010001') == buff.getbits()
def test_make_error_block_iso_i2(): # ISO/IEC 18004:2006(E) - I.2 Encoding a QR Code symbol -- page 94 # Input: 01234567 # Symbol: 1-M s = '00010000 00100000 00001100 01010110 01100001 10000000 11101100 00010001 11101100 00010001 11101100 00010001 11101100 00010001 11101100 00010001' data_block = Buffer(bits(s)).toints() error_s = '10100101 00100100 11010100 11000001 11101101 00110110 11000111 10000111 00101100 01010101' error_block = Buffer(bits(error_s)).toints() ec_info = consts.ECC[1][consts.ERROR_LEVEL_M][0] assert ec_info.num_total - ec_info.num_data == len(error_block) assert bytearray(error_block) == encoder.make_error_block(ec_info, data_block)
def test_make_error_block_iso_i3(): # ISO/IEC 18004:2006(E) - I.3 Encoding a Micro QR Code symbol -- page 96 # Input: 01234567 # Symbol: M2-L s = '01000000 00011000 10101100 11000011 00000000' data_block = Buffer(bits(s)).toints() error_s = '10000110 00001101 00100010 10101110 00110000' error_block = Buffer(bits(error_s)).toints() ec_info = consts.ECC[consts.VERSION_M2][consts.ERROR_LEVEL_L][0] assert ec_info.num_total - ec_info.num_data == len(error_block) assert bytearray(error_block) == encoder.make_error_block(ec_info, data_block)
def test_make_error_block1(): # <http://www.thonky.com/qr-code-tutorial/structure-final-message> # 5-Q codeword = '01000011 01010101 01000110 10000110 01010111 00100110 01010101 ' \ '11000010 01110111 00110010 00000110 00010010 00000110 01100111 ' \ '00100110' codeword_ints = [67, 85, 70, 134, 87, 38, 85, 194, 119, 50, 6, 18, 6, 103, 38] buff = Buffer(bits(codeword)) assert codeword_ints == list(buff.toints()) error_block = bytearray([213, 199, 11, 45, 115, 247, 241, 223, 229, 248, 154, 117, 154, 111, 86, 161, 111, 39]) ec_infos = consts.ECC[5][consts.ERROR_LEVEL_Q] data_blocks, error_blocks = encoder.make_blocks(ec_infos, buff) assert error_block == error_blocks[0]
def test_make_error_block2(): # <http://www.thonky.com/qr-code-tutorial/structure-final-message> # 5-Q codeword = '11110110 11110110 01000010 00000111 01110110 10000110 11110010 ' \ '00000111 00100110 01010110 00010110 11000110 11000111 10010010 ' \ '00000110' codeword_ints = [246, 246, 66, 7, 118, 134, 242, 7, 38, 86, 22, 198, 199, 146, 6] buff = Buffer(bits(codeword)) assert codeword_ints == list(buff.toints()) error_block = bytearray([87, 204, 96, 60, 202, 182, 124, 157, 200, 134, 27, 129, 209, 17, 163, 163, 120, 133]) ec_infos = consts.ECC[5][consts.ERROR_LEVEL_Q] data_blocks, error_blocks = encoder.make_blocks(ec_infos, buff) assert error_block == error_blocks[0]
def test_make_error_block3(): # <http://www.thonky.com/qr-code-tutorial/structure-final-message> # 5-Q codeword = '10110110 11100110 11110111 01110111 00110010 00000111 01110110 ' \ '10000110 01010111 00100110 01010010 00000110 10000110 10010111 ' \ '00110010 00000111' codeword_ints = [182, 230, 247, 119, 50, 7, 118, 134, 87, 38, 82, 6, 134, 151, 50, 7] buff = Buffer(bits(codeword)) assert codeword_ints == list(buff.toints()) error_block = bytearray([148, 116, 177, 212, 76, 133, 75, 242, 238, 76, 195, 230, 189, 10, 108, 240, 192, 141]) ec_infos = (consts.ECC[5][consts.ERROR_LEVEL_Q][1],) data_blocks, error_blocks = encoder.make_blocks(ec_infos, buff) assert error_block == error_blocks[0]
def test_make_error_block4(): # <http://www.thonky.com/qr-code-tutorial/structure-final-message> # 5-Q codeword = '01000110 11110111 01110110 01010110 11000010 00000110 10010111 ' \ '00110010 00010000 11101100 00010001 11101100 00010001 11101100 ' \ '00010001 11101100' codeword_ints = [70, 247, 118, 86, 194, 6, 151, 50, 16, 236, 17, 236, 17, 236, 17, 236] buff = Buffer(bits(codeword)) assert codeword_ints == list(buff.toints()) error_block = bytearray([235, 159, 5, 173, 24, 147, 59, 33, 106, 40, 255, 172, 82, 2, 131, 32, 178, 236]) ec_infos = (consts.ECC[5][consts.ERROR_LEVEL_Q][1],) data_blocks, error_blocks = encoder.make_blocks(ec_infos, buff) assert error_block == error_blocks[0]
def test_write_segment_eci_standard_value(): # See ISO/IEC 18004:2006(E) -- 6.4.2.1 ECI Designator - EXAMPLE (page 24) encoding = 'ISO-8859-7' #TODO: ? # NOTE: ISO/IEC 18004:2006(E) uses "ΑΒΓΔΕ" but text says: # (character values A1HEX, A2HEX, A3HEX, A4HEX, A5HEX) and result seems # to use the A...HEX values as well s = '\u2018\u2019\u00A3\u20AC\u20AF'.encode(encoding) seg = encoder.make_segment(s, consts.MODE_BYTE, encoding) buff = Buffer() v, vrange = None, consts.VERSION_RANGE_01_09 encoder.write_segment(buff, seg, v, vrange, True) expected = bits('0111 00001001 0100 00000101 10100001 10100010 10100011 10100100 10100101') result = buff.getbits() assert len(expected) == len(result) assert expected == result
def test_make_final_message_iso_i3(): # ISO/IEC 18004:2015(E) - I.3 Encoding a Micro QR Code symbol -- page 96 # Input: 01234567 # Symbol: M2-L s = '01000000 00011000 10101100 11000011 00000000' codewords = Buffer(bits(s)).toints() expected_s = '01000000 00011000 10101100 11000011 00000000 10000110 00001101 00100010 10101110 00110000' expected = bits(expected_s) assert expected == encoder.make_final_message(consts.VERSION_M2, consts.ERROR_LEVEL_L, codewords).getbits()
def test_make_final_message_iso_i2(): # ISO/IEC 18004:2015(E) - I.2 Encoding a QR Code symbol -- page 94 # Input: 01234567 # Symbol: 1-M s = '00010000 00100000 00001100 01010110 01100001 10000000 11101100 00010001 11101100 00010001 11101100 00010001 11101100 00010001 11101100 00010001' codewords = Buffer(bits(s)).toints() expected_s = '00010000 00100000 00001100 01010110 01100001 10000000 11101100 00010001 11101100 00010001 11101100 00010001 11101100 00010001 11101100 00010001 10100101 00100100 11010100 11000001 11101101 00110110 11000111 10000111 00101100 01010101' expected = bits(expected_s) assert expected == encoder.make_final_message(1, consts.ERROR_LEVEL_M, codewords).getbits()
def test_make_error_block0(): # <http://www.thonky.com/qr-code-tutorial/error-correction-coding> # 1-M codeword = '00100000 01011011 00001011 01111000 11010001 01110010 11011100 ' \ '01001101 01000011 01000000 11101100 00010001 11101100 00010001 ' \ '11101100 00010001' codeword_ints = [32, 91, 11, 120, 209, 114, 220, 77, 67, 64, 236, 17, 236, 17, 236, 17] buff = Buffer(bits(codeword)) assert codeword_ints == list(buff.toints()) error_block = bytearray([196, 35, 39, 119, 235, 215, 231, 226, 93, 23]) ec_infos = consts.ECC[1][consts.ERROR_LEVEL_M] assert 1 == len(ec_infos) ec_info = ec_infos[0] assert 1 == ec_info.num_blocks assert 10 == ec_info.num_total - ec_info.num_data data_blocks, error_blocks = encoder.make_blocks(ec_infos, buff) assert len(error_block) == len(error_blocks[0]) assert error_block == error_blocks[0]
def test_make_final_message_thonky(): # <http://www.thonky.com/qr-code-tutorial/structure-final-message> # 5-Q codewords = '01000011 01010101 01000110 10000110 01010111 00100110 01010101 11000010 01110111 00110010 00000110 00010010 00000110 01100111 00100110' \ '11110110 11110110 01000010 00000111 01110110 10000110 11110010 00000111 00100110 01010110 00010110 11000110 11000111 10010010 00000110' \ '10110110 11100110 11110111 01110111 00110010 00000111 01110110 10000110 01010111 00100110 01010010 00000110 10000110 10010111 00110010 00000111' \ '01000110 11110111 01110110 01010110 11000010 00000110 10010111 00110010 00010000 11101100 00010001 11101100 00010001 11101100 00010001 11101100' codewords_int = [ 67, 85, 70, 134, 87, 38, 85, 194, 119, 50, 6, 18, 6, 103, 38, 246, 246, 66, 7, 118, 134, 242, 7, 38, 86, 22, 198, 199, 146, 6, 182, 230, 247, 119, 50, 7, 118, 134, 87, 38, 82, 6, 134, 151, 50, 7, 70, 247, 118, 86, 194, 6, 151, 50, 16, 236, 17, 236, 17, 236, 17, 236 ] s = '01000011111101101011011001000110010101011111011011100110111101110100011001000010111101110111011010000110000001110111011101010110010101110111011000110010110000100010011010000110000001110000011001010101111100100111011010010111110000100000011110000110001100100111011100100110010101110001000000110010010101100010011011101100000001100001011001010010000100010001001011000110000001101110110000000110110001111000011000010001011001111001001010010111111011000010011000000110001100100001000100000111111011001101010101010111100101001110101111000111110011000111010010011111000010110110000010110001000001010010110100111100110101001010110101110011110010100100110000011000111101111011011010000101100100111111000101111100010010110011101111011111100111011111001000100001111001011100100011101110011010101111100010000110010011000010100010011010000110111100001111111111011101011000000111100110101011001001101011010001101111010101001001101111000100010000101000000010010101101010001101101100100000111010000110100011111100000010000001101111011110001100000010110010001001111000010110001101111011000000000' expected = bits(s) buff = Buffer(bits(codewords)) assert codewords_int == list(buff.toints()) res = encoder.make_final_message(5, consts.ERROR_LEVEL_Q, buff) assert len(expected) == len(res) assert expected == res.getbits()
def test_write_segment_bytes_thonky(eci): # <http://www.thonky.com/qr-code-tutorial/byte-mode-encoding/> s = b'Hello, world!' seg = encoder.make_segment(s, consts.MODE_BYTE, consts.DEFAULT_BYTE_ENCODING) buff = Buffer() v, vrange = None, consts.VERSION_RANGE_01_09 encoder.write_segment(buff, seg, v, vrange, eci=eci) assert bits('010000001101' '01001000' '01100101' '01101100' '01101100' '01101111' '00101100' '00100000' '01110111' '01101111' '01110010' '01101100' '01100100' '00100001') == buff.getbits()
def test_codeword_placement_iso_i3(): # ISO/IEC 18004:2015(E) - page 96 # 01234567 as M2-L symbol s = '01000000 00011000 10101100 11000011 00000000' codewords = Buffer(bits(s)).toints() version = consts.VERSION_M2 buff = encoder.make_final_message(version, consts.ERROR_LEVEL_L, codewords) expected_s = '01000000 00011000 10101100 11000011 00000000 10000110 00001101 00100010 10101110 00110000' expected = bits(expected_s) assert expected == buff.getbits() matrix = encoder.make_matrix(version) encoder.add_finder_patterns(matrix, is_micro=version < 1) encoder.add_codewords(matrix, buff, version=version) ref_matrix = read_matrix('iso-i3_code_placement') assert ref_matrix == matrix
def test_codeword_placement_iso_i2(): # ISO/IEC 18004:2015(E) - page 94 # 01234567 as 1-M symbol s = '00010000 00100000 00001100 01010110 01100001 10000000 11101100 00010001 ' \ '11101100 00010001 11101100 00010001 11101100 00010001 11101100 00010001' codewords = Buffer(bits(s)) version = 1 buff = encoder.make_final_message(version, consts.ERROR_LEVEL_M, codewords) expected_s = '00010000 00100000 00001100 01010110 01100001 10000000 11101100 ' \ '00010001 11101100 00010001 11101100 00010001 11101100 00010001 ' \ '11101100 00010001 10100101 00100100 11010100 11000001 11101101 ' \ '00110110 11000111 10000111 00101100 01010101' expected = bits(expected_s) assert expected == buff.getbits() matrix = encoder.make_matrix(version) encoder.add_finder_patterns(matrix, is_micro=version < 1) encoder.add_codewords(matrix, buff, version=version) ref_matrix = read_matrix('iso-i2_code_placement') assert ref_matrix == matrix