use crate::common::{
reedsolomon::{get_predefined_genericgf, PredefinedGenericGF, ReedSolomonDecoder},
BitMatrix, DecoderRXingResult, Result,
};
use super::{decoded_bit_stream_parser, BitMatrixParser, DataBlock};
pub struct Decoder(ReedSolomonDecoder);
impl Decoder {
pub fn new() -> Self {
Self(ReedSolomonDecoder::new(get_predefined_genericgf(
PredefinedGenericGF::DataMatrixField256,
)))
}
pub fn decode(&self, bits: &BitMatrix) -> Result<DecoderRXingResult> {
let decoded = self.perform_decode(bits, false, false);
if decoded.is_ok() {
return decoded;
}
self.perform_decode(&Self::flip_bitmatrix(bits)?, false, true)
}
fn flip_bitmatrix(bits: &BitMatrix) -> Result<BitMatrix> {
let mut res = BitMatrix::new(bits.getHeight(), bits.getWidth())?;
for y in 0..res.getHeight() {
for x in 0..res.getWidth() {
{
res.set_bool(
x,
y,
bits.get(bits.getWidth() - 1 - y, bits.getHeight() - 1 - x),
);
}
}
}
Ok(res)
}
pub fn decode_bools(&self, image: &Vec<Vec<bool>>) -> Result<DecoderRXingResult> {
self.perform_decode(&BitMatrix::parse_bools(image), false, false)
}
fn perform_decode(
&self,
bits: &BitMatrix,
fix259: bool,
is_flipped: bool,
) -> Result<DecoderRXingResult> {
let mut parser = BitMatrixParser::new(bits)?;
let codewords = parser.readCodewords()?;
let version = parser.getVersion();
let dataBlocks = DataBlock::getDataBlocks(&codewords, version, fix259)?;
let totalBytes = dataBlocks
.iter()
.fold(0, |acc, db| acc + db.getNumDataCodewords());
let mut resultBytes = vec![0u8; totalBytes as usize];
let dataBlocksCount = dataBlocks.len();
for j in 0..dataBlocksCount {
let dataBlock = &dataBlocks[j];
let mut codewordBytes = dataBlock.getCodewords().to_vec();
let numDataCodewords = dataBlock.getNumDataCodewords() as usize;
let errors_corrected = self.correctErrors(&mut codewordBytes, numDataCodewords as u32);
if errors_corrected.is_err() && !fix259 {
return self.perform_decode(bits, true, is_flipped);
} else if errors_corrected.is_err() {
return Err(errors_corrected.err().unwrap());
}
for i in 0..numDataCodewords {
resultBytes[i * dataBlocksCount + j] = codewordBytes[i];
}
}
decoded_bit_stream_parser::decode(&resultBytes, is_flipped)
}
fn correctErrors(&self, codewordBytes: &mut [u8], numDataCodewords: u32) -> Result<()> {
let _numCodewords = codewordBytes.len();
let mut codewordsInts: Vec<i32> = codewordBytes.iter().map(|x| *x as i32).collect();
self.0.decode(
&mut codewordsInts,
codewordBytes.len() as i32 - numDataCodewords as i32,
)?;
for i in 0..numDataCodewords as usize {
codewordBytes[i] = codewordsInts[i] as u8;
}
Ok(())
}
}
impl Default for Decoder {
fn default() -> Self {
Self::new()
}
}