mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 04:12:34 +00:00
wip: inop dx_film_edge port and filtered reader
This commit is contained in:
@@ -119,6 +119,7 @@ impl Display for BarcodeFormat {
|
||||
BarcodeFormat::UPC_A => "upc a",
|
||||
BarcodeFormat::UPC_E => "upc e",
|
||||
BarcodeFormat::UPC_EAN_EXTENSION => "upc/ean extension",
|
||||
BarcodeFormat::DXFilmEdge => "DXFilmEdge",
|
||||
_ => "unsuported",
|
||||
}
|
||||
)
|
||||
@@ -166,6 +167,7 @@ impl From<&str> for BarcodeFormat {
|
||||
"upc e" | "upc_e" | "upce" => BarcodeFormat::UPC_E,
|
||||
"upc ean extension" | "upc extension" | "ean extension" | "upc/ean extension"
|
||||
| "upc_ean_extension" => BarcodeFormat::UPC_EAN_EXTENSION,
|
||||
"DXFilmEdge" | "dxfilmedge" | "dx film edge" => BarcodeFormat::DXFilmEdge,
|
||||
_ => BarcodeFormat::UNSUPORTED_FORMAT,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ use crate::{
|
||||
|
||||
pub struct BinaryBitmap<B: Binarizer> {
|
||||
binarizer: B,
|
||||
matrix: Option<BitMatrix>,
|
||||
pub(crate) matrix: Option<BitMatrix>,
|
||||
}
|
||||
|
||||
impl<B: Binarizer> BinaryBitmap<B> {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
use image::{DynamicImage, ImageBuffer, Luma};
|
||||
use image::{DynamicImage, GenericImageView, ImageBuffer, Luma, Pixel};
|
||||
use imageproc::geometric_transformations::rotate_about_center;
|
||||
|
||||
use crate::common::Result;
|
||||
@@ -108,6 +108,33 @@ impl LuminanceSource for BufferedImageLuminanceSource {
|
||||
pixels
|
||||
}
|
||||
|
||||
fn get_column(&self, x: usize) -> Vec<u8> {
|
||||
let width = self.get_height(); // - self.left as usize;
|
||||
|
||||
let pixels: Vec<u8> = || -> Option<Vec<u8>> {
|
||||
Some(
|
||||
self.image
|
||||
.as_luma8()?
|
||||
.rows()
|
||||
.skip(self.top as usize)
|
||||
.fold(Vec::default(), |mut acc, e| {
|
||||
acc.push(
|
||||
e.into_iter()
|
||||
.nth(self.left as usize + x)
|
||||
.unwrap_or(&Luma([0_u8])),
|
||||
);
|
||||
acc
|
||||
})
|
||||
.iter()
|
||||
.map(|&p| p.0[0])
|
||||
.collect(),
|
||||
)
|
||||
}()
|
||||
.unwrap_or_default();
|
||||
|
||||
pixels
|
||||
}
|
||||
|
||||
fn get_matrix(&self) -> Vec<u8> {
|
||||
if self.height == self.image.height() as usize && self.width == self.image.width() as usize
|
||||
{
|
||||
@@ -201,4 +228,8 @@ impl LuminanceSource for BufferedImageLuminanceSource {
|
||||
top: 0,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_luma8_point(&self, x: usize, y: usize) -> u8 {
|
||||
self.image.get_pixel(x as u32, y as u32).to_luma().0[0]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ impl<'a> PatternView<'a> {
|
||||
pub fn isValidWithN(&self, n: usize) -> bool {
|
||||
!self.data.0.is_empty()
|
||||
&& self.start <= self.current + self.start
|
||||
&& self.current + n <= (self.data.0.len())
|
||||
&& self.current + n < (self.data.0.len())
|
||||
/*return _data && _data >= _base && _data + n <= _end;*/
|
||||
}
|
||||
pub fn isValid(&self) -> bool {
|
||||
@@ -271,7 +271,10 @@ impl<'a> PatternView<'a> {
|
||||
}
|
||||
|
||||
pub fn extend(&mut self) {
|
||||
self.count = std::cmp::max(0, self.data.len() - (self.current + self.start))
|
||||
self.count = std::cmp::max(
|
||||
0,
|
||||
self.data.len() as isize - (self.current + self.start) as isize,
|
||||
) as usize
|
||||
}
|
||||
|
||||
fn try_get_index(&self, index: isize) -> Option<PatternType> {
|
||||
|
||||
@@ -27,7 +27,7 @@ use once_cell::unsync::OnceCell;
|
||||
use crate::common::Result;
|
||||
use crate::{Binarizer, Exceptions, LuminanceSource};
|
||||
|
||||
use super::{BitArray, BitMatrix};
|
||||
use super::{BitArray, BitMatrix, LineOrientation};
|
||||
|
||||
const LUMINANCE_BITS: usize = 5;
|
||||
const LUMINANCE_SHIFT: usize = 8 - LUMINANCE_BITS;
|
||||
@@ -107,8 +107,55 @@ impl<LS: LuminanceSource> Binarizer for GlobalHistogramBinarizer<LS> {
|
||||
Ok(Cow::Borrowed(row))
|
||||
}
|
||||
|
||||
fn get_black_line(&self, l: usize, lt: super::LineOrientation) -> Result<Cow<BitArray>> {
|
||||
unimplemented!()
|
||||
fn get_black_line(&self, l: usize, lt: LineOrientation) -> Result<Cow<BitArray>> {
|
||||
if lt == LineOrientation::Row {
|
||||
self.get_black_row(l)
|
||||
} else {
|
||||
let col = self.black_column_cache[l].get_or_try_init(|| {
|
||||
let source = self.get_luminance_source();
|
||||
let width = source.get_height();
|
||||
let mut col = BitArray::with_size(width);
|
||||
|
||||
// self.initArrays(width);
|
||||
let localLuminances = source.get_column(l);
|
||||
let mut localBuckets = [0; LUMINANCE_BUCKETS]; //self.buckets.clone();
|
||||
for x in 0..width {
|
||||
// for (int x = 0; x < width; x++) {
|
||||
localBuckets[((localLuminances[x]) >> LUMINANCE_SHIFT) as usize] += 1;
|
||||
}
|
||||
let blackPoint = Self::estimateBlackPoint(&localBuckets)?;
|
||||
|
||||
if width < 3 {
|
||||
// Special case for very small images
|
||||
for (x, lum) in localLuminances.iter().enumerate().take(width) {
|
||||
// for x in 0..width {
|
||||
// for (int x = 0; x < width; x++) {
|
||||
if (*lum as u32) < blackPoint {
|
||||
col.set(x);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let mut left = localLuminances[0]; // & 0xff;
|
||||
let mut center = localLuminances[1]; // & 0xff;
|
||||
for x in 1..width - 1 {
|
||||
// for (int x = 1; x < width - 1; x++) {
|
||||
let right = localLuminances[x + 1];
|
||||
// A simple -1 4 -1 box filter with a weight of 2.
|
||||
if ((center as i64 * 4) - left as i64 - right as i64) / 2
|
||||
< blackPoint as i64
|
||||
{
|
||||
col.set(x);
|
||||
}
|
||||
left = center;
|
||||
center = right;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(col)
|
||||
})?;
|
||||
|
||||
Ok(Cow::Borrowed(col))
|
||||
}
|
||||
}
|
||||
|
||||
// Does not sharpen the data, as this call is intended to only be used by 2D Readers.
|
||||
|
||||
216
src/filtered_image_reader.rs
Normal file
216
src/filtered_image_reader.rs
Normal file
@@ -0,0 +1,216 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{Binarizer, BinaryBitmap, Exceptions, Luma8LuminanceSource, LuminanceSource, Reader};
|
||||
|
||||
use crate::common::{BitMatrix, Result};
|
||||
|
||||
pub const DEFAULT_DOWNSCALE_THRESHHOLD: usize = 500;
|
||||
pub const DEFAULT_DOWNSCALE_FACTOR: usize = 3;
|
||||
|
||||
/// Passed image data is ignored, only the image data
|
||||
pub struct FilteredImageReader<R: Reader, B: Binarizer<Source = Luma8LuminanceSource>> {
|
||||
reader: R,
|
||||
source: Luma8LuminanceSource,
|
||||
binarizer: B,
|
||||
}
|
||||
|
||||
impl<R: Reader, B: Binarizer<Source = Luma8LuminanceSource>> FilteredImageReader<R, B> {
|
||||
pub fn new<I: LuminanceSource + Clone + Into<Luma8LuminanceSource>>(
|
||||
reader: R,
|
||||
source: I,
|
||||
binarizer: B,
|
||||
) -> Self {
|
||||
Self {
|
||||
reader,
|
||||
source: source.into(),
|
||||
binarizer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Reader, B1: Binarizer<Source = Luma8LuminanceSource>> Reader
|
||||
for FilteredImageReader<R, B1>
|
||||
{
|
||||
fn decode<B: crate::Binarizer>(
|
||||
&mut self,
|
||||
_image: &mut crate::BinaryBitmap<B>,
|
||||
) -> crate::common::Result<crate::RXingResult> {
|
||||
self.decode_with_hints(_image, &HashMap::default())
|
||||
}
|
||||
|
||||
fn decode_with_hints<B: crate::Binarizer>(
|
||||
&mut self,
|
||||
_image: &mut crate::BinaryBitmap<B>,
|
||||
hints: &crate::DecodingHintDictionary,
|
||||
) -> crate::common::Result<crate::RXingResult> {
|
||||
let pyramids = LumImagePyramid::new(
|
||||
self.source.clone(),
|
||||
DEFAULT_DOWNSCALE_THRESHHOLD,
|
||||
DEFAULT_DOWNSCALE_FACTOR,
|
||||
)
|
||||
.ok_or(Exceptions::ILLEGAL_ARGUMENT)?;
|
||||
for layer in pyramids.layers {
|
||||
let mut b = BinaryBitmap::new(self.binarizer.create_binarizer(layer));
|
||||
for close in [false, true] {
|
||||
if close {
|
||||
let Ok(_) = b.close() else {
|
||||
continue;
|
||||
};
|
||||
}
|
||||
if let Ok(res) = self.reader.decode_with_hints(&mut b, hints) {
|
||||
return Ok(res);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(Exceptions::NOT_FOUND)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct LumImagePyramid {
|
||||
buffers: Vec<Luma8LuminanceSource>,
|
||||
pub layers: Vec<Luma8LuminanceSource>,
|
||||
}
|
||||
|
||||
impl Default for LumImagePyramid {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
buffers: Default::default(),
|
||||
layers: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LumImagePyramid {
|
||||
pub fn new(image: Luma8LuminanceSource, threshold: usize, factor: usize) -> Option<Self> {
|
||||
let mut new_self = Self::default();
|
||||
|
||||
new_self.layers.push(image);
|
||||
// TODO: if only matrix codes were considered, then using std::min would be sufficient (see #425)
|
||||
while threshold > 0
|
||||
&& std::cmp::max(
|
||||
new_self.layers.last()?.get_width(),
|
||||
new_self.layers.last()?.get_height(),
|
||||
) > threshold
|
||||
&& std::cmp::min(
|
||||
new_self.layers.last()?.get_width(),
|
||||
new_self.layers.last()?.get_height(),
|
||||
) >= factor
|
||||
{
|
||||
new_self.add_layer_with_factor(factor).ok()?;
|
||||
}
|
||||
|
||||
if false {
|
||||
// Reversing the layers means we'd start with the smallest. that can make sense if we are only looking for a
|
||||
// single symbol. If we start with the higher resolution, we get better (high res) position information.
|
||||
// TODO: see if masking out higher res layers based on found symbols in lower res helps overall performance.
|
||||
new_self.layers.reverse();
|
||||
}
|
||||
|
||||
Some(new_self)
|
||||
}
|
||||
|
||||
fn add_layer<const N: usize>(&mut self) -> Result<()> {
|
||||
let siv = self.layers.last().ok_or(Exceptions::ILLEGAL_ARGUMENT)?;
|
||||
|
||||
self.buffers.push(Luma8LuminanceSource::with_empty_image(
|
||||
siv.get_width() / N,
|
||||
siv.get_height() / N,
|
||||
));
|
||||
|
||||
let div = self
|
||||
.buffers
|
||||
.last_mut()
|
||||
.ok_or(Exceptions::ILLEGAL_ARGUMENT)?;
|
||||
|
||||
let div_height = div.get_height();
|
||||
let div_width = div.get_width();
|
||||
|
||||
let d_vec = div.get_matrix_mut();
|
||||
|
||||
for d in d_vec.iter_mut() {
|
||||
for dy in 0..div_height {
|
||||
// for (int dy = 0; dy < div.height(); ++dy){
|
||||
for dx in 0..div_width {
|
||||
// for (int dx = 0; dx < div.width(); ++dx) {
|
||||
let mut sum = (N * N) as u8 / 2;
|
||||
for ty in 0..N {
|
||||
// for (int ty = 0; ty < N; ++ty){
|
||||
for tx in 0..N {
|
||||
// for (int tx = 0; tx < N; ++tx) {
|
||||
sum += siv.get_luma8_point(dx * N + tx, dy * N + ty);
|
||||
}
|
||||
}
|
||||
*d = sum / (N * N) as u8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.layers.push(
|
||||
self.buffers
|
||||
.last()
|
||||
.ok_or(Exceptions::ILLEGAL_ARGUMENT)?
|
||||
.clone(),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_layer_with_factor(&mut self, factor: usize) -> Result<()> {
|
||||
// help the compiler's auto-vectorizer by hard-coding the scale factor
|
||||
match factor {
|
||||
2 => self.add_layer::<2>(),
|
||||
3 => self.add_layer::<3>(),
|
||||
4 => self.add_layer::<4>(),
|
||||
_ => Err(Exceptions::illegal_argument_with(
|
||||
"Invalid ReaderOptions::downscaleFactor",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const SET_V: u32 = 0xff; // allows playing with SIMD binarization
|
||||
|
||||
impl<B: Binarizer> BinaryBitmap<B> {
|
||||
pub fn close(&mut self) -> Result<()> {
|
||||
if let Some(mut matrix) = self.matrix.as_mut() {
|
||||
// if (_cache->matrix) {
|
||||
// auto& matrix = *const_cast<BitMatrix*>(_cache->matrix.get());
|
||||
let mut tmp = BitMatrix::new(matrix.width(), matrix.height())?;
|
||||
|
||||
// dilate
|
||||
SumFilter(matrix, &mut tmp, |sum| {
|
||||
return u32::from(sum > 0 * SET_V) * SET_V;
|
||||
});
|
||||
// erode
|
||||
SumFilter(&tmp, &mut matrix, |sum| {
|
||||
return u32::from(sum == 9 * SET_V) * SET_V;
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
// _closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
fn SumFilter<F>(input: &BitMatrix, output: &mut BitMatrix, func: F)
|
||||
where
|
||||
F: Fn(u32) -> u32,
|
||||
{
|
||||
for row in 1..output.height() {
|
||||
for col in 0..output.width() - 1 {
|
||||
let in0 = input.getRow(row); //.row(0).begin();
|
||||
let in1 = input.getRow(row + 1); //.row(1).begin();
|
||||
let in2 = input.getRow(row + 2); //.row(2).begin();
|
||||
|
||||
let mut sum = 0;
|
||||
for j in 0..3 {
|
||||
// for (int j = 0; j < 3; ++j){
|
||||
sum += in0.get(j) as u32 + in1.get(j) as u32 + in2.get(j) as u32;
|
||||
}
|
||||
|
||||
output.set_bool(row, col, func(sum) != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,6 +104,9 @@ pub mod helpers;
|
||||
mod luma_luma_source;
|
||||
pub use luma_luma_source::*;
|
||||
|
||||
mod filtered_image_reader;
|
||||
pub use filtered_image_reader::*;
|
||||
|
||||
#[cfg(feature = "svg_read")]
|
||||
mod svg_luminance_source;
|
||||
#[cfg(feature = "svg_read")]
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::common::Result;
|
||||
use crate::LuminanceSource;
|
||||
|
||||
/// A simple luma8 source for bytes, supports cropping but not rotation
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Luma8LuminanceSource {
|
||||
/// image dimension in form (x,y)
|
||||
dimensions: (u32, u32),
|
||||
@@ -27,6 +28,19 @@ impl LuminanceSource for Luma8LuminanceSource {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn get_column(&self, x: usize) -> Vec<u8> {
|
||||
self.data
|
||||
.chunks_exact(self.original_dimension.0 as usize)
|
||||
.skip(self.origin.1 as usize)
|
||||
.fold(Vec::default(), |mut acc, e| {
|
||||
acc.push(e[self.origin.0 as usize + x as usize]);
|
||||
acc
|
||||
})
|
||||
.iter()
|
||||
.map(|byte| Self::invert_if_should(*byte, self.inverted))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn get_matrix(&self) -> Vec<u8> {
|
||||
self.data
|
||||
.iter()
|
||||
@@ -93,6 +107,10 @@ impl LuminanceSource for Luma8LuminanceSource {
|
||||
"This luminance source does not support rotation by 45 degrees.",
|
||||
))
|
||||
}
|
||||
|
||||
fn get_luma8_point(&self, x: usize, y: usize) -> u8 {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Luma8LuminanceSource {
|
||||
@@ -159,6 +177,20 @@ impl Luma8LuminanceSource {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_empty_image(width: usize, height: usize) -> Self {
|
||||
Self {
|
||||
dimensions: (width as u32, height as u32),
|
||||
origin: (0, 0),
|
||||
data: vec![0u8; width * height],
|
||||
inverted: false,
|
||||
original_dimension: (width as u32, height as u32),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_matrix_mut(&mut self) -> &mut Vec<u8> {
|
||||
&mut self.data
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn invert_if_should(byte: u8, invert: bool) -> u8 {
|
||||
if invert {
|
||||
|
||||
@@ -48,6 +48,9 @@ pub trait LuminanceSource {
|
||||
*/
|
||||
fn get_row(&self, y: usize) -> Vec<u8>;
|
||||
|
||||
/// Get a column of of the image
|
||||
fn get_column(&self, x: usize) -> Vec<u8>;
|
||||
|
||||
/**
|
||||
* Fetches luminance data for the underlying bitmap. Values should be fetched using:
|
||||
* {@code int luminance = array[y * width + x] & 0xff}
|
||||
@@ -149,6 +152,8 @@ pub trait LuminanceSource {
|
||||
iv
|
||||
}
|
||||
|
||||
fn get_luma8_point(&self, x: usize, y: usize) -> u8;
|
||||
|
||||
/*
|
||||
@Override
|
||||
public final String toString() {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use crate::common::Result;
|
||||
use crate::oned::cpp::ODReader;
|
||||
use crate::qrcode::cpp_port::QrReader;
|
||||
use crate::{
|
||||
aztec::AztecReader, datamatrix::DataMatrixReader, maxicode::MaxiCodeReader,
|
||||
@@ -194,6 +195,9 @@ impl MultiFormatReader {
|
||||
BarcodeFormat::MAXICODE => {
|
||||
MaxiCodeReader::default().decode_with_hints(image, &self.hints)
|
||||
}
|
||||
BarcodeFormat::DXFilmEdge => {
|
||||
ODReader::new(&self.hints).decode_with_hints(image, &self.hints)
|
||||
}
|
||||
_ => Err(Exceptions::UNSUPPORTED_OPERATION),
|
||||
};
|
||||
if res.is_ok() {
|
||||
@@ -230,6 +234,9 @@ impl MultiFormatReader {
|
||||
if let Ok(res) = MaxiCodeReader::default().decode_with_hints(image, &self.hints) {
|
||||
return Ok(res);
|
||||
}
|
||||
if let Ok(res) = ODReader::new(&self.hints).decode_with_hints(image, &self.hints) {
|
||||
return Ok(res);
|
||||
}
|
||||
|
||||
if self.try_harder {
|
||||
if let Ok(res) = self.one_d_reader.decode_with_hints(image, &self.hints) {
|
||||
|
||||
@@ -71,7 +71,7 @@ fn DistIsBelowThreshold(a: PointI, b: PointI, threshold: PointI) -> bool {
|
||||
}
|
||||
|
||||
// DX Film Edge clock track found on 35mm films.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub(super) struct Clock {
|
||||
hasFrameNr: bool, // = false; // Clock track (thus data track) with frame number (longer version)
|
||||
rowNumber: u32, // = 0,
|
||||
|
||||
@@ -17,7 +17,7 @@ use crate::{Binarizer, DecodeHintType, DecodeHintValue};
|
||||
use crate::common::{LineOrientation, Quadrilateral, Result};
|
||||
|
||||
use super::dxfilm_edge_reader::DXFilmEdgeReader;
|
||||
use super::row_reader::RowReader;
|
||||
use super::row_reader::{DecodingState, RowReader};
|
||||
|
||||
pub struct ODReader<'a> {
|
||||
reader: DXFilmEdgeReader<'a>, // THIS IS WRONG, SEE BELOW ONLY DOES ONE
|
||||
@@ -47,11 +47,11 @@ impl<'a> ODReader<'_> {
|
||||
isPure: bool,
|
||||
maxSymbols: u32,
|
||||
minLineCount: u32,
|
||||
returnErrors: bool,
|
||||
_returnErrors: bool,
|
||||
) -> Vec<RXingResult> {
|
||||
let mut res: Vec<Option<RXingResult>> = Vec::new();
|
||||
|
||||
let mut decodingState: Vec<&mut Option<super::row_reader::DecodingState>> = Vec::new();
|
||||
let mut decodingState: Vec<Option<DecodingState>> = vec![Some(DecodingState::default()); 1];
|
||||
// std::vector<std::unique_ptr<RowReader::DecodingState>> decodingState(readers.size());
|
||||
|
||||
let mut minLineCount = minLineCount;
|
||||
@@ -120,6 +120,7 @@ impl<'a> ODReader<'_> {
|
||||
checkRows.pop();
|
||||
isCheckRow = true;
|
||||
if (rowNumber < 0 || rowNumber >= height) {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -134,6 +135,7 @@ impl<'a> ODReader<'_> {
|
||||
) {
|
||||
r.as_ref().into()
|
||||
} else {
|
||||
i += 1;
|
||||
continue;
|
||||
};
|
||||
// let img = if rotate {let a = image.rotate_counter_clockwise(); &a} else {image};
|
||||
@@ -182,7 +184,7 @@ impl<'a> ODReader<'_> {
|
||||
let mut next = PatternView::new(&bars);
|
||||
loop {
|
||||
let mut result_hld = readers[r]
|
||||
.decodePattern(rowNumber as u32, &mut next, decodingState[r])
|
||||
.decodePattern(rowNumber as u32, &mut next, &mut decodingState[r])
|
||||
.ok();
|
||||
if result_hld.is_some()
|
||||
/*|| (returnErrors && result.is_none())*/
|
||||
@@ -277,6 +279,7 @@ impl<'a> ODReader<'_> {
|
||||
// make sure we make progress and we start the next try on a bar
|
||||
next.shift(2 - (next.index() % 2));
|
||||
next.extend();
|
||||
|
||||
if !(tryHarder && next.size() > 0) {
|
||||
break;
|
||||
}
|
||||
@@ -371,29 +374,7 @@ impl<'a> ODReader<'_> {
|
||||
_hints: &DecodingHintDictionary,
|
||||
image: &BinaryBitmap<B>,
|
||||
) -> Result<RXingResult> {
|
||||
let mut result = Self::DoDecode(
|
||||
&self.reader,
|
||||
image,
|
||||
self.try_harder,
|
||||
false,
|
||||
self.is_pure,
|
||||
1,
|
||||
self.min_line_count,
|
||||
self.return_errors,
|
||||
);
|
||||
|
||||
if (result.is_empty() && self.try_rotate) {
|
||||
result = Self::DoDecode(
|
||||
&self.reader,
|
||||
image,
|
||||
self.try_harder,
|
||||
true,
|
||||
self.is_pure,
|
||||
1,
|
||||
self.min_line_count,
|
||||
self.return_errors,
|
||||
);
|
||||
}
|
||||
let result = self.decode_with_max_symbols(_hints, image, u32::MAX)?;
|
||||
|
||||
result.first().cloned().ok_or(Exceptions::NOT_FOUND)
|
||||
// return FirstOrDefault(std::move(result));
|
||||
|
||||
@@ -41,7 +41,7 @@ type Alphabet = Vec<char>;
|
||||
// // virtual ~DecodingState() = default;
|
||||
// }
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct DecodingState {
|
||||
// DXO
|
||||
pub centerRow: u32,
|
||||
|
||||
@@ -256,6 +256,10 @@ impl LuminanceSource for PlanarYUVLuminanceSource {
|
||||
row
|
||||
}
|
||||
|
||||
fn get_column(&self, x: usize) -> Vec<u8> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_matrix(&self) -> Vec<u8> {
|
||||
let width = self.get_width();
|
||||
let height = self.get_height();
|
||||
@@ -332,4 +336,8 @@ impl LuminanceSource for PlanarYUVLuminanceSource {
|
||||
fn invert(&mut self) {
|
||||
self.invert = !self.invert;
|
||||
}
|
||||
|
||||
fn get_luma8_point(&self, x: usize, y: usize) -> u8 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,10 @@ impl LuminanceSource for RGBLuminanceSource {
|
||||
row
|
||||
}
|
||||
|
||||
fn get_column(&self, x: usize) -> Vec<u8> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_matrix(&self) -> Vec<u8> {
|
||||
let width = self.get_width();
|
||||
let height = self.get_height();
|
||||
@@ -127,6 +131,14 @@ impl LuminanceSource for RGBLuminanceSource {
|
||||
fn invert(&mut self) {
|
||||
self.invert = !self.invert;
|
||||
}
|
||||
|
||||
fn get_luma8_point(&self, x: usize, y: usize) -> u8 {
|
||||
let width = self.get_width();
|
||||
let row_offset = (y + self.top) * self.dataWidth + self.left;
|
||||
let col_offset = (x + self.left);
|
||||
|
||||
self.luminances[row_offset + col_offset]
|
||||
}
|
||||
}
|
||||
|
||||
impl RGBLuminanceSource {
|
||||
|
||||
@@ -11,6 +11,10 @@ impl LuminanceSource for SVGLuminanceSource {
|
||||
self.0.get_row(y)
|
||||
}
|
||||
|
||||
fn get_column(&self, x: usize) -> Vec<u8> {
|
||||
self.0.get_column(x)
|
||||
}
|
||||
|
||||
fn get_matrix(&self) -> Vec<u8> {
|
||||
self.0.get_matrix()
|
||||
}
|
||||
@@ -46,6 +50,10 @@ impl LuminanceSource for SVGLuminanceSource {
|
||||
fn rotate_counter_clockwise_45(&self) -> Result<Self> {
|
||||
self.0.rotate_counter_clockwise_45().map(Self)
|
||||
}
|
||||
|
||||
fn get_luma8_point(&self, x: usize, y: usize) -> u8 {
|
||||
self.0.get_luma8_point(x, y)
|
||||
}
|
||||
}
|
||||
|
||||
impl SVGLuminanceSource {
|
||||
|
||||
BIN
test_resources/blackbox/dxfilmedge-1/1.jpg
Normal file
BIN
test_resources/blackbox/dxfilmedge-1/1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
1
test_resources/blackbox/dxfilmedge-1/1.txt
Normal file
1
test_resources/blackbox/dxfilmedge-1/1.txt
Normal file
@@ -0,0 +1 @@
|
||||
36-2/21
|
||||
BIN
test_resources/blackbox/dxfilmedge-1/2.png
Normal file
BIN
test_resources/blackbox/dxfilmedge-1/2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
1
test_resources/blackbox/dxfilmedge-1/2.txt
Normal file
1
test_resources/blackbox/dxfilmedge-1/2.txt
Normal file
@@ -0,0 +1 @@
|
||||
80-11/23
|
||||
BIN
test_resources/blackbox/dxfilmedge-1/3.jpg
Normal file
BIN
test_resources/blackbox/dxfilmedge-1/3.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
1
test_resources/blackbox/dxfilmedge-1/3.txt
Normal file
1
test_resources/blackbox/dxfilmedge-1/3.txt
Normal file
@@ -0,0 +1 @@
|
||||
10-3
|
||||
27
tests/dx_film_edge.rs
Normal file
27
tests/dx_film_edge.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
// dxfilmedge-1
|
||||
|
||||
#![cfg(feature = "image")]
|
||||
|
||||
use rxing::{BarcodeFormat, MultiFormatReader};
|
||||
|
||||
mod common;
|
||||
|
||||
/**
|
||||
* @author Sean Owen
|
||||
*/
|
||||
#[cfg(feature = "image-formats")]
|
||||
#[test]
|
||||
fn dx_film_edge() {
|
||||
let mut tester = common::AbstractBlackBoxTestCase::new(
|
||||
"test_resources/blackbox/dxfilmedge-1",
|
||||
MultiFormatReader::default(),
|
||||
BarcodeFormat::DXFilmEdge,
|
||||
);
|
||||
|
||||
tester.add_test(1, 2, 0.0);
|
||||
tester.add_test(1, 2, 90.0);
|
||||
tester.add_test(1, 2, 180.0);
|
||||
tester.add_test(1, 2, 320.0);
|
||||
|
||||
tester.test_black_box()
|
||||
}
|
||||
Reference in New Issue
Block a user