mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-28 05:12:34 +00:00
auto-format common module
This commit is contained in:
1001
src/common.rs
1001
src/common.rs
File diff suppressed because it is too large
Load Diff
@@ -1,17 +1,15 @@
|
|||||||
use crate::{NotFoundException,ResultPoint};
|
use crate::common::{BitMatrix, BitMatrix};
|
||||||
use crate::common::{BitMatrix,BitMatrix};
|
use crate::{NotFoundException, ResultPoint};
|
||||||
|
|
||||||
// MathUtils.java
|
// MathUtils.java
|
||||||
/**
|
/**
|
||||||
* General math-related and numeric utility functions.
|
* General math-related and numeric utility functions.
|
||||||
*/
|
*/
|
||||||
pub struct MathUtils {
|
pub struct MathUtils {}
|
||||||
}
|
|
||||||
|
|
||||||
impl MathUtils {
|
impl MathUtils {
|
||||||
|
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self{}
|
Self {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,8 +21,8 @@ impl MathUtils {
|
|||||||
* @param d real value to round
|
* @param d real value to round
|
||||||
* @return nearest {@code int}
|
* @return nearest {@code int}
|
||||||
*/
|
*/
|
||||||
pub fn round( d: f32) -> i32 {
|
pub fn round(d: f32) -> i32 {
|
||||||
return (d + ( if d < 0.0f32 { -0.5f32 } else { 0.5f32 })) as i32;
|
return (d + (if d < 0.0f32 { -0.5f32 } else { 0.5f32 })) as i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,7 +32,7 @@ impl MathUtils {
|
|||||||
* @param bY point B y coordinate
|
* @param bY point B y coordinate
|
||||||
* @return Euclidean distance between points A and B
|
* @return Euclidean distance between points A and B
|
||||||
*/
|
*/
|
||||||
pub fn distance( a_x: f32, a_y: f32, b_x: f32, b_y: f32) -> f32 {
|
pub fn distance(a_x: f32, a_y: f32, b_x: f32, b_y: f32) -> f32 {
|
||||||
let x_diff: f64 = a_x - b_x;
|
let x_diff: f64 = a_x - b_x;
|
||||||
let y_diff: f64 = a_y - b_y;
|
let y_diff: f64 = a_y - b_y;
|
||||||
return Math::sqrt(x_diff * x_diff + y_diff * y_diff) as f32;
|
return Math::sqrt(x_diff * x_diff + y_diff * y_diff) as f32;
|
||||||
@@ -47,7 +45,7 @@ impl MathUtils {
|
|||||||
* @param bY point B y coordinate
|
* @param bY point B y coordinate
|
||||||
* @return Euclidean distance between points A and B
|
* @return Euclidean distance between points A and B
|
||||||
*/
|
*/
|
||||||
pub fn distance( a_x: i32, a_y: i32, b_x: i32, b_y: i32) -> f32 {
|
pub fn distance(a_x: i32, a_y: i32, b_x: i32, b_y: i32) -> f32 {
|
||||||
let x_diff: f64 = a_x - b_x;
|
let x_diff: f64 = a_x - b_x;
|
||||||
let y_diff: f64 = a_y - b_y;
|
let y_diff: f64 = a_y - b_y;
|
||||||
return Math::sqrt(x_diff * x_diff + y_diff * y_diff) as f32;
|
return Math::sqrt(x_diff * x_diff + y_diff * y_diff) as f32;
|
||||||
@@ -57,7 +55,7 @@ impl MathUtils {
|
|||||||
* @param array values to sum
|
* @param array values to sum
|
||||||
* @return sum of values in array
|
* @return sum of values in array
|
||||||
*/
|
*/
|
||||||
pub fn sum( array: &Vec<i32>) -> i32 {
|
pub fn sum(array: &Vec<i32>) -> i32 {
|
||||||
let mut count: i32 = 0;
|
let mut count: i32 = 0;
|
||||||
for a in array {
|
for a in array {
|
||||||
count += a;
|
count += a;
|
||||||
@@ -79,14 +77,12 @@ impl MathUtils {
|
|||||||
const MAX_MODULES: i32 = 32;
|
const MAX_MODULES: i32 = 32;
|
||||||
#[deprecated]
|
#[deprecated]
|
||||||
pub struct MonochromeRectangleDetector {
|
pub struct MonochromeRectangleDetector {
|
||||||
|
image: BitMatrix,
|
||||||
image: BitMatrix
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MonochromeRectangleDetector {
|
impl MonochromeRectangleDetector {
|
||||||
|
pub fn new(image: &BitMatrix) -> Self {
|
||||||
pub fn new( image: &BitMatrix) -> Self {
|
Self { image }
|
||||||
Self{ image }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,7 +95,7 @@ impl MonochromeRectangleDetector {
|
|||||||
* third, the rightmost
|
* third, the rightmost
|
||||||
* @throws NotFoundException if no Data Matrix Code can be found
|
* @throws NotFoundException if no Data Matrix Code can be found
|
||||||
*/
|
*/
|
||||||
pub fn detect(&self) -> /* throws NotFoundException */Result<Vec<ResultPoint>, Rc<Exception>> {
|
pub fn detect(&self) -> Result<Vec<ResultPoint>, Rc<Exception>> {
|
||||||
let height: i32 = self.image.get_height();
|
let height: i32 = self.image.get_height();
|
||||||
let width: i32 = self.image.get_width();
|
let width: i32 = self.image.get_width();
|
||||||
let half_height: i32 = height / 2;
|
let half_height: i32 = height / 2;
|
||||||
@@ -110,17 +106,67 @@ impl MonochromeRectangleDetector {
|
|||||||
let mut bottom: i32 = height;
|
let mut bottom: i32 = height;
|
||||||
let mut left: i32 = 0;
|
let mut left: i32 = 0;
|
||||||
let mut right: i32 = width;
|
let mut right: i32 = width;
|
||||||
let point_a: ResultPoint = self.find_corner_from_center(half_width, 0, left, right, half_height, -delta_y, top, bottom, half_width / 2);
|
let point_a: ResultPoint = self.find_corner_from_center(
|
||||||
|
half_width,
|
||||||
|
0,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
half_height,
|
||||||
|
-delta_y,
|
||||||
|
top,
|
||||||
|
bottom,
|
||||||
|
half_width / 2,
|
||||||
|
);
|
||||||
top = point_a.get_y() as i32 - 1;
|
top = point_a.get_y() as i32 - 1;
|
||||||
let point_b: ResultPoint = self.find_corner_from_center(half_width, -delta_x, left, right, half_height, 0, top, bottom, half_height / 2);
|
let point_b: ResultPoint = self.find_corner_from_center(
|
||||||
|
half_width,
|
||||||
|
-delta_x,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
half_height,
|
||||||
|
0,
|
||||||
|
top,
|
||||||
|
bottom,
|
||||||
|
half_height / 2,
|
||||||
|
);
|
||||||
left = point_b.get_x() as i32 - 1;
|
left = point_b.get_x() as i32 - 1;
|
||||||
let point_c: ResultPoint = self.find_corner_from_center(half_width, delta_x, left, right, half_height, 0, top, bottom, half_height / 2);
|
let point_c: ResultPoint = self.find_corner_from_center(
|
||||||
|
half_width,
|
||||||
|
delta_x,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
half_height,
|
||||||
|
0,
|
||||||
|
top,
|
||||||
|
bottom,
|
||||||
|
half_height / 2,
|
||||||
|
);
|
||||||
right = point_c.get_x() as i32 + 1;
|
right = point_c.get_x() as i32 + 1;
|
||||||
let point_d: ResultPoint = self.find_corner_from_center(half_width, 0, left, right, half_height, delta_y, top, bottom, half_width / 2);
|
let point_d: ResultPoint = self.find_corner_from_center(
|
||||||
|
half_width,
|
||||||
|
0,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
half_height,
|
||||||
|
delta_y,
|
||||||
|
top,
|
||||||
|
bottom,
|
||||||
|
half_width / 2,
|
||||||
|
);
|
||||||
bottom = point_d.get_y() as i32 + 1;
|
bottom = point_d.get_y() as i32 + 1;
|
||||||
// Go try to find point A again with better information -- might have been off at first.
|
// Go try to find point A again with better information -- might have been off at first.
|
||||||
point_a = self.find_corner_from_center(half_width, 0, left, right, half_height, -delta_y, top, bottom, half_width / 4);
|
point_a = self.find_corner_from_center(
|
||||||
return Ok( vec![point_a, point_b, point_c, point_d, ]);
|
half_width,
|
||||||
|
0,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
half_height,
|
||||||
|
-delta_y,
|
||||||
|
top,
|
||||||
|
bottom,
|
||||||
|
half_width / 4,
|
||||||
|
);
|
||||||
|
return Ok(vec![point_a, point_b, point_c, point_d]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -141,7 +187,18 @@ impl MonochromeRectangleDetector {
|
|||||||
* @return a {@link ResultPoint} encapsulating the corner that was found
|
* @return a {@link ResultPoint} encapsulating the corner that was found
|
||||||
* @throws NotFoundException if such a point cannot be found
|
* @throws NotFoundException if such a point cannot be found
|
||||||
*/
|
*/
|
||||||
fn find_corner_from_center(&self, center_x: i32, delta_x: i32, left: i32, right: i32, center_y: i32, delta_y: i32, top: i32, bottom: i32, max_white_run: i32) -> Result<ResultPoint, NotFoundException> {
|
fn find_corner_from_center(
|
||||||
|
&self,
|
||||||
|
center_x: i32,
|
||||||
|
delta_x: i32,
|
||||||
|
left: i32,
|
||||||
|
right: i32,
|
||||||
|
center_y: i32,
|
||||||
|
delta_y: i32,
|
||||||
|
top: i32,
|
||||||
|
bottom: i32,
|
||||||
|
max_white_run: i32,
|
||||||
|
) -> Result<ResultPoint, NotFoundException> {
|
||||||
let last_range: Vec<i32> = null;
|
let last_range: Vec<i32> = null;
|
||||||
{
|
{
|
||||||
let mut y: i32 = center_y;
|
let mut y: i32 = center_y;
|
||||||
@@ -158,7 +215,7 @@ impl MonochromeRectangleDetector {
|
|||||||
}
|
}
|
||||||
if range == null {
|
if range == null {
|
||||||
if last_range == null {
|
if last_range == null {
|
||||||
return Err( NotFoundException::get_not_found_instance());
|
return Err(NotFoundException::get_not_found_instance());
|
||||||
}
|
}
|
||||||
// lastRange was found
|
// lastRange was found
|
||||||
if delta_x == 0 {
|
if delta_x == 0 {
|
||||||
@@ -166,7 +223,10 @@ impl MonochromeRectangleDetector {
|
|||||||
if last_range[0] < center_x {
|
if last_range[0] < center_x {
|
||||||
if last_range[1] > center_x {
|
if last_range[1] > center_x {
|
||||||
// straddle, choose one or the other based on direction
|
// straddle, choose one or the other based on direction
|
||||||
return Ok(ResultPoint::new(last_range[ if delta_y > 0 { 0 } else { 1 }], last_y));
|
return Ok(ResultPoint::new(
|
||||||
|
last_range[if delta_y > 0 { 0 } else { 1 }],
|
||||||
|
last_y,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
return Ok(ResultPoint::new(last_range[0], last_y));
|
return Ok(ResultPoint::new(last_range[0], last_y));
|
||||||
} else {
|
} else {
|
||||||
@@ -176,7 +236,10 @@ impl MonochromeRectangleDetector {
|
|||||||
let last_x: i32 = x - delta_x;
|
let last_x: i32 = x - delta_x;
|
||||||
if last_range[0] < center_y {
|
if last_range[0] < center_y {
|
||||||
if last_range[1] > center_y {
|
if last_range[1] > center_y {
|
||||||
return Ok(ResultPoint::new(last_x, last_range[ if delta_x < 0 { 0 } else { 1 }]));
|
return Ok(ResultPoint::new(
|
||||||
|
last_x,
|
||||||
|
last_range[if delta_x < 0 { 0 } else { 1 }],
|
||||||
|
));
|
||||||
}
|
}
|
||||||
return Ok(ResultPoint::new(last_x, last_range[0]));
|
return Ok(ResultPoint::new(last_x, last_range[0]));
|
||||||
} else {
|
} else {
|
||||||
@@ -191,7 +254,7 @@ impl MonochromeRectangleDetector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Err( NotFoundException::get_not_found_instance());
|
return Err(NotFoundException::get_not_found_instance());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -208,20 +271,40 @@ impl MonochromeRectangleDetector {
|
|||||||
* @return int[] with start and end of found range, or null if no such range is found
|
* @return int[] with start and end of found range, or null if no such range is found
|
||||||
* (e.g. only white was found)
|
* (e.g. only white was found)
|
||||||
*/
|
*/
|
||||||
fn black_white_range(&self, fixed_dimension: i32, max_white_run: i32, min_dim: i32, max_dim: i32, horizontal: bool) -> Option<Vec<i32>> {
|
fn black_white_range(
|
||||||
|
&self,
|
||||||
|
fixed_dimension: i32,
|
||||||
|
max_white_run: i32,
|
||||||
|
min_dim: i32,
|
||||||
|
max_dim: i32,
|
||||||
|
horizontal: bool,
|
||||||
|
) -> Option<Vec<i32>> {
|
||||||
let center: i32 = (min_dim + max_dim) / 2;
|
let center: i32 = (min_dim + max_dim) / 2;
|
||||||
// Scan left/up first
|
// Scan left/up first
|
||||||
let mut start: i32 = center;
|
let mut start: i32 = center;
|
||||||
while start >= min_dim {
|
while start >= min_dim {
|
||||||
if if horizontal { self.image.get(start, fixed_dimension) } else { self.image.get(fixed_dimension, start) } {
|
if if horizontal {
|
||||||
|
self.image.get(start, fixed_dimension)
|
||||||
|
} else {
|
||||||
|
self.image.get(fixed_dimension, start)
|
||||||
|
} {
|
||||||
start -= 1;
|
start -= 1;
|
||||||
} else {
|
} else {
|
||||||
let white_run_start: i32 = start;
|
let white_run_start: i32 = start;
|
||||||
loop { {
|
loop {
|
||||||
|
{
|
||||||
start -= 1;
|
start -= 1;
|
||||||
}if !(start >= min_dim && !( if horizontal { self.image.get(start, fixed_dimension) } else { self.image.get(fixed_dimension, start) })) {
|
}
|
||||||
|
if !(start >= min_dim
|
||||||
|
&& !(if horizontal {
|
||||||
|
self.image.get(start, fixed_dimension)
|
||||||
|
} else {
|
||||||
|
self.image.get(fixed_dimension, start)
|
||||||
|
}))
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
} }
|
}
|
||||||
|
}
|
||||||
let white_run_size: i32 = white_run_start - start;
|
let white_run_size: i32 = white_run_start - start;
|
||||||
if start < min_dim || white_run_size > max_white_run {
|
if start < min_dim || white_run_size > max_white_run {
|
||||||
start = white_run_start;
|
start = white_run_start;
|
||||||
@@ -233,13 +316,28 @@ impl MonochromeRectangleDetector {
|
|||||||
// Then try right/down
|
// Then try right/down
|
||||||
let mut end: i32 = center;
|
let mut end: i32 = center;
|
||||||
while end < max_dim {
|
while end < max_dim {
|
||||||
if if horizontal { self.image.get(end, fixed_dimension) } else { self.image.get(fixed_dimension, end) } {
|
if if horizontal {
|
||||||
|
self.image.get(end, fixed_dimension)
|
||||||
|
} else {
|
||||||
|
self.image.get(fixed_dimension, end)
|
||||||
|
} {
|
||||||
end += 1;
|
end += 1;
|
||||||
} else {
|
} else {
|
||||||
let white_run_start: i32 = end;
|
let white_run_start: i32 = end;
|
||||||
loop { {
|
loop {
|
||||||
|
{
|
||||||
end += 1;
|
end += 1;
|
||||||
}if !(end < max_dim && !( if horizontal { self.image.get(end, fixed_dimension) } else { self.image.get(fixed_dimension, end) })) {break;}}
|
}
|
||||||
|
if !(end < max_dim
|
||||||
|
&& !(if horizontal {
|
||||||
|
self.image.get(end, fixed_dimension)
|
||||||
|
} else {
|
||||||
|
self.image.get(fixed_dimension, end)
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
let white_run_size: i32 = end - white_run_start;
|
let white_run_size: i32 = end - white_run_start;
|
||||||
if end >= max_dim || white_run_size > max_white_run {
|
if end >= max_dim || white_run_size > max_white_run {
|
||||||
end = white_run_start;
|
end = white_run_start;
|
||||||
@@ -248,8 +346,11 @@ impl MonochromeRectangleDetector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
end -= 1;
|
end -= 1;
|
||||||
return if end > start { Some(vec![start, end, ])
|
return if end > start {
|
||||||
} else { null };
|
Some(vec![start, end])
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,7 +370,6 @@ const INIT_SIZE: i32 = 10;
|
|||||||
|
|
||||||
const CORR: i32 = 1;
|
const CORR: i32 = 1;
|
||||||
pub struct WhiteRectangleDetector {
|
pub struct WhiteRectangleDetector {
|
||||||
|
|
||||||
image: BitMatrix,
|
image: BitMatrix,
|
||||||
|
|
||||||
height: i32,
|
height: i32,
|
||||||
@@ -282,13 +382,17 @@ pub struct WhiteRectangleDetector {
|
|||||||
|
|
||||||
down_init: i32,
|
down_init: i32,
|
||||||
|
|
||||||
up_init: i32
|
up_init: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WhiteRectangleDetector {
|
impl WhiteRectangleDetector {
|
||||||
|
pub fn new(image: &BitMatrix) -> Result<Self, NotFoundException> {
|
||||||
pub fn new( image: &BitMatrix) -> Result<Self, NotFoundException> {
|
this(
|
||||||
this(image, INIT_SIZE, image.get_width() / 2, image.get_height() / 2)
|
image,
|
||||||
|
INIT_SIZE,
|
||||||
|
image.get_width() / 2,
|
||||||
|
image.get_height() / 2,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -298,9 +402,14 @@ impl WhiteRectangleDetector {
|
|||||||
* @param y y position of search center
|
* @param y y position of search center
|
||||||
* @throws NotFoundException if image is too small to accommodate {@code initSize}
|
* @throws NotFoundException if image is too small to accommodate {@code initSize}
|
||||||
*/
|
*/
|
||||||
pub fn new( image: &BitMatrix, init_size: i32, x: i32, y: i32) -> Result<Self,NotFoundException> {
|
pub fn new(
|
||||||
let mut new_wrd : Self;
|
image: &BitMatrix,
|
||||||
new_wrd .image = image;
|
init_size: i32,
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
) -> Result<Self, NotFoundException> {
|
||||||
|
let mut new_wrd: Self;
|
||||||
|
new_wrd.image = image;
|
||||||
new_wrd.height = image.get_height();
|
new_wrd.height = image.get_height();
|
||||||
new_wrd.width = image.get_width();
|
new_wrd.width = image.get_width();
|
||||||
let halfsize: i32 = init_size / 2;
|
let halfsize: i32 = init_size / 2;
|
||||||
@@ -309,7 +418,7 @@ impl WhiteRectangleDetector {
|
|||||||
new_wrd.up_init = y - halfsize;
|
new_wrd.up_init = y - halfsize;
|
||||||
new_wrd.down_init = y + halfsize;
|
new_wrd.down_init = y + halfsize;
|
||||||
if up_init < 0 || left_init < 0 || down_init >= height || right_init >= width {
|
if up_init < 0 || left_init < 0 || down_init >= height || right_init >= width {
|
||||||
return Err( NotFoundException::get_not_found_instance());
|
return Err(NotFoundException::get_not_found_instance());
|
||||||
}
|
}
|
||||||
Ok(new_wrd)
|
Ok(new_wrd)
|
||||||
}
|
}
|
||||||
@@ -345,7 +454,9 @@ impl WhiteRectangleDetector {
|
|||||||
// . |
|
// . |
|
||||||
// .....
|
// .....
|
||||||
let right_border_not_white: bool = true;
|
let right_border_not_white: bool = true;
|
||||||
while (right_border_not_white || !at_least_one_black_point_found_on_right) && right < self.width {
|
while (right_border_not_white || !at_least_one_black_point_found_on_right)
|
||||||
|
&& right < self.width
|
||||||
|
{
|
||||||
right_border_not_white = self.contains_black_point(up, down, right, false);
|
right_border_not_white = self.contains_black_point(up, down, right, false);
|
||||||
if right_border_not_white {
|
if right_border_not_white {
|
||||||
right += 1;
|
right += 1;
|
||||||
@@ -363,7 +474,9 @@ impl WhiteRectangleDetector {
|
|||||||
// . .
|
// . .
|
||||||
// .___.
|
// .___.
|
||||||
let bottom_border_not_white: bool = true;
|
let bottom_border_not_white: bool = true;
|
||||||
while (bottom_border_not_white || !at_least_one_black_point_found_on_bottom) && down < self.height {
|
while (bottom_border_not_white || !at_least_one_black_point_found_on_bottom)
|
||||||
|
&& down < self.height
|
||||||
|
{
|
||||||
bottom_border_not_white = self.contains_black_point(left, right, down, true);
|
bottom_border_not_white = self.contains_black_point(left, right, down, true);
|
||||||
if bottom_border_not_white {
|
if bottom_border_not_white {
|
||||||
down += 1;
|
down += 1;
|
||||||
@@ -428,7 +541,7 @@ impl WhiteRectangleDetector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if z == null {
|
if z == null {
|
||||||
return Err( NotFoundException::get_not_found_instance());
|
return Err(NotFoundException::get_not_found_instance());
|
||||||
}
|
}
|
||||||
let mut t: ResultPoint = null;
|
let mut t: ResultPoint = null;
|
||||||
//go down right
|
//go down right
|
||||||
@@ -443,7 +556,7 @@ impl WhiteRectangleDetector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if t == null {
|
if t == null {
|
||||||
return Err( NotFoundException::get_not_found_instance());
|
return Err(NotFoundException::get_not_found_instance());
|
||||||
}
|
}
|
||||||
let mut x: ResultPoint = null;
|
let mut x: ResultPoint = null;
|
||||||
//go down left
|
//go down left
|
||||||
@@ -458,7 +571,7 @@ impl WhiteRectangleDetector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if x == null {
|
if x == null {
|
||||||
return Err( NotFoundException::get_not_found_instance());
|
return Err(NotFoundException::get_not_found_instance());
|
||||||
}
|
}
|
||||||
let mut y: ResultPoint = null;
|
let mut y: ResultPoint = null;
|
||||||
//go up left
|
//go up left
|
||||||
@@ -473,15 +586,21 @@ impl WhiteRectangleDetector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if y == null {
|
if y == null {
|
||||||
return Err( NotFoundException::get_not_found_instance());
|
return Err(NotFoundException::get_not_found_instance());
|
||||||
}
|
}
|
||||||
return Ok(self.center_edges(&y, &z, &x, &t));
|
return Ok(self.center_edges(&y, &z, &x, &t));
|
||||||
} else {
|
} else {
|
||||||
return Err( NotFoundException::get_not_found_instance());
|
return Err(NotFoundException::get_not_found_instance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_black_point_on_segment(&self, a_x: f32, a_y: f32, b_x: f32, b_y: f32) -> Option<ResultPoint> {
|
fn get_black_point_on_segment(
|
||||||
|
&self,
|
||||||
|
a_x: f32,
|
||||||
|
a_y: f32,
|
||||||
|
b_x: f32,
|
||||||
|
b_y: f32,
|
||||||
|
) -> Option<ResultPoint> {
|
||||||
let dist: i32 = MathUtils::round(&MathUtils::distance(a_x, a_y, b_x, b_y));
|
let dist: i32 = MathUtils::round(&MathUtils::distance(a_x, a_y, b_x, b_y));
|
||||||
let x_step: f32 = (b_x - a_x) / dist;
|
let x_step: f32 = (b_x - a_x) / dist;
|
||||||
let y_step: f32 = (b_y - a_y) / dist;
|
let y_step: f32 = (b_y - a_y) / dist;
|
||||||
@@ -515,7 +634,13 @@ impl WhiteRectangleDetector {
|
|||||||
* point and the last, the bottommost. The second point will be
|
* point and the last, the bottommost. The second point will be
|
||||||
* leftmost and the third, the rightmost
|
* leftmost and the third, the rightmost
|
||||||
*/
|
*/
|
||||||
fn center_edges(&self, y: &ResultPoint, z: &ResultPoint, x: &ResultPoint, t: &ResultPoint) -> Vec<ResultPoint> {
|
fn center_edges(
|
||||||
|
&self,
|
||||||
|
y: &ResultPoint,
|
||||||
|
z: &ResultPoint,
|
||||||
|
x: &ResultPoint,
|
||||||
|
t: &ResultPoint,
|
||||||
|
) -> Vec<ResultPoint> {
|
||||||
//
|
//
|
||||||
// t t
|
// t t
|
||||||
// z x
|
// z x
|
||||||
@@ -531,11 +656,19 @@ impl WhiteRectangleDetector {
|
|||||||
let ti: f32 = t.get_x();
|
let ti: f32 = t.get_x();
|
||||||
let tj: f32 = t.get_y();
|
let tj: f32 = t.get_y();
|
||||||
if yi < self.width / 2.0f32 {
|
if yi < self.width / 2.0f32 {
|
||||||
return vec![ResultPoint::new(ti - CORR, tj + CORR), ResultPoint::new(zi + CORR, zj + CORR), ResultPoint::new(xi - CORR, xj - CORR), ResultPoint::new(yi + CORR, yj - CORR), ]
|
return vec![
|
||||||
;
|
ResultPoint::new(ti - CORR, tj + CORR),
|
||||||
|
ResultPoint::new(zi + CORR, zj + CORR),
|
||||||
|
ResultPoint::new(xi - CORR, xj - CORR),
|
||||||
|
ResultPoint::new(yi + CORR, yj - CORR),
|
||||||
|
];
|
||||||
} else {
|
} else {
|
||||||
return vec![ResultPoint::new(ti + CORR, tj + CORR), ResultPoint::new(zi + CORR, zj - CORR), ResultPoint::new(xi - CORR, xj + CORR), ResultPoint::new(yi - CORR, yj - CORR), ]
|
return vec![
|
||||||
;
|
ResultPoint::new(ti + CORR, tj + CORR),
|
||||||
|
ResultPoint::new(zi + CORR, zj - CORR),
|
||||||
|
ResultPoint::new(xi - CORR, xj + CORR),
|
||||||
|
ResultPoint::new(yi - CORR, yj - CORR),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,7 +694,6 @@ impl WhiteRectangleDetector {
|
|||||||
x += 1;
|
x += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
{
|
{
|
||||||
let mut y: i32 = a;
|
let mut y: i32 = a;
|
||||||
@@ -574,9 +706,7 @@ impl WhiteRectangleDetector {
|
|||||||
y += 1;
|
y += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,14 +9,12 @@
|
|||||||
* @author Sean Owen
|
* @author Sean Owen
|
||||||
*/
|
*/
|
||||||
struct GenericGFPoly {
|
struct GenericGFPoly {
|
||||||
|
|
||||||
field: GenericGF,
|
field: GenericGF,
|
||||||
|
|
||||||
coefficients: Vec<i32>
|
coefficients: Vec<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenericGFPoly {
|
impl GenericGFPoly {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param field the {@link GenericGF} instance representing the field to use
|
* @param field the {@link GenericGF} instance representing the field to use
|
||||||
* to perform computations
|
* to perform computations
|
||||||
@@ -26,7 +24,7 @@ impl GenericGFPoly {
|
|||||||
* or if leading coefficient is 0 and this is not a
|
* or if leading coefficient is 0 and this is not a
|
||||||
* constant polynomial (that is, it is not the monomial "0")
|
* constant polynomial (that is, it is not the monomial "0")
|
||||||
*/
|
*/
|
||||||
fn new( field: &GenericGF, coefficients: &Vec<i32>) -> Result<Self,IllegalArgumentException> {
|
fn new(field: &GenericGF, coefficients: &Vec<i32>) -> Result<Self, IllegalArgumentException> {
|
||||||
let mut new_poly: GenericGFPoly;
|
let mut new_poly: GenericGFPoly;
|
||||||
if coefficients.len() == 0 {
|
if coefficients.len() == 0 {
|
||||||
return Err(IllegalArgumentException::new());
|
return Err(IllegalArgumentException::new());
|
||||||
@@ -40,7 +38,7 @@ impl GenericGFPoly {
|
|||||||
first_non_zero += 1;
|
first_non_zero += 1;
|
||||||
}
|
}
|
||||||
if first_non_zero == coefficients_length {
|
if first_non_zero == coefficients_length {
|
||||||
new_poly.coefficients = vec![0, ];
|
new_poly.coefficients = vec![0];
|
||||||
} else {
|
} else {
|
||||||
new_poly.coefficients = coefficients;
|
new_poly.coefficients = coefficients;
|
||||||
//System::arraycopy(&coefficients, first_non_zero, let .coefficients, 0, let .coefficients.len());
|
//System::arraycopy(&coefficients, first_non_zero, let .coefficients, 0, let .coefficients.len());
|
||||||
@@ -98,7 +96,10 @@ impl GenericGFPoly {
|
|||||||
let mut i: i32 = 1;
|
let mut i: i32 = 1;
|
||||||
while i < size {
|
while i < size {
|
||||||
{
|
{
|
||||||
result = GenericGF::add_or_subtract(&self.field.multiply(a, result), self.coefficients[i]);
|
result = GenericGF::add_or_subtract(
|
||||||
|
&self.field.multiply(a, result),
|
||||||
|
self.coefficients[i],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
@@ -107,9 +108,14 @@ impl GenericGFPoly {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_or_subtract(&self, other: &GenericGFPoly) -> Result<GenericGFPoly,IllegalArgumentException> {
|
fn add_or_subtract(
|
||||||
|
&self,
|
||||||
|
other: &GenericGFPoly,
|
||||||
|
) -> Result<GenericGFPoly, IllegalArgumentException> {
|
||||||
if !self.field.equals(other.field) {
|
if !self.field.equals(other.field) {
|
||||||
return Err( IllegalArgumentException::new("GenericGFPolys do not have same GenericGF field") );
|
return Err(IllegalArgumentException::new(
|
||||||
|
"GenericGFPolys do not have same GenericGF field",
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if self.is_zero() {
|
if self.is_zero() {
|
||||||
return other;
|
return other;
|
||||||
@@ -132,7 +138,10 @@ impl GenericGFPoly {
|
|||||||
let mut i: i32 = length_diff;
|
let mut i: i32 = length_diff;
|
||||||
while i < larger_coefficients.len() {
|
while i < larger_coefficients.len() {
|
||||||
{
|
{
|
||||||
sum_diff[i] = GenericGF::add_or_subtract(smaller_coefficients[i - length_diff], larger_coefficients[i]);
|
sum_diff[i] = GenericGF::add_or_subtract(
|
||||||
|
smaller_coefficients[i - length_diff],
|
||||||
|
larger_coefficients[i],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
@@ -141,9 +150,11 @@ impl GenericGFPoly {
|
|||||||
return GenericGFPoly::new(&self.field, &sum_diff);
|
return GenericGFPoly::new(&self.field, &sum_diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn multiply(&self, other: &GenericGFPoly) -> Result<GenericGFPoly,IllegalArgumentException> {
|
fn multiply(&self, other: &GenericGFPoly) -> Result<GenericGFPoly, IllegalArgumentException> {
|
||||||
if !self.field.equals(other.field) {
|
if !self.field.equals(other.field) {
|
||||||
return Err(IllegalArgumentException::new("GenericGFPolys do not have same GenericGF field"));
|
return Err(IllegalArgumentException::new(
|
||||||
|
"GenericGFPolys do not have same GenericGF field",
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if self.is_zero() || other.is_zero() {
|
if self.is_zero() || other.is_zero() {
|
||||||
return Ok(self.field.get_zero());
|
return Ok(self.field.get_zero());
|
||||||
@@ -162,12 +173,14 @@ impl GenericGFPoly {
|
|||||||
let mut j: i32 = 0;
|
let mut j: i32 = 0;
|
||||||
while j < b_length {
|
while j < b_length {
|
||||||
{
|
{
|
||||||
product[i + j] = GenericGF::add_or_subtract(product[i + j], &self.field.multiply(a_coeff, b_coefficients[j]));
|
product[i + j] = GenericGF::add_or_subtract(
|
||||||
|
product[i + j],
|
||||||
|
&self.field.multiply(a_coeff, b_coefficients[j]),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
j += 1;
|
j += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
@@ -198,9 +211,13 @@ impl GenericGFPoly {
|
|||||||
return GenericGFPoly::new(&self.field, &product);
|
return GenericGFPoly::new(&self.field, &product);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn multiply_by_monomial(&self, degree: i32, coefficient: i32) -> Result<GenericGFPoly,IllegalArgumentException> {
|
fn multiply_by_monomial(
|
||||||
|
&self,
|
||||||
|
degree: i32,
|
||||||
|
coefficient: i32,
|
||||||
|
) -> Result<GenericGFPoly, IllegalArgumentException> {
|
||||||
if degree < 0 {
|
if degree < 0 {
|
||||||
return Err( IllegalArgumentException::new());
|
return Err(IllegalArgumentException::new());
|
||||||
}
|
}
|
||||||
if coefficient == 0 {
|
if coefficient == 0 {
|
||||||
return Ok(self.field.get_zero());
|
return Ok(self.field.get_zero());
|
||||||
@@ -220,12 +237,17 @@ impl GenericGFPoly {
|
|||||||
return GenericGFPoly::new(&self.field, &product);
|
return GenericGFPoly::new(&self.field, &product);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn divide(&self, other: &GenericGFPoly) -> Result<Vec<GenericGFPoly>,IllegalArgumentException> {
|
fn divide(
|
||||||
|
&self,
|
||||||
|
other: &GenericGFPoly,
|
||||||
|
) -> Result<Vec<GenericGFPoly>, IllegalArgumentException> {
|
||||||
if !self.field.equals(other.field) {
|
if !self.field.equals(other.field) {
|
||||||
return Err( IllegalArgumentException::new("GenericGFPolys do not have same GenericGF field"));
|
return Err(IllegalArgumentException::new(
|
||||||
|
"GenericGFPolys do not have same GenericGF field",
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if other.is_zero() {
|
if other.is_zero() {
|
||||||
return Err( IllegalArgumentException::new("Divide by 0"));
|
return Err(IllegalArgumentException::new("Divide by 0"));
|
||||||
}
|
}
|
||||||
let mut quotient: GenericGFPoly = self.field.get_zero();
|
let mut quotient: GenericGFPoly = self.field.get_zero();
|
||||||
let mut remainder: GenericGFPoly = self;
|
let mut remainder: GenericGFPoly = self;
|
||||||
@@ -233,13 +255,17 @@ impl GenericGFPoly {
|
|||||||
let inverse_denominator_leading_term: i32 = self.field.inverse(denominator_leading_term);
|
let inverse_denominator_leading_term: i32 = self.field.inverse(denominator_leading_term);
|
||||||
while remainder.get_degree() >= other.get_degree() && !remainder.is_zero() {
|
while remainder.get_degree() >= other.get_degree() && !remainder.is_zero() {
|
||||||
let degree_difference: i32 = remainder.get_degree() - other.get_degree();
|
let degree_difference: i32 = remainder.get_degree() - other.get_degree();
|
||||||
let scale: i32 = self.field.multiply(&remainder.get_coefficient(&remainder.get_degree()), inverse_denominator_leading_term);
|
let scale: i32 = self.field.multiply(
|
||||||
|
&remainder.get_coefficient(&remainder.get_degree()),
|
||||||
|
inverse_denominator_leading_term,
|
||||||
|
);
|
||||||
let term: GenericGFPoly = other.multiply_by_monomial(degree_difference, scale);
|
let term: GenericGFPoly = other.multiply_by_monomial(degree_difference, scale);
|
||||||
let iteration_quotient: GenericGFPoly = self.field.build_monomial(degree_difference, scale);
|
let iteration_quotient: GenericGFPoly =
|
||||||
|
self.field.build_monomial(degree_difference, scale);
|
||||||
quotient = quotient.add_or_subtract(&iteration_quotient);
|
quotient = quotient.add_or_subtract(&iteration_quotient);
|
||||||
remainder = remainder.add_or_subtract(&term);
|
remainder = remainder.add_or_subtract(&term);
|
||||||
}
|
}
|
||||||
return Ok(vec![quotient, remainder, ]);
|
return Ok(vec![quotient, remainder]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_string(&self) -> String {
|
pub fn to_string(&self) -> String {
|
||||||
@@ -311,26 +337,25 @@ impl GenericGFPoly {
|
|||||||
const AZTEC_DATA_12: GenericGF = GenericGF::new(0x1069, 4096, 1);
|
const AZTEC_DATA_12: GenericGF = GenericGF::new(0x1069, 4096, 1);
|
||||||
|
|
||||||
// x^10 + x^3 + 1
|
// x^10 + x^3 + 1
|
||||||
const AZTEC_DATA_10: GenericGF = GenericGF::new(0x409, 1024, 1);
|
const AZTEC_DATA_10: GenericGF = GenericGF::new(0x409, 1024, 1);
|
||||||
|
|
||||||
// x^6 + x + 1
|
// x^6 + x + 1
|
||||||
const AZTEC_DATA_6: GenericGF = GenericGF::new(0x43, 64, 1);
|
const AZTEC_DATA_6: GenericGF = GenericGF::new(0x43, 64, 1);
|
||||||
|
|
||||||
// x^4 + x + 1
|
// x^4 + x + 1
|
||||||
const AZTEC_PARAM: GenericGF = GenericGF::new(0x13, 16, 1);
|
const AZTEC_PARAM: GenericGF = GenericGF::new(0x13, 16, 1);
|
||||||
|
|
||||||
// x^8 + x^4 + x^3 + x^2 + 1
|
// x^8 + x^4 + x^3 + x^2 + 1
|
||||||
const QR_CODE_FIELD_256: GenericGF = GenericGF::new(0x011D, 256, 0);
|
const QR_CODE_FIELD_256: GenericGF = GenericGF::new(0x011D, 256, 0);
|
||||||
|
|
||||||
// x^8 + x^5 + x^3 + x^2 + 1
|
// x^8 + x^5 + x^3 + x^2 + 1
|
||||||
const DATA_MATRIX_FIELD_256: GenericGF = GenericGF::new(0x012D, 256, 1);
|
const DATA_MATRIX_FIELD_256: GenericGF = GenericGF::new(0x012D, 256, 1);
|
||||||
|
|
||||||
const AZTEC_DATA_8: GenericGF = DATA_MATRIX_FIELD_256;
|
const AZTEC_DATA_8: GenericGF = DATA_MATRIX_FIELD_256;
|
||||||
|
|
||||||
const MAXICODE_FIELD_64: GenericGF = AZTEC_DATA_6;
|
const MAXICODE_FIELD_64: GenericGF = AZTEC_DATA_6;
|
||||||
|
|
||||||
pub struct GenericGF {
|
pub struct GenericGF {
|
||||||
|
|
||||||
exp_table: Vec<i32>,
|
exp_table: Vec<i32>,
|
||||||
|
|
||||||
log_table: Vec<i32>,
|
log_table: Vec<i32>,
|
||||||
@@ -343,11 +368,10 @@ pub struct GenericGF {
|
|||||||
|
|
||||||
primitive: i32,
|
primitive: i32,
|
||||||
|
|
||||||
generator_base: i32
|
generator_base: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenericGF {
|
impl GenericGF {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a representation of GF(size) using the given primitive polynomial.
|
* Create a representation of GF(size) using the given primitive polynomial.
|
||||||
*
|
*
|
||||||
@@ -359,11 +383,11 @@ impl GenericGF {
|
|||||||
* (g(x) = (x+a^b)(x+a^(b+1))...(x+a^(b+2t-1))).
|
* (g(x) = (x+a^b)(x+a^(b+1))...(x+a^(b+2t-1))).
|
||||||
* In most cases it should be 1, but for QR code it is 0.
|
* In most cases it should be 1, but for QR code it is 0.
|
||||||
*/
|
*/
|
||||||
pub fn new( primitive: i32, size: i32, b: i32) -> Self {
|
pub fn new(primitive: i32, size: i32, b: i32) -> Self {
|
||||||
let mut new_generic_gf : GenericGF;
|
let mut new_generic_gf: GenericGF;
|
||||||
new_generic_gf .primitive = primitive;
|
new_generic_gf.primitive = primitive;
|
||||||
new_generic_gf .size = size;
|
new_generic_gf.size = size;
|
||||||
new_generic_gf .generatorBase = b;
|
new_generic_gf.generatorBase = b;
|
||||||
exp_table = [0; size];
|
exp_table = [0; size];
|
||||||
log_table = [0; size];
|
log_table = [0; size];
|
||||||
let mut x: i32 = 1;
|
let mut x: i32 = 1;
|
||||||
@@ -394,8 +418,8 @@ impl GenericGF {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// logTable[0] == 0 but this should never be used
|
// logTable[0] == 0 but this should never be used
|
||||||
new_generic_gf.zero = GenericGFPoly::new( 0, &vec![0, ]);
|
new_generic_gf.zero = GenericGFPoly::new(0, &vec![0]);
|
||||||
new_generic_gf.one = GenericGFPoly::new( 0, &vec![1, ]);
|
new_generic_gf.one = GenericGFPoly::new(0, &vec![1]);
|
||||||
|
|
||||||
new_generic_gf
|
new_generic_gf
|
||||||
}
|
}
|
||||||
@@ -411,9 +435,13 @@ impl GenericGF {
|
|||||||
/**
|
/**
|
||||||
* @return the monomial representing coefficient * x^degree
|
* @return the monomial representing coefficient * x^degree
|
||||||
*/
|
*/
|
||||||
fn build_monomial(&self, degree: i32, coefficient: i32) -> Result<GenericGFPoly,IllegalArgumentException> {
|
fn build_monomial(
|
||||||
|
&self,
|
||||||
|
degree: i32,
|
||||||
|
coefficient: i32,
|
||||||
|
) -> Result<GenericGFPoly, IllegalArgumentException> {
|
||||||
if degree < 0 {
|
if degree < 0 {
|
||||||
return Err( IllegalArgumentException::new());
|
return Err(IllegalArgumentException::new());
|
||||||
}
|
}
|
||||||
if coefficient == 0 {
|
if coefficient == 0 {
|
||||||
return Ok(self.zero);
|
return Ok(self.zero);
|
||||||
@@ -428,7 +456,7 @@ impl GenericGF {
|
|||||||
*
|
*
|
||||||
* @return sum/difference of a and b
|
* @return sum/difference of a and b
|
||||||
*/
|
*/
|
||||||
fn add_or_subtract( a: i32, b: i32) -> i32 {
|
fn add_or_subtract(a: i32, b: i32) -> i32 {
|
||||||
return a ^ b;
|
return a ^ b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,9 +470,9 @@ impl GenericGF {
|
|||||||
/**
|
/**
|
||||||
* @return base 2 log of a in GF(size)
|
* @return base 2 log of a in GF(size)
|
||||||
*/
|
*/
|
||||||
fn log(&self, a: i32) -> Result<i32,IllegalArgumentException> {
|
fn log(&self, a: i32) -> Result<i32, IllegalArgumentException> {
|
||||||
if a == 0 {
|
if a == 0 {
|
||||||
return Err( IllegalArgumentException::new());
|
return Err(IllegalArgumentException::new());
|
||||||
}
|
}
|
||||||
return self.log_table[a];
|
return self.log_table[a];
|
||||||
}
|
}
|
||||||
@@ -452,9 +480,9 @@ impl GenericGF {
|
|||||||
/**
|
/**
|
||||||
* @return multiplicative inverse of a
|
* @return multiplicative inverse of a
|
||||||
*/
|
*/
|
||||||
fn inverse(&self, a: i32) -> Result<i32,ArithmeticException> {
|
fn inverse(&self, a: i32) -> Result<i32, ArithmeticException> {
|
||||||
if a == 0 {
|
if a == 0 {
|
||||||
return Err( ArithmeticException::new());
|
return Err(ArithmeticException::new());
|
||||||
}
|
}
|
||||||
return self.exp_table[self.size - self.log_table[a] - 1];
|
return self.exp_table[self.size - self.log_table[a] - 1];
|
||||||
}
|
}
|
||||||
@@ -478,7 +506,11 @@ impl GenericGF {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_string(&self) -> String {
|
pub fn to_string(&self) -> String {
|
||||||
return format!("GF(0x{},{})", Integer::to_hex_string(self.primitive), self.size);
|
return format!(
|
||||||
|
"GF(0x{},{})",
|
||||||
|
Integer::to_hex_string(self.primitive),
|
||||||
|
self.size
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -506,14 +538,12 @@ impl GenericGF {
|
|||||||
* @author sanfordsquires
|
* @author sanfordsquires
|
||||||
*/
|
*/
|
||||||
pub struct ReedSolomonDecoder {
|
pub struct ReedSolomonDecoder {
|
||||||
|
field: GenericGF,
|
||||||
field: GenericGF
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReedSolomonDecoder {
|
impl ReedSolomonDecoder {
|
||||||
|
pub fn new(field: &GenericGF) -> Self {
|
||||||
pub fn new( field: &GenericGF) -> Self {
|
Self { field }
|
||||||
Self{ field }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -533,7 +563,8 @@ impl ReedSolomonDecoder {
|
|||||||
let mut i: i32 = 0;
|
let mut i: i32 = 0;
|
||||||
while i < two_s {
|
while i < two_s {
|
||||||
{
|
{
|
||||||
let eval: i32 = poly.evaluate_at(&self.field.exp(i + self.field.get_generator_base()));
|
let eval: i32 =
|
||||||
|
poly.evaluate_at(&self.field.exp(i + self.field.get_generator_base()));
|
||||||
syndrome_coefficients[syndrome_coefficients.len() - 1 - i] = eval;
|
syndrome_coefficients[syndrome_coefficients.len() - 1 - i] = eval;
|
||||||
if eval != 0 {
|
if eval != 0 {
|
||||||
no_error = false;
|
no_error = false;
|
||||||
@@ -547,7 +578,8 @@ impl ReedSolomonDecoder {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let syndrome: GenericGFPoly = GenericGFPoly::new(&self.field, &syndrome_coefficients);
|
let syndrome: GenericGFPoly = GenericGFPoly::new(&self.field, &syndrome_coefficients);
|
||||||
let sigma_omega: Vec<GenericGFPoly> = self.run_euclidean_algorithm(&self.field.build_monomial(two_s, 1), &syndrome, two_s);
|
let sigma_omega: Vec<GenericGFPoly> =
|
||||||
|
self.run_euclidean_algorithm(&self.field.build_monomial(two_s, 1), &syndrome, two_s);
|
||||||
let sigma: GenericGFPoly = sigma_omega[0];
|
let sigma: GenericGFPoly = sigma_omega[0];
|
||||||
let omega: GenericGFPoly = sigma_omega[1];
|
let omega: GenericGFPoly = sigma_omega[1];
|
||||||
let error_locations: Vec<i32> = self.find_error_locations(&sigma);
|
let error_locations: Vec<i32> = self.find_error_locations(&sigma);
|
||||||
@@ -558,18 +590,23 @@ impl ReedSolomonDecoder {
|
|||||||
{
|
{
|
||||||
let mut position: i32 = received.len() - 1 - self.field.log(error_locations[i]);
|
let mut position: i32 = received.len() - 1 - self.field.log(error_locations[i]);
|
||||||
if position < 0 {
|
if position < 0 {
|
||||||
return Err( ReedSolomonException::new("Bad error location"));
|
return Err(ReedSolomonException::new("Bad error location"));
|
||||||
}
|
}
|
||||||
received[position] = GenericGF::add_or_subtract(received[position], error_magnitudes[i]);
|
received[position] =
|
||||||
|
GenericGF::add_or_subtract(received[position], error_magnitudes[i]);
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_euclidean_algorithm(&self, a: &GenericGFPoly, b: &GenericGFPoly, R: i32) -> Result<Vec<GenericGFPoly>, ReedSolomonException+IllegalStateException> {
|
fn run_euclidean_algorithm(
|
||||||
|
&self,
|
||||||
|
a: &GenericGFPoly,
|
||||||
|
b: &GenericGFPoly,
|
||||||
|
R: i32,
|
||||||
|
) -> Result<Vec<GenericGFPoly>, ReedSolomonException + IllegalStateException> {
|
||||||
// Assume a's degree is >= b's
|
// Assume a's degree is >= b's
|
||||||
if a.get_degree() < b.get_degree() {
|
if a.get_degree() < b.get_degree() {
|
||||||
let temp: GenericGFPoly = a;
|
let temp: GenericGFPoly = a;
|
||||||
@@ -589,7 +626,7 @@ impl ReedSolomonDecoder {
|
|||||||
// Divide rLastLast by rLast, with quotient in q and remainder in r
|
// Divide rLastLast by rLast, with quotient in q and remainder in r
|
||||||
if r_last.is_zero() {
|
if r_last.is_zero() {
|
||||||
// Oops, Euclidean algorithm already terminated?
|
// Oops, Euclidean algorithm already terminated?
|
||||||
return Err( ReedSolomonException::new("r_{i-1} was zero"));
|
return Err(ReedSolomonException::new("r_{i-1} was zero"));
|
||||||
}
|
}
|
||||||
r = r_last_last;
|
r = r_last_last;
|
||||||
let mut q: GenericGFPoly = self.field.get_zero();
|
let mut q: GenericGFPoly = self.field.get_zero();
|
||||||
@@ -597,31 +634,39 @@ impl ReedSolomonDecoder {
|
|||||||
let dlt_inverse: i32 = self.field.inverse(denominator_leading_term);
|
let dlt_inverse: i32 = self.field.inverse(denominator_leading_term);
|
||||||
while r.get_degree() >= r_last.get_degree() && !r.is_zero() {
|
while r.get_degree() >= r_last.get_degree() && !r.is_zero() {
|
||||||
let degree_diff: i32 = r.get_degree() - r_last.get_degree();
|
let degree_diff: i32 = r.get_degree() - r_last.get_degree();
|
||||||
let scale: i32 = self.field.multiply(&r.get_coefficient(&r.get_degree()), dlt_inverse);
|
let scale: i32 = self
|
||||||
|
.field
|
||||||
|
.multiply(&r.get_coefficient(&r.get_degree()), dlt_inverse);
|
||||||
q = q.add_or_subtract(&self.field.build_monomial(degree_diff, scale));
|
q = q.add_or_subtract(&self.field.build_monomial(degree_diff, scale));
|
||||||
r = r.add_or_subtract(&r_last.multiply_by_monomial(degree_diff, scale));
|
r = r.add_or_subtract(&r_last.multiply_by_monomial(degree_diff, scale));
|
||||||
}
|
}
|
||||||
t = q.multiply(&t_last).add_or_subtract(t_last_last);
|
t = q.multiply(&t_last).add_or_subtract(t_last_last);
|
||||||
if r.get_degree() >= r_last.get_degree() {
|
if r.get_degree() >= r_last.get_degree() {
|
||||||
return Err( IllegalStateException::new(format!("Division algorithm failed to reduce polynomial? r: {}, rLast: {}", r, r_last)));
|
return Err(IllegalStateException::new(format!(
|
||||||
|
"Division algorithm failed to reduce polynomial? r: {}, rLast: {}",
|
||||||
|
r, r_last
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let sigma_tilde_at_zero: i32 = t.get_coefficient(0);
|
let sigma_tilde_at_zero: i32 = t.get_coefficient(0);
|
||||||
if sigma_tilde_at_zero == 0 {
|
if sigma_tilde_at_zero == 0 {
|
||||||
return Err( ReedSolomonException::new("sigmaTilde(0) was zero"));
|
return Err(ReedSolomonException::new("sigmaTilde(0) was zero"));
|
||||||
}
|
}
|
||||||
let inverse: i32 = self.field.inverse(sigma_tilde_at_zero);
|
let inverse: i32 = self.field.inverse(sigma_tilde_at_zero);
|
||||||
let sigma: GenericGFPoly = t.multiply(inverse);
|
let sigma: GenericGFPoly = t.multiply(inverse);
|
||||||
let omega: GenericGFPoly = r.multiply(inverse);
|
let omega: GenericGFPoly = r.multiply(inverse);
|
||||||
return Ok( vec![sigma, omega, ]);
|
return Ok(vec![sigma, omega]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_error_locations(&self, error_locator: &GenericGFPoly) -> Result<Vec<i32>, ReedSolomonException> {
|
fn find_error_locations(
|
||||||
|
&self,
|
||||||
|
error_locator: &GenericGFPoly,
|
||||||
|
) -> Result<Vec<i32>, ReedSolomonException> {
|
||||||
// This is a direct application of Chien's search
|
// This is a direct application of Chien's search
|
||||||
let num_errors: i32 = error_locator.get_degree();
|
let num_errors: i32 = error_locator.get_degree();
|
||||||
if num_errors == 1 {
|
if num_errors == 1 {
|
||||||
// shortcut
|
// shortcut
|
||||||
return Ok( vec![error_locator.get_coefficient(1), ]);
|
return Ok(vec![error_locator.get_coefficient(1)]);
|
||||||
}
|
}
|
||||||
let mut result: [i32; num_errors] = [0; num_errors];
|
let mut result: [i32; num_errors] = [0; num_errors];
|
||||||
let mut e: i32 = 0;
|
let mut e: i32 = 0;
|
||||||
@@ -639,12 +684,18 @@ impl ReedSolomonDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if e != num_errors {
|
if e != num_errors {
|
||||||
return Err( ReedSolomonException::new("Error locator degree does not match number of roots"));
|
return Err(ReedSolomonException::new(
|
||||||
|
"Error locator degree does not match number of roots",
|
||||||
|
));
|
||||||
}
|
}
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_error_magnitudes(&self, error_evaluator: &GenericGFPoly, error_locations: &Vec<i32>) -> Vec<i32> {
|
fn find_error_magnitudes(
|
||||||
|
&self,
|
||||||
|
error_evaluator: &GenericGFPoly,
|
||||||
|
error_locations: &Vec<i32>,
|
||||||
|
) -> Vec<i32> {
|
||||||
// This is directly applying Forney's Formula
|
// This is directly applying Forney's Formula
|
||||||
let s: i32 = error_locations.len();
|
let s: i32 = error_locations.len();
|
||||||
let mut result: [i32; s] = [0; s];
|
let mut result: [i32; s] = [0; s];
|
||||||
@@ -663,8 +714,13 @@ impl ReedSolomonDecoder {
|
|||||||
// GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse)));
|
// GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse)));
|
||||||
// Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug.
|
// Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug.
|
||||||
// Below is a funny-looking workaround from Steven Parkes
|
// Below is a funny-looking workaround from Steven Parkes
|
||||||
let term: i32 = self.field.multiply(error_locations[j], xi_inverse);
|
let term: i32 =
|
||||||
let term_plus1: i32 = if (term & 0x1) == 0 { term | 1 } else { term & 1 };
|
self.field.multiply(error_locations[j], xi_inverse);
|
||||||
|
let term_plus1: i32 = if (term & 0x1) == 0 {
|
||||||
|
term | 1
|
||||||
|
} else {
|
||||||
|
term & 1
|
||||||
|
};
|
||||||
denominator = self.field.multiply(denominator, term_plus1);
|
denominator = self.field.multiply(denominator, term_plus1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -672,7 +728,10 @@ impl ReedSolomonDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result[i] = self.field.multiply(&error_evaluator.evaluate_at(xi_inverse), &self.field.inverse(denominator));
|
result[i] = self.field.multiply(
|
||||||
|
&error_evaluator.evaluate_at(xi_inverse),
|
||||||
|
&self.field.inverse(denominator),
|
||||||
|
);
|
||||||
if self.field.get_generator_base() != 0 {
|
if self.field.get_generator_base() != 0 {
|
||||||
result[i] = self.field.multiply(result[i], xi_inverse);
|
result[i] = self.field.multiply(result[i], xi_inverse);
|
||||||
}
|
}
|
||||||
@@ -693,48 +752,55 @@ impl ReedSolomonDecoder {
|
|||||||
* @author William Rucklidge
|
* @author William Rucklidge
|
||||||
*/
|
*/
|
||||||
pub struct ReedSolomonEncoder {
|
pub struct ReedSolomonEncoder {
|
||||||
|
|
||||||
field: GenericGF,
|
field: GenericGF,
|
||||||
|
|
||||||
cached_generators: Vector<GenericGFPoly>
|
cached_generators: Vector<GenericGFPoly>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReedSolomonEncoder {
|
impl ReedSolomonEncoder {
|
||||||
|
pub fn new(field: &GenericGF) -> Self {
|
||||||
pub fn new( field: &GenericGF) -> Self {
|
|
||||||
let mut new_rse;
|
let mut new_rse;
|
||||||
new_rse .field = field;
|
new_rse.field = field;
|
||||||
new_rse .cachedGenerators = Vector::new();
|
new_rse.cachedGenerators = Vector::new();
|
||||||
cached_generators.add(GenericGFPoly::new(field, &vec![1, ]));
|
cached_generators.add(GenericGFPoly::new(field, &vec![1]));
|
||||||
new_rse
|
new_rse
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_generator(&self, degree: i32) -> GenericGFPoly {
|
fn build_generator(&self, degree: i32) -> GenericGFPoly {
|
||||||
if degree >= self.cached_generators.size() {
|
if degree >= self.cached_generators.size() {
|
||||||
let last_generator: GenericGFPoly = self.cached_generators.get(self.cached_generators.size() - 1);
|
let last_generator: GenericGFPoly = self
|
||||||
|
.cached_generators
|
||||||
|
.get(self.cached_generators.size() - 1);
|
||||||
{
|
{
|
||||||
let mut d: i32 = self.cached_generators.size();
|
let mut d: i32 = self.cached_generators.size();
|
||||||
while d <= degree {
|
while d <= degree {
|
||||||
{
|
{
|
||||||
let next_generator: GenericGFPoly = last_generator.multiply(GenericGFPoly::new(&self.field, &vec![1, self.field.exp(d - 1 + self.field.get_generator_base()), ]));
|
let next_generator: GenericGFPoly =
|
||||||
|
last_generator.multiply(GenericGFPoly::new(
|
||||||
|
&self.field,
|
||||||
|
&vec![1, self.field.exp(d - 1 + self.field.get_generator_base())],
|
||||||
|
));
|
||||||
self.cached_generators.add(next_generator);
|
self.cached_generators.add(next_generator);
|
||||||
last_generator = next_generator;
|
last_generator = next_generator;
|
||||||
}
|
}
|
||||||
d += 1;
|
d += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return self.cached_generators.get(degree);
|
return self.cached_generators.get(degree);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode(&self, to_encode: &Vec<i32>, ec_bytes: i32) -> Result<(),IllegalArgumentException> {
|
pub fn encode(
|
||||||
|
&self,
|
||||||
|
to_encode: &Vec<i32>,
|
||||||
|
ec_bytes: i32,
|
||||||
|
) -> Result<(), IllegalArgumentException> {
|
||||||
if ec_bytes == 0 {
|
if ec_bytes == 0 {
|
||||||
return Err( IllegalArgumentException::new("No error correction bytes"));
|
return Err(IllegalArgumentException::new("No error correction bytes"));
|
||||||
}
|
}
|
||||||
let data_bytes: i32 = to_encode.len() - ec_bytes;
|
let data_bytes: i32 = to_encode.len() - ec_bytes;
|
||||||
if data_bytes <= 0 {
|
if data_bytes <= 0 {
|
||||||
return Err( IllegalArgumentException::new("No data bytes provided"));
|
return Err(IllegalArgumentException::new("No data bytes provided"));
|
||||||
}
|
}
|
||||||
let generator: GenericGFPoly = self.build_generator(ec_bytes);
|
let generator: GenericGFPoly = self.build_generator(ec_bytes);
|
||||||
let info_coefficients: [i32; data_bytes] = [0; data_bytes];
|
let info_coefficients: [i32; data_bytes] = [0; data_bytes];
|
||||||
@@ -754,7 +820,13 @@ impl ReedSolomonEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System::arraycopy(&coefficients, 0, &to_encode, data_bytes + num_zero_coefficients, coefficients.len());
|
System::arraycopy(
|
||||||
|
&coefficients,
|
||||||
|
0,
|
||||||
|
&to_encode,
|
||||||
|
data_bytes + num_zero_coefficients,
|
||||||
|
coefficients.len(),
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -767,12 +839,11 @@ impl ReedSolomonEncoder {
|
|||||||
* @author Sean Owen
|
* @author Sean Owen
|
||||||
*/
|
*/
|
||||||
pub struct ReedSolomonException {
|
pub struct ReedSolomonException {
|
||||||
message: String
|
message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReedSolomonException {
|
impl ReedSolomonException {
|
||||||
|
pub fn new(message: &String) -> Self {
|
||||||
pub fn new( message: &String) -> Self {
|
ReedSolomonException { message }
|
||||||
ReedSolomonException{message}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user