qrcode encoder pass

This commit is contained in:
Henry Schimke
2022-10-05 13:44:51 -05:00
parent 9c27185f7b
commit 4c51e2611c
3 changed files with 50 additions and 31 deletions

View File

@@ -60,6 +60,15 @@ impl ErrorCorrectionLevel {
ErrorCorrectionLevel::H => 0x02, ErrorCorrectionLevel::H => 0x02,
} }
} }
pub fn get_ordinal(&self) -> u8 {
match self {
ErrorCorrectionLevel::L => 0,
ErrorCorrectionLevel::M => 1,
ErrorCorrectionLevel::Q => 2,
ErrorCorrectionLevel::H => 3,
}
}
} }
impl TryFrom<u8> for ErrorCorrectionLevel { impl TryFrom<u8> for ErrorCorrectionLevel {

View File

@@ -90,7 +90,7 @@ impl Version {
} }
pub fn getECBlocksForLevel(&self, ecLevel: ErrorCorrectionLevel) -> &ECBlocks { pub fn getECBlocksForLevel(&self, ecLevel: ErrorCorrectionLevel) -> &ECBlocks {
&self.ecBlocks[ecLevel.get_value() as usize] &self.ecBlocks[ecLevel.get_ordinal() as usize]
} }
/** /**

View File

@@ -38,6 +38,7 @@ use std::collections::HashMap;
use encoding::EncodingRef; use encoding::EncodingRef;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use unicode_segmentation::UnicodeSegmentation;
use crate::{ use crate::{
common::{ common::{
@@ -151,7 +152,11 @@ pub fn encode_with_hints(
version = rn.getVersion(); version = rn.getVersion();
} else { } else {
//Switch to default encoding //Switch to default encoding
let encoding = if encoding.is_some() { encoding.unwrap() } else { DEFAULT_BYTE_MODE_ENCODING }; let encoding = if encoding.is_some() {
encoding.unwrap()
} else {
DEFAULT_BYTE_MODE_ENCODING
};
// Pick an encoding mode appropriate for the content. Note that this will not attempt to use // Pick an encoding mode appropriate for the content. Note that this will not attempt to use
// multiple modes / segments even if that were more efficient. // multiple modes / segments even if that were more efficient.
@@ -213,7 +218,7 @@ pub fn encode_with_hints(
let numLetters = if mode == Mode::BYTE { let numLetters = if mode == Mode::BYTE {
dataBits.getSizeInBytes() dataBits.getSizeInBytes()
} else { } else {
content.len() content.graphemes(true).count()
}; };
appendLengthInfo(numLetters as u32, version, mode, &mut headerAndDataBits)?; appendLengthInfo(numLetters as u32, version, mode, &mut headerAndDataBits)?;
// Put data together into the overall payload // Put data together into the overall payload
@@ -362,11 +367,10 @@ fn chooseModeWithEncoding(content: &str, encoding: EncodingRef) -> Mode {
} }
pub fn isOnlyDoubleByteKanji(content: &str) -> bool { pub fn isOnlyDoubleByteKanji(content: &str) -> bool {
let bytes = if let Ok(byt) = SHIFT_JIS_CHARSET let bytes = if let Ok(byt) = SHIFT_JIS_CHARSET.encode(content, encoding::EncoderTrap::Strict) {
.encode(content, encoding::EncoderTrap::Strict) {
byt byt
} else { } else {
return false return false;
}; };
let length = bytes.len(); let length = bytes.len();
if length % 2 != 0 { if length % 2 != 0 {
@@ -395,8 +399,9 @@ fn chooseMaskPattern(
// We try all mask patterns to choose the best one. // We try all mask patterns to choose the best one.
for maskPattern in 0..QRCode::NUM_MASK_PATTERNS { for maskPattern in 0..QRCode::NUM_MASK_PATTERNS {
// for (int maskPattern = 0; maskPattern < QRCode.NUM_MASK_PATTERNS; maskPattern++) { // for (int maskPattern = 0; maskPattern < QRCode.NUM_MASK_PATTERNS; maskPattern++) {
matrix_util::buildMatrix(bits, ecLevel, version, maskPattern, matrix)?; let mut matrix = matrix.clone();
let penalty = calculateMaskPenalty(matrix); matrix_util::buildMatrix(bits, ecLevel, version, maskPattern, &mut matrix)?;
let penalty = calculateMaskPenalty(&matrix);
if penalty < minPenalty { if penalty < minPenalty {
minPenalty = penalty; minPenalty = penalty;
bestMaskPattern = maskPattern; bestMaskPattern = maskPattern;
@@ -470,7 +475,9 @@ pub fn terminateBits(num_data_bytes: u32, bits: &mut BitArray) -> Result<(), Exc
// If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24). // If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24).
let num_padding_bytes = num_data_bytes as isize - bits.getSizeInBytes() as isize; let num_padding_bytes = num_data_bytes as isize - bits.getSizeInBytes() as isize;
for i in 0..num_padding_bytes { for i in 0..num_padding_bytes {
if i >= num_padding_bytes{ break } if i >= num_padding_bytes {
break;
}
// for (int i = 0; i < numPaddingBytes; ++i) { // for (int i = 0; i < numPaddingBytes; ++i) {
bits.appendBits(if (i & 0x01) == 0 { 0xEC } else { 0x11 }, 8)?; bits.appendBits(if (i & 0x01) == 0 { 0xEC } else { 0x11 }, 8)?;
} }
@@ -651,7 +658,8 @@ pub fn generateECBytes(dataBytes: &[u8], numEcBytesInBlock: usize) -> Vec<u8> {
ReedSolomonEncoder::new(get_predefined_genericgf( ReedSolomonEncoder::new(get_predefined_genericgf(
PredefinedGenericGF::QrCodeField256, PredefinedGenericGF::QrCodeField256,
)) ))
.encode(&mut toEncode, numEcBytesInBlock).expect("rs encode must complete"); .encode(&mut toEncode, numEcBytesInBlock)
.expect("rs encode must complete");
let mut ecBytes = vec![0u8; numEcBytesInBlock]; let mut ecBytes = vec![0u8; numEcBytesInBlock];
for i in 0..numEcBytesInBlock { for i in 0..numEcBytesInBlock {
@@ -704,12 +712,10 @@ pub fn appendBytes(
Mode::ALPHANUMERIC => appendAlphanumericBytes(content, bits), Mode::ALPHANUMERIC => appendAlphanumericBytes(content, bits),
Mode::BYTE => append8BitBytes(content, bits, encoding), Mode::BYTE => append8BitBytes(content, bits, encoding),
Mode::KANJI => appendKanjiBytes(content, bits), Mode::KANJI => appendKanjiBytes(content, bits),
_ => { _ => Err(Exceptions::WriterException(format!(
Err(Exceptions::WriterException(format!(
"Invalid mode: {:?}", "Invalid mode: {:?}",
mode mode
))) ))),
}
} }
// switch (mode) { // switch (mode) {
// case NUMERIC: // case NUMERIC:
@@ -779,7 +785,11 @@ pub fn appendAlphanumericBytes(content: &str, bits: &mut BitArray) -> Result<(),
Ok(()) Ok(())
} }
pub fn append8BitBytes(content: &str, bits: &mut BitArray, encoding: EncodingRef) -> Result<(),Exceptions> { pub fn append8BitBytes(
content: &str,
bits: &mut BitArray,
encoding: EncodingRef,
) -> Result<(), Exceptions> {
let bytes = encoding let bytes = encoding
.encode(content, encoding::EncoderTrap::Strict) .encode(content, encoding::EncoderTrap::Strict)
.expect("should encode"); .expect("should encode");