From 98e30a1d801f2e9899f0cc8b6ac373981284fb2a Mon Sep 17 00:00:00 2001 From: Henry Schimke Date: Thu, 30 Mar 2023 15:01:31 -0500 Subject: [PATCH] porting formatinformation and eclevel --- .../cpp_essentials/base_extentions/mod.rs | 1 + .../base_extentions/qr_ec_level.rs | 27 +++++ .../base_extentions/qr_formatinformation.rs | 100 ++++++++++++++---- src/qrcode/decoder/format_information.rs | 11 +- 4 files changed, 114 insertions(+), 25 deletions(-) create mode 100644 src/common/cpp_essentials/base_extentions/qr_ec_level.rs diff --git a/src/common/cpp_essentials/base_extentions/mod.rs b/src/common/cpp_essentials/base_extentions/mod.rs index 06e69f7..5c34e18 100644 --- a/src/common/cpp_essentials/base_extentions/mod.rs +++ b/src/common/cpp_essentials/base_extentions/mod.rs @@ -1,3 +1,4 @@ mod bitmatrix; +mod qr_ec_level; mod qr_formatinformation; mod qrcode_version; diff --git a/src/common/cpp_essentials/base_extentions/qr_ec_level.rs b/src/common/cpp_essentials/base_extentions/qr_ec_level.rs new file mode 100644 index 0000000..365c7d3 --- /dev/null +++ b/src/common/cpp_essentials/base_extentions/qr_ec_level.rs @@ -0,0 +1,27 @@ +use crate::common::Result; +use crate::qrcode::decoder::ErrorCorrectionLevel; + +impl ErrorCorrectionLevel { + pub fn ECLevelFromBits(bits: u8, isMicro: bool) -> Self { + if (isMicro) { + let LEVEL_FOR_BITS: [ErrorCorrectionLevel; 8] = [ + ErrorCorrectionLevel::L, + ErrorCorrectionLevel::L, + ErrorCorrectionLevel::M, + ErrorCorrectionLevel::L, + ErrorCorrectionLevel::M, + ErrorCorrectionLevel::L, + ErrorCorrectionLevel::M, + ErrorCorrectionLevel::Q, + ]; + return LEVEL_FOR_BITS[bits as usize & 0x07]; + } + let LEVEL_FOR_BITS: [ErrorCorrectionLevel; 4] = [ + ErrorCorrectionLevel::M, + ErrorCorrectionLevel::L, + ErrorCorrectionLevel::H, + ErrorCorrectionLevel::Q, + ]; + return LEVEL_FOR_BITS[bits as usize & 0x3]; + } +} diff --git a/src/common/cpp_essentials/base_extentions/qr_formatinformation.rs b/src/common/cpp_essentials/base_extentions/qr_formatinformation.rs index 15001e6..ebd87e6 100644 --- a/src/common/cpp_essentials/base_extentions/qr_formatinformation.rs +++ b/src/common/cpp_essentials/base_extentions/qr_formatinformation.rs @@ -1,4 +1,43 @@ -use crate::qrcode::decoder::FormatInformation; +use crate::common::Result; + +use crate::qrcode::decoder::{ + ErrorCorrectionLevel, FormatInformation, FORMAT_INFO_DECODE_LOOKUP, FORMAT_INFO_MASK_QR, +}; + +pub const FORMAT_INFO_DECODE_LOOKUP_MICRO: [[u32; 2]; 32] = [ + [0x4445, 0x00], + [0x4172, 0x01], + [0x4E2B, 0x02], + [0x4B1C, 0x03], + [0x55AE, 0x04], + [0x5099, 0x05], + [0x5FC0, 0x06], + [0x5AF7, 0x07], + [0x6793, 0x08], + [0x62A4, 0x09], + [0x6DFD, 0x0A], + [0x68CA, 0x0B], + [0x7678, 0x0C], + [0x734F, 0x0D], + [0x7C16, 0x0E], + [0x7921, 0x0F], + [0x06DE, 0x10], + [0x03E9, 0x11], + [0x0CB0, 0x12], + [0x0987, 0x13], + [0x1735, 0x14], + [0x1202, 0x15], + [0x1D5B, 0x16], + [0x186C, 0x17], + [0x2508, 0x18], + [0x203F, 0x19], + [0x2F66, 0x1A], + [0x2A51, 0x1B], + [0x34E3, 0x1C], + [0x31D4, 0x1D], + [0x3E8D, 0x1E], + [0x3BBA, 0x1F], +]; impl FormatInformation { /** @@ -6,35 +45,50 @@ impl FormatInformation { * @param formatInfoBits2 second copy of same info; both are checked at the same time to establish best match */ pub fn DecodeQR(formatInfoBits1: u32, formatInfoBits2: u32) -> Self { - todo!() - // // maks out the 'Dark Module' for mirrored and non-mirrored case (see Figure 25 in ISO/IEC 18004:2015) - // uint32_t mirroredFormatInfoBits2 = MirrorBits(((formatInfoBits2 >> 1) & 0b111111110000000) | (formatInfoBits2 & 0b1111111)); - // formatInfoBits2 = ((formatInfoBits2 >> 1) & 0b111111100000000) | (formatInfoBits2 & 0b11111111); - // auto fi = FindBestFormatInfo(FORMAT_INFO_MASK_QR, FORMAT_INFO_DECODE_LOOKUP, - // {formatInfoBits1, formatInfoBits2, MirrorBits(formatInfoBits1), mirroredFormatInfoBits2}); + // maks out the 'Dark Module' for mirrored and non-mirrored case (see Figure 25 in ISO/IEC 18004:2015) + let mirroredFormatInfoBits2 = Self::MirrorBits( + ((formatInfoBits2 >> 1) & 0b111111110000000) | (formatInfoBits2 & 0b1111111), + ); + let formatInfoBits2 = + ((formatInfoBits2 >> 1) & 0b111111100000000) | (formatInfoBits2 & 0b11111111); + let mut fi = Self::FindBestFormatInfo( + FORMAT_INFO_MASK_QR, + FORMAT_INFO_DECODE_LOOKUP, + &[ + formatInfoBits1, + formatInfoBits2, + Self::MirrorBits(formatInfoBits1), + mirroredFormatInfoBits2, + ], + ); - // // Use bits 3/4 for error correction, and 0-2 for mask. - // fi.ecLevel = ECLevelFromBits((fi.index >> 3) & 0x03); - // fi.dataMask = static_cast(fi.index & 0x07); - // fi.isMirrored = fi.bitsIndex > 1; + // Use bits 3/4 for error correction, and 0-2 for mask. + fi.error_correction_level = + ErrorCorrectionLevel::ECLevelFromBits((fi.index >> 3) & 0x03, true); + fi.data_mask = fi.index & 0x07; + fi.isMirrored = fi.bitsIndex > 1; - // return fi; + fi } pub fn DecodeMQR(formatInfoBits: u32) -> Self { - todo!() - // // We don't use the additional masking (with 0x4445) to work around potentially non complying MicroQRCode encoders - // let fi = FindBestFormatInfo(0, FORMAT_INFO_DECODE_LOOKUP_MICRO, {formatInfoBits, MirrorBits(formatInfoBits)}); + // We don't use the additional masking (with 0x4445) to work around potentially non complying MicroQRCode encoders + let mut fi = Self::FindBestFormatInfo( + 0, + FORMAT_INFO_DECODE_LOOKUP_MICRO, + &[formatInfoBits, Self::MirrorBits(formatInfoBits)], + ); - // constexpr uint8_t BITS_TO_VERSION[] = {1, 2, 2, 3, 3, 4, 4, 4}; + const BITS_TO_VERSION: [u8; 8] = [1, 2, 2, 3, 3, 4, 4, 4]; - // // Bits 2/3/4 contain both error correction level and version, 0/1 contain mask. - // fi.ecLevel = ECLevelFromBits((fi.index >> 2) & 0x07, true); - // fi.dataMask = static_cast(fi.index & 0x03); - // fi.microVersion = BITS_TO_VERSION[(fi.index >> 2) & 0x07]; - // fi.isMirrored = fi.bitsIndex == 1; + // Bits 2/3/4 contain both error correction level and version, 0/1 contain mask. + fi.error_correction_level = + ErrorCorrectionLevel::ECLevelFromBits((fi.index >> 2) & 0x07, true); + fi.data_mask = (fi.index & 0x03); + fi.microVersion = BITS_TO_VERSION[((fi.index >> 2) & 0x07) as usize] as u32; + fi.isMirrored = fi.bitsIndex == 1; - // return fi; + fi } pub fn MirrorBits(bits: u32) -> u32 { @@ -42,7 +96,7 @@ impl FormatInformation { // return BitHacks::Reverse(bits) >> 17; } - pub fn FindBestFormatInfo(mask: u32, lookup: [(u32, u32); 32], bits: &[u32]) -> Self { + pub fn FindBestFormatInfo(mask: u32, lookup: [[u32; 2]; 32], bits: &[u32]) -> Self { todo!() // FormatInformation fi; diff --git a/src/qrcode/decoder/format_information.rs b/src/qrcode/decoder/format_information.rs index 65800c2..492b445 100644 --- a/src/qrcode/decoder/format_information.rs +++ b/src/qrcode/decoder/format_information.rs @@ -18,12 +18,12 @@ use crate::common::Result; use super::ErrorCorrectionLevel; -const FORMAT_INFO_MASK_QR: u32 = 0x5412; +pub const FORMAT_INFO_MASK_QR: u32 = 0x5412; /** * See ISO 18004:2006, Annex C, Table C.1 */ -const FORMAT_INFO_DECODE_LOOKUP: [[u32; 2]; 32] = [ +pub const FORMAT_INFO_DECODE_LOOKUP: [[u32; 2]; 32] = [ [0x5412, 0x00], [0x5125, 0x01], [0x5E7C, 0x02], @@ -73,6 +73,9 @@ pub struct FormatInformation { pub data_mask: u8, pub microVersion: u32, pub isMirrored: bool, + + pub index: u8, // = 255; + pub bitsIndex: u8, // = 255; } impl Default for FormatInformation { @@ -83,6 +86,8 @@ impl Default for FormatInformation { data_mask: Default::default(), microVersion: 0, isMirrored: false, + index: 255, + bitsIndex: 255, } } } @@ -99,6 +104,8 @@ impl FormatInformation { error_correction_level: errorCorrectionLevel, data_mask: dataMask, isMirrored: false, + index: 255, + bitsIndex: 255, }) }