use anyhow::Error;
use image::DynamicImage;
use image::GrayImage;
use crate::decode::{Decode, QRDecoder, QRDecoderWithInfo};
use crate::detect::{Detect, LineScan, Location};
use crate::extract::{Extract, QRExtractor};
use crate::prepare::{BlockedMean, Prepare};
use crate::util::qr::{QRData, QRError, QRInfo, QRLocation};
pub struct Decoder<IMG, PREPD, RESULT> {
prepare: Box<dyn Prepare<IMG, PREPD>>,
detect: Box<dyn Detect<PREPD>>,
qr: ExtractDecode<PREPD, QRLocation, QRData, RESULT, QRError>,
}
impl<IMG, PREPD, RESULT> Decoder<IMG, PREPD, RESULT> {
pub fn decode(&self, source: &IMG) -> Vec<Result<RESULT, Error>> {
let prepared = self.prepare.prepare(source);
let locations = self.detect.detect(&prepared);
if locations.is_empty() {
return vec![];
}
let mut all_decoded = vec![];
for location in locations {
match location {
Location::QR(qrloc) => {
let extracted = self.qr.extract.extract(&prepared, qrloc);
let decoded = self.qr.decode.decode(extracted);
all_decoded.push(decoded.map_err(Error::from));
}
}
}
all_decoded
}
}
pub fn default_decoder() -> Decoder<DynamicImage, GrayImage, String> {
default_builder().build()
}
pub fn default_decoder_with_info() -> Decoder<DynamicImage, GrayImage, (String, QRInfo)> {
default_builder_with_info().build()
}
pub struct DecoderBuilder<IMG, PREPD, RESULT> {
prepare: Option<Box<dyn Prepare<IMG, PREPD>>>,
detect: Option<Box<dyn Detect<PREPD>>>,
qr: Option<ExtractDecode<PREPD, QRLocation, QRData, RESULT, QRError>>,
}
impl<IMG, PREPD, RESULT> DecoderBuilder<IMG, PREPD, RESULT> {
pub fn new() -> DecoderBuilder<IMG, PREPD, RESULT> {
DecoderBuilder {
prepare: None,
detect: None,
qr: None,
}
}
pub fn prepare(
&mut self,
prepare: Box<dyn Prepare<IMG, PREPD>>,
) -> &mut DecoderBuilder<IMG, PREPD, RESULT> {
self.prepare = Some(prepare);
self
}
pub fn detect(
&mut self,
detect: Box<dyn Detect<PREPD>>,
) -> &mut DecoderBuilder<IMG, PREPD, RESULT> {
self.detect = Some(detect);
self
}
pub fn qr(
&mut self,
extract: Box<dyn Extract<PREPD, QRLocation, QRData, QRError>>,
decode: Box<dyn Decode<QRData, RESULT, QRError>>,
) -> &mut DecoderBuilder<IMG, PREPD, RESULT> {
self.qr = Some(ExtractDecode { extract, decode });
self
}
pub fn build(self) -> Decoder<IMG, PREPD, RESULT> {
if self.prepare.is_none() {
panic!("Cannot build Decoder without Prepare component");
}
if self.detect.is_none() {
panic!("Cannot build Decoder without Detect component");
}
Decoder {
prepare: self.prepare.unwrap(),
detect: self.detect.unwrap(),
qr: self.qr.unwrap(),
}
}
}
pub fn default_builder() -> DecoderBuilder<DynamicImage, GrayImage, String> {
let mut db = DecoderBuilder::new();
db.prepare(Box::new(BlockedMean::new(5, 7)));
db.detect(Box::new(LineScan::new()));
db.qr(Box::new(QRExtractor::new()), Box::new(QRDecoder::new()));
db
}
pub fn default_builder_with_info() -> DecoderBuilder<DynamicImage, GrayImage, (String, QRInfo)> {
let mut db = DecoderBuilder::new();
db.prepare(Box::new(BlockedMean::new(5, 7)));
db.detect(Box::new(LineScan::new()));
db.qr(
Box::new(QRExtractor::new()),
Box::new(QRDecoderWithInfo::new()),
);
db
}
struct ExtractDecode<PREPD, LOC, DATA, RESULT, ERROR> {
extract: Box<dyn Extract<PREPD, LOC, DATA, ERROR>>,
decode: Box<dyn Decode<DATA, RESULT, ERROR>>,
}