lib/rqrcode/qrcode/qr_util.rb in rqrcode-0.3.4 vs lib/rqrcode/qrcode/qr_util.rb in rqrcode-0.4.0

- old
+ new

@@ -59,11 +59,22 @@ G15 = 1 << 10 | 1 << 8 | 1 << 5 | 1 << 4 | 1 << 2 | 1 << 1 | 1 << 0 G18 = 1 << 12 | 1 << 11 | 1 << 10 | 1 << 9 | 1 << 8 | 1 << 5 | 1 << 2 | 1 << 0 G15_MASK = 1 << 14 | 1 << 12 | 1 << 10 | 1 << 4 | 1 << 1 + DEMERIT_POINTS_1 = 3 + DEMERIT_POINTS_2 = 3 + DEMERIT_POINTS_3 = 40 + DEMERIT_POINTS_4 = 10 + BITS_FOR_MODE = { + QRMODE[:mode_number] => [10, 12, 14], + QRMODE[:mode_alpha_num] => [9, 11, 13], + QRMODE[:mode_8bit_byte] => [8, 16, 16], + QRMODE[:mode_kanji] => [8, 10, 12], + } + def QRUtil.get_bch_type_info( data ) d = data << 10 while QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G15) >= 0 d ^= (G15 << (QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G15))) end @@ -96,30 +107,15 @@ PATTERN_POSITION_TABLE[ type_number - 1 ] end def QRUtil.get_mask( mask_pattern, i, j ) - case mask_pattern - when QRMASKPATTERN[:pattern000] - (i + j) % 2 == 0 - when QRMASKPATTERN[:pattern001] - i % 2 == 0 - when QRMASKPATTERN[:pattern010] - j % 3 == 0 - when QRMASKPATTERN[:pattern011] - (i + j) % 3 == 0 - when QRMASKPATTERN[:pattern100] - ((i / 2).floor + (j / 3).floor ) % 2 == 0 - when QRMASKPATTERN[:pattern101] - (i * j) % 2 + (i * j) % 3 == 0 - when QRMASKPATTERN[:pattern110] - ( (i * j) % 2 + (i * j) % 3) % 2 == 0 - when QRMASKPATTERN[:pattern111] - ( (i * j) % 3 + (i + j) % 2) % 2 == 0 - else + if mask_pattern > QRMASKCOMPUTATIONS.size raise QRCodeRunTimeError, "bad mask_pattern: #{mask_pattern}" end + + return QRMASKCOMPUTATIONS[mask_pattern].call(i, j) end def QRUtil.get_error_correct_polynomial( error_correct_length ) a = QRPolynomial.new( [1], 0 ) @@ -130,125 +126,143 @@ a end - def QRUtil.get_length_in_bits( mode, type ) - if 1 <= type && type < 10 + def QRUtil.get_length_in_bits(mode, type) + if !QRMODE.value?(mode) + raise QRCodeRunTimeError, "Unknown mode: #{mode}" + end + if type > 40 + raise QRCodeRunTimeError, "Unknown type: #{type}" + end + + if 1 <= type && type <= 9 # 1 - 9 - case mode - when QRMODE[:mode_number] then 10 - when QRMODE[:mode_alpha_num] then 9 - when QRMODE[:mode_8bit_byte] then 8 - when QRMODE[:mode_kanji] then 8 - else - raise QRCodeRunTimeError, "mode: #{mode}" - end + macro_type = 0 + elsif type <= 26 + # 10 - 26 + macro_type = 1 + elsif type <= 40 + # 27 - 40 + macro_type = 2 + end - elsif type < 27 + return BITS_FOR_MODE[mode][macro_type] + end - # 10 -26 - case mode - when QRMODE[:mode_number] then 12 - when QRMODE[:mode_alpha_num] then 11 - when QRMODE[:mode_8bit_byte] then 16 - when QRMODE[:mode_kanji] then 10 - else - raise QRCodeRunTimeError, "mode: #{mode}" - end + def QRUtil.get_lost_points(modules) + demerit_points = 0 - elsif type < 41 + demerit_points += QRUtil.demerit_points_1_same_color(modules) + demerit_points += QRUtil.demerit_points_2_full_blocks(modules) + demerit_points += QRUtil.demerit_points_3_dangerous_patterns(modules) + demerit_points += QRUtil.demerit_points_4_dark_ratio(modules) - # 27 - 40 - case mode - when QRMODE[:mode_number] then 14 - when QRMODE[:mode_alpha_num] then 13 - when QRMODE[:mode_8bit_byte] then 16 - when QRMODE[:mode_kanji] then 12 - else - raise QRCodeRunTimeError, "mode: #{mode}" - end - - else - raise QRCodeRunTimeError, "type: #{type}" - end + return demerit_points end + def QRUtil.demerit_points_1_same_color(modules) + demerit_points = 0 + module_count = modules.size - def QRUtil.get_lost_point( qr_code ) - module_count = qr_code.module_count - lost_point = 0 - # level1 - ( 0...module_count ).each do |row| - ( 0...module_count ).each do |col| + (0...module_count).each do |row| + (0...module_count).each do |col| same_count = 0 - dark = qr_code.is_dark( row, col ) + dark = modules[row][col] ( -1..1 ).each do |r| next if row + r < 0 || module_count <= row + r ( -1..1 ).each do |c| next if col + c < 0 || module_count <= col + c next if r == 0 && c == 0 - if dark == qr_code.is_dark( row + r, col + c ) + if dark == modules[row + r][col + c] same_count += 1 end end end if same_count > 5 - lost_point += (3 + same_count - 5) - end + demerit_points += (DEMERIT_POINTS_1 + same_count - 5) + end end end + return demerit_points + end + + def QRUtil.demerit_points_2_full_blocks(modules) + demerit_points = 0 + module_count = modules.size + # level 2 - ( 0...( module_count - 1 ) ).each do |row| - ( 0...( module_count - 1 ) ).each do |col| + (0...(module_count - 1)).each do |row| + (0...(module_count - 1)).each do |col| count = 0 - count = count + 1 if qr_code.is_dark( row, col ) - count = count + 1 if qr_code.is_dark( row + 1, col ) - count = count + 1 if qr_code.is_dark( row, col + 1 ) - count = count + 1 if qr_code.is_dark( row + 1, col + 1 ) - lost_point = lost_point + 3 if (count == 0 || count == 4) - end + count += 1 if modules[row][col] + count += 1 if modules[row + 1][col] + count += 1 if modules[row][col + 1] + count += 1 if modules[row + 1][col + 1] + if (count == 0 || count == 4) + demerit_points += DEMERIT_POINTS_2 + end + end end + return demerit_points + end + + def QRUtil.demerit_points_3_dangerous_patterns(modules) + demerit_points = 0 + module_count = modules.size + # level 3 - ( 0...module_count ).each do |row| - ( 0...( module_count - 6 ) ).each do |col| - if qr_code.is_dark( row, col ) && !qr_code.is_dark( row, col + 1 ) && qr_code.is_dark( row, col + 2 ) && qr_code.is_dark( row, col + 3 ) && qr_code.is_dark( row, col + 4 ) && !qr_code.is_dark( row, col + 5 ) && qr_code.is_dark( row, col + 6 ) - lost_point = lost_point + 40 + modules.each do |row| + (module_count - 6).times do |col_idx| + if row[col_idx] && + !row[col_idx + 1] && + row[col_idx + 2] && + row[col_idx + 3] && + row[col_idx + 4] && + !row[col_idx + 5] && + row[col_idx + 6] + demerit_points += DEMERIT_POINTS_3 end end end - ( 0...module_count ).each do |col| - ( 0...( module_count - 6 ) ).each do |row| - if qr_code.is_dark(row, col) && !qr_code.is_dark(row + 1, col) && qr_code.is_dark(row + 2, col) && qr_code.is_dark(row + 3, col) && qr_code.is_dark(row + 4, col) && !qr_code.is_dark(row + 5, col) && qr_code.is_dark(row + 6, col) - lost_point = lost_point + 40 + (0...module_count).each do |col| + (0...(module_count - 6)).each do |row| + if modules[row][col] && + !modules[row + 1][col] && + modules[row + 2][col] && + modules[row + 3][col] && + modules[row + 4][col] && + !modules[row + 5][col] && + modules[row + 6][col] + demerit_points += DEMERIT_POINTS_3 end end end - # level 4 - dark_count = 0 + return demerit_points + end - ( 0...module_count ).each do |col| - ( 0...module_count ).each do |row| - if qr_code.is_dark(row, col) - dark_count = dark_count + 1 - end - end + def QRUtil.demerit_points_4_dark_ratio(modules) + # level 4 + dark_count = modules.reduce(0) do |sum, col| + sum + col.count(true) end - ratio = (100 * dark_count / module_count / module_count - 50).abs / 5 - lost_point = lost_point * 10 + ratio = dark_count / (modules.size * modules.size) + ratio_delta = (100 * ratio - 50).abs / 5 - lost_point - end + demerit_points = ratio_delta * DEMERIT_POINTS_4 + return demerit_points + end end end