From ba39b03bb57d505fa0f065df28c129cb9e9ac184 Mon Sep 17 00:00:00 2001 From: Henry Schimke Date: Wed, 17 Aug 2022 14:52:31 -0500 Subject: [PATCH] auto-format common module --- src/common.rs | 4295 ++++++++++++++++++++----------------- src/common/detector.rs | 852 ++++---- src/common/readsolomon.rs | 949 ++++---- 3 files changed, 3296 insertions(+), 2800 deletions(-) diff --git a/src/common.rs b/src/common.rs index e4cfede..b69d79b 100644 --- a/src/common.rs +++ b/src/common.rs @@ -3,7 +3,10 @@ pub mod readsolomon; use std::collections::HashMap; -use crate::{Binarizer,LuminanceSource,NotFoundException,FormatException,NotFoundException,Binarizer,ResultPoint}; +use crate::{ + Binarizer, Binarizer, FormatException, LuminanceSource, NotFoundException, NotFoundException, + ResultPoint, +}; // ECIInput.java /** @@ -12,89 +15,88 @@ use crate::{Binarizer,LuminanceSource,NotFoundException,FormatException,NotFound * @author Alex Geller */ pub trait ECIInput { + /** + * Returns the length of this input. The length is the number + * of {@code byte}s in or ECIs in the sequence. + * + * @return the number of {@code char}s in this sequence + */ + fn length(&self) -> i32; /** - * Returns the length of this input. The length is the number - * of {@code byte}s in or ECIs in the sequence. - * - * @return the number of {@code char}s in this sequence - */ - fn length(&self) -> i32 ; + * Returns the {@code byte} value at the specified index. An index ranges from zero + * to {@code length() - 1}. The first {@code byte} value of the sequence is at + * index zero, the next at index one, and so on, as for array + * indexing. + * + * @param index the index of the {@code byte} value to be returned + * + * @return the specified {@code byte} value as character or the FNC1 character + * + * @throws IndexOutOfBoundsException + * if the {@code index} argument is negative or not less than + * {@code length()} + * @throws IllegalArgumentException + * if the value at the {@code index} argument is an ECI (@see #isECI) + */ + fn char_at(&self, index: i32) -> char; /** - * Returns the {@code byte} value at the specified index. An index ranges from zero - * to {@code length() - 1}. The first {@code byte} value of the sequence is at - * index zero, the next at index one, and so on, as for array - * indexing. - * - * @param index the index of the {@code byte} value to be returned - * - * @return the specified {@code byte} value as character or the FNC1 character - * - * @throws IndexOutOfBoundsException - * if the {@code index} argument is negative or not less than - * {@code length()} - * @throws IllegalArgumentException - * if the value at the {@code index} argument is an ECI (@see #isECI) - */ - fn char_at(&self, index: i32) -> char ; + * Returns a {@code CharSequence} that is a subsequence of this sequence. + * The subsequence starts with the {@code char} value at the specified index and + * ends with the {@code char} value at index {@code end - 1}. The length + * (in {@code char}s) of the + * returned sequence is {@code end - start}, so if {@code start == end} + * then an empty sequence is returned. + * + * @param start the start index, inclusive + * @param end the end index, exclusive + * + * @return the specified subsequence + * + * @throws IndexOutOfBoundsException + * if {@code start} or {@code end} are negative, + * if {@code end} is greater than {@code length()}, + * or if {@code start} is greater than {@code end} + * @throws IllegalArgumentException + * if a value in the range {@code start}-{@code end} is an ECI (@see #isECI) + */ + fn sub_sequence(&self, start: i32, end: i32) -> CharSequence; /** - * Returns a {@code CharSequence} that is a subsequence of this sequence. - * The subsequence starts with the {@code char} value at the specified index and - * ends with the {@code char} value at index {@code end - 1}. The length - * (in {@code char}s) of the - * returned sequence is {@code end - start}, so if {@code start == end} - * then an empty sequence is returned. - * - * @param start the start index, inclusive - * @param end the end index, exclusive - * - * @return the specified subsequence - * - * @throws IndexOutOfBoundsException - * if {@code start} or {@code end} are negative, - * if {@code end} is greater than {@code length()}, - * or if {@code start} is greater than {@code end} - * @throws IllegalArgumentException - * if a value in the range {@code start}-{@code end} is an ECI (@see #isECI) - */ - fn sub_sequence(&self, start: i32, end: i32) -> CharSequence ; + * Determines if a value is an ECI + * + * @param index the index of the value + * + * @return true if the value at position {@code index} is an ECI + * + * @throws IndexOutOfBoundsException + * if the {@code index} argument is negative or not less than + * {@code length()} + */ + fn is_e_c_i(&self, index: i32) -> bool; /** - * Determines if a value is an ECI - * - * @param index the index of the value - * - * @return true if the value at position {@code index} is an ECI - * - * @throws IndexOutOfBoundsException - * if the {@code index} argument is negative or not less than - * {@code length()} - */ - fn is_e_c_i(&self, index: i32) -> bool ; + * Returns the {@code int} ECI value at the specified index. An index ranges from zero + * to {@code length() - 1}. The first {@code byte} value of the sequence is at + * index zero, the next at index one, and so on, as for array + * indexing. + * + * @param index the index of the {@code int} value to be returned + * + * @return the specified {@code int} ECI value. + * The ECI specified the encoding of all bytes with a higher index until the + * next ECI or until the end of the input if no other ECI follows. + * + * @throws IndexOutOfBoundsException + * if the {@code index} argument is negative or not less than + * {@code length()} + * @throws IllegalArgumentException + * if the value at the {@code index} argument is not an ECI (@see #isECI) + */ + fn get_e_c_i_value(&self, index: i32) -> i32; - /** - * Returns the {@code int} ECI value at the specified index. An index ranges from zero - * to {@code length() - 1}. The first {@code byte} value of the sequence is at - * index zero, the next at index one, and so on, as for array - * indexing. - * - * @param index the index of the {@code int} value to be returned - * - * @return the specified {@code int} ECI value. - * The ECI specified the encoding of all bytes with a higher index until the - * next ECI or until the end of the input if no other ECI follows. - * - * @throws IndexOutOfBoundsException - * if the {@code index} argument is negative or not less than - * {@code length()} - * @throws IllegalArgumentException - * if the value at the {@code index} argument is not an ECI (@see #isECI) - */ - fn get_e_c_i_value(&self, index: i32) -> i32 ; - - fn have_n_characters(&self, index: i32, n: i32) -> bool ; + fn have_n_characters(&self, index: i32, n: i32) -> bool; } // GridSampler.java @@ -115,98 +117,129 @@ pub trait ECIInput { //let grid_sampler: dyn GridSampler = DefaultGridSampler::new(); pub struct GridSampler { - grid_sampler: dyn GridSampler + grid_sampler: dyn GridSampler, } impl GridSampler { - pub fn new() -> Self { - Self { grid_sampler: DefaultGridSampler::new() } + Self { + grid_sampler: DefaultGridSampler::new(), + } } /** - * Sets the implementation of GridSampler used by the library. One global - * instance is stored, which may sound problematic. But, the implementation provided - * ought to be appropriate for the entire platform, and all uses of this library - * in the whole lifetime of the JVM. For instance, an Android activity can swap in - * an implementation that takes advantage of native platform libraries. - * - * @param newGridSampler The platform-specific object to install. - */ - pub fn set_grid_sampler( new_grid_sampler: &GridSampler) { + * Sets the implementation of GridSampler used by the library. One global + * instance is stored, which may sound problematic. But, the implementation provided + * ought to be appropriate for the entire platform, and all uses of this library + * in the whole lifetime of the JVM. For instance, an Android activity can swap in + * an implementation that takes advantage of native platform libraries. + * + * @param newGridSampler The platform-specific object to install. + */ + pub fn set_grid_sampler(new_grid_sampler: &GridSampler) { grid_sampler = new_grid_sampler; } /** - * @return the current implementation of GridSampler - */ - pub fn get_instance() -> GridSampler { + * @return the current implementation of GridSampler + */ + pub fn get_instance() -> GridSampler { return grid_sampler; } /** - * Samples an image for a rectangular matrix of bits of the given dimension. The sampling - * transformation is determined by the coordinates of 4 points, in the original and transformed - * image space. - * - * @param image image to sample - * @param dimensionX width of {@link BitMatrix} to sample from image - * @param dimensionY height of {@link BitMatrix} to sample from image - * @param p1ToX point 1 preimage X - * @param p1ToY point 1 preimage Y - * @param p2ToX point 2 preimage X - * @param p2ToY point 2 preimage Y - * @param p3ToX point 3 preimage X - * @param p3ToY point 3 preimage Y - * @param p4ToX point 4 preimage X - * @param p4ToY point 4 preimage Y - * @param p1FromX point 1 image X - * @param p1FromY point 1 image Y - * @param p2FromX point 2 image X - * @param p2FromY point 2 image Y - * @param p3FromX point 3 image X - * @param p3FromY point 3 image Y - * @param p4FromX point 4 image X - * @param p4FromY point 4 image Y - * @return {@link BitMatrix} representing a grid of points sampled from the image within a region - * defined by the "from" parameters - * @throws NotFoundException if image can't be sampled, for example, if the transformation defined - * by the given points is invalid or results in sampling outside the image boundaries - */ - pub fn sample_grid(&self, image: &BitMatrix, dimension_x: i32, dimension_y: i32, p1_to_x: f32, p1_to_y: f32, p2_to_x: f32, p2_to_y: f32, p3_to_x: f32, p3_to_y: f32, p4_to_x: f32, p4_to_y: f32, p1_from_x: f32, p1_from_y: f32, p2_from_x: f32, p2_from_y: f32, p3_from_x: f32, p3_from_y: f32, p4_from_x: f32, p4_from_y: f32) -> Result ; + * Samples an image for a rectangular matrix of bits of the given dimension. The sampling + * transformation is determined by the coordinates of 4 points, in the original and transformed + * image space. + * + * @param image image to sample + * @param dimensionX width of {@link BitMatrix} to sample from image + * @param dimensionY height of {@link BitMatrix} to sample from image + * @param p1ToX point 1 preimage X + * @param p1ToY point 1 preimage Y + * @param p2ToX point 2 preimage X + * @param p2ToY point 2 preimage Y + * @param p3ToX point 3 preimage X + * @param p3ToY point 3 preimage Y + * @param p4ToX point 4 preimage X + * @param p4ToY point 4 preimage Y + * @param p1FromX point 1 image X + * @param p1FromY point 1 image Y + * @param p2FromX point 2 image X + * @param p2FromY point 2 image Y + * @param p3FromX point 3 image X + * @param p3FromY point 3 image Y + * @param p4FromX point 4 image X + * @param p4FromY point 4 image Y + * @return {@link BitMatrix} representing a grid of points sampled from the image within a region + * defined by the "from" parameters + * @throws NotFoundException if image can't be sampled, for example, if the transformation defined + * by the given points is invalid or results in sampling outside the image boundaries + */ + pub fn sample_grid( + &self, + image: &BitMatrix, + dimension_x: i32, + dimension_y: i32, + p1_to_x: f32, + p1_to_y: f32, + p2_to_x: f32, + p2_to_y: f32, + p3_to_x: f32, + p3_to_y: f32, + p4_to_x: f32, + p4_to_y: f32, + p1_from_x: f32, + p1_from_y: f32, + p2_from_x: f32, + p2_from_y: f32, + p3_from_x: f32, + p3_from_y: f32, + p4_from_x: f32, + p4_from_y: f32, + ) -> Result; - pub fn sample_grid(&self, image: &BitMatrix, dimension_x: i32, dimension_y: i32, transform: &PerspectiveTransform) -> Result ; + pub fn sample_grid( + &self, + image: &BitMatrix, + dimension_x: i32, + dimension_y: i32, + transform: &PerspectiveTransform, + ) -> Result; /** - *

Checks a set of points that have been transformed to sample points on an image against - * the image's dimensions to see if the point are even within the image.

- * - *

This method will actually "nudge" the endpoints back onto the image if they are found to be - * barely (less than 1 pixel) off the image. This accounts for imperfect detection of finder - * patterns in an image where the QR Code runs all the way to the image border.

- * - *

For efficiency, the method will check points from either end of the line until one is found - * to be within the image. Because the set of points are assumed to be linear, this is valid.

- * - * @param image image into which the points should map - * @param points actual points in x1,y1,...,xn,yn form - * @throws NotFoundException if an endpoint is lies outside the image boundaries - */ - pub fn check_and_nudge_points( image: &BitMatrix, points: &Vec) -> Result<(), NotFoundException> { - let width: i32 = image.get_width(); - let height: i32 = image.get_height(); + *

Checks a set of points that have been transformed to sample points on an image against + * the image's dimensions to see if the point are even within the image.

+ * + *

This method will actually "nudge" the endpoints back onto the image if they are found to be + * barely (less than 1 pixel) off the image. This accounts for imperfect detection of finder + * patterns in an image where the QR Code runs all the way to the image border.

+ * + *

For efficiency, the method will check points from either end of the line until one is found + * to be within the image. Because the set of points are assumed to be linear, this is valid.

+ * + * @param image image into which the points should map + * @param points actual points in x1,y1,...,xn,yn form + * @throws NotFoundException if an endpoint is lies outside the image boundaries + */ + pub fn check_and_nudge_points( + image: &BitMatrix, + points: &Vec, + ) -> Result<(), NotFoundException> { + let width: i32 = image.get_width(); + let height: i32 = image.get_height(); // Check and nudge points from start until we see some that are OK: - let mut nudged: bool = true; + let mut nudged: bool = true; // points.length must be even - let max_offset: i32 = points.len() - 1; - { - let mut offset: i32 = 0; + let max_offset: i32 = points.len() - 1; + { + let mut offset: i32 = 0; while offset < max_offset && nudged { { - let x: i32 = points[offset] as i32; - let y: i32 = points[offset + 1] as i32; + let x: i32 = points[offset] as i32; + let y: i32 = points[offset + 1] as i32; if x < -1 || x > width || y < -1 || y > height { - return Err( NotFoundException::get_not_found_instance()); + return Err(NotFoundException::get_not_found_instance()); } nudged = false; if x == -1 { @@ -225,19 +258,19 @@ impl GridSampler { } } offset += 2; - } - } + } + } // Check and nudge points from end: nudged = true; - { - let mut offset: i32 = points.len() - 2; + { + let mut offset: i32 = points.len() - 2; while offset >= 0 && nudged { { - let x: i32 = points[offset] as i32; - let y: i32 = points[offset + 1] as i32; + let x: i32 = points[offset] as i32; + let y: i32 = points[offset + 1] as i32; if x < -1 || x > width || y < -1 || y > height { - return Err( NotFoundException::get_not_found_instance()); + return Err(NotFoundException::get_not_found_instance()); } nudged = false; if x == -1 { @@ -256,11 +289,10 @@ impl GridSampler { } } offset -= 2; - } - } - - Ok(()) + } + } + Ok(()) } } @@ -285,238 +317,234 @@ const LUMINANCE_BUCKETS: i32 = 1 << LUMINANCE_BITS; const EMPTY: [i8; 0] = [0; 0]; pub struct GlobalHistogramBinarizer { - //super: Binarizer; + //super: Binarizer; + luminances: Vec, - luminances: Vec, - - buckets: Vec + buckets: Vec, } impl Binarizer for GlobalHistogramBinarizer { // Applies simple sharpening to the row data to improve performance of the 1D Readers. - fn get_black_row(&self, y: i32, row: &BitArray) -> Result { - let source: LuminanceSource = get_luminance_source(); - let width: i32 = source.get_width(); - if row == null || row.get_size() < width { - row = &BitArray::new(None, Some(width)); - } else { - row.clear(); - } - self.init_arrays(width); - let local_luminances: Vec = source.get_row(y, &self.luminances); - let local_buckets: Vec = self.buckets; - { - let mut x: i32 = 0; - while x < width { - { - local_buckets[(local_luminances[x] & 0xff) >> LUMINANCE_SHIFT] += 1; - } - x += 1; + fn get_black_row(&self, y: i32, row: &BitArray) -> Result { + let source: LuminanceSource = get_luminance_source(); + let width: i32 = source.get_width(); + if row == null || row.get_size() < width { + row = &BitArray::new(None, Some(width)); + } else { + row.clear(); } - } - - let black_point: i32 = ::estimate_black_point(&local_buckets); - if width < 3 { - // Special case for very small images + self.init_arrays(width); + let local_luminances: Vec = source.get_row(y, &self.luminances); + let local_buckets: Vec = self.buckets; { let mut x: i32 = 0; - while x < width { - { - if (local_luminances[x] & 0xff) < black_point { - row.set(x); - } - } - x += 1; + while x < width { + { + local_buckets[(local_luminances[x] & 0xff) >> LUMINANCE_SHIFT] += 1; + } + x += 1; } } - } else { - let mut left: i32 = local_luminances[0] & 0xff; - let mut center: i32 = local_luminances[1] & 0xff; + let black_point: i32 = ::estimate_black_point(&local_buckets); + if width < 3 { + // Special case for very small images + { + let mut x: i32 = 0; + while x < width { + { + if (local_luminances[x] & 0xff) < black_point { + row.set(x); + } + } + x += 1; + } + } + } else { + let mut left: i32 = local_luminances[0] & 0xff; + let mut center: i32 = local_luminances[1] & 0xff; + { + let mut x: i32 = 1; + while x < width - 1 { + { + let right: i32 = local_luminances[x + 1] & 0xff; + // A simple -1 4 -1 box filter with a weight of 2. + if ((center * 4) - left - right) / 2 < black_point { + row.set(x); + } + left = center; + center = right; + } + x += 1; + } + } + } + return Ok(row); + } + + // Does not sharpen the data, as this call is intended to only be used by 2D Readers. + fn get_black_matrix(&self) -> Result> { + let source: LuminanceSource = get_luminance_source(); + let width: i32 = source.get_width(); + let height: i32 = source.get_height(); + let matrix: BitMatrix = BitMatrix::new(width, height, None, None); + // Quickly calculates the histogram by sampling four rows from the image. This proved to be + // more robust on the blackbox tests than sampling a diagonal as we used to do. + self.init_arrays(width); + let local_buckets: Vec = self.buckets; { - let mut x: i32 = 1; - while x < width - 1 { - { - let right: i32 = local_luminances[x + 1] & 0xff; - // A simple -1 4 -1 box filter with a weight of 2. - if ((center * 4) - left - right) / 2 < black_point { - row.set(x); - } - left = center; - center = right; - } - x += 1; + let mut y: i32 = 1; + while y < 5 { + { + let row: i32 = height * y / 5; + let local_luminances: Vec = source.get_row(row, &self.luminances); + let right: i32 = (width * 4) / 5; + { + let mut x: i32 = width / 5; + while x < right { + { + let mut pixel: i32 = local_luminances[x] & 0xff; + local_buckets[pixel >> LUMINANCE_SHIFT] += 1; + } + x += 1; + } + } + } + y += 1; } } - } - return Ok(row); -} - -// Does not sharpen the data, as this call is intended to only be used by 2D Readers. - fn get_black_matrix(&self) -> /* throws NotFoundException */Result> { - let source: LuminanceSource = get_luminance_source(); - let width: i32 = source.get_width(); - let height: i32 = source.get_height(); - let matrix: BitMatrix = BitMatrix::new(width, height, None, None); - // Quickly calculates the histogram by sampling four rows from the image. This proved to be - // more robust on the blackbox tests than sampling a diagonal as we used to do. - self.init_arrays(width); - let local_buckets: Vec = self.buckets; - { - let mut y: i32 = 1; - while y < 5 { - { - let row: i32 = height * y / 5; - let local_luminances: Vec = source.get_row(row, &self.luminances); - let right: i32 = (width * 4) / 5; + let black_point: i32 = ::estimate_black_point(&local_buckets); + // We delay reading the entire image luminance until the black point estimation succeeds. + // Although we end up reading four rows twice, it is consistent with our motto of + // "fail quickly" which is necessary for continuous scanning. + let local_luminances: Vec = source.get_matrix(); + { + let mut y: i32 = 0; + while y < height { { - let mut x: i32 = width / 5; - while x < right { - { - let mut pixel: i32 = local_luminances[x] & 0xff; - local_buckets[pixel >> LUMINANCE_SHIFT] += 1; - } - x += 1; + let offset: i32 = y * width; + { + let mut x: i32 = 0; + while x < width { + { + let pixel: i32 = local_luminances[offset + x] & 0xff; + if pixel < black_point { + matrix.set(x, y); + } + } + x += 1; + } } } - - } - y += 1; + y += 1; + } } + + return Ok(matrix); } - let black_point: i32 = ::estimate_black_point(&local_buckets); - // We delay reading the entire image luminance until the black point estimation succeeds. - // Although we end up reading four rows twice, it is consistent with our motto of - // "fail quickly" which is necessary for continuous scanning. - let local_luminances: Vec = source.get_matrix(); - { - let mut y: i32 = 0; - while y < height { - { - let offset: i32 = y * width; - { - let mut x: i32 = 0; - while x < width { - { - let pixel: i32 = local_luminances[offset + x] & 0xff; - if pixel < black_point { - matrix.set(x, y); - } - } - x += 1; - } - } - - } - y += 1; - } + fn create_binarizer(&self, source: &LuminanceSource) -> Binarizer { + return GlobalHistogramBinarizer::new(source); } - - return Ok(matrix); -} - - fn create_binarizer(&self, source: &LuminanceSource) -> Binarizer { - return GlobalHistogramBinarizer::new(source); -} } impl GlobalHistogramBinarizer { + pub fn new(source: &LuminanceSource) -> GlobalHistogramBinarizer { + super(source); + luminances = EMPTY; + buckets = [0; LUMINANCE_BUCKETS]; + } - pub fn new( source: &LuminanceSource) -> GlobalHistogramBinarizer { - super(source); - luminances = EMPTY; - buckets = [0; LUMINANCE_BUCKETS]; - } - - fn init_arrays(&self, luminance_size: i32) { - if self.luminances.len() < luminance_size { - self.luminances = [0; luminance_size]; - } + fn init_arrays(&self, luminance_size: i32) { + if self.luminances.len() < luminance_size { + self.luminances = [0; luminance_size]; + } { let mut x: i32 = 0; - while x < LUMINANCE_BUCKETS { - { - self.buckets[x] = 0; - } - x += 1; + while x < LUMINANCE_BUCKETS { + { + self.buckets[x] = 0; + } + x += 1; } } + } - } - - fn estimate_black_point( buckets: &Vec) -> Result { - // Find the tallest peak in the histogram. + fn estimate_black_point(buckets: &Vec) -> Result { + // Find the tallest peak in the histogram. let num_buckets: i32 = buckets.len(); let max_bucket_count: i32 = 0; let first_peak: i32 = 0; let first_peak_size: i32 = 0; { let mut x: i32 = 0; - while x < num_buckets { - { - if buckets[x] > first_peak_size { - first_peak = x; - first_peak_size = buckets[x]; - } - if buckets[x] > max_bucket_count { - max_bucket_count = buckets[x]; - } - } - x += 1; + while x < num_buckets { + { + if buckets[x] > first_peak_size { + first_peak = x; + first_peak_size = buckets[x]; + } + if buckets[x] > max_bucket_count { + max_bucket_count = buckets[x]; + } + } + x += 1; } } - // Find the second-tallest peak which is somewhat far from the tallest peak. + // Find the second-tallest peak which is somewhat far from the tallest peak. let second_peak: i32 = 0; let second_peak_score: i32 = 0; { let mut x: i32 = 0; - while x < num_buckets { - { + while x < num_buckets { + { let distance_to_biggest: i32 = x - first_peak; - // Encourage more distant second peaks by multiplying by square of distance. + // Encourage more distant second peaks by multiplying by square of distance. let score: i32 = buckets[x] * distance_to_biggest * distance_to_biggest; - if score > second_peak_score { - second_peak = x; - second_peak_score = score; - } - } - x += 1; + if score > second_peak_score { + second_peak = x; + second_peak_score = score; + } + } + x += 1; } } - // Make sure firstPeak corresponds to the black peak. - if first_peak > second_peak { + // Make sure firstPeak corresponds to the black peak. + if first_peak > second_peak { let temp: i32 = first_peak; - first_peak = second_peak; - second_peak = temp; - } - // than waste time trying to decode the image, and risk false positives. - if second_peak - first_peak <= num_buckets / 16 { - return Err( NotFoundException::get_not_found_instance()); - } - // Find a valley between them that is low and closer to the white peak. + first_peak = second_peak; + second_peak = temp; + } + // than waste time trying to decode the image, and risk false positives. + if second_peak - first_peak <= num_buckets / 16 { + return Err(NotFoundException::get_not_found_instance()); + } + // Find a valley between them that is low and closer to the white peak. let best_valley: i32 = second_peak - 1; let best_valley_score: i32 = -1; { let mut x: i32 = second_peak - 1; - while x > first_peak { - { + while x > first_peak { + { let from_first: i32 = x - first_peak; - let score: i32 = from_first * from_first * (second_peak - x) * (max_bucket_count - buckets[x]); - if score > best_valley_score { - best_valley = x; - best_valley_score = score; - } - } - x -= 1; + let score: i32 = from_first + * from_first + * (second_peak - x) + * (max_bucket_count - buckets[x]); + if score > best_valley_score { + best_valley = x; + best_valley_score = score; + } + } + x -= 1; } } - return Ok(best_valley << LUMINANCE_SHIFT); - } + return Ok(best_valley << LUMINANCE_SHIFT); + } } // BitArray.java @@ -526,401 +554,402 @@ impl GlobalHistogramBinarizer { * @author Sean Owen */ -const EMPTY_BITS : Vec = Vec!([]); +const EMPTY_BITS: Vec = Vec!([]); const LOAD_FACTOR: f32 = 0.75f32; #[derive(Cloneable, Eq, Hash)] pub struct BitArray { + bits: Vec, - bits: Vec, - - size: i32 + size: i32, } impl BitArray { + fn new(bits: Option<&Vec>, size: Option) -> Self { + let mut new_bit_array: Self; - fn new( bits: Option<&Vec>, size: Option) -> Self { - let mut new_bit_array : Self; - new_bit_array.size = size.unwrap_or(0); new_bit_array.bits = bits.unwrap_or(&BitArray::make_array(new_bit_array.size)); - + new_bit_array - } + } - pub fn get_size(&self) -> i32 { - return self.size; - } + pub fn get_size(&self) -> i32 { + return self.size; + } - pub fn get_size_in_bytes(&self) -> i32 { - return (self.size + 7) / 8; - } + pub fn get_size_in_bytes(&self) -> i32 { + return (self.size + 7) / 8; + } - fn ensure_capacity(&self, new_size: i32) { - if new_size > self.bits.len() * 32 { + fn ensure_capacity(&self, new_size: i32) { + if new_size > self.bits.len() * 32 { let new_bits: Vec = ::make_array(Math::ceil(new_size / LOAD_FACTOR) as i32); - System::arraycopy(&self.bits, 0, &new_bits, 0, self.bits.len()); - self.bits = new_bits; - } - } + System::arraycopy(&self.bits, 0, &new_bits, 0, self.bits.len()); + self.bits = new_bits; + } + } - /** - * @param i bit to get - * @return true iff bit i is set - */ - pub fn get(&self, i: i32) -> bool { - return (self.bits[i / 32] & (1 << (i & 0x1F))) != 0; - } + /** + * @param i bit to get + * @return true iff bit i is set + */ + pub fn get(&self, i: i32) -> bool { + return (self.bits[i / 32] & (1 << (i & 0x1F))) != 0; + } - /** - * Sets bit i. - * - * @param i bit to set - */ - pub fn set(&self, i: i32) { - self.bits[i / 32] |= 1 << (i & 0x1F); - } + /** + * Sets bit i. + * + * @param i bit to set + */ + pub fn set(&self, i: i32) { + self.bits[i / 32] |= 1 << (i & 0x1F); + } - /** - * Flips bit i. - * - * @param i bit to set - */ - pub fn flip(&self, i: i32) { - self.bits[i / 32] ^= 1 << (i & 0x1F); - } + /** + * Flips bit i. + * + * @param i bit to set + */ + pub fn flip(&self, i: i32) { + self.bits[i / 32] ^= 1 << (i & 0x1F); + } - /** - * @param from first bit to check - * @return index of first bit that is set, starting from the given index, or size if none are set - * at or beyond this given index - * @see #getNextUnset(int) - */ - pub fn get_next_set(&self, from: i32) -> i32 { - if from >= self.size { - return self.size; - } + /** + * @param from first bit to check + * @return index of first bit that is set, starting from the given index, or size if none are set + * at or beyond this given index + * @see #getNextUnset(int) + */ + pub fn get_next_set(&self, from: i32) -> i32 { + if from >= self.size { + return self.size; + } let bits_offset: i32 = from / 32; let current_bits: i32 = self.bits[bits_offset]; - // mask off lesser bits first - current_bits &= -(1 << (from & 0x1F)); - while current_bits == 0 { - if bits_offset += 1 == self.bits.len() { - return self.size; - } - current_bits = self.bits[bits_offset]; - } + // mask off lesser bits first + current_bits &= -(1 << (from & 0x1F)); + while current_bits == 0 { + if bits_offset += 1 == self.bits.len() { + return self.size; + } + current_bits = self.bits[bits_offset]; + } let result: i32 = (bits_offset * 32) + Integer::number_of_trailing_zeros(current_bits); - return Math::min(result, self.size); - } + return Math::min(result, self.size); + } - /** - * @param from index to start looking for unset bit - * @return index of next unset bit, or {@code size} if none are unset until the end - * @see #getNextSet(int) - */ - pub fn get_next_unset(&self, from: i32) -> i32 { - if from >= self.size { - return self.size; - } + /** + * @param from index to start looking for unset bit + * @return index of next unset bit, or {@code size} if none are unset until the end + * @see #getNextSet(int) + */ + pub fn get_next_unset(&self, from: i32) -> i32 { + if from >= self.size { + return self.size; + } let bits_offset: i32 = from / 32; let current_bits: i32 = !self.bits[bits_offset]; - // mask off lesser bits first - current_bits &= -(1 << (from & 0x1F)); - while current_bits == 0 { - if bits_offset += 1 == self.bits.len() { - return self.size; - } - current_bits = !self.bits[bits_offset]; - } + // mask off lesser bits first + current_bits &= -(1 << (from & 0x1F)); + while current_bits == 0 { + if bits_offset += 1 == self.bits.len() { + return self.size; + } + current_bits = !self.bits[bits_offset]; + } let result: i32 = (bits_offset * 32) + Integer::number_of_trailing_zeros(current_bits); - return Math::min(result, self.size); - } + return Math::min(result, self.size); + } - /** - * Sets a block of 32 bits, starting at bit i. - * - * @param i first bit to set - * @param newBits the new value of the next 32 bits. Note again that the least-significant bit - * corresponds to bit i, the next-least-significant to i+1, and so on. - */ - pub fn set_bulk(&self, i: i32, new_bits: i32) { - self.bits[i / 32] = new_bits; - } + /** + * Sets a block of 32 bits, starting at bit i. + * + * @param i first bit to set + * @param newBits the new value of the next 32 bits. Note again that the least-significant bit + * corresponds to bit i, the next-least-significant to i+1, and so on. + */ + pub fn set_bulk(&self, i: i32, new_bits: i32) { + self.bits[i / 32] = new_bits; + } - /** - * Sets a range of bits. - * - * @param start start of range, inclusive. - * @param end end of range, exclusive - */ - pub fn set_range(&self, start: i32, end: i32) -> Result<(),IllegalArgumentException> { - if end < start || start < 0 || end > self.size { - return Err( IllegalArgumentException::new()); - } - if end == start { - return; - } - // will be easier to treat this as the last actually set bit -- inclusive - end -= 1; + /** + * Sets a range of bits. + * + * @param start start of range, inclusive. + * @param end end of range, exclusive + */ + pub fn set_range(&self, start: i32, end: i32) -> Result<(), IllegalArgumentException> { + if end < start || start < 0 || end > self.size { + return Err(IllegalArgumentException::new()); + } + if end == start { + return; + } + // will be easier to treat this as the last actually set bit -- inclusive + end -= 1; let first_int: i32 = start / 32; let last_int: i32 = end / 32; { let mut i: i32 = first_int; - while i <= last_int { - { - let first_bit: i32 = if i > first_int { 0 } else { start & 0x1F }; - let last_bit: i32 = if i < last_int { 31 } else { end & 0x1F }; - // Ones from firstBit to lastBit, inclusive + while i <= last_int { + { + let first_bit: i32 = if i > first_int { 0 } else { start & 0x1F }; + let last_bit: i32 = if i < last_int { 31 } else { end & 0x1F }; + // Ones from firstBit to lastBit, inclusive let mask: i32 = (2 << last_bit) - (1 << first_bit); - self.bits[i] |= mask; - } - i += 1; + self.bits[i] |= mask; + } + i += 1; } } Ok(()) + } - } - - /** - * Clears all bits (sets to false). - */ - pub fn clear(&self) { + /** + * Clears all bits (sets to false). + */ + pub fn clear(&self) { let max: i32 = self.bits.len(); { let mut i: i32 = 0; - while i < max { - { - self.bits[i] = 0; - } - i += 1; + while i < max { + { + self.bits[i] = 0; + } + i += 1; } } + } - } - - /** - * Efficient method to check if a range of bits is set, or not set. - * - * @param start start of range, inclusive. - * @param end end of range, exclusive - * @param value if true, checks that bits in range are set, otherwise checks that they are not set - * @return true iff all bits are set or not set in range, according to value argument - * @throws IllegalArgumentException if end is less than start or the range is not contained in the array - */ - pub fn is_range(&self, start: i32, end: i32, value: bool) -> Result { - if end < start || start < 0 || end > self.size { - return Err( IllegalArgumentException::new()); - } - if end == start { - // empty range matches - return Ok(true); - } - // will be easier to treat this as the last actually set bit -- inclusive - end -= 1; + /** + * Efficient method to check if a range of bits is set, or not set. + * + * @param start start of range, inclusive. + * @param end end of range, exclusive + * @param value if true, checks that bits in range are set, otherwise checks that they are not set + * @return true iff all bits are set or not set in range, according to value argument + * @throws IllegalArgumentException if end is less than start or the range is not contained in the array + */ + pub fn is_range( + &self, + start: i32, + end: i32, + value: bool, + ) -> Result { + if end < start || start < 0 || end > self.size { + return Err(IllegalArgumentException::new()); + } + if end == start { + // empty range matches + return Ok(true); + } + // will be easier to treat this as the last actually set bit -- inclusive + end -= 1; let first_int: i32 = start / 32; let last_int: i32 = end / 32; { let mut i: i32 = first_int; - while i <= last_int { - { - let first_bit: i32 = if i > first_int { 0 } else { start & 0x1F }; - let last_bit: i32 = if i < last_int { 31 } else { end & 0x1F }; - // Ones from firstBit to lastBit, inclusive + while i <= last_int { + { + let first_bit: i32 = if i > first_int { 0 } else { start & 0x1F }; + let last_bit: i32 = if i < last_int { 31 } else { end & 0x1F }; + // Ones from firstBit to lastBit, inclusive let mask: i32 = (2 << last_bit) - (1 << first_bit); - // equals the mask, or we're looking for 0s and the masked portion is not all 0s - if (self.bits[i] & mask) != ( if value { mask } else { 0 }) { - return Ok(false); - } - } - i += 1; + // equals the mask, or we're looking for 0s and the masked portion is not all 0s + if (self.bits[i] & mask) != (if value { mask } else { 0 }) { + return Ok(false); + } + } + i += 1; } } - return Ok(true); - } + return Ok(true); + } - pub fn append_bit(&self, bit: bool) { - self.ensure_capacity(self.size + 1); - if bit { - self.bits[self.size / 32] |= 1 << (self.size & 0x1F); - } - self.size += 1; - } + pub fn append_bit(&self, bit: bool) { + self.ensure_capacity(self.size + 1); + if bit { + self.bits[self.size / 32] |= 1 << (self.size & 0x1F); + } + self.size += 1; + } - /** - * Appends the least-significant bits, from value, in order from most-significant to - * least-significant. For example, appending 6 bits from 0x000001E will append the bits - * 0, 1, 1, 1, 1, 0 in that order. - * - * @param value {@code int} containing bits to append - * @param numBits bits from value to append - */ - pub fn append_bits(&self, value: i32, num_bits: i32) -> Result<(),IllegalArgumentException> { - if num_bits < 0 || num_bits > 32 { - return Err( IllegalArgumentException::new("Num bits must be between 0 and 32")); - } + /** + * Appends the least-significant bits, from value, in order from most-significant to + * least-significant. For example, appending 6 bits from 0x000001E will append the bits + * 0, 1, 1, 1, 1, 0 in that order. + * + * @param value {@code int} containing bits to append + * @param numBits bits from value to append + */ + pub fn append_bits(&self, value: i32, num_bits: i32) -> Result<(), IllegalArgumentException> { + if num_bits < 0 || num_bits > 32 { + return Err(IllegalArgumentException::new( + "Num bits must be between 0 and 32", + )); + } let next_size: i32 = self.size; - self.ensure_capacity(next_size + num_bits); + self.ensure_capacity(next_size + num_bits); { let num_bits_left: i32 = num_bits - 1; - while num_bits_left >= 0 { - { - if (value & (1 << num_bits_left)) != 0 { - self.bits[next_size / 32] |= 1 << (next_size & 0x1F); - } - next_size += 1; - } - num_bits_left -= 1; + while num_bits_left >= 0 { + { + if (value & (1 << num_bits_left)) != 0 { + self.bits[next_size / 32] |= 1 << (next_size & 0x1F); + } + next_size += 1; + } + num_bits_left -= 1; } } - self.size = next_size; - Ok(()) - } + self.size = next_size; + Ok(()) + } - pub fn append_bit_array(&self, other: &BitArray) { + pub fn append_bit_array(&self, other: &BitArray) { let other_size: i32 = other.size; - self.ensure_capacity(self.size + other_size); + self.ensure_capacity(self.size + other_size); { let mut i: i32 = 0; - while i < other_size { - { - self.append_bit(&other.get(i)); - } - i += 1; + while i < other_size { + { + self.append_bit(&other.get(i)); + } + i += 1; } } + } - } - - pub fn xor(&self, other: &BitArray) -> Result((),IllegalArgumentException) { - if self.size != other.size { - return Err( IllegalArgumentException::new("Sizes don't match")); - } + pub fn xor(&self, other: &BitArray) -> Result((), IllegalArgumentException) { + if self.size != other.size { + return Err(IllegalArgumentException::new("Sizes don't match")); + } { let mut i: i32 = 0; - while i < self.bits.len() { - { - // The last int could be incomplete (i.e. not have 32 bits in - // it) but there is no problem since 0 XOR 0 == 0. - self.bits[i] ^= other.bits[i]; - } - i += 1; + while i < self.bits.len() { + { + // The last int could be incomplete (i.e. not have 32 bits in + // it) but there is no problem since 0 XOR 0 == 0. + self.bits[i] ^= other.bits[i]; + } + i += 1; } } -Ok(()) - } + Ok(()) + } - /** - * - * @param bitOffset first bit to start writing - * @param array array to write into. Bytes are written most-significant byte first. This is the opposite - * of the internal representation, which is exposed by {@link #getBitArray()} - * @param offset position in array to start writing - * @param numBytes how many bytes to write - */ - pub fn to_bytes(&self, bit_offset: i32, array: &Vec, offset: i32, num_bytes: i32) { + /** + * + * @param bitOffset first bit to start writing + * @param array array to write into. Bytes are written most-significant byte first. This is the opposite + * of the internal representation, which is exposed by {@link #getBitArray()} + * @param offset position in array to start writing + * @param numBytes how many bytes to write + */ + pub fn to_bytes(&self, bit_offset: i32, array: &Vec, offset: i32, num_bytes: i32) { { let mut i: i32 = 0; - while i < num_bytes { - { + while i < num_bytes { + { let the_byte: i32 = 0; { let mut j: i32 = 0; - while j < 8 { - { - if self.get(bit_offset) { - the_byte |= 1 << (7 - j); - } - bit_offset += 1; - } - j += 1; + while j < 8 { + { + if self.get(bit_offset) { + the_byte |= 1 << (7 - j); + } + bit_offset += 1; + } + j += 1; } } - array[offset + i] = the_byte as i8; - } - i += 1; + array[offset + i] = the_byte as i8; + } + i += 1; } } + } - } + /** + * @return underlying array of ints. The first element holds the first 32 bits, and the least + * significant bit is bit 0. + */ + pub fn get_bit_array(&self) -> Vec { + return self.bits; + } - /** - * @return underlying array of ints. The first element holds the first 32 bits, and the least - * significant bit is bit 0. - */ - pub fn get_bit_array(&self) -> Vec { - return self.bits; - } - - /** - * Reverses all bits in the array. - */ - pub fn reverse(&self) { + /** + * Reverses all bits in the array. + */ + pub fn reverse(&self) { let new_bits: [i32; self.bits.len()] = [0; self.bits.len()]; - // reverse all int's first + // reverse all int's first let mut len: i32 = (self.size - 1) / 32; let old_bits_len: i32 = len + 1; { let mut i: i32 = 0; - while i < old_bits_len { - { - new_bits[len - i] = Integer::reverse(self.bits[i]); - } - i += 1; + while i < old_bits_len { + { + new_bits[len - i] = Integer::reverse(self.bits[i]); + } + i += 1; } } - // now correct the int's if the bit size isn't a multiple of 32 - if self.size != old_bits_len * 32 { + // now correct the int's if the bit size isn't a multiple of 32 + if self.size != old_bits_len * 32 { let left_offset: i32 = old_bits_len * 32 - self.size; let current_int: i32 = new_bits[0] >> /* >>> */ left_offset; { let mut i: i32 = 1; - while i < old_bits_len { - { + while i < old_bits_len { + { let next_int: i32 = new_bits[i]; - current_int |= next_int << (32 - left_offset); - new_bits[i - 1] = current_int; - current_int = next_int >> /* >>> */ left_offset; - } - i += 1; + current_int |= next_int << (32 - left_offset); + new_bits[i - 1] = current_int; + current_int = next_int >> /* >>> */ left_offset; + } + i += 1; } } - new_bits[old_bits_len - 1] = current_int; - } - self.bits = new_bits; - } + new_bits[old_bits_len - 1] = current_int; + } + self.bits = new_bits; + } - fn make_array( size: i32) -> Vec { - return [0; (size + 31) / 32]; - } + fn make_array(size: i32) -> Vec { + return [0; (size + 31) / 32]; + } - pub fn to_string(&self) -> String { + pub fn to_string(&self) -> String { let result: StringBuilder = StringBuilder::new(self.size + (self.size / 8) + 1); { let mut i: i32 = 0; - while i < self.size { - { - if (i & 0x07) == 0 { - result.append(' '); - } - result.append( if self.get(i) { 'X' } else { '.' }); - } - i += 1; + while i < self.size { + { + if (i & 0x07) == 0 { + result.append(' '); + } + result.append(if self.get(i) { 'X' } else { '.' }); + } + i += 1; } } - return result.to_string(); - } + return result.to_string(); + } - /*pub fn clone(&self) -> BitArray { - return BitArray::new(&self.bits.clone(), self.size); - }*/ + /*pub fn clone(&self) -> BitArray { + return BitArray::new(&self.bits.clone(), self.size); + }*/ } // BitMatrix.java @@ -941,65 +970,70 @@ Ok(()) */ #[derive(Cloneable, Eq, Hash)] pub struct BitMatrix { + width: i32, - width: i32, + height: i32, - height: i32, + row_size: i32, - row_size: i32, - - bits: Vec + bits: Vec, } impl BitMatrix { + /** + * Creates an empty square {@code BitMatrix}. + * + * @param dimension height and width + */ /** - * Creates an empty square {@code BitMatrix}. - * - * @param dimension height and width - */ + * Creates an empty {@code BitMatrix}. + * + * @param width bit matrix width + * @param height bit matrix height + */ - /** - * Creates an empty {@code BitMatrix}. - * - * @param width bit matrix width - * @param height bit matrix height - */ - - fn new( width: i32, height: i32, row_size: Option, bits: Option<&Vec>) -> Result{ + fn new( + width: i32, + height: i32, + row_size: Option, + bits: Option<&Vec>, + ) -> Result { if width < 1 || height < 1 { - return Err( IllegalArgumentException::new("Both dimensions must be greater than 0")); + return Err(IllegalArgumentException::new( + "Both dimensions must be greater than 0", + )); } - Ok(Self{ + Ok(Self { width: width, height: height, row_size: row_size.unwrap_or((width + 31) / 32), - bits: bits.unwrap_or([0; row_size * height]) + bits: bits.unwrap_or([0; row_size * height]), }) } - fn new_dimension(dimension:i32) { + fn new_dimension(dimension: i32) { BitMatrix::new(dimension, dimension, None, None) } /** - * Interprets a 2D array of booleans as a {@code BitMatrix}, where "true" means an "on" bit. - * - * @param image bits of the image, as a row-major 2D array. Elements are arrays representing rows - * @return {@code BitMatrix} representation of image - */ - pub fn parse( image: &Vec>) -> BitMatrix { - let height: i32 = image.len(); - let width: i32 = image[0].len(); - let bits: BitMatrix = BitMatrix::new(width, height, None, None); - { - let mut i: i32 = 0; + * Interprets a 2D array of booleans as a {@code BitMatrix}, where "true" means an "on" bit. + * + * @param image bits of the image, as a row-major 2D array. Elements are arrays representing rows + * @return {@code BitMatrix} representation of image + */ + pub fn parse(image: &Vec>) -> BitMatrix { + let height: i32 = image.len(); + let width: i32 = image[0].len(); + let bits: BitMatrix = BitMatrix::new(width, height, None, None); + { + let mut i: i32 = 0; while i < height { { - let image_i: Vec = image[i]; - { - let mut j: i32 = 0; + let image_i: Vec = image[i]; + { + let mut j: i32 = 0; while j < width { { if image_i[j] { @@ -1007,34 +1041,40 @@ impl BitMatrix { } } j += 1; - } - } - + } + } } i += 1; - } - } + } + } return bits; } - pub fn parse( string_representation: &String, set_string: &String, unset_string: &String) -> Result { + pub fn parse( + string_representation: &String, + set_string: &String, + unset_string: &String, + ) -> Result { if string_representation == null { - return Err( IllegalArgumentException::new()); + return Err(IllegalArgumentException::new()); } - let mut bits: [bool; string_representation.length()] = [false; string_representation.length()]; - let bits_pos: i32 = 0; - let row_start_pos: i32 = 0; - let row_length: i32 = -1; - let n_rows: i32 = 0; - let mut pos: i32 = 0; + let mut bits: [bool; string_representation.length()] = + [false; string_representation.length()]; + let bits_pos: i32 = 0; + let row_start_pos: i32 = 0; + let row_length: i32 = -1; + let n_rows: i32 = 0; + let mut pos: i32 = 0; while pos < string_representation.length() { - if string_representation.char_at(pos) == '\n' || string_representation.char_at(pos) == '\r' { + if string_representation.char_at(pos) == '\n' + || string_representation.char_at(pos) == '\r' + { if bits_pos > row_start_pos { if row_length == -1 { row_length = bits_pos - row_start_pos; } else if bits_pos - row_start_pos != row_length { - return Err( IllegalArgumentException::new("row lengths do not match")); + return Err(IllegalArgumentException::new("row lengths do not match")); } row_start_pos = bits_pos; n_rows += 1; @@ -1049,7 +1089,10 @@ impl BitMatrix { bits[bits_pos] = false; bits_pos += 1; } else { - return Err( IllegalArgumentException::new(format!("illegal character encountered: {}", string_representation.substring(pos)))); + return Err(IllegalArgumentException::new(format!( + "illegal character encountered: {}", + string_representation.substring(pos) + ))); } } // no EOL at end? @@ -1057,13 +1100,13 @@ impl BitMatrix { if row_length == -1 { row_length = bits_pos - row_start_pos; } else if bits_pos - row_start_pos != row_length { - return Err( IllegalArgumentException::new("row lengths do not match")); + return Err(IllegalArgumentException::new("row lengths do not match")); } n_rows += 1; } - let matrix: BitMatrix = BitMatrix::new(row_length, n_rows, None, None); - { - let mut i: i32 = 0; + let matrix: BitMatrix = BitMatrix::new(row_length, n_rows, None, None); + { + let mut i: i32 = 0; while i < bits_pos { { if bits[i] { @@ -1071,246 +1114,253 @@ impl BitMatrix { } } i += 1; - } - } + } + } return Ok(matrix); } /** - *

Gets the requested bit, where true means black.

- * - * @param x The horizontal component (i.e. which column) - * @param y The vertical component (i.e. which row) - * @return value of given bit in matrix - */ - pub fn get(&self, x: i32, y: i32) -> bool { - let offset: i32 = y * self.row_size + (x / 32); + *

Gets the requested bit, where true means black.

+ * + * @param x The horizontal component (i.e. which column) + * @param y The vertical component (i.e. which row) + * @return value of given bit in matrix + */ + pub fn get(&self, x: i32, y: i32) -> bool { + let offset: i32 = y * self.row_size + (x / 32); return ((self.bits[offset] >> /* >>> */ (x & 0x1f)) & 1) != 0; } /** - *

Sets the given bit to true.

- * - * @param x The horizontal component (i.e. which column) - * @param y The vertical component (i.e. which row) - */ - pub fn set(&self, x: i32, y: i32) { - let mut offset: i32 = y * self.row_size + (x / 32); + *

Sets the given bit to true.

+ * + * @param x The horizontal component (i.e. which column) + * @param y The vertical component (i.e. which row) + */ + pub fn set(&self, x: i32, y: i32) { + let mut offset: i32 = y * self.row_size + (x / 32); self.bits[offset] |= 1 << (x & 0x1f); } - pub fn unset(&self, x: i32, y: i32) { - let mut offset: i32 = y * self.row_size + (x / 32); + pub fn unset(&self, x: i32, y: i32) { + let mut offset: i32 = y * self.row_size + (x / 32); self.bits[offset] &= !(1 << (x & 0x1f)); } /** - *

Flips the given bit.

- * - * @param x The horizontal component (i.e. which column) - * @param y The vertical component (i.e. which row) - */ - pub fn flip(&self, x: i32, y: i32) { - let mut offset: i32 = y * self.row_size + (x / 32); + *

Flips the given bit.

+ * + * @param x The horizontal component (i.e. which column) + * @param y The vertical component (i.e. which row) + */ + pub fn flip(&self, x: i32, y: i32) { + let mut offset: i32 = y * self.row_size + (x / 32); self.bits[offset] ^= 1 << (x & 0x1f); } /** - *

Flips every bit in the matrix.

- */ - pub fn flip(&self) { - let max: i32 = self.bits.len(); - { - let mut i: i32 = 0; + *

Flips every bit in the matrix.

+ */ + pub fn flip(&self) { + let max: i32 = self.bits.len(); + { + let mut i: i32 = 0; while i < max { { self.bits[i] = !self.bits[i]; } i += 1; - } - } - + } + } } /** - * Exclusive-or (XOR): Flip the bit in this {@code BitMatrix} if the corresponding - * mask bit is set. - * - * @param mask XOR mask - */ - pub fn xor(&self, mask: &BitMatrix) -> Result<(),IllegalArgumentException> { + * Exclusive-or (XOR): Flip the bit in this {@code BitMatrix} if the corresponding + * mask bit is set. + * + * @param mask XOR mask + */ + pub fn xor(&self, mask: &BitMatrix) -> Result<(), IllegalArgumentException> { if self.width != mask.width || self.height != mask.height || self.row_size != mask.rowSize { - return Err( IllegalArgumentException::new("input matrix dimensions do not match")); + return Err(IllegalArgumentException::new( + "input matrix dimensions do not match", + )); } - let row_array: BitArray = BitArray::new(None,Some(self.width)); - { - let mut y: i32 = 0; + let row_array: BitArray = BitArray::new(None, Some(self.width)); + { + let mut y: i32 = 0; while y < self.height { { - let mut offset: i32 = y * self.row_size; - let row: Vec = mask.get_row(y, &row_array).get_bit_array(); - { - let mut x: i32 = 0; + let mut offset: i32 = y * self.row_size; + let row: Vec = mask.get_row(y, &row_array).get_bit_array(); + { + let mut x: i32 = 0; while x < self.row_size { { self.bits[offset + x] ^= row[x]; } x += 1; - } - } - + } + } } y += 1; - } - } -Ok(()) + } + } + Ok(()) } /** - * Clears all bits (sets to false). - */ - pub fn clear(&self) { - let max: i32 = self.bits.len(); - { - let mut i: i32 = 0; + * Clears all bits (sets to false). + */ + pub fn clear(&self) { + let max: i32 = self.bits.len(); + { + let mut i: i32 = 0; while i < max { { self.bits[i] = 0; } i += 1; - } - } - + } + } } /** - *

Sets a square region of the bit matrix to true.

- * - * @param left The horizontal position to begin at (inclusive) - * @param top The vertical position to begin at (inclusive) - * @param width The width of the region - * @param height The height of the region - */ - pub fn set_region(&self, left: i32, top: i32, width: i32, height: i32) -> Result<(),IllegalArgumentException> { + *

Sets a square region of the bit matrix to true.

+ * + * @param left The horizontal position to begin at (inclusive) + * @param top The vertical position to begin at (inclusive) + * @param width The width of the region + * @param height The height of the region + */ + pub fn set_region( + &self, + left: i32, + top: i32, + width: i32, + height: i32, + ) -> Result<(), IllegalArgumentException> { if top < 0 || left < 0 { - return Err( IllegalArgumentException::new("Left and top must be nonnegative")); + return Err(IllegalArgumentException::new( + "Left and top must be nonnegative", + )); } if height < 1 || width < 1 { - return Err( IllegalArgumentException::new("Height and width must be at least 1")); + return Err(IllegalArgumentException::new( + "Height and width must be at least 1", + )); } - let right: i32 = left + width; - let bottom: i32 = top + height; + let right: i32 = left + width; + let bottom: i32 = top + height; if bottom > self.height || right > self.width { - return Err( IllegalArgumentException::new("The region must fit inside the matrix")); + return Err(IllegalArgumentException::new( + "The region must fit inside the matrix", + )); } - { - let mut y: i32 = top; + { + let mut y: i32 = top; while y < bottom { { - let mut offset: i32 = y * self.row_size; - { - let mut x: i32 = left; + let mut offset: i32 = y * self.row_size; + { + let mut x: i32 = left; while x < right { { self.bits[offset + (x / 32)] |= 1 << (x & 0x1f); } x += 1; - } - } - + } + } } y += 1; - } - } -Ok(()) + } + } + Ok(()) } /** - * A fast method to retrieve one row of data from the matrix as a BitArray. - * - * @param y The row to retrieve - * @param row An optional caller-allocated BitArray, will be allocated if null or too small - * @return The resulting BitArray - this reference should always be used even when passing - * your own row - */ - pub fn get_row(&self, y: i32, row: &BitArray) -> BitArray { + * A fast method to retrieve one row of data from the matrix as a BitArray. + * + * @param y The row to retrieve + * @param row An optional caller-allocated BitArray, will be allocated if null or too small + * @return The resulting BitArray - this reference should always be used even when passing + * your own row + */ + pub fn get_row(&self, y: i32, row: &BitArray) -> BitArray { if row == null || row.get_size() < self.width { row = &BitArray::new(None, Some(self.width)); } else { row.clear(); } - let offset: i32 = y * self.row_size; - { - let mut x: i32 = 0; + let offset: i32 = y * self.row_size; + { + let mut x: i32 = 0; while x < self.row_size { { row.set_bulk(x * 32, self.bits[offset + x]); } x += 1; - } - } + } + } return row; } /** - * @param y row to set - * @param row {@link BitArray} to copy from - */ - pub fn set_row(&self, y: i32, row: &BitArray) { - System::arraycopy(&row.get_bit_array(), 0, &self.bits, y * self.row_size, self.row_size); + * @param y row to set + * @param row {@link BitArray} to copy from + */ + pub fn set_row(&self, y: i32, row: &BitArray) { + System::arraycopy( + &row.get_bit_array(), + 0, + &self.bits, + y * self.row_size, + self.row_size, + ); } /** - * Modifies this {@code BitMatrix} to represent the same but rotated the given degrees (0, 90, 180, 270) - * - * @param degrees number of degrees to rotate through counter-clockwise (0, 90, 180, 270) - */ - pub fn rotate(&self, degrees: i32) -> Result<(),IllegalArgumentException> { + * Modifies this {@code BitMatrix} to represent the same but rotated the given degrees (0, 90, 180, 270) + * + * @param degrees number of degrees to rotate through counter-clockwise (0, 90, 180, 270) + */ + pub fn rotate(&self, degrees: i32) -> Result<(), IllegalArgumentException> { match degrees % 360 { - 0 => - { - Ok(()) - - } - 90 => - { - self.rotate90(); - Ok(()) - - } - 180 => - { - self.rotate180(); - Ok(()) - - } - 270 => - { - self.rotate90(); - self.rotate180(); - Ok(()) - } - _ => { - Err( IllegalArgumentException::new("degrees must be a multiple of 0, 90, 180, or 270")) - } + 0 => Ok(()), + 90 => { + self.rotate90(); + Ok(()) + } + 180 => { + self.rotate180(); + Ok(()) + } + 270 => { + self.rotate90(); + self.rotate180(); + Ok(()) + } + _ => Err(IllegalArgumentException::new( + "degrees must be a multiple of 0, 90, 180, or 270", + )), } } /** - * Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees - */ - pub fn rotate180(&self) { - let top_row: BitArray = BitArray::new(None, Some(self.width)); - let bottom_row: BitArray = BitArray::new(None, Some(self.width)); - let max_height: i32 = (self.height + 1) / 2; - { - let mut i: i32 = 0; + * Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees + */ + pub fn rotate180(&self) { + let top_row: BitArray = BitArray::new(None, Some(self.width)); + let bottom_row: BitArray = BitArray::new(None, Some(self.width)); + let max_height: i32 = (self.height + 1) / 2; + { + let mut i: i32 = 0; while i < max_height { { top_row = self.get_row(i, &top_row); - let bottom_row_index: i32 = self.height - 1 - i; + let bottom_row_index: i32 = self.height - 1 - i; bottom_row = self.get_row(bottom_row_index, &bottom_row); top_row.reverse(); bottom_row.reverse(); @@ -1318,41 +1368,40 @@ Ok(()) self.set_row(bottom_row_index, &top_row); } i += 1; - } - } - + } + } } /** - * Modifies this {@code BitMatrix} to represent the same but rotated 90 degrees counterclockwise - */ - pub fn rotate90(&self) { - let new_width: i32 = self.height; - let new_height: i32 = self.width; - let new_row_size: i32 = (new_width + 31) / 32; - let new_bits: [i32; new_row_size * new_height] = [0; new_row_size * new_height]; - { - let mut y: i32 = 0; + * Modifies this {@code BitMatrix} to represent the same but rotated 90 degrees counterclockwise + */ + pub fn rotate90(&self) { + let new_width: i32 = self.height; + let new_height: i32 = self.width; + let new_row_size: i32 = (new_width + 31) / 32; + let new_bits: [i32; new_row_size * new_height] = [0; new_row_size * new_height]; + { + let mut y: i32 = 0; while y < self.height { { - { - let mut x: i32 = 0; + { + let mut x: i32 = 0; while x < self.width { { - let offset: i32 = y * self.row_size + (x / 32); + let offset: i32 = y * self.row_size + (x / 32); if ((self.bits[offset] >> /* >>> */ (x & 0x1f)) & 1) != 0 { - let new_offset: i32 = (new_height - 1 - x) * new_row_size + (y / 32); + let new_offset: i32 = + (new_height - 1 - x) * new_row_size + (y / 32); new_bits[new_offset] |= 1 << (y & 0x1f); } } x += 1; - } - } - + } + } } y += 1; - } - } + } + } self.width = new_width; self.height = new_height; @@ -1361,24 +1410,24 @@ Ok(()) } /** - * This is useful in detecting the enclosing rectangle of a 'pure' barcode. - * - * @return {@code left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white - */ - pub fn get_enclosing_rectangle(&self) -> Option> { - let mut left: i32 = self.width; - let mut top: i32 = self.height; - let mut right: i32 = -1; - let mut bottom: i32 = -1; - { - let mut y: i32 = 0; + * This is useful in detecting the enclosing rectangle of a 'pure' barcode. + * + * @return {@code left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white + */ + pub fn get_enclosing_rectangle(&self) -> Option> { + let mut left: i32 = self.width; + let mut top: i32 = self.height; + let mut right: i32 = -1; + let mut bottom: i32 = -1; + { + let mut y: i32 = 0; while y < self.height { { - { - let mut x32: i32 = 0; + { + let mut x32: i32 = 0; while x32 < self.row_size { { - let the_bits: i32 = self.bits[y * self.row_size + x32]; + let the_bits: i32 = self.bits[y * self.row_size + x32]; if the_bits != 0 { if y < top { top = y; @@ -1387,7 +1436,7 @@ Ok(()) bottom = y; } if x32 * 32 < left { - let mut bit: i32 = 0; + let mut bit: i32 = 0; while (the_bits << (31 - bit)) == 0 { bit += 1; } @@ -1396,7 +1445,7 @@ Ok(()) } } if x32 * 32 + 31 > right { - let mut bit: i32 = 31; + let mut bit: i32 = 31; while (the_bits >> /* >>> */ bit) == 0 { bit -= 1; } @@ -1407,89 +1456,85 @@ Ok(()) } } x32 += 1; - } - } - + } + } } y += 1; - } - } + } + } if right < left || bottom < top { return null; } - return Some(vec![left, top, right - left + 1, bottom - top + 1, ]) - ; + return Some(vec![left, top, right - left + 1, bottom - top + 1]); } /** - * This is useful in detecting a corner of a 'pure' barcode. - * - * @return {@code x,y} coordinate of top-left-most 1 bit, or null if it is all white - */ - pub fn get_top_left_on_bit(&self) -> Option> { - let bits_offset: i32 = 0; + * This is useful in detecting a corner of a 'pure' barcode. + * + * @return {@code x,y} coordinate of top-left-most 1 bit, or null if it is all white + */ + pub fn get_top_left_on_bit(&self) -> Option> { + let bits_offset: i32 = 0; while bits_offset < self.bits.len() && self.bits[bits_offset] == 0 { bits_offset += 1; } if bits_offset == self.bits.len() { return null; } - let y: i32 = bits_offset / self.row_size; - let mut x: i32 = (bits_offset % self.row_size) * 32; - let the_bits: i32 = self.bits[bits_offset]; - let mut bit: i32 = 0; + let y: i32 = bits_offset / self.row_size; + let mut x: i32 = (bits_offset % self.row_size) * 32; + let the_bits: i32 = self.bits[bits_offset]; + let mut bit: i32 = 0; while (the_bits << (31 - bit)) == 0 { bit += 1; } x += bit; - return Some(vec![x, y, ]) - ; + return Some(vec![x, y]); } - pub fn get_bottom_right_on_bit(&self) -> Vec { - let bits_offset: i32 = self.bits.len() - 1; + pub fn get_bottom_right_on_bit(&self) -> Vec { + let bits_offset: i32 = self.bits.len() - 1; while bits_offset >= 0 && self.bits[bits_offset] == 0 { bits_offset -= 1; } if bits_offset < 0 { return null; } - let y: i32 = bits_offset / self.row_size; - let mut x: i32 = (bits_offset % self.row_size) * 32; - let the_bits: i32 = self.bits[bits_offset]; - let mut bit: i32 = 31; + let y: i32 = bits_offset / self.row_size; + let mut x: i32 = (bits_offset % self.row_size) * 32; + let the_bits: i32 = self.bits[bits_offset]; + let mut bit: i32 = 31; while (the_bits >> /* >>> */ bit) == 0 { bit -= 1; } x += bit; - return vec![x, y, ] - ; + return vec![x, y]; } /** - * @return The width of the matrix - */ - pub fn get_width(&self) -> i32 { + * @return The width of the matrix + */ + pub fn get_width(&self) -> i32 { return self.width; } /** - * @return The height of the matrix - */ - pub fn get_height(&self) -> i32 { + * @return The height of the matrix + */ + pub fn get_height(&self) -> i32 { return self.height; } /** - * @return The row size of the matrix - */ - pub fn get_row_size(&self) -> i32 { + * @return The row size of the matrix + */ + pub fn get_row_size(&self) -> i32 { return self.row_size; } - pub fn hash_code(&self) -> i32 { - let mut hash: i32 = self.width; + pub fn hash_code(&self) -> i32 { + let mut hash: i32 = self.width; hash = 31 * hash + self.width; hash = 31 * hash + self.height; hash = 31 * hash + self.row_size; @@ -1498,37 +1543,55 @@ Ok(()) } /** - * @param setString representation of a set bit - * @param unsetString representation of an unset bit - * @param lineSeparator newline character in string representation - * @return string representation of entire matrix utilizing given strings and line separator - * @deprecated call {@link #toString(String,String)} only, which uses \n line separator always - */ - pub fn to_string(&self, set_string: Option<&str>, unset_string: Option<&str>, line_separator: Option<&str>) -> String { - return self.build_to_string(set_string.unwrap_or("X "), unset_string.unwrap_or(" "), line_separator.unwrap_or("\n")); + * @param setString representation of a set bit + * @param unsetString representation of an unset bit + * @param lineSeparator newline character in string representation + * @return string representation of entire matrix utilizing given strings and line separator + * @deprecated call {@link #toString(String,String)} only, which uses \n line separator always + */ + pub fn to_string( + &self, + set_string: Option<&str>, + unset_string: Option<&str>, + line_separator: Option<&str>, + ) -> String { + return self.build_to_string( + set_string.unwrap_or("X "), + unset_string.unwrap_or(" "), + line_separator.unwrap_or("\n"), + ); } - fn build_to_string(&self, set_string: &String, unset_string: &String, line_separator: &String) -> String { - let result: StringBuilder = StringBuilder::new(self.height * (self.width + 1)); - { - let mut y: i32 = 0; + fn build_to_string( + &self, + set_string: &String, + unset_string: &String, + line_separator: &String, + ) -> String { + let result: StringBuilder = StringBuilder::new(self.height * (self.width + 1)); + { + let mut y: i32 = 0; while y < self.height { { - { - let mut x: i32 = 0; + { + let mut x: i32 = 0; while x < self.width { { - result.append( if self.get(x, y) { set_string } else { unset_string }); + result.append(if self.get(x, y) { + set_string + } else { + unset_string + }); } x += 1; - } - } + } + } result.append(&line_separator); } y += 1; - } - } + } + } return result.to_string(); } @@ -1549,93 +1612,91 @@ Ok(()) * @author Sean Owen */ pub struct BitSource { + bytes: Vec, - bytes: Vec, + byte_offset: i32, - byte_offset: i32, - - bit_offset: i32 + bit_offset: i32, } impl BitSource { + /** + * @param bytes bytes from which this will read bits. Bits will be read from the first byte first. + * Bits are read within a byte from most-significant to least-significant bit. + */ + pub fn new(bytes: &Vec) -> Self { + let mut new_bs; + new_bs.bytes = bytes; - /** - * @param bytes bytes from which this will read bits. Bits will be read from the first byte first. - * Bits are read within a byte from most-significant to least-significant bit. - */ - pub fn new( bytes: &Vec) -> Self { - let mut new_bs; - new_bs.bytes = bytes; - - new_bs - } + new_bs + } - /** - * @return index of next bit in current byte which would be read by the next call to {@link #readBits(int)}. - */ - pub fn get_bit_offset(&self) -> i32 { - return self.bit_offset; - } + /** + * @return index of next bit in current byte which would be read by the next call to {@link #readBits(int)}. + */ + pub fn get_bit_offset(&self) -> i32 { + return self.bit_offset; + } - /** - * @return index of next byte in input byte array which would be read by the next call to {@link #readBits(int)}. - */ - pub fn get_byte_offset(&self) -> i32 { - return self.byte_offset; - } + /** + * @return index of next byte in input byte array which would be read by the next call to {@link #readBits(int)}. + */ + pub fn get_byte_offset(&self) -> i32 { + return self.byte_offset; + } - /** - * @param numBits number of bits to read - * @return int representing the bits read. The bits will appear as the least-significant - * bits of the int - * @throws IllegalArgumentException if numBits isn't in [1,32] or more than is available - */ - pub fn read_bits(&self, num_bits: i32) -> Result { - if num_bits < 1 || num_bits > 32 || num_bits > self.available() { - return Err( IllegalArgumentException::new(&String::value_of(num_bits))); - } + /** + * @param numBits number of bits to read + * @return int representing the bits read. The bits will appear as the least-significant + * bits of the int + * @throws IllegalArgumentException if numBits isn't in [1,32] or more than is available + */ + pub fn read_bits(&self, num_bits: i32) -> Result { + if num_bits < 1 || num_bits > 32 || num_bits > self.available() { + return Err(IllegalArgumentException::new(&String::value_of(num_bits))); + } let mut result: i32 = 0; - // First, read remainder from current byte - if self.bit_offset > 0 { + // First, read remainder from current byte + if self.bit_offset > 0 { let bits_left: i32 = 8 - self.bit_offset; let to_read: i32 = Math::min(num_bits, bits_left); let bits_to_not_read: i32 = bits_left - to_read; let mask: i32 = (0xFF >> (8 - to_read)) << bits_to_not_read; - result = (self.bytes[self.byte_offset] & mask) >> bits_to_not_read; - num_bits -= to_read; - self.bit_offset += to_read; - if self.bit_offset == 8 { - self.bit_offset = 0; - self.byte_offset += 1; - } - } - // Next read whole bytes - if num_bits > 0 { - while num_bits >= 8 { - result = (result << 8) | (self.bytes[self.byte_offset] & 0xFF); - self.byte_offset += 1; - num_bits -= 8; - } - // Finally read a partial byte - if num_bits > 0 { + result = (self.bytes[self.byte_offset] & mask) >> bits_to_not_read; + num_bits -= to_read; + self.bit_offset += to_read; + if self.bit_offset == 8 { + self.bit_offset = 0; + self.byte_offset += 1; + } + } + // Next read whole bytes + if num_bits > 0 { + while num_bits >= 8 { + result = (result << 8) | (self.bytes[self.byte_offset] & 0xFF); + self.byte_offset += 1; + num_bits -= 8; + } + // Finally read a partial byte + if num_bits > 0 { let bits_to_not_read: i32 = 8 - num_bits; let mask: i32 = (0xFF >> bits_to_not_read) << bits_to_not_read; - result = (result << num_bits) | ((self.bytes[self.byte_offset] & mask) >> bits_to_not_read); - self.bit_offset += num_bits; - } - } - return Ok(result); - } + result = (result << num_bits) + | ((self.bytes[self.byte_offset] & mask) >> bits_to_not_read); + self.bit_offset += num_bits; + } + } + return Ok(result); + } - /** - * @return number of bits that can be read successfully - */ - pub fn available(&self) -> i32 { - return 8 * (self.bytes.len() - self.byte_offset) - self.bit_offset; - } + /** + * @return number of bits that can be read successfully + */ + pub fn available(&self) -> i32 { + return 8 * (self.bytes.len() - self.byte_offset) - self.bit_offset; + } } - // CharacterSetECI.java /** * Encapsulates a Character Set ECI, according to "Extended Channel Interpretations" 5.3.1.1 @@ -1644,72 +1705,68 @@ impl BitSource { * @author Sean Owen */ pub enum CharacterSetECI { - // Enum name is a Java encoding valid for java.lang and java.io - Cp437, - ISO8859_1, - ISO8859_2, - ISO8859_3, - ISO8859_4, - ISO8859_5, - // ISO8859_6(8, "ISO-8859-6"), - ISO8859_7, - // ISO8859_8(10, "ISO-8859-8"), - ISO8859_9, - // ISO8859_10(12, "ISO-8859-10"), - // ISO8859_11(13, "ISO-8859-11"), - ISO8859_13, - // ISO8859_14(16, "ISO-8859-14"), - ISO8859_15, - ISO8859_16, - SJIS, - Cp1250, - Cp1251, - Cp1252, - Cp1256, - UnicodeBigUnmarked, - UTF8, - ASCII, - Big5, - GB18030, - EUC_KR + Cp437, + ISO8859_1, + ISO8859_2, + ISO8859_3, + ISO8859_4, + ISO8859_5, + // ISO8859_6(8, "ISO-8859-6"), + ISO8859_7, + // ISO8859_8(10, "ISO-8859-8"), + ISO8859_9, + // ISO8859_10(12, "ISO-8859-10"), + // ISO8859_11(13, "ISO-8859-11"), + ISO8859_13, + // ISO8859_14(16, "ISO-8859-14"), + ISO8859_15, + ISO8859_16, + SJIS, + Cp1250, + Cp1251, + Cp1252, + Cp1256, + UnicodeBigUnmarked, + UTF8, + ASCII, + Big5, + GB18030, + EUC_KR, /* - /* - - // Enum name is a Java encoding valid for java.lang and java.io - Cp437(new int[]{0,2}), - ISO8859_1(new int[]{1,3}, "ISO-8859-1"), - ISO8859_2(4, "ISO-8859-2"), - ISO8859_3(5, "ISO-8859-3"), - ISO8859_4(6, "ISO-8859-4"), - ISO8859_5(7, "ISO-8859-5"), - // ISO8859_6(8, "ISO-8859-6"), - ISO8859_7(9, "ISO-8859-7"), - // ISO8859_8(10, "ISO-8859-8"), - ISO8859_9(11, "ISO-8859-9"), - // ISO8859_10(12, "ISO-8859-10"), - // ISO8859_11(13, "ISO-8859-11"), - ISO8859_13(15, "ISO-8859-13"), - // ISO8859_14(16, "ISO-8859-14"), - ISO8859_15(17, "ISO-8859-15"), - ISO8859_16(18, "ISO-8859-16"), - SJIS(20, "Shift_JIS"), - Cp1250(21, "windows-1250"), - Cp1251(22, "windows-1251"), - Cp1252(23, "windows-1252"), - Cp1256(24, "windows-1256"), - UnicodeBigUnmarked(25, "UTF-16BE", "UnicodeBig"), - UTF8(26, "UTF-8"), - ASCII(new int[] {27, 170}, "US-ASCII"), - Big5(28), - GB18030(29, "GB2312", "EUC_CN", "GBK"), - EUC_KR(30, "EUC-KR"); - - */ + // Enum name is a Java encoding valid for java.lang and java.io + Cp437(new int[]{0,2}), + ISO8859_1(new int[]{1,3}, "ISO-8859-1"), + ISO8859_2(4, "ISO-8859-2"), + ISO8859_3(5, "ISO-8859-3"), + ISO8859_4(6, "ISO-8859-4"), + ISO8859_5(7, "ISO-8859-5"), + // ISO8859_6(8, "ISO-8859-6"), + ISO8859_7(9, "ISO-8859-7"), + // ISO8859_8(10, "ISO-8859-8"), + ISO8859_9(11, "ISO-8859-9"), + // ISO8859_10(12, "ISO-8859-10"), + // ISO8859_11(13, "ISO-8859-11"), + ISO8859_13(15, "ISO-8859-13"), + // ISO8859_14(16, "ISO-8859-14"), + ISO8859_15(17, "ISO-8859-15"), + ISO8859_16(18, "ISO-8859-16"), + SJIS(20, "Shift_JIS"), + Cp1250(21, "windows-1250"), + Cp1251(22, "windows-1251"), + Cp1252(23, "windows-1252"), + Cp1256(24, "windows-1256"), + UnicodeBigUnmarked(25, "UTF-16BE", "UnicodeBig"), + UTF8(26, "UTF-8"), + ASCII(new int[] {27, 170}, "US-ASCII"), + Big5(28), + GB18030(29, "GB2312", "EUC_CN", "GBK"), + EUC_KR(30, "EUC-KR"); + + */ } -impl CharacterSetECI { - +impl CharacterSetECI { /* fn new( value: i32) -> CharacterSetECI { this( : vec![i32; 1] = vec![value, ] @@ -1732,51 +1789,52 @@ impl CharacterSetECI { } */ - /** - * @param charset Java character set object - * @return CharacterSetECI representing ECI for character encoding, or null if it is legal - * but unsupported - */ - pub fn get_character_set_e_c_i( charset: &str) -> Result,&'static str> { + * @param charset Java character set object + * @return CharacterSetECI representing ECI for character encoding, or null if it is legal + * but unsupported + */ + pub fn get_character_set_e_c_i(charset: &str) -> Result, &'static str> { //return NAME_TO_ECI::get(&charset.name()); let eci = match charset { "Cp437" => Self::Cp437, -"ISO-8859-1" => Self::ISO8859_1, -"ISO-8859-2" => Self::ISO8859_2, -"ISO-8859-3" => Self::ISO8859_3, -"ISO-8859-4" => Self::ISO8859_4, -"ISO-8859-5" => Self::ISO8859_5, -"ISO-8859-7" => Self::ISO8859_7, -"ISO-8859-9" => Self::ISO8859_9, -"ISO-8859-13" => Self::ISO8859_13, -"ISO-8859-15" => Self::ISO8859_15, -"ISO-8859-16" => Self::ISO8859_16, -"Shift_JIS" => Self::SJIS, -"windows-1250" => Self::Cp1250, -"windows-1251" => Self::Cp1251, -"windows-1252" => Self::Cp1252, -"windows-1256" => Self::Cp1256, -"UTF-16BE" | "UnicodeBig" => Self::UnicodeBigUnmarked, -"UTF-8" => Self::UTF8, -"US-ASCII" => Self::ASCII, -"Big5" => Self::Big5, -"GB2312"| "EUC_CN"| "GBK" => Self::GB18030, -"EUC-KR" => Self::EUC_KR, -_ => return Err("Invalid charset") + "ISO-8859-1" => Self::ISO8859_1, + "ISO-8859-2" => Self::ISO8859_2, + "ISO-8859-3" => Self::ISO8859_3, + "ISO-8859-4" => Self::ISO8859_4, + "ISO-8859-5" => Self::ISO8859_5, + "ISO-8859-7" => Self::ISO8859_7, + "ISO-8859-9" => Self::ISO8859_9, + "ISO-8859-13" => Self::ISO8859_13, + "ISO-8859-15" => Self::ISO8859_15, + "ISO-8859-16" => Self::ISO8859_16, + "Shift_JIS" => Self::SJIS, + "windows-1250" => Self::Cp1250, + "windows-1251" => Self::Cp1251, + "windows-1252" => Self::Cp1252, + "windows-1256" => Self::Cp1256, + "UTF-16BE" | "UnicodeBig" => Self::UnicodeBigUnmarked, + "UTF-8" => Self::UTF8, + "US-ASCII" => Self::ASCII, + "Big5" => Self::Big5, + "GB2312" | "EUC_CN" | "GBK" => Self::GB18030, + "EUC-KR" => Self::EUC_KR, + _ => return Err("Invalid charset"), }; Ok(Some(eci)) } /** - * @param value character set ECI value - * @return {@code CharacterSetECI} representing ECI of given value, or null if it is legal but - * unsupported - * @throws FormatException if ECI value is invalid - */ - pub fn get_character_set_e_c_i_by_value( value: i32) -> Result, FormatException> { + * @param value character set ECI value + * @return {@code CharacterSetECI} representing ECI of given value, or null if it is legal but + * unsupported + * @throws FormatException if ECI value is invalid + */ + pub fn get_character_set_e_c_i_by_value( + value: i32, + ) -> Result, FormatException> { if value < 0 || value >= 900 { - return Err( FormatException::get_format_instance()); + return Err(FormatException::get_format_instance()); } let eci = match value { 0 | 2 => Self::Cp437, @@ -1787,27 +1845,26 @@ _ => return Err("Invalid charset") 7 => Self::ISO8859_5, 9 => Self::ISO8859_7, 11 => Self::ISO8859_9, -15 => Self::ISO8859_13, -17 => Self::ISO8859_15, -18 => Self::ISO8859_16, -20 =>Self::SJIS, -21 =>Self::Cp1250, -22 =>Self::Cp1251, -23 =>Self::Cp1252, -24 =>Self::Cp1256, -25 =>Self::UnicodeBigUnmarked, -26 =>Self::UTF8, -27 | 170 =>Self::ASCII, -28 =>Self::Big5, -29 =>Self::GB18030, -30 =>Self::EUC_KR, -_ => return Err( FormatException::get_format_instance()) - + 15 => Self::ISO8859_13, + 17 => Self::ISO8859_15, + 18 => Self::ISO8859_16, + 20 => Self::SJIS, + 21 => Self::Cp1250, + 22 => Self::Cp1251, + 23 => Self::Cp1252, + 24 => Self::Cp1256, + 25 => Self::UnicodeBigUnmarked, + 26 => Self::UTF8, + 27 | 170 => Self::ASCII, + 28 => Self::Big5, + 29 => Self::GB18030, + 30 => Self::EUC_KR, + _ => return Err(FormatException::get_format_instance()), }; return Ok(Some(eci)); } - pub fn get_value(v: Self) -> i32 { + pub fn get_value(v: Self) -> i32 { match v { CharacterSetECI::Cp437 => 0, CharacterSetECI::ISO8859_1 => 1, @@ -1835,15 +1892,15 @@ _ => return Err( FormatException::get_format_instance()) } /* - * @param name character set ECI encoding name - * @return CharacterSetECI representing ECI for character encoding, or null if it is legal - * but unsupported - */ - /* - pub fn get_character_set_e_c_i_by_name( name: &str) -> Result { - return NAME_TO_ECI::get(&name); - } - */ + * @param name character set ECI encoding name + * @return CharacterSetECI representing ECI for character encoding, or null if it is legal + * but unsupported + */ + /* + pub fn get_character_set_e_c_i_by_name( name: &str) -> Result { + return NAME_TO_ECI::get(&name); + } + */ } // DecoderResult.java @@ -1855,142 +1912,147 @@ _ => return Err( FormatException::get_format_instance()) * @author Sean Owen */ pub struct DecoderResult { + raw_bytes: Vec, - raw_bytes: Vec, + num_bits: i32, - num_bits: i32, + text: String, - text: String, + byte_segments: List>, - byte_segments: List>, + ec_level: String, - ec_level: String, + errors_corrected: Integer, - errors_corrected: Integer, + erasures: Integer, - erasures: Integer, + other: Object, - other: Object, + structured_append_parity: i32, - structured_append_parity: i32, + structured_append_sequence_number: i32, - structured_append_sequence_number: i32, - - symbology_modifier: i32 + symbology_modifier: i32, } impl DecoderResult { + pub fn new( + raw_bytes: &Vec, + text: &String, + byte_segments: &List>, + ec_level: &String, + sa_sequence: Option, + sa_parity: Option, + symbology_modifier: Option, + ) -> Self { + let mut new_dr: Self; - pub fn new( raw_bytes: &Vec, text: &String, byte_segments: &List>, ec_level: &String, sa_sequence: Option, sa_parity: Option, symbology_modifier: Option) -> Self { - let mut new_dr : Self; + new_dr.raw_bytes = raw_bytes; + new_dr.text = text; + new_dr.byte_segments = byte_segments; + new_dr.ec_level = ec_level; - new_dr.raw_bytes = raw_bytes; - new_dr.text = text; - new_dr.byte_segments = byte_segments; - new_dr.ec_level = ec_level; + new_dr.symbology_modifier = symbology_modifier.unwrap_or(0); - new_dr.symbology_modifier = symbology_modifier.unwrap_or(0); + new_dr.structured_append_parity = sa_parity.unwrap_or(-1); + new_dr.structured_append_sequence_number = sa_sequence.unwrap_or(-1); - new_dr.structured_append_parity = sa_parity.unwrap_or(-1); - new_dr.structured_append_sequence_number = sa_sequence.unwrap_or(-1); + new_dr.num_bits = raw_bytes.len() * 8; - new_dr.num_bits = raw_bytes.len() * 8; + new_dr + } + /** + * @return raw bytes representing the result, or {@code null} if not applicable + */ + pub fn get_raw_bytes(&self) -> Option> { + return Some(self.raw_bytes); + } + /** + * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length + * @since 3.3.0 + */ + pub fn get_num_bits(&self) -> i32 { + return self.num_bits; + } - new_dr - } - /** - * @return raw bytes representing the result, or {@code null} if not applicable - */ - pub fn get_raw_bytes(&self) -> Option> { - return Some(self.raw_bytes); - } + /** + * @param numBits overrides the number of bits that are valid in {@link #getRawBytes()} + * @since 3.3.0 + */ + pub fn set_num_bits(&self, num_bits: i32) { + self.numBits = num_bits; + } - /** - * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length - * @since 3.3.0 - */ - pub fn get_num_bits(&self) -> i32 { - return self.num_bits; - } + /** + * @return text representation of the result + */ + pub fn get_text(&self) -> String { + return self.text; + } - /** - * @param numBits overrides the number of bits that are valid in {@link #getRawBytes()} - * @since 3.3.0 - */ - pub fn set_num_bits(&self, num_bits: i32) { - self.numBits = num_bits; - } + /** + * @return list of byte segments in the result, or {@code null} if not applicable + */ + pub fn get_byte_segments(&self) -> Option>> { + return self.byte_segments; + } - /** - * @return text representation of the result - */ - pub fn get_text(&self) -> String { - return self.text; - } + /** + * @return name of error correction level used, or {@code null} if not applicable + */ + pub fn get_e_c_level(&self) -> Option { + return Some(self.ec_level); + } - /** - * @return list of byte segments in the result, or {@code null} if not applicable - */ - pub fn get_byte_segments(&self) -> Option>> { - return self.byte_segments; - } + /** + * @return number of errors corrected, or {@code null} if not applicable + */ + pub fn get_errors_corrected(&self) -> Option { + return self.errors_corrected; + } - /** - * @return name of error correction level used, or {@code null} if not applicable - */ - pub fn get_e_c_level(&self) -> Option { - return Some(self.ec_level); - } + pub fn set_errors_corrected(&self, errors_corrected: &Integer) { + self.errorsCorrected = errors_corrected; + } - /** - * @return number of errors corrected, or {@code null} if not applicable - */ - pub fn get_errors_corrected(&self) -> Option { - return self.errors_corrected; - } + /** + * @return number of erasures corrected, or {@code null} if not applicable + */ + pub fn get_erasures(&self) -> Option { + return self.erasures; + } - pub fn set_errors_corrected(&self, errors_corrected: &Integer) { - self.errorsCorrected = errors_corrected; - } + pub fn set_erasures(&self, erasures: &Integer) { + self.erasures = erasures; + } - /** - * @return number of erasures corrected, or {@code null} if not applicable - */ - pub fn get_erasures(&self) -> Option { - return self.erasures; - } + /** + * @return arbitrary additional metadata + */ + pub fn get_other(&self) -> Object { + return self.other; + } - pub fn set_erasures(&self, erasures: &Integer) { - self.erasures = erasures; - } + pub fn set_other(&self, other: &Object) { + self.other = other; + } - /** - * @return arbitrary additional metadata - */ - pub fn get_other(&self) -> Object { - return self.other; - } + pub fn has_structured_append(&self) -> bool { + return self.structured_append_parity >= 0 && self.structured_append_sequence_number >= 0; + } - pub fn set_other(&self, other: &Object) { - self.other = other; - } + pub fn get_structured_append_parity(&self) -> i32 { + return self.structured_append_parity; + } - pub fn has_structured_append(&self) -> bool { - return self.structured_append_parity >= 0 && self.structured_append_sequence_number >= 0; - } + pub fn get_structured_append_sequence_number(&self) -> i32 { + return self.structured_append_sequence_number; + } - pub fn get_structured_append_parity(&self) -> i32 { - return self.structured_append_parity; - } - - pub fn get_structured_append_sequence_number(&self) -> i32 { - return self.structured_append_sequence_number; - } - - pub fn get_symbology_modifier(&self) -> i32 { - return self.symbology_modifier; - } + pub fn get_symbology_modifier(&self) -> i32 { + return self.symbology_modifier; + } } // DefaultGridSampler.java @@ -2003,34 +2065,63 @@ pub struct DefaultGridSampler { } impl GridSampler for DefaultGridSampler { - - fn sample_grid(&self, image: &BitMatrix, dimension_x: i32, dimension_y: i32, p1_to_x: f32, p1_to_y: f32, p2_to_x: f32, p2_to_y: f32, p3_to_x: f32, p3_to_y: f32, p4_to_x: f32, p4_to_y: f32, p1_from_x: f32, p1_from_y: f32, p2_from_x: f32, p2_from_y: f32, p3_from_x: f32, p3_from_y: f32, p4_from_x: f32, p4_from_y: f32) -> Result { - let transform: PerspectiveTransform = PerspectiveTransform::quadrilateral_to_quadrilateral(p1_to_x, p1_to_y, p2_to_x, p2_to_y, p3_to_x, p3_to_y, p4_to_x, p4_to_y, p1_from_x, p1_from_y, p2_from_x, p2_from_y, p3_from_x, p3_from_y, p4_from_x, p4_from_y); + fn sample_grid( + &self, + image: &BitMatrix, + dimension_x: i32, + dimension_y: i32, + p1_to_x: f32, + p1_to_y: f32, + p2_to_x: f32, + p2_to_y: f32, + p3_to_x: f32, + p3_to_y: f32, + p4_to_x: f32, + p4_to_y: f32, + p1_from_x: f32, + p1_from_y: f32, + p2_from_x: f32, + p2_from_y: f32, + p3_from_x: f32, + p3_from_y: f32, + p4_from_x: f32, + p4_from_y: f32, + ) -> Result { + let transform: PerspectiveTransform = PerspectiveTransform::quadrilateral_to_quadrilateral( + p1_to_x, p1_to_y, p2_to_x, p2_to_y, p3_to_x, p3_to_y, p4_to_x, p4_to_y, p1_from_x, + p1_from_y, p2_from_x, p2_from_y, p3_from_x, p3_from_y, p4_from_x, p4_from_y, + ); return Ok(self.sample_grid(image, dimension_x, dimension_y, transform)); } - fn sample_grid(&self, image: &BitMatrix, dimension_x: i32, dimension_y: i32, transform: &PerspectiveTransform) -> Result { + fn sample_grid( + &self, + image: &BitMatrix, + dimension_x: i32, + dimension_y: i32, + transform: &PerspectiveTransform, + ) -> Result { if dimension_x <= 0 || dimension_y <= 0 { - return Err( NotFoundException::get_not_found_instance()); + return Err(NotFoundException::get_not_found_instance()); } - let bits: BitMatrix = BitMatrix::new(dimension_x, dimension_y, None, None); - let mut points: [f32; 2.0 * dimension_x] = [0.0; 2.0 * dimension_x]; - { - let mut y: i32 = 0; + let bits: BitMatrix = BitMatrix::new(dimension_x, dimension_y, None, None); + let mut points: [f32; 2.0 * dimension_x] = [0.0; 2.0 * dimension_x]; + { + let mut y: i32 = 0; while y < dimension_y { { - let max: i32 = points.len(); - let i_value: f32 = y + 0.5f32; - { - let mut x: i32 = 0; + let max: i32 = points.len(); + let i_value: f32 = y + 0.5f32; + { + let mut x: i32 = 0; while x < max { { points[x] = (x / 2.0) as f32 + 0.5f32; points[x + 1] = i_value; } x += 2; - } - } + } + } transform.transform_points(&points); // Quick check to see if points transformed to something inside the image; @@ -2039,18 +2130,18 @@ impl GridSampler for DefaultGridSampler { let tryResult1 = 0; //'try1: loop { //{ - { - let mut x: i32 = 0; - while x < max { - { - if image.get(points[x] as i32, points[x + 1] as i32) { - // Black(-ish) pixel - bits.set(x / 2, y); - } + { + let mut x: i32 = 0; + while x < max { + { + if image.get(points[x] as i32, points[x + 1] as i32) { + // Black(-ish) pixel + bits.set(x / 2, y); } - x += 2; - } - } + } + x += 2; + } + } //} //break 'try1 @@ -2060,11 +2151,10 @@ impl GridSampler for DefaultGridSampler { // return Err( NotFoundException::get_not_found_instance()); // } 0 => break //} - } y += 1; - } - } + } + } return Ok(bits); } @@ -2079,28 +2169,28 @@ impl GridSampler for DefaultGridSampler { * @author Sean Owen */ pub struct DetectorResult { + bits: BitMatrix, - bits: BitMatrix, - - points: Vec + points: Vec, } impl DetectorResult { + pub fn new(bits: &BitMatrix, points: &Vec) -> Self { + Self { + bits: bits, + points: points, + } + } - pub fn new( bits: &BitMatrix, points: &Vec) -> Self { - Self { bits: bits, points: points } - } + pub fn get_bits(&self) -> BitMatrix { + return self.bits; + } - pub fn get_bits(&self) -> BitMatrix { - return self.bits; - } - - pub fn get_points(&self) -> Vec { - return self.points; - } + pub fn get_points(&self) -> Vec { + return self.points; + } } - // ECIEncoderSet.java /** * Set of CharsetEncoders for a given input string @@ -2120,14 +2210,12 @@ impl DetectorResult { // List of encoders that potentially encode characters not in ISO-8859-1 in one byte. //const ENCODERS: List = ArrayList<>::new(); pub struct ECIEncoderSet { + encoders: Vec, - encoders: Vec, - - priority_encoder_index: i32 + priority_encoder_index: i32, } impl ECIEncoderSet { - /*static { let names: vec![Vec; 20] = vec!["IBM437", "ISO-8859-2", "ISO-8859-3", "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", "ISO-8859-7", "ISO-8859-8", "ISO-8859-9", "ISO-8859-10", "ISO-8859-11", "ISO-8859-13", "ISO-8859-14", "ISO-8859-15", "ISO-8859-16", "windows-1250", "windows-1251", "windows-1252", "windows-1256", "Shift_JIS", ] ; @@ -2150,26 +2238,27 @@ impl ECIEncoderSet { }*/ /** - * Constructs an encoder set - * - * @param stringToEncode the string that needs to be encoded - * @param priorityCharset The preferred {@link Charset} or null. - * @param fnc1 fnc1 denotes the character in the input that represents the FNC1 character or -1 for a non-GS1 bar - * code. When specified, it is considered an error to pass it as argument to the methods canEncode() or encode(). - */ - pub fn new( string_to_encode: &str, priority_charset: &Charset, fnc1: i32) -> ECIEncoderSet { - let needed_encoders: Vec = Vec::new(); + * Constructs an encoder set + * + * @param stringToEncode the string that needs to be encoded + * @param priorityCharset The preferred {@link Charset} or null. + * @param fnc1 fnc1 denotes the character in the input that represents the FNC1 character or -1 for a non-GS1 bar + * code. When specified, it is considered an error to pass it as argument to the methods canEncode() or encode(). + */ + pub fn new(string_to_encode: &str, priority_charset: &Charset, fnc1: i32) -> ECIEncoderSet { + let needed_encoders: Vec = Vec::new(); //we always need the ISO-8859-1 encoder. It is the default encoding needed_encoders.add(&StandardCharsets::ISO_8859_1::new_encoder()); - let need_unicode_encoder: bool = priority_charset != null && priority_charset.name().starts_with("UTF"); - //Walk over the input string and see if all characters can be encoded with the list of encoders - { - let mut i: i32 = 0; + let need_unicode_encoder: bool = + priority_charset != null && priority_charset.name().starts_with("UTF"); + //Walk over the input string and see if all characters can be encoded with the list of encoders + { + let mut i: i32 = 0; while i < string_to_encode.length() { { - let can_encode: bool = false; - for encoder in needed_encoders { - let c: char = string_to_encode.char_at(i); + let can_encode: bool = false; + for encoder in needed_encoders { + let c: char = string_to_encode.char_at(i); if c == fnc1 || encoder.can_encode(c) { can_encode = true; break; @@ -2177,7 +2266,7 @@ impl ECIEncoderSet { } if !can_encode { //for the character at position i we don't yet have an encoder in the list - for encoder in ENCODERS { + for encoder in ENCODERS { if encoder.can_encode(&string_to_encode.char_at(i)) { //Good, we found an encoder that can encode the character. We add him to the list and continue scanning //the input @@ -2194,87 +2283,91 @@ impl ECIEncoderSet { } } i += 1; - } - } + } + } if needed_encoders.size() == 1 && !need_unicode_encoder { //the entire input can be encoded by the ISO-8859-1 encoder - encoders = vec![needed_encoders.get(0), ] - ; + encoders = vec![needed_encoders.get(0)]; } else { // we need more than one single byte encoder or we need a Unicode encoder. // In this case we append a UTF-8 and UTF-16 encoder to the list encoders = [None; needed_encoders.size() + 2]; - let mut index: i32 = 0; - for encoder in needed_encoders { - encoders[index += 1 ] = encoder; + let mut index: i32 = 0; + for encoder in needed_encoders { + encoders[index += 1] = encoder; } encoders[index] = StandardCharsets::UTF_8::new_encoder(); encoders[index + 1] = StandardCharsets::UTF_16BE::new_encoder(); } //Compute priorityEncoderIndex by looking up priorityCharset in encoders - let priority_encoder_index_value: i32 = -1; + let priority_encoder_index_value: i32 = -1; if priority_charset != null { - { - let mut i: i32 = 0; + { + let mut i: i32 = 0; while i < encoders.len() { { - if encoders[i] != null && priority_charset.name().equals(&encoders[i].charset().name()) { + if encoders[i] != null + && priority_charset + .name() + .equals(&encoders[i].charset().name()) + { priority_encoder_index_value = i; break; } } i += 1; - } - } - + } + } } priority_encoder_index = priority_encoder_index_value; //invariants - assert!( encoders[0].charset().equals(StandardCharsets::ISO_8859_1)); + assert!(encoders[0].charset().equals(StandardCharsets::ISO_8859_1)); } - pub fn length(&self) -> i32 { + pub fn length(&self) -> i32 { return self.encoders.len(); } - pub fn get_charset_name(&self, index: i32) -> String { - assert!( index < self.length()); + pub fn get_charset_name(&self, index: i32) -> String { + assert!(index < self.length()); return self.encoders[index].charset().name(); } - pub fn get_charset(&self, index: i32) -> Charset { - assert!( index < self.length()); + pub fn get_charset(&self, index: i32) -> Charset { + assert!(index < self.length()); return self.encoders[index].charset(); } - pub fn get_e_c_i_value(&self, encoder_index: i32) -> i32 { - return CharacterSetECI::get_value(CharacterSetECI::get_character_set_e_c_i(&self.encoders[encoder_index].charset())); + pub fn get_e_c_i_value(&self, encoder_index: i32) -> i32 { + return CharacterSetECI::get_value(CharacterSetECI::get_character_set_e_c_i( + &self.encoders[encoder_index].charset(), + )); } /* - * returns -1 if no priority charset was defined - */ - pub fn get_priority_encoder_index(&self) -> i32 { + * returns -1 if no priority charset was defined + */ + pub fn get_priority_encoder_index(&self) -> i32 { return self.priority_encoder_index; } - pub fn can_encode(&self, c: char, encoder_index: i32) -> bool { - assert!( encoder_index < self.length()); - let encoder: CharsetEncoder = self.encoders[encoder_index]; + pub fn can_encode(&self, c: char, encoder_index: i32) -> bool { + assert!(encoder_index < self.length()); + let encoder: CharsetEncoder = self.encoders[encoder_index]; return encoder.can_encode(format!("{}", c)); } - pub fn encode(&self, c: char, encoder_index: i32) -> Vec { - assert!( encoder_index < self.length()); - let encoder: CharsetEncoder = self.encoders[encoder_index]; - assert!( encoder.can_encode(format!("{}", c))); + pub fn encode(&self, c: char, encoder_index: i32) -> Vec { + assert!(encoder_index < self.length()); + let encoder: CharsetEncoder = self.encoders[encoder_index]; + assert!(encoder.can_encode(format!("{}", c))); return (format!("{}", c)).get_bytes(&encoder.charset()); } - pub fn encode(&self, s: &String, encoder_index: i32) -> Vec { - assert!( encoder_index < self.length()); - let encoder: CharsetEncoder = self.encoders[encoder_index]; + pub fn encode(&self, s: &String, encoder_index: i32) -> Vec { + assert!(encoder_index < self.length()); + let encoder: CharsetEncoder = self.encoders[encoder_index]; return s.get_bytes(&encoder.charset()); } } @@ -2286,132 +2379,138 @@ impl ECIEncoderSet { * @author Alex Geller */ pub struct ECIStringBuilder { + current_bytes: StringBuilder, - current_bytes: StringBuilder, + result: StringBuilder, - result: StringBuilder, - - current_charset: Charset + current_charset: Charset, } impl ECIStringBuilder { + pub fn new() -> Self { + let mut neweci_sb; + neweci_sb.current_bytes = StringBuilder::new(initial_capacity.unwrape_or(0)); - pub fn new() -> Self { - let mut neweci_sb; - neweci_sb.current_bytes = StringBuilder::new(initial_capacity.unwrape_or(0)); + neweci_sb + } - neweci_sb - } + /** + * Appends {@code value} as a byte value + * + * @param value character whose lowest byte is to be appended + */ + pub fn append(&self, value: char) { + self.current_bytes.append((value & 0xff) as char); + } - /** - * Appends {@code value} as a byte value - * - * @param value character whose lowest byte is to be appended - */ - pub fn append(&self, value: char) { - self.current_bytes.append((value & 0xff) as char); - } + /** + * Appends {@code value} as a byte value + * + * @param value byte to append + */ + pub fn append(&self, value: i8) { + self.current_bytes.append((value & 0xff) as char); + } - /** - * Appends {@code value} as a byte value - * - * @param value byte to append - */ - pub fn append(&self, value: i8) { - self.current_bytes.append((value & 0xff) as char); - } + /** + * Appends the characters in {@code value} as bytes values + * + * @param value string to append + */ + pub fn append(&self, value: &String) { + self.current_bytes.append(&value); + } - /** - * Appends the characters in {@code value} as bytes values - * - * @param value string to append - */ - pub fn append(&self, value: &String) { - self.current_bytes.append(&value); - } + /** + * Append the string repesentation of {@code value} (short for {@code append(String.valueOf(value))}) + * + * @param value int to append as a string + */ + pub fn append(&self, value: i32) { + self.append(&String::value_of(value)); + } - /** - * Append the string repesentation of {@code value} (short for {@code append(String.valueOf(value))}) - * - * @param value int to append as a string - */ - pub fn append(&self, value: i32) { - self.append(&String::value_of(value)); - } + /** + * Appends ECI value to output. + * + * @param value ECI value to append, as an int + * @throws FormatException on invalid ECI value + */ + pub fn append_e_c_i(&self, value: i32) -> Result<(), FormatException> { + self.encode_current_bytes_if_any(); + let character_set_e_c_i: CharacterSetECI = + CharacterSetECI::get_character_set_e_c_i_by_value(value); + if character_set_e_c_i == null { + return Err(FormatException::get_format_instance()); + } + self.current_charset = character_set_e_c_i.get_charset(); + Ok(()) + } - /** - * Appends ECI value to output. - * - * @param value ECI value to append, as an int - * @throws FormatException on invalid ECI value - */ - pub fn append_e_c_i(&self, value: i32) -> Result<(), FormatException> { - self.encode_current_bytes_if_any(); - let character_set_e_c_i: CharacterSetECI = CharacterSetECI::get_character_set_e_c_i_by_value(value); - if character_set_e_c_i == null { - return Err( FormatException::get_format_instance()); - } - self.current_charset = character_set_e_c_i.get_charset(); - Ok(()) - } + fn encode_current_bytes_if_any(&self) { + if self.current_charset.equals(StandardCharsets::ISO_8859_1) { + if self.current_bytes.length() > 0 { + if self.result == null { + self.result = self.current_bytes; + self.current_bytes = StringBuilder::new(); + } else { + self.result.append(&self.current_bytes); + self.current_bytes = StringBuilder::new(); + } + } + } else if self.current_bytes.length() > 0 { + let bytes: Vec = self + .current_bytes + .to_string() + .get_bytes(StandardCharsets::ISO_8859_1); + self.current_bytes = StringBuilder::new(); + if self.result == null { + //self.result = StringBuilder::new(String::new(&bytes, &self.current_charset)); + self.result = StringBuilder::new(String::from(&bytes)); + } else { + //self.result.append(String::new(&bytes, &self.current_charset)); + self.result.append(String::from(&bytes)); + } + } + } - fn encode_current_bytes_if_any(&self) { - if self.current_charset.equals(StandardCharsets::ISO_8859_1) { - if self.current_bytes.length() > 0 { - if self.result == null { - self.result = self.current_bytes; - self.current_bytes = StringBuilder::new(); - } else { - self.result.append(&self.current_bytes); - self.current_bytes = StringBuilder::new(); - } - } - } else if self.current_bytes.length() > 0 { - let bytes: Vec = self.current_bytes.to_string().get_bytes(StandardCharsets::ISO_8859_1); - self.current_bytes = StringBuilder::new(); - if self.result == null { - //self.result = StringBuilder::new(String::new(&bytes, &self.current_charset)); - self.result = StringBuilder::new(String::from(&bytes)); - } else { - //self.result.append(String::new(&bytes, &self.current_charset)); - self.result.append(String::from(&bytes)); - } - } - } + /** + * Appends the characters from {@code value} (unlike all other append methods of this class who append bytes) + * + * @param value characters to append + */ + pub fn append_characters(&self, value: &StringBuilder) { + self.encode_current_bytes_if_any(); + self.result.append(&value); + } - /** - * Appends the characters from {@code value} (unlike all other append methods of this class who append bytes) - * - * @param value characters to append - */ - pub fn append_characters(&self, value: &StringBuilder) { - self.encode_current_bytes_if_any(); - self.result.append(&value); - } + /** + * Short for {@code toString().length()} (if possible, use {@link #isEmpty()} instead) + * + * @return length of string representation in characters + */ + pub fn length(&self) -> i32 { + return self.to_string().length(); + } - /** - * Short for {@code toString().length()} (if possible, use {@link #isEmpty()} instead) - * - * @return length of string representation in characters - */ - pub fn length(&self) -> i32 { - return self.to_string().length(); - } + /** + * @return true iff nothing has been appended + */ + pub fn is_empty(&self) -> bool { + return self.current_bytes.length() == 0 + && (self.result == null || self.result.length() == 0); + } - /** - * @return true iff nothing has been appended - */ - pub fn is_empty(&self) -> bool { - return self.current_bytes.length() == 0 && (self.result == null || self.result.length() == 0); - } - - pub fn to_string(&self) -> String { - self.encode_current_bytes_if_any(); - return if self.result == null { "".to_owned() } else { self.result.to_string() }; - } + pub fn to_string(&self) -> String { + self.encode_current_bytes_if_any(); + return if self.result == null { + "".to_owned() + } else { + self.result.to_string() + }; + } } - // HybridBinarizer.java /** * This class implements a local thresholding algorithm, which while slower than the @@ -2436,135 +2535,164 @@ impl ECIStringBuilder { const BLOCK_SIZE_POWER: i32 = 3; // ...0100...00 - const BLOCK_SIZE: i32 = 1 << BLOCK_SIZE_POWER; +const BLOCK_SIZE: i32 = 1 << BLOCK_SIZE_POWER; // ...0011...11 - const BLOCK_SIZE_MASK: i32 = BLOCK_SIZE - 1; +const BLOCK_SIZE_MASK: i32 = BLOCK_SIZE - 1; - const MINIMUM_DIMENSION: i32 = BLOCK_SIZE * 5; +const MINIMUM_DIMENSION: i32 = BLOCK_SIZE * 5; - const MIN_DYNAMIC_RANGE: i32 = 24; +const MIN_DYNAMIC_RANGE: i32 = 24; pub struct HybridBinarizer { //super: GlobalHistogramBinarizer; - - matrix: BitMatrix + matrix: BitMatrix, } -impl GlobalHistogramBinarizer for HybridBinarizer{ - /** - * Calculates the final BitMatrix once for all requests. This could be called once from the - * constructor instead, but there are some advantages to doing it lazily, such as making - * profiling easier, and not doing heavy lifting when callers don't expect it. - */ - fn get_black_matrix(&self) -> Result { - if self.matrix != null { +impl GlobalHistogramBinarizer for HybridBinarizer { + /** + * Calculates the final BitMatrix once for all requests. This could be called once from the + * constructor instead, but there are some advantages to doing it lazily, such as making + * profiling easier, and not doing heavy lifting when callers don't expect it. + */ + fn get_black_matrix(&self) -> Result { + if self.matrix != null { + return Ok(self.matrix); + } + let source: LuminanceSource = get_luminance_source(); + let width: i32 = source.get_width(); + let height: i32 = source.get_height(); + if width >= MINIMUM_DIMENSION && height >= MINIMUM_DIMENSION { + let luminances: Vec = source.get_matrix(); + let sub_width: i32 = width >> BLOCK_SIZE_POWER; + if (width & BLOCK_SIZE_MASK) != 0 { + sub_width += 1; + } + let sub_height: i32 = height >> BLOCK_SIZE_POWER; + if (height & BLOCK_SIZE_MASK) != 0 { + sub_height += 1; + } + let black_points: Vec> = + ::calculate_black_points(&luminances, sub_width, sub_height, width, height); + let new_matrix: BitMatrix = BitMatrix::new(width, height, None, None); + ::calculate_threshold_for_block( + &luminances, + sub_width, + sub_height, + width, + height, + &black_points, + new_matrix, + ); + self.matrix = new_matrix; + } else { + // If the image is too small, fall back to the global histogram approach. + self.matrix = super.get_black_matrix(); + } return Ok(self.matrix); } - let source: LuminanceSource = get_luminance_source(); - let width: i32 = source.get_width(); - let height: i32 = source.get_height(); - if width >= MINIMUM_DIMENSION && height >= MINIMUM_DIMENSION { - let luminances: Vec = source.get_matrix(); - let sub_width: i32 = width >> BLOCK_SIZE_POWER; - if (width & BLOCK_SIZE_MASK) != 0 { - sub_width += 1; - } - let sub_height: i32 = height >> BLOCK_SIZE_POWER; - if (height & BLOCK_SIZE_MASK) != 0 { - sub_height += 1; - } - let black_points: Vec> = ::calculate_black_points(&luminances, sub_width, sub_height, width, height); - let new_matrix: BitMatrix = BitMatrix::new(width, height, None, None); - ::calculate_threshold_for_block(&luminances, sub_width, sub_height, width, height, &black_points, new_matrix); - self.matrix = new_matrix; - } else { - // If the image is too small, fall back to the global histogram approach. - self.matrix = super.get_black_matrix(); - } - return Ok(self.matrix); -} - fn create_binarizer(&self, source: &LuminanceSource) -> Binarizer { - return HybridBinarizer::new(source); -} + fn create_binarizer(&self, source: &LuminanceSource) -> Binarizer { + return HybridBinarizer::new(source); + } } impl HybridBinarizer { - - pub fn new( source: &LuminanceSource) -> Self { + pub fn new(source: &LuminanceSource) -> Self { //super(source); HybridBinarizer::new(source) } - - /** - * For each block in the image, calculate the average black point using a 5x5 grid - * of the blocks around it. Also handles the corner cases (fractional blocks are computed based - * on the last pixels in the row/column which are also used in the previous block). - */ - fn calculate_threshold_for_block( luminances: &Vec, sub_width: i32, sub_height: i32, width: i32, height: i32, black_points: &Vec>, matrix: &BitMatrix) { - let max_y_offset: i32 = height - BLOCK_SIZE; - let max_x_offset: i32 = width - BLOCK_SIZE; - { - let mut y: i32 = 0; + * For each block in the image, calculate the average black point using a 5x5 grid + * of the blocks around it. Also handles the corner cases (fractional blocks are computed based + * on the last pixels in the row/column which are also used in the previous block). + */ + fn calculate_threshold_for_block( + luminances: &Vec, + sub_width: i32, + sub_height: i32, + width: i32, + height: i32, + black_points: &Vec>, + matrix: &BitMatrix, + ) { + let max_y_offset: i32 = height - BLOCK_SIZE; + let max_x_offset: i32 = width - BLOCK_SIZE; + { + let mut y: i32 = 0; while y < sub_height { { - let mut yoffset: i32 = y << BLOCK_SIZE_POWER; + let mut yoffset: i32 = y << BLOCK_SIZE_POWER; if yoffset > max_y_offset { yoffset = max_y_offset; } - let top: i32 = ::cap(y, sub_height - 3); - { - let mut x: i32 = 0; + let top: i32 = ::cap(y, sub_height - 3); + { + let mut x: i32 = 0; while x < sub_width { { - let mut xoffset: i32 = x << BLOCK_SIZE_POWER; + let mut xoffset: i32 = x << BLOCK_SIZE_POWER; if xoffset > max_x_offset { xoffset = max_x_offset; } - let left: i32 = ::cap(x, sub_width - 3); - let mut sum: i32 = 0; - { - let mut z: i32 = -2; + let left: i32 = ::cap(x, sub_width - 3); + let mut sum: i32 = 0; + { + let mut z: i32 = -2; while z <= 2 { { - let black_row: Vec = black_points[top + z]; - sum += black_row[left - 2] + black_row[left - 1] + black_row[left] + black_row[left + 1] + black_row[left + 2]; + let black_row: Vec = black_points[top + z]; + sum += black_row[left - 2] + + black_row[left - 1] + + black_row[left] + + black_row[left + 1] + + black_row[left + 2]; } z += 1; - } - } + } + } - let average: i32 = sum / 25; - ::threshold_block(&luminances, xoffset, yoffset, average, width, matrix); + let average: i32 = sum / 25; + ::threshold_block( + &luminances, + xoffset, + yoffset, + average, + width, + matrix, + ); } x += 1; - } - } - + } + } } y += 1; - } - } - + } + } } - fn cap( value: i32, max: i32) -> i32 { - return if value < 2 { 2 } else { Math::min(value, max) }; + fn cap(value: i32, max: i32) -> i32 { + return if value < 2 { 2 } else { Math::min(value, max) }; } /** - * Applies a single threshold to a block of pixels. - */ - fn threshold_block( luminances: &Vec, xoffset: i32, yoffset: i32, threshold: i32, stride: i32, matrix: &BitMatrix) { - { - let mut y: i32 = 0; - let mut offset: i32 = yoffset * stride + xoffset; + * Applies a single threshold to a block of pixels. + */ + fn threshold_block( + luminances: &Vec, + xoffset: i32, + yoffset: i32, + threshold: i32, + stride: i32, + matrix: &BitMatrix, + ) { + { + let mut y: i32 = 0; + let mut offset: i32 = yoffset * stride + xoffset; while y < BLOCK_SIZE { { - { - let mut x: i32 = 0; + { + let mut x: i32 = 0; while x < BLOCK_SIZE { { // Comparison needs to be <= so that black == 0 pixels are black even if the threshold is 0. @@ -2573,55 +2701,60 @@ impl HybridBinarizer { } } x += 1; - } - } - + } + } } y += 1; offset += stride; - } - } - + } + } } /** - * Calculates a single black point for each block of pixels and saves it away. - * See the following thread for a discussion of this algorithm: - * http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0 - */ - fn calculate_black_points( luminances: &Vec, sub_width: i32, sub_height: i32, width: i32, height: i32) -> Vec> { - let max_y_offset: i32 = height - BLOCK_SIZE; - let max_x_offset: i32 = width - BLOCK_SIZE; - let black_points: [[i32; sub_width]; sub_height] = [[0; sub_width]; sub_height]; - { - let mut y: i32 = 0; + * Calculates a single black point for each block of pixels and saves it away. + * See the following thread for a discussion of this algorithm: + * http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0 + */ + fn calculate_black_points( + luminances: &Vec, + sub_width: i32, + sub_height: i32, + width: i32, + height: i32, + ) -> Vec> { + let max_y_offset: i32 = height - BLOCK_SIZE; + let max_x_offset: i32 = width - BLOCK_SIZE; + let black_points: [[i32; sub_width]; sub_height] = [[0; sub_width]; sub_height]; + { + let mut y: i32 = 0; while y < sub_height { { - let mut yoffset: i32 = y << BLOCK_SIZE_POWER; + let mut yoffset: i32 = y << BLOCK_SIZE_POWER; if yoffset > max_y_offset { yoffset = max_y_offset; } - { - let mut x: i32 = 0; + { + let mut x: i32 = 0; while x < sub_width { { - let mut xoffset: i32 = x << BLOCK_SIZE_POWER; + let mut xoffset: i32 = x << BLOCK_SIZE_POWER; if xoffset > max_x_offset { xoffset = max_x_offset; } - let mut sum: i32 = 0; - let mut min: i32 = 0xFF; - let mut max: i32 = 0; - { - let mut yy: i32 = 0; - let mut offset: i32 = yoffset * width + xoffset; + let mut sum: i32 = 0; + let mut min: i32 = 0xFF; + let mut max: i32 = 0; + { + let mut yy: i32 = 0; + let mut offset: i32 = yoffset * width + xoffset; while yy < BLOCK_SIZE { { - { - let mut xx: i32 = 0; + { + let mut xx: i32 = 0; while xx < BLOCK_SIZE { { - let pixel: i32 = luminances[offset + xx] & 0xFF; + let pixel: i32 = + luminances[offset + xx] & 0xFF; sum += pixel; // still looking for good contrast if pixel < min { @@ -2632,42 +2765,42 @@ impl HybridBinarizer { } } xx += 1; - } - } + } + } // short-circuit min/max tests once dynamic range is met if max - min > MIN_DYNAMIC_RANGE { // finish the rest of the rows quickly - { + { yy += 1; offset += width; while yy < BLOCK_SIZE { { - { - let mut xx: i32 = 0; + { + let mut xx: i32 = 0; while xx < BLOCK_SIZE { { - sum += luminances[offset + xx] & 0xFF; + sum += luminances + [offset + xx] + & 0xFF; } xx += 1; - } - } - + } + } } yy += 1; offset += width; - } - } - + } + } } } yy += 1; offset += width; - } - } + } + } // The default estimate is the average of the values in the block. - let mut average: i32 = sum >> (BLOCK_SIZE_POWER * 2); + let mut average: i32 = sum >> (BLOCK_SIZE_POWER * 2); if max - min <= MIN_DYNAMIC_RANGE { // If variation within the block is low, assume this is a block with only light or only // dark pixels. In that case we do not want to use the average, as it would divide this @@ -2683,7 +2816,11 @@ impl HybridBinarizer { // background for which reasonable black point estimates were made. The bp estimated at // the boundaries is used for the interior. // The (min < bp) is arbitrary but works better than other heuristics that were tried. - let average_neighbor_black_point: i32 = (black_points[y - 1][x] + (2 * black_points[y][x - 1]) + black_points[y - 1][x - 1]) / 4; + let average_neighbor_black_point: i32 = (black_points + [y - 1][x] + + (2 * black_points[y][x - 1]) + + black_points[y - 1][x - 1]) + / 4; if min < average_neighbor_black_point { average = average_neighbor_black_point; } @@ -2692,13 +2829,12 @@ impl HybridBinarizer { black_points[y][x] = average; } x += 1; - } - } - + } + } } y += 1; - } - } + } + } return black_points; } @@ -2716,19 +2852,18 @@ impl HybridBinarizer { // approximated (latch + 2 codewords) const COST_PER_ECI: i32 = 3; pub struct MinimalECIInput { + bytes: Vec, - bytes: Vec, - - fnc1: i32 + fnc1: i32, } -impl ECIInput for MinimalECIInput{ - fn have_n_characters(&self, index: i32, n: i32) -> bool { +impl ECIInput for MinimalECIInput { + fn have_n_characters(&self, index: i32, n: i32) -> bool { if index + n - 1 >= self.bytes.len() { return false; } - { - let mut i: i32 = 0; + { + let mut i: i32 = 0; while i < n { { if self.is_e_c_i(index + i) { @@ -2736,211 +2871,220 @@ impl ECIInput for MinimalECIInput{ } } i += 1; - } - } + } + } return true; } /** - * Returns the {@code int} ECI value at the specified index. An index ranges from zero - * to {@code length() - 1}. The first {@code byte} value of the sequence is at - * index zero, the next at index one, and so on, as for array - * indexing. - * - * @param index the index of the {@code int} value to be returned - * - * @return the specified {@code int} ECI value. - * The ECI specified the encoding of all bytes with a higher index until the - * next ECI or until the end of the input if no other ECI follows. - * - * @throws IndexOutOfBoundsException - * if the {@code index} argument is negative or not less than - * {@code length()} - * @throws IllegalArgumentException - * if the value at the {@code index} argument is not an ECI (@see #isECI) - */ - fn get_e_c_i_value(&self, index: i32) -> Result { - if index < 0 || index >= self.length() { - return Err( IndexOutOfBoundsException::new(format!("{}", index))); + * Returns the {@code int} ECI value at the specified index. An index ranges from zero + * to {@code length() - 1}. The first {@code byte} value of the sequence is at + * index zero, the next at index one, and so on, as for array + * indexing. + * + * @param index the index of the {@code int} value to be returned + * + * @return the specified {@code int} ECI value. + * The ECI specified the encoding of all bytes with a higher index until the + * next ECI or until the end of the input if no other ECI follows. + * + * @throws IndexOutOfBoundsException + * if the {@code index} argument is negative or not less than + * {@code length()} + * @throws IllegalArgumentException + * if the value at the {@code index} argument is not an ECI (@see #isECI) + */ + fn get_e_c_i_value( + &self, + index: i32, + ) -> Result { + if index < 0 || index >= self.length() { + return Err(IndexOutOfBoundsException::new(format!("{}", index))); + } + if !self.is_e_c_i(index) { + return Err(IllegalArgumentException::new(format!( + "value at {} is not an ECI but a character", + index + ))); + } + return self.bytes[index] - 256; } - if !self.is_e_c_i(index) { - return Err( IllegalArgumentException::new(format!("value at {} is not an ECI but a character", index))); - } - return self.bytes[index] - 256; -} -/** - * Determines if a value is an ECI - * - * @param index the index of the value - * - * @return true if the value at position {@code index} is an ECI - * - * @throws IndexOutOfBoundsException - * if the {@code index} argument is negative or not less than - * {@code length()} - */ - fn is_e_c_i(&self, index: i32) -> Result { - if index < 0 || index >= self.length() { - return Err( IndexOutOfBoundsException::new(format!("{}", index))); + /** + * Determines if a value is an ECI + * + * @param index the index of the value + * + * @return true if the value at position {@code index} is an ECI + * + * @throws IndexOutOfBoundsException + * if the {@code index} argument is negative or not less than + * {@code length()} + */ + fn is_e_c_i(&self, index: i32) -> Result { + if index < 0 || index >= self.length() { + return Err(IndexOutOfBoundsException::new(format!("{}", index))); + } + return Ok(self.bytes[index] > 255 && self.bytes[index] <= 999); } - return Ok(self.bytes[index] > 255 && self.bytes[index] <= 999) -} -/** - * Returns a {@code CharSequence} that is a subsequence of this sequence. - * The subsequence starts with the {@code char} value at the specified index and - * ends with the {@code char} value at index {@code end - 1}. The length - * (in {@code char}s) of the - * returned sequence is {@code end - start}, so if {@code start == end} - * then an empty sequence is returned. - * - * @param start the start index, inclusive - * @param end the end index, exclusive - * - * @return the specified subsequence - * - * @throws IndexOutOfBoundsException - * if {@code start} or {@code end} are negative, - * if {@code end} is greater than {@code length()}, - * or if {@code start} is greater than {@code end} - * @throws IllegalArgumentException - * if a value in the range {@code start}-{@code end} is an ECI (@see #isECI) - */ - fn sub_sequence(&self, start: i32, end: i32) -> Result { - if start < 0 || start > end || end > self.length() { - return Err( IndexOutOfBoundsException::new(format!("{}", start))); - } - let result: StringBuilder = StringBuilder::new(); - { - let mut i: i32 = start; - while i < end { - { - if self.is_e_c_i(i) { - return Err( IllegalArgumentException::new(format!("value at {} is not a character but an ECI", i))); + /** + * Returns a {@code CharSequence} that is a subsequence of this sequence. + * The subsequence starts with the {@code char} value at the specified index and + * ends with the {@code char} value at index {@code end - 1}. The length + * (in {@code char}s) of the + * returned sequence is {@code end - start}, so if {@code start == end} + * then an empty sequence is returned. + * + * @param start the start index, inclusive + * @param end the end index, exclusive + * + * @return the specified subsequence + * + * @throws IndexOutOfBoundsException + * if {@code start} or {@code end} are negative, + * if {@code end} is greater than {@code length()}, + * or if {@code start} is greater than {@code end} + * @throws IllegalArgumentException + * if a value in the range {@code start}-{@code end} is an ECI (@see #isECI) + */ + fn sub_sequence( + &self, + start: i32, + end: i32, + ) -> Result { + if start < 0 || start > end || end > self.length() { + return Err(IndexOutOfBoundsException::new(format!("{}", start))); + } + let result: StringBuilder = StringBuilder::new(); + { + let mut i: i32 = start; + while i < end { + { + if self.is_e_c_i(i) { + return Err(IllegalArgumentException::new(format!( + "value at {} is not a character but an ECI", + i + ))); + } + result.append(&self.char_at(i)); } - result.append(&self.char_at(i)); + i += 1; } - i += 1; - } - } + } - return result; -} - -/** - * Returns the {@code byte} value at the specified index. An index ranges from zero - * to {@code length() - 1}. The first {@code byte} value of the sequence is at - * index zero, the next at index one, and so on, as for array - * indexing. - * - * @param index the index of the {@code byte} value to be returned - * - * @return the specified {@code byte} value as character or the FNC1 character - * - * @throws IndexOutOfBoundsException - * if the {@code index} argument is negative or not less than - * {@code length()} - * @throws IllegalArgumentException - * if the value at the {@code index} argument is an ECI (@see #isECI) - */ - fn char_at(&self, index: i32) -> Result { - if index < 0 || index >= self.length() { - return Err( IndexOutOfBoundsException::new(format!("{}", index))); + return result; } - if self.is_e_c_i(index) { - return Err( IllegalArgumentException::new(format!("value at {} is not a character but an ECI", index))); + + /** + * Returns the {@code byte} value at the specified index. An index ranges from zero + * to {@code length() - 1}. The first {@code byte} value of the sequence is at + * index zero, the next at index one, and so on, as for array + * indexing. + * + * @param index the index of the {@code byte} value to be returned + * + * @return the specified {@code byte} value as character or the FNC1 character + * + * @throws IndexOutOfBoundsException + * if the {@code index} argument is negative or not less than + * {@code length()} + * @throws IllegalArgumentException + * if the value at the {@code index} argument is an ECI (@see #isECI) + */ + fn char_at( + &self, + index: i32, + ) -> Result { + if index < 0 || index >= self.length() { + return Err(IndexOutOfBoundsException::new(format!("{}", index))); + } + if self.is_e_c_i(index) { + return Err(IllegalArgumentException::new(format!( + "value at {} is not a character but an ECI", + index + ))); + } + return if self.is_f_n_c1(index) { + Ok(self.fnc1 as char) + } else { + Ok(self.bytes[index] as char) + }; } - return if self.is_f_n_c1(index) { Ok(self.fnc1 as char) } else { Ok(self.bytes[index] as char) }; -} - -/** - * Returns the length of this input. The length is the number - * of {@code byte}s, FNC1 characters or ECIs in the sequence. - * - * @return the number of {@code char}s in this sequence - */ - fn length(&self) -> i32 { - return self.bytes.len(); -} - + /** + * Returns the length of this input. The length is the number + * of {@code byte}s, FNC1 characters or ECIs in the sequence. + * + * @return the number of {@code char}s in this sequence + */ + fn length(&self) -> i32 { + return self.bytes.len(); + } } impl MinimalECIInput { - /** - * Constructs a minimal input - * - * @param stringToEncode the character string to encode - * @param priorityCharset The preferred {@link Charset}. When the value of the argument is null, the algorithm - * chooses charsets that leads to a minimal representation. Otherwise the algorithm will use the priority - * charset to encode any character in the input that can be encoded by it if the charset is among the - * supported charsets. - * @param fnc1 denotes the character in the input that represents the FNC1 character or -1 if this is not GS1 - * input. - */ - pub fn new( string_to_encode: &String, priority_charset: &Charset, fnc1: i32) -> Self { + * Constructs a minimal input + * + * @param stringToEncode the character string to encode + * @param priorityCharset The preferred {@link Charset}. When the value of the argument is null, the algorithm + * chooses charsets that leads to a minimal representation. Otherwise the algorithm will use the priority + * charset to encode any character in the input that can be encoded by it if the charset is among the + * supported charsets. + * @param fnc1 denotes the character in the input that represents the FNC1 character or -1 if this is not GS1 + * input. + */ + pub fn new(string_to_encode: &String, priority_charset: &Charset, fnc1: i32) -> Self { let mut new_mecii: Self; - new_mecii .fnc1 = fnc1; - let encoder_set: ECIEncoderSet = ECIEncoderSet::new(&string_to_encode, &priority_charset, fnc1); + new_mecii.fnc1 = fnc1; + let encoder_set: ECIEncoderSet = + ECIEncoderSet::new(&string_to_encode, &priority_charset, fnc1); if encoder_set.length() == 1 { //optimization for the case when all can be encoded without ECI in ISO-8859-1 - bytes = [0; string_to_encode.length()]; - { - let mut i: i32 = 0; + bytes = [0; string_to_encode.length()]; + { + let mut i: i32 = 0; while i < bytes.len() { { - let c: char = string_to_encode.char_at(i); - bytes[i] = if c == fnc1 { 1000 } else { c as i32 }; + let c: char = string_to_encode.char_at(i); + bytes[i] = if c == fnc1 { 1000 } else { c as i32 }; } i += 1; - } - } - + } + } } else { bytes = ::encode_minimally(&string_to_encode, encoder_set, fnc1); } } - pub fn get_f_n_c1_character(&self) -> i32 { + pub fn get_f_n_c1_character(&self) -> i32 { return self.fnc1; } - - - - - - - - - /** - * Determines if a value is the FNC1 character - * - * @param index the index of the value - * - * @return true if the value at position {@code index} is the FNC1 character - * - * @throws IndexOutOfBoundsException - * if the {@code index} argument is negative or not less than - * {@code length()} - */ - pub fn is_f_n_c1(&self, index: i32) -> Result { + * Determines if a value is the FNC1 character + * + * @param index the index of the value + * + * @return true if the value at position {@code index} is the FNC1 character + * + * @throws IndexOutOfBoundsException + * if the {@code index} argument is negative or not less than + * {@code length()} + */ + pub fn is_f_n_c1(&self, index: i32) -> Result { if index < 0 || index >= self.length() { - return Err( IndexOutOfBoundsException::new(format!("{}", index))); + return Err(IndexOutOfBoundsException::new(format!("{}", index))); } return Ok(self.bytes[index] == 1000); } - - - pub fn to_string(&self) -> String { - let result: StringBuilder = StringBuilder::new(); - { - let mut i: i32 = 0; + pub fn to_string(&self) -> String { + let result: StringBuilder = StringBuilder::new(); + { + let mut i: i32 = 0; while i < self.length() { { if i > 0 { @@ -2959,85 +3103,110 @@ impl MinimalECIInput { } } i += 1; - } - } + } + } return result.to_string(); } - fn add_edge( edges: &Vec>, to: i32, edge: &InputEdge) { - if edges[to][edge.encoderIndex] == null || edges[to][edge.encoderIndex].cachedTotalSize > edge.cachedTotalSize { + fn add_edge(edges: &Vec>, to: i32, edge: &InputEdge) { + if edges[to][edge.encoderIndex] == null + || edges[to][edge.encoderIndex].cachedTotalSize > edge.cachedTotalSize + { edges[to][edge.encoderIndex] = edge; } } - fn add_edges( string_to_encode: &String, encoder_set: &ECIEncoderSet, edges: &Vec>, from: i32, previous: &InputEdge, fnc1: i32) { - let ch: char = string_to_encode.char_at(from); - let mut start: i32 = 0; - let mut end: i32 = encoder_set.length(); - if encoder_set.get_priority_encoder_index() >= 0 && (ch == fnc1 || encoder_set.can_encode(ch, &encoder_set.get_priority_encoder_index())) { + fn add_edges( + string_to_encode: &String, + encoder_set: &ECIEncoderSet, + edges: &Vec>, + from: i32, + previous: &InputEdge, + fnc1: i32, + ) { + let ch: char = string_to_encode.char_at(from); + let mut start: i32 = 0; + let mut end: i32 = encoder_set.length(); + if encoder_set.get_priority_encoder_index() >= 0 + && (ch == fnc1 || encoder_set.can_encode(ch, &encoder_set.get_priority_encoder_index())) + { start = encoder_set.get_priority_encoder_index(); end = start + 1; } - { - let mut i: i32 = start; + { + let mut i: i32 = start; while i < end { { if ch == fnc1 || encoder_set.can_encode(ch, i) { - ::add_edge(edges, from + 1, InputEdge::new(ch, encoder_set, i, previous, fnc1)); + ::add_edge( + edges, + from + 1, + InputEdge::new(ch, encoder_set, i, previous, fnc1), + ); } } i += 1; - } - } - + } + } } - fn encode_minimally( string_to_encode: &String, encoder_set: &ECIEncoderSet, fnc1: i32) -> Result,RuntimeException> { - let input_length: i32 = string_to_encode.length(); + fn encode_minimally( + string_to_encode: &String, + encoder_set: &ECIEncoderSet, + fnc1: i32, + ) -> Result, RuntimeException> { + let input_length: i32 = string_to_encode.length(); // Array that represents vertices. There is a vertex for every character and encoding. - let mut edges: [[Option; encoder_set.length()]; input_length + 1] = [[None; encoder_set.length()]; input_length + 1]; + let mut edges: [[Option; encoder_set.length()]; input_length + 1] = + [[None; encoder_set.length()]; input_length + 1]; ::add_edges(&string_to_encode, encoder_set, edges, 0, null, fnc1); - { - let mut i: i32 = 1; + { + let mut i: i32 = 1; while i <= input_length { { - { - let mut j: i32 = 0; + { + let mut j: i32 = 0; while j < encoder_set.length() { { if edges[i][j] != null && i < input_length { - ::add_edges(&string_to_encode, encoder_set, edges, i, edges[i][j], fnc1); + ::add_edges( + &string_to_encode, + encoder_set, + edges, + i, + edges[i][j], + fnc1, + ); } } j += 1; - } - } + } + } //optimize memory by removing edges that have been passed. - { - let mut j: i32 = 0; + { + let mut j: i32 = 0; while j < encoder_set.length() { { edges[i - 1][j] = null; } j += 1; - } - } - + } + } } i += 1; - } - } + } + } - let minimal_j: i32 = -1; - let minimal_size: i32 = Integer::MAX_VALUE; - { - let mut j: i32 = 0; + let minimal_j: i32 = -1; + let minimal_size: i32 = Integer::MAX_VALUE; + { + let mut j: i32 = 0; while j < encoder_set.length() { { if edges[input_length][j] != null { - let edge: InputEdge = edges[input_length][j]; + let edge: InputEdge = edges[input_length][j]; if edge.cachedTotalSize < minimal_size { minimal_size = edge.cachedTotalSize; minimal_j = j; @@ -3045,87 +3214,104 @@ impl MinimalECIInput { } } j += 1; - } - } + } + } if minimal_j < 0 { - return Err( RuntimeException::new(format!("Internal error: failed to encode \"{}\"", string_to_encode))); + return Err(RuntimeException::new(format!( + "Internal error: failed to encode \"{}\"", + string_to_encode + ))); } - let ints_a_l: List =Vec::new(); - let mut current: InputEdge = edges[input_length][minimal_j]; + let ints_a_l: List = Vec::new(); + let mut current: InputEdge = edges[input_length][minimal_j]; while current != null { if current.is_f_n_c1() { ints_a_l.add(0, 1000); } else { - let bytes: Vec = encoder_set.encode(current.c, current.encoderIndex); - { - let mut i: i32 = bytes.len() - 1; + let bytes: Vec = encoder_set.encode(current.c, current.encoderIndex); + { + let mut i: i32 = bytes.len() - 1; while i >= 0 { { ints_a_l.add(0, (bytes[i] & 0xFF)); } i -= 1; - } - } - + } + } } - let previous_encoder_index: i32 = if current.previous == null { 0 } else { current.previous.encoderIndex }; + let previous_encoder_index: i32 = if current.previous == null { + 0 + } else { + current.previous.encoderIndex + }; if previous_encoder_index != current.encoderIndex { ints_a_l.add(0, 256 + encoder_set.get_e_c_i_value(current.encoderIndex)); } current = current.previous; } - let mut ints: [i32; ints_a_l.size()] = [0; ints_a_l.size()]; - { - let mut i: i32 = 0; + let mut ints: [i32; ints_a_l.size()] = [0; ints_a_l.size()]; + { + let mut i: i32 = 0; while i < ints.len() { { ints[i] = ints_a_l.get(i); } i += 1; - } - } + } + } return ints; } - } struct InputEdge { - c: char, - //the encoding of this edge + //the encoding of this edge encoder_index: i32, previous: InputEdge, - cached_total_size: i32 + cached_total_size: i32, } impl InputEdge { + fn new( + c: char, + encoder_set: &ECIEncoderSet, + encoder_index: i32, + previous: &InputEdge, + fnc1: i32, + ) -> Self { + let mut new_ie: Self; + new_ie.c = if c == fnc1 { 1000 } else { c }; + new_ie.encoderIndex = encoder_index; + new_ie.previous = previous; + let mut size: i32 = if new_ie.c == 1000 { + 1 + } else { + encoder_set.encode(c, encoder_index).len() + }; + let previous_encoder_index: i32 = if previous == null { + 0 + } else { + previous.encoderIndex + }; + if previous_encoder_index != encoder_index { + size += COST_PER_ECI; + } + if previous != null { + size += previous.cachedTotalSize; + } + new_ie.cachedTotalSize = size; - fn new( c: char, encoder_set: &ECIEncoderSet, encoder_index: i32, previous: &InputEdge, fnc1: i32) -> Self { - let mut new_ie : Self; - new_ie .c = if c == fnc1 { 1000 } else { c }; - new_ie .encoderIndex = encoder_index; - new_ie .previous = previous; - let mut size: i32 = if new_ie .c == 1000 { 1 } else { encoder_set.encode(c, encoder_index).len() }; - let previous_encoder_index: i32 = if previous == null { 0 } else { previous.encoderIndex }; - if previous_encoder_index != encoder_index { - size += COST_PER_ECI; - } - if previous != null { - size += previous.cachedTotalSize; - } - new_ie .cachedTotalSize = size; + new_ie + } - new_ie - } - - fn is_f_n_c1(&self) -> bool { - return self.c == 1000; - } + fn is_f_n_c1(&self) -> bool { + return self.c == 1000; + } } // PerspectiveTransform.java @@ -3137,39 +3323,76 @@ impl InputEdge { * @author Sean Owen */ pub struct PerspectiveTransform { + a11: f32, - a11: f32, + a12: f32, - a12: f32, + a13: f32, - a13: f32, + a21: f32, - a21: f32, + a22: f32, - a22: f32, + a23: f32, - a23: f32, + a31: f32, - a31: f32, + a32: f32, - a32: f32, - - a33: f32 + a33: f32, } impl PerspectiveTransform { + fn new( + a11: f32, + a21: f32, + a31: f32, + a12: f32, + a22: f32, + a32: f32, + a13: f32, + a23: f32, + a33: f32, + ) -> Self { + Self { + a11: a11, + a12: a12, + a13: a13, + a21: a21, + a22: a22, + a23: a23, + a31: a31, + a32: a32, + a33: a33, + } + } - fn new( a11: f32, a21: f32, a31: f32, a12: f32, a22: f32, a32: f32, a13: f32, a23: f32, a33: f32) -> Self { - Self { a11: a11, a12: a12, a13: a13, a21: a21, a22: a22, a23: a23, a31: a31, a32: a32, a33: a33 } - } + pub fn quadrilateral_to_quadrilateral( + x0: f32, + y0: f32, + x1: f32, + y1: f32, + x2: f32, + y2: f32, + x3: f32, + y3: f32, + x0p: f32, + y0p: f32, + x1p: f32, + y1p: f32, + x2p: f32, + y2p: f32, + x3p: f32, + y3p: f32, + ) -> PerspectiveTransform { + let q_to_s: PerspectiveTransform = + ::quadrilateral_to_square(x0, y0, x1, y1, x2, y2, x3, y3); + let s_to_q: PerspectiveTransform = + ::square_to_quadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p); + return s_to_q.times(&q_to_s); + } - pub fn quadrilateral_to_quadrilateral( x0: f32, y0: f32, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32, x0p: f32, y0p: f32, x1p: f32, y1p: f32, x2p: f32, y2p: f32, x3p: f32, y3p: f32) -> PerspectiveTransform { - let q_to_s: PerspectiveTransform = ::quadrilateral_to_square(x0, y0, x1, y1, x2, y2, x3, y3); - let s_to_q: PerspectiveTransform = ::square_to_quadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p); - return s_to_q.times(&q_to_s); - } - - pub fn transform_points(&self, points: &Vec) { + pub fn transform_points(&self, points: &Vec) { let a11: f32 = self.a11; let a12: f32 = self.a12; let a13: f32 = self.a13; @@ -3179,49 +3402,66 @@ impl PerspectiveTransform { let a31: f32 = self.a31; let a32: f32 = self.a32; let a33: f32 = self.a33; - // points.length must be even + // points.length must be even let max_i: i32 = points.len() - 1; { let mut i: i32 = 0; - while i < max_i { - { + while i < max_i { + { let x: f32 = points[i]; let y: f32 = points[i + 1]; let denominator: f32 = a13 * x + a23 * y + a33; - points[i] = (a11 * x + a21 * y + a31) / denominator; - points[i + 1] = (a12 * x + a22 * y + a32) / denominator; - } - i += 2; + points[i] = (a11 * x + a21 * y + a31) / denominator; + points[i + 1] = (a12 * x + a22 * y + a32) / denominator; + } + i += 2; } } + } - } - - pub fn transform_points(&self, x_values: &Vec, y_values: &Vec) { + pub fn transform_points(&self, x_values: &Vec, y_values: &Vec) { let n: i32 = x_values.len(); { let mut i: i32 = 0; - while i < n { - { + while i < n { + { let x: f32 = x_values[i]; let y: f32 = y_values[i]; let denominator: f32 = self.a13 * x + self.a23 * y + self.a33; - x_values[i] = (self.a11 * x + self.a21 * y + self.a31) / denominator; - y_values[i] = (self.a12 * x + self.a22 * y + self.a32) / denominator; - } - i += 1; + x_values[i] = (self.a11 * x + self.a21 * y + self.a31) / denominator; + y_values[i] = (self.a12 * x + self.a22 * y + self.a32) / denominator; + } + i += 1; } } + } - } - - pub fn square_to_quadrilateral( x0: f32, y0: f32, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32) -> PerspectiveTransform { + pub fn square_to_quadrilateral( + x0: f32, + y0: f32, + x1: f32, + y1: f32, + x2: f32, + y2: f32, + x3: f32, + y3: f32, + ) -> PerspectiveTransform { let dx3: f32 = x0 - x1 + x2 - x3; let dy3: f32 = y0 - y1 + y2 - y3; - if dx3 == 0.0f32 && dy3 == 0.0f32 { - // Affine - return PerspectiveTransform::new(x1 - x0, x2 - x1, x0, y1 - y0, y2 - y1, y0, 0.0f32, 0.0f32, 1.0f32); - } else { + if dx3 == 0.0f32 && dy3 == 0.0f32 { + // Affine + return PerspectiveTransform::new( + x1 - x0, + x2 - x1, + x0, + y1 - y0, + y2 - y1, + y0, + 0.0f32, + 0.0f32, + 1.0f32, + ); + } else { let dx1: f32 = x1 - x2; let dx2: f32 = x3 - x2; let dy1: f32 = y1 - y2; @@ -3229,23 +3469,62 @@ impl PerspectiveTransform { let denominator: f32 = dx1 * dy2 - dx2 * dy1; let a13: f32 = (dx3 * dy2 - dx2 * dy3) / denominator; let a23: f32 = (dx1 * dy3 - dx3 * dy1) / denominator; - return PerspectiveTransform::new(x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0, y1 - y0 + a13 * y1, y3 - y0 + a23 * y3, y0, a13, a23, 1.0f32); - } - } + return PerspectiveTransform::new( + x1 - x0 + a13 * x1, + x3 - x0 + a23 * x3, + x0, + y1 - y0 + a13 * y1, + y3 - y0 + a23 * y3, + y0, + a13, + a23, + 1.0f32, + ); + } + } - pub fn quadrilateral_to_square( x0: f32, y0: f32, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32) -> PerspectiveTransform { - // Here, the adjoint serves as the inverse: - return ::square_to_quadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).build_adjoint(); - } + pub fn quadrilateral_to_square( + x0: f32, + y0: f32, + x1: f32, + y1: f32, + x2: f32, + y2: f32, + x3: f32, + y3: f32, + ) -> PerspectiveTransform { + // Here, the adjoint serves as the inverse: + return ::square_to_quadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).build_adjoint(); + } - fn build_adjoint(&self) -> PerspectiveTransform { - // Adjoint is the transpose of the cofactor matrix: - return PerspectiveTransform::new(self.a22 * self.a33 - self.a23 * self.a32, self.a23 * self.a31 - self.a21 * self.a33, self.a21 * self.a32 - self.a22 * self.a31, self.a13 * self.a32 - self.a12 * self.a33, self.a11 * self.a33 - self.a13 * self.a31, self.a12 * self.a31 - self.a11 * self.a32, self.a12 * self.a23 - self.a13 * self.a22, self.a13 * self.a21 - self.a11 * self.a23, self.a11 * self.a22 - self.a12 * self.a21); - } + fn build_adjoint(&self) -> PerspectiveTransform { + // Adjoint is the transpose of the cofactor matrix: + return PerspectiveTransform::new( + self.a22 * self.a33 - self.a23 * self.a32, + self.a23 * self.a31 - self.a21 * self.a33, + self.a21 * self.a32 - self.a22 * self.a31, + self.a13 * self.a32 - self.a12 * self.a33, + self.a11 * self.a33 - self.a13 * self.a31, + self.a12 * self.a31 - self.a11 * self.a32, + self.a12 * self.a23 - self.a13 * self.a22, + self.a13 * self.a21 - self.a11 * self.a23, + self.a11 * self.a22 - self.a12 * self.a21, + ); + } - fn times(&self, other: &PerspectiveTransform) -> PerspectiveTransform { - return PerspectiveTransform::new(self.a11 * other.a11 + self.a21 * other.a12 + self.a31 * other.a13, self.a11 * other.a21 + self.a21 * other.a22 + self.a31 * other.a23, self.a11 * other.a31 + self.a21 * other.a32 + self.a31 * other.a33, self.a12 * other.a11 + self.a22 * other.a12 + self.a32 * other.a13, self.a12 * other.a21 + self.a22 * other.a22 + self.a32 * other.a23, self.a12 * other.a31 + self.a22 * other.a32 + self.a32 * other.a33, self.a13 * other.a11 + self.a23 * other.a12 + self.a33 * other.a13, self.a13 * other.a21 + self.a23 * other.a22 + self.a33 * other.a23, self.a13 * other.a31 + self.a23 * other.a32 + self.a33 * other.a33); - } + fn times(&self, other: &PerspectiveTransform) -> PerspectiveTransform { + return PerspectiveTransform::new( + self.a11 * other.a11 + self.a21 * other.a12 + self.a31 * other.a13, + self.a11 * other.a21 + self.a21 * other.a22 + self.a31 * other.a23, + self.a11 * other.a31 + self.a21 * other.a32 + self.a31 * other.a33, + self.a12 * other.a11 + self.a22 * other.a12 + self.a32 * other.a13, + self.a12 * other.a21 + self.a22 * other.a22 + self.a32 * other.a23, + self.a12 * other.a31 + self.a22 * other.a32 + self.a32 * other.a33, + self.a13 * other.a11 + self.a23 * other.a12 + self.a33 * other.a13, + self.a13 * other.a21 + self.a23 * other.a22 + self.a33 * other.a23, + self.a13 * other.a31 + self.a23 * other.a32 + self.a33 * other.a33, + ); + } } // StringUtils.java @@ -3264,58 +3543,59 @@ const GB2312_CHARSET: Charset = Charset::for_name("GB2312"); const EUC_JP: Charset = Charset::for_name("EUC_JP"); -const ASSUME_SHIFT_JIS: bool = SHIFT_JIS_CHARSET::equals(&PLATFORM_DEFAULT_ENCODING) || EUC_JP::equals(&PLATFORM_DEFAULT_ENCODING); +const ASSUME_SHIFT_JIS: bool = SHIFT_JIS_CHARSET::equals(&PLATFORM_DEFAULT_ENCODING) + || EUC_JP::equals(&PLATFORM_DEFAULT_ENCODING); // Retained for ABI compatibility with earlier versions const SHIFT_JIS: &'static str = "SJIS"; const GB2312: &'static str = "GB2312"; -pub struct StringUtils { -} +pub struct StringUtils {} impl StringUtils { + fn new() -> StringUtils {} - fn new() -> StringUtils { - } - - /** - * @param bytes bytes encoding a string, whose encoding should be guessed - * @param hints decode hints if applicable - * @return name of guessed encoding; at the moment will only guess one of: - * "SJIS", "UTF8", "ISO8859_1", or the platform default encoding if none - * of these can possibly be correct - */ - pub fn guess_encoding( bytes: &Vec, hints: &HashMap) -> &str { + /** + * @param bytes bytes encoding a string, whose encoding should be guessed + * @param hints decode hints if applicable + * @return name of guessed encoding; at the moment will only guess one of: + * "SJIS", "UTF8", "ISO8859_1", or the platform default encoding if none + * of these can possibly be correct + */ + pub fn guess_encoding(bytes: &Vec, hints: &HashMap) -> &str { let c: Charset = ::guess_charset(&bytes, &hints); - if c == SHIFT_JIS_CHARSET { - return "SJIS"; - } else if c == StandardCharsets::UTF_8 { - return "UTF8"; - } else if c == StandardCharsets::ISO_8859_1 { - return "ISO8859_1"; - } - return c.name(); - } + if c == SHIFT_JIS_CHARSET { + return "SJIS"; + } else if c == StandardCharsets::UTF_8 { + return "UTF8"; + } else if c == StandardCharsets::ISO_8859_1 { + return "ISO8859_1"; + } + return c.name(); + } - /** - * @param bytes bytes encoding a string, whose encoding should be guessed - * @param hints decode hints if applicable - * @return Charset of guessed encoding; at the moment will only guess one of: - * {@link #SHIFT_JIS_CHARSET}, {@link StandardCharsets#UTF_8}, - * {@link StandardCharsets#ISO_8859_1}, {@link StandardCharsets#UTF_16}, - * or the platform default encoding if - * none of these can possibly be correct - */ - pub fn guess_charset( bytes: &Vec, hints: &HashMap) -> Charset { - if hints != null && hints.contains_key(DecodeHintType::CHARACTER_SET) { - return Charset::for_name(&hints.get(DecodeHintType::CHARACTER_SET).to_string()); - } - // First try UTF-16, assuming anything with its BOM is UTF-16 - if bytes.len() > 2 && ((bytes[0] == 0xFE as i8 && bytes[1] == 0xFF as i8) || (bytes[0] == 0xFF as i8 && bytes[1] == 0xFE as i8)) { - return StandardCharsets::UTF_16; - } - // For now, merely tries to distinguish ISO-8859-1, UTF-8 and Shift_JIS, - // which should be by far the most common encodings. + /** + * @param bytes bytes encoding a string, whose encoding should be guessed + * @param hints decode hints if applicable + * @return Charset of guessed encoding; at the moment will only guess one of: + * {@link #SHIFT_JIS_CHARSET}, {@link StandardCharsets#UTF_8}, + * {@link StandardCharsets#ISO_8859_1}, {@link StandardCharsets#UTF_16}, + * or the platform default encoding if + * none of these can possibly be correct + */ + pub fn guess_charset(bytes: &Vec, hints: &HashMap) -> Charset { + if hints != null && hints.contains_key(DecodeHintType::CHARACTER_SET) { + return Charset::for_name(&hints.get(DecodeHintType::CHARACTER_SET).to_string()); + } + // First try UTF-16, assuming anything with its BOM is UTF-16 + if bytes.len() > 2 + && ((bytes[0] == 0xFE as i8 && bytes[1] == 0xFF as i8) + || (bytes[0] == 0xFF as i8 && bytes[1] == 0xFE as i8)) + { + return StandardCharsets::UTF_16; + } + // For now, merely tries to distinguish ISO-8859-1, UTF-8 and Shift_JIS, + // which should be by far the most common encodings. let length: i32 = bytes.len(); let can_be_i_s_o88591: bool = true; let can_be_shift_j_i_s: bool = true; @@ -3331,117 +3611,132 @@ impl StringUtils { let sjis_max_katakana_word_length: i32 = 0; let sjis_max_double_bytes_word_length: i32 = 0; let iso_high_other: i32 = 0; - let utf8bom: bool = bytes.len() > 3 && bytes[0] == 0xEF as i8 && bytes[1] == 0xBB as i8 && bytes[2] == 0xBF as i8; + let utf8bom: bool = bytes.len() > 3 + && bytes[0] == 0xEF as i8 + && bytes[1] == 0xBB as i8 + && bytes[2] == 0xBF as i8; { let mut i: i32 = 0; - while i < length && (can_be_i_s_o88591 || can_be_shift_j_i_s || can_be_u_t_f8) { - { + while i < length && (can_be_i_s_o88591 || can_be_shift_j_i_s || can_be_u_t_f8) { + { let value: i32 = bytes[i] & 0xFF; - // UTF-8 stuff - if can_be_u_t_f8 { - if utf8_bytes_left > 0 { - if (value & 0x80) == 0 { - can_be_u_t_f8 = false; - } else { - utf8_bytes_left -= 1; - } - } else if (value & 0x80) != 0 { - if (value & 0x40) == 0 { - can_be_u_t_f8 = false; - } else { - utf8_bytes_left += 1; - if (value & 0x20) == 0 { - utf2_bytes_chars += 1; - } else { - utf8_bytes_left += 1; - if (value & 0x10) == 0 { - utf3_bytes_chars += 1; - } else { - utf8_bytes_left += 1; - if (value & 0x08) == 0 { - utf4_bytes_chars += 1; - } else { - can_be_u_t_f8 = false; - } - } - } - } - } - } - // ISO-8859-1 stuff - if can_be_i_s_o88591 { - if value > 0x7F && value < 0xA0 { - can_be_i_s_o88591 = false; - } else if value > 0x9F && (value < 0xC0 || value == 0xD7 || value == 0xF7) { - iso_high_other += 1; - } - } - // Shift_JIS stuff - if can_be_shift_j_i_s { - if sjis_bytes_left > 0 { - if value < 0x40 || value == 0x7F || value > 0xFC { - can_be_shift_j_i_s = false; - } else { - sjis_bytes_left -= 1; - } - } else if value == 0x80 || value == 0xA0 || value > 0xEF { - can_be_shift_j_i_s = false; - } else if value > 0xA0 && value < 0xE0 { - sjis_katakana_chars += 1; - sjis_cur_double_bytes_word_length = 0; - sjis_cur_katakana_word_length += 1; - if sjis_cur_katakana_word_length > sjis_max_katakana_word_length { - sjis_max_katakana_word_length = sjis_cur_katakana_word_length; - } - } else if value > 0x7F { - sjis_bytes_left += 1; - //sjisDoubleBytesChars++; - sjis_cur_katakana_word_length = 0; - sjis_cur_double_bytes_word_length += 1; - if sjis_cur_double_bytes_word_length > sjis_max_double_bytes_word_length { - sjis_max_double_bytes_word_length = sjis_cur_double_bytes_word_length; - } - } else { - //sjisLowChars++; - sjis_cur_katakana_word_length = 0; - sjis_cur_double_bytes_word_length = 0; - } - } - } - i += 1; + // UTF-8 stuff + if can_be_u_t_f8 { + if utf8_bytes_left > 0 { + if (value & 0x80) == 0 { + can_be_u_t_f8 = false; + } else { + utf8_bytes_left -= 1; + } + } else if (value & 0x80) != 0 { + if (value & 0x40) == 0 { + can_be_u_t_f8 = false; + } else { + utf8_bytes_left += 1; + if (value & 0x20) == 0 { + utf2_bytes_chars += 1; + } else { + utf8_bytes_left += 1; + if (value & 0x10) == 0 { + utf3_bytes_chars += 1; + } else { + utf8_bytes_left += 1; + if (value & 0x08) == 0 { + utf4_bytes_chars += 1; + } else { + can_be_u_t_f8 = false; + } + } + } + } + } + } + // ISO-8859-1 stuff + if can_be_i_s_o88591 { + if value > 0x7F && value < 0xA0 { + can_be_i_s_o88591 = false; + } else if value > 0x9F && (value < 0xC0 || value == 0xD7 || value == 0xF7) { + iso_high_other += 1; + } + } + // Shift_JIS stuff + if can_be_shift_j_i_s { + if sjis_bytes_left > 0 { + if value < 0x40 || value == 0x7F || value > 0xFC { + can_be_shift_j_i_s = false; + } else { + sjis_bytes_left -= 1; + } + } else if value == 0x80 || value == 0xA0 || value > 0xEF { + can_be_shift_j_i_s = false; + } else if value > 0xA0 && value < 0xE0 { + sjis_katakana_chars += 1; + sjis_cur_double_bytes_word_length = 0; + sjis_cur_katakana_word_length += 1; + if sjis_cur_katakana_word_length > sjis_max_katakana_word_length { + sjis_max_katakana_word_length = sjis_cur_katakana_word_length; + } + } else if value > 0x7F { + sjis_bytes_left += 1; + //sjisDoubleBytesChars++; + sjis_cur_katakana_word_length = 0; + sjis_cur_double_bytes_word_length += 1; + if sjis_cur_double_bytes_word_length > sjis_max_double_bytes_word_length + { + sjis_max_double_bytes_word_length = + sjis_cur_double_bytes_word_length; + } + } else { + //sjisLowChars++; + sjis_cur_katakana_word_length = 0; + sjis_cur_double_bytes_word_length = 0; + } + } + } + i += 1; } } - if can_be_u_t_f8 && utf8_bytes_left > 0 { - can_be_u_t_f8 = false; - } - if can_be_shift_j_i_s && sjis_bytes_left > 0 { - can_be_shift_j_i_s = false; - } - // Easy -- if there is BOM or at least 1 valid not-single byte character (and no evidence it can't be UTF-8), done - if can_be_u_t_f8 && (utf8bom || utf2_bytes_chars + utf3_bytes_chars + utf4_bytes_chars > 0) { - return StandardCharsets::UTF_8; - } - // Easy -- if assuming Shift_JIS or >= 3 valid consecutive not-ascii characters (and no evidence it can't be), done - if can_be_shift_j_i_s && (ASSUME_SHIFT_JIS || sjis_max_katakana_word_length >= 3 || sjis_max_double_bytes_word_length >= 3) { - return SHIFT_JIS_CHARSET; - } - // - then we conclude Shift_JIS, else ISO-8859-1 - if can_be_i_s_o88591 && can_be_shift_j_i_s { - return if (sjis_max_katakana_word_length == 2 && sjis_katakana_chars == 2) || iso_high_other * 10 >= length { SHIFT_JIS_CHARSET } else { StandardCharsets::ISO_8859_1 }; - } - // Otherwise, try in order ISO-8859-1, Shift JIS, UTF-8 and fall back to default platform encoding - if can_be_i_s_o88591 { - return StandardCharsets::ISO_8859_1; - } - if can_be_shift_j_i_s { - return SHIFT_JIS_CHARSET; - } - if can_be_u_t_f8 { - return StandardCharsets::UTF_8; - } - // Otherwise, we take a wild guess with platform encoding - return PLATFORM_DEFAULT_ENCODING; - } + if can_be_u_t_f8 && utf8_bytes_left > 0 { + can_be_u_t_f8 = false; + } + if can_be_shift_j_i_s && sjis_bytes_left > 0 { + can_be_shift_j_i_s = false; + } + // Easy -- if there is BOM or at least 1 valid not-single byte character (and no evidence it can't be UTF-8), done + if can_be_u_t_f8 && (utf8bom || utf2_bytes_chars + utf3_bytes_chars + utf4_bytes_chars > 0) + { + return StandardCharsets::UTF_8; + } + // Easy -- if assuming Shift_JIS or >= 3 valid consecutive not-ascii characters (and no evidence it can't be), done + if can_be_shift_j_i_s + && (ASSUME_SHIFT_JIS + || sjis_max_katakana_word_length >= 3 + || sjis_max_double_bytes_word_length >= 3) + { + return SHIFT_JIS_CHARSET; + } + // - then we conclude Shift_JIS, else ISO-8859-1 + if can_be_i_s_o88591 && can_be_shift_j_i_s { + return if (sjis_max_katakana_word_length == 2 && sjis_katakana_chars == 2) + || iso_high_other * 10 >= length + { + SHIFT_JIS_CHARSET + } else { + StandardCharsets::ISO_8859_1 + }; + } + // Otherwise, try in order ISO-8859-1, Shift JIS, UTF-8 and fall back to default platform encoding + if can_be_i_s_o88591 { + return StandardCharsets::ISO_8859_1; + } + if can_be_shift_j_i_s { + return SHIFT_JIS_CHARSET; + } + if can_be_u_t_f8 { + return StandardCharsets::UTF_8; + } + // Otherwise, we take a wild guess with platform encoding + return PLATFORM_DEFAULT_ENCODING; + } } - diff --git a/src/common/detector.rs b/src/common/detector.rs index 2a0dd07..7a566ea 100644 --- a/src/common/detector.rs +++ b/src/common/detector.rs @@ -1,65 +1,63 @@ -use crate::{NotFoundException,ResultPoint}; -use crate::common::{BitMatrix,BitMatrix}; +use crate::common::{BitMatrix, BitMatrix}; +use crate::{NotFoundException, ResultPoint}; // MathUtils.java /** * General math-related and numeric utility functions. */ -pub struct MathUtils { -} +pub struct MathUtils {} impl MathUtils { - fn new() -> Self { - Self{} + Self {} } /** - * Ends up being a bit faster than {@link Math#round(float)}. This merely rounds its - * argument to the nearest int, where x.5 rounds up to x+1. Semantics of this shortcut - * differ slightly from {@link Math#round(float)} in that half rounds down for negative - * values. -2.5 rounds to -3, not -2. For purposes here it makes no difference. - * - * @param d real value to round - * @return nearest {@code int} - */ - pub fn round( d: f32) -> i32 { - return (d + ( if d < 0.0f32 { -0.5f32 } else { 0.5f32 })) as i32; + * Ends up being a bit faster than {@link Math#round(float)}. This merely rounds its + * argument to the nearest int, where x.5 rounds up to x+1. Semantics of this shortcut + * differ slightly from {@link Math#round(float)} in that half rounds down for negative + * values. -2.5 rounds to -3, not -2. For purposes here it makes no difference. + * + * @param d real value to round + * @return nearest {@code int} + */ + pub fn round(d: f32) -> i32 { + return (d + (if d < 0.0f32 { -0.5f32 } else { 0.5f32 })) as i32; } /** - * @param aX point A x coordinate - * @param aY point A y coordinate - * @param bX point B x coordinate - * @param bY point B y coordinate - * @return Euclidean distance between points A and B - */ - 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 y_diff: f64 = a_y - b_y; + * @param aX point A x coordinate + * @param aY point A y coordinate + * @param bX point B x coordinate + * @param bY point B y coordinate + * @return Euclidean distance between points A and B + */ + 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 y_diff: f64 = a_y - b_y; return Math::sqrt(x_diff * x_diff + y_diff * y_diff) as f32; } /** - * @param aX point A x coordinate - * @param aY point A y coordinate - * @param bX point B x coordinate - * @param bY point B y coordinate - * @return Euclidean distance between points A and B - */ - 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 y_diff: f64 = a_y - b_y; + * @param aX point A x coordinate + * @param aY point A y coordinate + * @param bX point B x coordinate + * @param bY point B y coordinate + * @return Euclidean distance between points A and B + */ + 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 y_diff: f64 = a_y - b_y; return Math::sqrt(x_diff * x_diff + y_diff * y_diff) as f32; } /** - * @param array values to sum - * @return sum of values in array - */ - pub fn sum( array: &Vec) -> i32 { - let mut count: i32 = 0; - for a in array { + * @param array values to sum + * @return sum of values in array + */ + pub fn sum(array: &Vec) -> i32 { + let mut count: i32 = 0; + for a in array { count += a; } return count; @@ -79,76 +77,135 @@ impl MathUtils { const MAX_MODULES: i32 = 32; #[deprecated] pub struct MonochromeRectangleDetector { - - image: BitMatrix + image: BitMatrix, } impl MonochromeRectangleDetector { - - pub fn new( image: &BitMatrix) -> Self { - Self{ image } + pub fn new(image: &BitMatrix) -> Self { + Self { image } } /** - *

Detects a rectangular region of black and white -- mostly black -- with a region of mostly - * white, in an image.

- * - * @return {@link ResultPoint}[] describing the corners of the rectangular region. The first and - * last points are opposed on the diagonal, as are the second and third. The first point will be - * the topmost point and the last, the bottommost. The second point will be leftmost and the - * third, the rightmost - * @throws NotFoundException if no Data Matrix Code can be found - */ - pub fn detect(&self) -> /* throws NotFoundException */Result, Rc> { - let height: i32 = self.image.get_height(); - let width: i32 = self.image.get_width(); - let half_height: i32 = height / 2; - let half_width: i32 = width / 2; - let delta_y: i32 = Math::max(1, height / (MAX_MODULES * 8)); - let delta_x: i32 = Math::max(1, width / (MAX_MODULES * 8)); - let mut top: i32 = 0; - let mut bottom: i32 = height; - let mut left: i32 = 0; - 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); + *

Detects a rectangular region of black and white -- mostly black -- with a region of mostly + * white, in an image.

+ * + * @return {@link ResultPoint}[] describing the corners of the rectangular region. The first and + * last points are opposed on the diagonal, as are the second and third. The first point will be + * the topmost point and the last, the bottommost. The second point will be leftmost and the + * third, the rightmost + * @throws NotFoundException if no Data Matrix Code can be found + */ + pub fn detect(&self) -> Result, Rc> { + let height: i32 = self.image.get_height(); + let width: i32 = self.image.get_width(); + let half_height: i32 = height / 2; + let half_width: i32 = width / 2; + let delta_y: i32 = Math::max(1, height / (MAX_MODULES * 8)); + let delta_x: i32 = Math::max(1, width / (MAX_MODULES * 8)); + let mut top: i32 = 0; + let mut bottom: i32 = height; + let mut left: i32 = 0; + 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, + ); 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; - 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; - 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; // 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); - return Ok( vec![point_a, point_b, point_c, point_d, ]); + point_a = self.find_corner_from_center( + 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]); } /** - * Attempts to locate a corner of the barcode by scanning up, down, left or right from a center - * point which should be within the barcode. - * - * @param centerX center's x component (horizontal) - * @param deltaX same as deltaY but change in x per step instead - * @param left minimum value of x - * @param right maximum value of x - * @param centerY center's y component (vertical) - * @param deltaY change in y per step. If scanning up this is negative; down, positive; - * left or right, 0 - * @param top minimum value of y to search through (meaningless when di == 0) - * @param bottom maximum value of y - * @param maxWhiteRun maximum run of white pixels that can still be considered to be within - * the barcode - * @return a {@link ResultPoint} encapsulating the corner that was 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 { - let last_range: Vec = null; - { - let mut y: i32 = center_y; - let mut x: i32 = center_x; + * Attempts to locate a corner of the barcode by scanning up, down, left or right from a center + * point which should be within the barcode. + * + * @param centerX center's x component (horizontal) + * @param deltaX same as deltaY but change in x per step instead + * @param left minimum value of x + * @param right maximum value of x + * @param centerY center's y component (vertical) + * @param deltaY change in y per step. If scanning up this is negative; down, positive; + * left or right, 0 + * @param top minimum value of y to search through (meaningless when di == 0) + * @param bottom maximum value of y + * @param maxWhiteRun maximum run of white pixels that can still be considered to be within + * the barcode + * @return a {@link ResultPoint} encapsulating the corner that was 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 { + let last_range: Vec = null; + { + let mut y: i32 = center_y; + let mut x: i32 = center_x; while y < bottom && y >= top && x < right && x >= left { { - let mut range: Vec; + let mut range: Vec; if delta_x == 0 { // horizontal slices, up and down range = self.black_white_range(y, max_white_run, left, right, true); @@ -158,25 +215,31 @@ impl MonochromeRectangleDetector { } if range == null { if last_range == null { - return Err( NotFoundException::get_not_found_instance()); + return Err(NotFoundException::get_not_found_instance()); } // lastRange was found if delta_x == 0 { - let last_y: i32 = y - delta_y; + let last_y: i32 = y - delta_y; if last_range[0] < center_x { if last_range[1] > center_x { // 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)); } else { return Ok(ResultPoint::new(last_range[1], last_y)); } } else { - let last_x: i32 = x - delta_x; + let last_x: i32 = x - delta_x; if last_range[0] < 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])); } else { @@ -188,41 +251,61 @@ impl MonochromeRectangleDetector { } y += delta_y; x += delta_x; - } - } + } + } - return Err( NotFoundException::get_not_found_instance()); + return Err(NotFoundException::get_not_found_instance()); } /** - * Computes the start and end of a region of pixels, either horizontally or vertically, that could - * be part of a Data Matrix barcode. - * - * @param fixedDimension if scanning horizontally, this is the row (the fixed vertical location) - * where we are scanning. If scanning vertically it's the column, the fixed horizontal location - * @param maxWhiteRun largest run of white pixels that can still be considered part of the - * barcode region - * @param minDim minimum pixel location, horizontally or vertically, to consider - * @param maxDim maximum pixel location, horizontally or vertically, to consider - * @param horizontal if true, we're scanning left-right, instead of up-down - * @return int[] with start and end of found range, or null if no such range is 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> { - let center: i32 = (min_dim + max_dim) / 2; + * Computes the start and end of a region of pixels, either horizontally or vertically, that could + * be part of a Data Matrix barcode. + * + * @param fixedDimension if scanning horizontally, this is the row (the fixed vertical location) + * where we are scanning. If scanning vertically it's the column, the fixed horizontal location + * @param maxWhiteRun largest run of white pixels that can still be considered part of the + * barcode region + * @param minDim minimum pixel location, horizontally or vertically, to consider + * @param maxDim maximum pixel location, horizontally or vertically, to consider + * @param horizontal if true, we're scanning left-right, instead of up-down + * @return int[] with start and end of found range, or null if no such range is 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> { + let center: i32 = (min_dim + max_dim) / 2; // Scan left/up first - let mut start: i32 = center; + let mut start: i32 = center; 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; } else { - let white_run_start: i32 = start; - loop { { - start -= 1; - }if !(start >= min_dim && !( if horizontal { self.image.get(start, fixed_dimension) } else { self.image.get(fixed_dimension, start) })) { - break; - } } - let white_run_size: i32 = white_run_start - start; + let white_run_start: i32 = start; + loop { + { + start -= 1; + } + if !(start >= min_dim + && !(if horizontal { + self.image.get(start, fixed_dimension) + } else { + self.image.get(fixed_dimension, start) + })) + { + break; + } + } + let white_run_size: i32 = white_run_start - start; if start < min_dim || white_run_size > max_white_run { start = white_run_start; break; @@ -231,16 +314,31 @@ impl MonochromeRectangleDetector { } start += 1; // Then try right/down - let mut end: i32 = center; + let mut end: i32 = center; 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; } else { - let white_run_start: i32 = end; - loop { { - end += 1; - }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_start: i32 = end; + loop { + { + end += 1; + } + 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; if end >= max_dim || white_run_size > max_white_run { end = white_run_start; break; @@ -248,8 +346,11 @@ impl MonochromeRectangleDetector { } } end -= 1; - return if end > start { Some(vec![start, end, ]) - } else { null }; + return if end > start { + Some(vec![start, end]) + } else { + null + }; } } @@ -269,66 +370,74 @@ const INIT_SIZE: i32 = 10; const CORR: i32 = 1; pub struct WhiteRectangleDetector { + image: BitMatrix, - image: BitMatrix, + height: i32, - height: i32, + width: i32, - width: i32, + left_init: i32, - left_init: i32, + right_init: i32, - right_init: i32, + down_init: i32, - down_init: i32, - - up_init: i32 + up_init: i32, } impl WhiteRectangleDetector { + pub fn new(image: &BitMatrix) -> Result { + this( + image, + INIT_SIZE, + image.get_width() / 2, + image.get_height() / 2, + ) + } - pub fn new( image: &BitMatrix) -> Result { - this(image, INIT_SIZE, image.get_width() / 2, image.get_height() / 2) - } - - /** - * @param image barcode image to find a rectangle in - * @param initSize initial size of search area around center - * @param x x position of search center - * @param y y position of search center - * @throws NotFoundException if image is too small to accommodate {@code initSize} - */ - pub fn new( image: &BitMatrix, init_size: i32, x: i32, y: i32) -> Result { - let mut new_wrd : Self; - new_wrd .image = image; - new_wrd.height = image.get_height(); - new_wrd.width = image.get_width(); + /** + * @param image barcode image to find a rectangle in + * @param initSize initial size of search area around center + * @param x x position of search center + * @param y y position of search center + * @throws NotFoundException if image is too small to accommodate {@code initSize} + */ + pub fn new( + image: &BitMatrix, + init_size: i32, + x: i32, + y: i32, + ) -> Result { + let mut new_wrd: Self; + new_wrd.image = image; + new_wrd.height = image.get_height(); + new_wrd.width = image.get_width(); let halfsize: i32 = init_size / 2; new_wrd.left_init = x - halfsize; new_wrd.right_init = x + halfsize; new_wrd.up_init = y - halfsize; new_wrd.down_init = y + halfsize; - if up_init < 0 || left_init < 0 || down_init >= height || right_init >= width { - return Err( NotFoundException::get_not_found_instance()); - } - Ok(new_wrd) - } + if up_init < 0 || left_init < 0 || down_init >= height || right_init >= width { + return Err(NotFoundException::get_not_found_instance()); + } + Ok(new_wrd) + } - /** - *

- * Detects a candidate barcode-like rectangular region within an image. It - * starts around the center of the image, increases the size of the candidate - * region until it finds a white rectangular region. - *

- * - * @return {@link ResultPoint}[] describing the corners of the rectangular - * region. The first and last points are opposed on the diagonal, as - * are the second and third. The first point will be the topmost - * point and the last, the bottommost. The second point will be - * leftmost and the third, the rightmost - * @throws NotFoundException if no Data Matrix Code can be found - */ - pub fn detect(&self) -> Result, NotFoundException> { + /** + *

+ * Detects a candidate barcode-like rectangular region within an image. It + * starts around the center of the image, increases the size of the candidate + * region until it finds a white rectangular region. + *

+ * + * @return {@link ResultPoint}[] describing the corners of the rectangular + * region. The first and last points are opposed on the diagonal, as + * are the second and third. The first point will be the topmost + * point and the last, the bottommost. The second point will be + * leftmost and the third, the rightmost + * @throws NotFoundException if no Data Matrix Code can be found + */ + pub fn detect(&self) -> Result, NotFoundException> { let mut left: i32 = self.left_init; let mut right: i32 = self.right_init; let mut up: i32 = self.up_init; @@ -339,189 +448,205 @@ impl WhiteRectangleDetector { let at_least_one_black_point_found_on_bottom: bool = false; let at_least_one_black_point_found_on_left: bool = false; let at_least_one_black_point_found_on_top: bool = false; - while a_black_point_found_on_border { - a_black_point_found_on_border = false; - // ..... - // . | - // ..... + while a_black_point_found_on_border { + a_black_point_found_on_border = false; + // ..... + // . | + // ..... let right_border_not_white: bool = true; - 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); - if right_border_not_white { - right += 1; - a_black_point_found_on_border = true; - at_least_one_black_point_found_on_right = true; - } else if !at_least_one_black_point_found_on_right { - right += 1; - } - } - if right >= self.width { - size_exceeded = true; - break; - } - // ..... - // . . - // .___. + 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); + if right_border_not_white { + right += 1; + a_black_point_found_on_border = true; + at_least_one_black_point_found_on_right = true; + } else if !at_least_one_black_point_found_on_right { + right += 1; + } + } + if right >= self.width { + size_exceeded = true; + break; + } + // ..... + // . . + // .___. let bottom_border_not_white: bool = true; - 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); - if bottom_border_not_white { - down += 1; - a_black_point_found_on_border = true; - at_least_one_black_point_found_on_bottom = true; - } else if !at_least_one_black_point_found_on_bottom { - down += 1; - } - } - if down >= self.height { - size_exceeded = true; - break; - } - // ..... - // | . - // ..... + 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); + if bottom_border_not_white { + down += 1; + a_black_point_found_on_border = true; + at_least_one_black_point_found_on_bottom = true; + } else if !at_least_one_black_point_found_on_bottom { + down += 1; + } + } + if down >= self.height { + size_exceeded = true; + break; + } + // ..... + // | . + // ..... let left_border_not_white: bool = true; - while (left_border_not_white || !at_least_one_black_point_found_on_left) && left >= 0 { - left_border_not_white = self.contains_black_point(up, down, left, false); - if left_border_not_white { - left -= 1; - a_black_point_found_on_border = true; - at_least_one_black_point_found_on_left = true; - } else if !at_least_one_black_point_found_on_left { - left -= 1; - } - } - if left < 0 { - size_exceeded = true; - break; - } - // .___. - // . . - // ..... + while (left_border_not_white || !at_least_one_black_point_found_on_left) && left >= 0 { + left_border_not_white = self.contains_black_point(up, down, left, false); + if left_border_not_white { + left -= 1; + a_black_point_found_on_border = true; + at_least_one_black_point_found_on_left = true; + } else if !at_least_one_black_point_found_on_left { + left -= 1; + } + } + if left < 0 { + size_exceeded = true; + break; + } + // .___. + // . . + // ..... let top_border_not_white: bool = true; - while (top_border_not_white || !at_least_one_black_point_found_on_top) && up >= 0 { - top_border_not_white = self.contains_black_point(left, right, up, true); - if top_border_not_white { - up -= 1; - a_black_point_found_on_border = true; - at_least_one_black_point_found_on_top = true; - } else if !at_least_one_black_point_found_on_top { - up -= 1; - } - } - if up < 0 { - size_exceeded = true; - break; - } - } - if !size_exceeded { + while (top_border_not_white || !at_least_one_black_point_found_on_top) && up >= 0 { + top_border_not_white = self.contains_black_point(left, right, up, true); + if top_border_not_white { + up -= 1; + a_black_point_found_on_border = true; + at_least_one_black_point_found_on_top = true; + } else if !at_least_one_black_point_found_on_top { + up -= 1; + } + } + if up < 0 { + size_exceeded = true; + break; + } + } + if !size_exceeded { let max_size: i32 = right - left; let mut z: ResultPoint = null; { let mut i: i32 = 1; - while z == null && i < max_size { - { - z = self.get_black_point_on_segment(left, down - i, left + i, down); - } - i += 1; + while z == null && i < max_size { + { + z = self.get_black_point_on_segment(left, down - i, left + i, down); + } + i += 1; } } - if z == null { - return Err( NotFoundException::get_not_found_instance()); - } + if z == null { + return Err(NotFoundException::get_not_found_instance()); + } let mut t: ResultPoint = null; - //go down right + //go down right { let mut i: i32 = 1; - while t == null && i < max_size { - { - t = self.get_black_point_on_segment(left, up + i, left + i, up); - } - i += 1; + while t == null && i < max_size { + { + t = self.get_black_point_on_segment(left, up + i, left + i, up); + } + i += 1; } } - if t == null { - return Err( NotFoundException::get_not_found_instance()); - } + if t == null { + return Err(NotFoundException::get_not_found_instance()); + } let mut x: ResultPoint = null; - //go down left + //go down left { let mut i: i32 = 1; - while x == null && i < max_size { - { - x = self.get_black_point_on_segment(right, up + i, right - i, up); - } - i += 1; + while x == null && i < max_size { + { + x = self.get_black_point_on_segment(right, up + i, right - i, up); + } + i += 1; } } - if x == null { - return Err( NotFoundException::get_not_found_instance()); - } + if x == null { + return Err(NotFoundException::get_not_found_instance()); + } let mut y: ResultPoint = null; - //go up left + //go up left { let mut i: i32 = 1; - while y == null && i < max_size { - { - y = self.get_black_point_on_segment(right, down - i, right - i, down); - } - i += 1; + while y == null && i < max_size { + { + y = self.get_black_point_on_segment(right, down - i, right - i, down); + } + i += 1; } } - if y == null { - return Err( NotFoundException::get_not_found_instance()); - } - return Ok(self.center_edges(&y, &z, &x, &t)); - } else { - return Err( NotFoundException::get_not_found_instance()); - } - } + if y == null { + return Err(NotFoundException::get_not_found_instance()); + } + return Ok(self.center_edges(&y, &z, &x, &t)); + } else { + 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 { + fn get_black_point_on_segment( + &self, + a_x: f32, + a_y: f32, + b_x: f32, + b_y: f32, + ) -> Option { 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 y_step: f32 = (b_y - a_y) / dist; { let mut i: i32 = 0; - while i < dist { - { + while i < dist { + { let x: i32 = MathUtils::round(a_x + i * x_step); let y: i32 = MathUtils::round(a_y + i * y_step); - if self.image.get(x, y) { - return Some(ResultPoint::new(x, y)); - } - } - i += 1; + if self.image.get(x, y) { + return Some(ResultPoint::new(x, y)); + } + } + i += 1; } } - return null; - } + return null; + } - /** - * recenters the points of a constant distance towards the center - * - * @param y bottom most point - * @param z left most point - * @param x right most point - * @param t top most point - * @return {@link ResultPoint}[] describing the corners of the rectangular - * region. The first and last points are opposed on the diagonal, as - * are the second and third. The first point will be the topmost - * point and the last, the bottommost. The second point will be - * leftmost and the third, the rightmost - */ - fn center_edges(&self, y: &ResultPoint, z: &ResultPoint, x: &ResultPoint, t: &ResultPoint) -> Vec { - // - // t t - // z x - // x OR z - // y y - // + /** + * recenters the points of a constant distance towards the center + * + * @param y bottom most point + * @param z left most point + * @param x right most point + * @param t top most point + * @return {@link ResultPoint}[] describing the corners of the rectangular + * region. The first and last points are opposed on the diagonal, as + * are the second and third. The first point will be the topmost + * point and the last, the bottommost. The second point will be + * leftmost and the third, the rightmost + */ + fn center_edges( + &self, + y: &ResultPoint, + z: &ResultPoint, + x: &ResultPoint, + t: &ResultPoint, + ) -> Vec { + // + // t t + // z x + // x OR z + // y y + // let yi: f32 = y.get_x(); let yj: f32 = y.get_y(); let zi: f32 = z.get_x(); @@ -530,53 +655,58 @@ impl WhiteRectangleDetector { let xj: f32 = x.get_y(); let ti: f32 = t.get_x(); let tj: f32 = t.get_y(); - 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), ] - ; - } 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), ] - ; - } - } + 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), + ]; + } 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), + ]; + } + } - /** - * Determines whether a segment contains a black point - * - * @param a min value of the scanned coordinate - * @param b max value of the scanned coordinate - * @param fixed value of fixed coordinate - * @param horizontal set to true if scan must be horizontal, false if vertical - * @return true if a black point has been found, else false. - */ - fn contains_black_point(&self, a: i32, b: i32, fixed: i32, horizontal: bool) -> bool { - if horizontal { + /** + * Determines whether a segment contains a black point + * + * @param a min value of the scanned coordinate + * @param b max value of the scanned coordinate + * @param fixed value of fixed coordinate + * @param horizontal set to true if scan must be horizontal, false if vertical + * @return true if a black point has been found, else false. + */ + fn contains_black_point(&self, a: i32, b: i32, fixed: i32, horizontal: bool) -> bool { + if horizontal { { let mut x: i32 = a; - while x <= b { - { - if self.image.get(x, fixed) { - return true; - } - } - x += 1; + while x <= b { + { + if self.image.get(x, fixed) { + return true; + } + } + x += 1; } } - - } else { + } else { { let mut y: i32 = a; - while y <= b { - { - if self.image.get(fixed, y) { - return true; - } - } - y += 1; + while y <= b { + { + if self.image.get(fixed, y) { + return true; + } + } + y += 1; } } - - } - return false; - } + } + return false; + } } - diff --git a/src/common/readsolomon.rs b/src/common/readsolomon.rs index ba458a0..a3aeede 100644 --- a/src/common/readsolomon.rs +++ b/src/common/readsolomon.rs @@ -9,145 +9,156 @@ * @author Sean Owen */ struct GenericGFPoly { + field: GenericGF, - field: GenericGF, - - coefficients: Vec + coefficients: Vec, } impl GenericGFPoly { - - /** - * @param field the {@link GenericGF} instance representing the field to use - * to perform computations - * @param coefficients coefficients as ints representing elements of GF(size), arranged - * from most significant (highest-power term) coefficient to least significant - * @throws IllegalArgumentException if argument is null or empty, - * or if leading coefficient is 0 and this is not a - * constant polynomial (that is, it is not the monomial "0") - */ - fn new( field: &GenericGF, coefficients: &Vec) -> Result { - let mut new_poly: GenericGFPoly; - if coefficients.len() == 0 { - return Err(IllegalArgumentException::new()); - } - new_poly.field = field; + /** + * @param field the {@link GenericGF} instance representing the field to use + * to perform computations + * @param coefficients coefficients as ints representing elements of GF(size), arranged + * from most significant (highest-power term) coefficient to least significant + * @throws IllegalArgumentException if argument is null or empty, + * or if leading coefficient is 0 and this is not a + * constant polynomial (that is, it is not the monomial "0") + */ + fn new(field: &GenericGF, coefficients: &Vec) -> Result { + let mut new_poly: GenericGFPoly; + if coefficients.len() == 0 { + return Err(IllegalArgumentException::new()); + } + new_poly.field = field; let coefficients_length: i32 = coefficients.len(); - if coefficients_length > 1 && coefficients[0] == 0 { - // Leading term must be non-zero for anything except the constant polynomial "0" + if coefficients_length > 1 && coefficients[0] == 0 { + // Leading term must be non-zero for anything except the constant polynomial "0" let first_non_zero: i32 = 1; - while first_non_zero < coefficients_length && coefficients[first_non_zero] == 0 { - first_non_zero += 1; - } - if first_non_zero == coefficients_length { - new_poly.coefficients = vec![0, ]; - } else { - new_poly.coefficients = coefficients; - //System::arraycopy(&coefficients, first_non_zero, let .coefficients, 0, let .coefficients.len()); - } - } else { - new_poly.coefficients = coefficients; - } - Ok(new_poly) - } + while first_non_zero < coefficients_length && coefficients[first_non_zero] == 0 { + first_non_zero += 1; + } + if first_non_zero == coefficients_length { + new_poly.coefficients = vec![0]; + } else { + new_poly.coefficients = coefficients; + //System::arraycopy(&coefficients, first_non_zero, let .coefficients, 0, let .coefficients.len()); + } + } else { + new_poly.coefficients = coefficients; + } + Ok(new_poly) + } - fn get_coefficients(&self) -> Vec { - return self.coefficients; - } + fn get_coefficients(&self) -> Vec { + return self.coefficients; + } - /** - * @return degree of this polynomial - */ - fn get_degree(&self) -> i32 { - return self.coefficients.len() - 1; - } + /** + * @return degree of this polynomial + */ + fn get_degree(&self) -> i32 { + return self.coefficients.len() - 1; + } - /** - * @return true iff this polynomial is the monomial "0" - */ - fn is_zero(&self) -> bool { - return self.coefficients[0] == 0; - } + /** + * @return true iff this polynomial is the monomial "0" + */ + fn is_zero(&self) -> bool { + return self.coefficients[0] == 0; + } - /** - * @return coefficient of x^degree term in this polynomial - */ - fn get_coefficient(&self, degree: i32) -> i32 { - return self.coefficients[self.coefficients.len() - 1 - degree]; - } + /** + * @return coefficient of x^degree term in this polynomial + */ + fn get_coefficient(&self, degree: i32) -> i32 { + return self.coefficients[self.coefficients.len() - 1 - degree]; + } - /** - * @return evaluation of this polynomial at a given point - */ - fn evaluate_at(&self, a: i32) -> i32 { - if a == 0 { - // Just return the x^0 coefficient - return self.get_coefficient(0); - } - if a == 1 { - // Just the sum of the coefficients + /** + * @return evaluation of this polynomial at a given point + */ + fn evaluate_at(&self, a: i32) -> i32 { + if a == 0 { + // Just return the x^0 coefficient + return self.get_coefficient(0); + } + if a == 1 { + // Just the sum of the coefficients let mut result: i32 = 0; - for coefficient in self.coefficients { - result = GenericGF::add_or_subtract(result, coefficient); - } - return result; - } + for coefficient in self.coefficients { + result = GenericGF::add_or_subtract(result, coefficient); + } + return result; + } let mut result: i32 = self.coefficients[0]; let size: i32 = self.coefficients.len(); { let mut i: i32 = 1; - while i < size { - { - result = GenericGF::add_or_subtract(&self.field.multiply(a, result), self.coefficients[i]); - } - i += 1; + while i < size { + { + result = GenericGF::add_or_subtract( + &self.field.multiply(a, result), + self.coefficients[i], + ); + } + i += 1; } } - return result; - } + return result; + } - fn add_or_subtract(&self, other: &GenericGFPoly) -> Result { - if !self.field.equals(other.field) { - return Err( IllegalArgumentException::new("GenericGFPolys do not have same GenericGF field") ); - } - if self.is_zero() { - return other; - } - if other.is_zero() { - return self; - } + fn add_or_subtract( + &self, + other: &GenericGFPoly, + ) -> Result { + if !self.field.equals(other.field) { + return Err(IllegalArgumentException::new( + "GenericGFPolys do not have same GenericGF field", + )); + } + if self.is_zero() { + return other; + } + if other.is_zero() { + return self; + } let smaller_coefficients: Vec = self.coefficients; let larger_coefficients: Vec = other.coefficients; - if smaller_coefficients.len() > larger_coefficients.len() { + if smaller_coefficients.len() > larger_coefficients.len() { let temp: Vec = smaller_coefficients; - smaller_coefficients = larger_coefficients; - larger_coefficients = temp; - } + smaller_coefficients = larger_coefficients; + larger_coefficients = temp; + } let sum_diff: [i32; larger_coefficients.len()] = [0; larger_coefficients.len()]; let length_diff: i32 = larger_coefficients.len() - smaller_coefficients.len(); - // Copy high-order terms only found in higher-degree polynomial's coefficients - System::arraycopy(&larger_coefficients, 0, &sum_diff, 0, length_diff); + // Copy high-order terms only found in higher-degree polynomial's coefficients + System::arraycopy(&larger_coefficients, 0, &sum_diff, 0, length_diff); { let mut i: i32 = length_diff; - while i < larger_coefficients.len() { - { - sum_diff[i] = GenericGF::add_or_subtract(smaller_coefficients[i - length_diff], larger_coefficients[i]); - } - i += 1; + while i < larger_coefficients.len() { + { + sum_diff[i] = GenericGF::add_or_subtract( + smaller_coefficients[i - length_diff], + larger_coefficients[i], + ); + } + i += 1; } } - return GenericGFPoly::new(&self.field, &sum_diff); - } + return GenericGFPoly::new(&self.field, &sum_diff); + } - fn multiply(&self, other: &GenericGFPoly) -> Result { - if !self.field.equals(other.field) { - return Err(IllegalArgumentException::new("GenericGFPolys do not have same GenericGF field")); - } - if self.is_zero() || other.is_zero() { - return Ok(self.field.get_zero()); - } + fn multiply(&self, other: &GenericGFPoly) -> Result { + if !self.field.equals(other.field) { + return Err(IllegalArgumentException::new( + "GenericGFPolys do not have same GenericGF field", + )); + } + if self.is_zero() || other.is_zero() { + return Ok(self.field.get_zero()); + } let a_coefficients: Vec = self.coefficients; let a_length: i32 = a_coefficients.len(); let b_coefficients: Vec = other.coefficients; @@ -155,143 +166,158 @@ impl GenericGFPoly { let mut product: [i32; a_length + b_length - 1] = [0; a_length + b_length - 1]; { let mut i: i32 = 0; - while i < a_length { - { + while i < a_length { + { let a_coeff: i32 = a_coefficients[i]; { let mut j: i32 = 0; - while j < b_length { - { - product[i + j] = GenericGF::add_or_subtract(product[i + j], &self.field.multiply(a_coeff, b_coefficients[j])); - } - j += 1; + while j < b_length { + { + product[i + j] = GenericGF::add_or_subtract( + product[i + j], + &self.field.multiply(a_coeff, b_coefficients[j]), + ); + } + j += 1; } } - - } - i += 1; + } + i += 1; } } - return GenericGFPoly::new(&self.field, &product); - } + return GenericGFPoly::new(&self.field, &product); + } - fn multiply(&self, scalar: i32) -> GenericGFPoly { - if scalar == 0 { - return self.field.get_zero(); - } - if scalar == 1 { - return self; - } + fn multiply(&self, scalar: i32) -> GenericGFPoly { + if scalar == 0 { + return self.field.get_zero(); + } + if scalar == 1 { + return self; + } let size: i32 = self.coefficients.len(); let mut product: [i32; size] = [0; size]; { let mut i: i32 = 0; - while i < size { - { - product[i] = self.field.multiply(self.coefficients[i], scalar); - } - i += 1; + while i < size { + { + product[i] = self.field.multiply(self.coefficients[i], scalar); + } + i += 1; } } - return GenericGFPoly::new(&self.field, &product); - } + return GenericGFPoly::new(&self.field, &product); + } - fn multiply_by_monomial(&self, degree: i32, coefficient: i32) -> Result { - if degree < 0 { - return Err( IllegalArgumentException::new()); - } - if coefficient == 0 { - return Ok(self.field.get_zero()); - } + fn multiply_by_monomial( + &self, + degree: i32, + coefficient: i32, + ) -> Result { + if degree < 0 { + return Err(IllegalArgumentException::new()); + } + if coefficient == 0 { + return Ok(self.field.get_zero()); + } let size: i32 = self.coefficients.len(); let mut product: [i32; size + degree] = [0; size + degree]; { let mut i: i32 = 0; - while i < size { - { - product[i] = self.field.multiply(self.coefficients[i], coefficient); - } - i += 1; + while i < size { + { + product[i] = self.field.multiply(self.coefficients[i], coefficient); + } + i += 1; } } - return GenericGFPoly::new(&self.field, &product); - } + return GenericGFPoly::new(&self.field, &product); + } - fn divide(&self, other: &GenericGFPoly) -> Result,IllegalArgumentException> { - if !self.field.equals(other.field) { - return Err( IllegalArgumentException::new("GenericGFPolys do not have same GenericGF field")); - } - if other.is_zero() { - return Err( IllegalArgumentException::new("Divide by 0")); - } + fn divide( + &self, + other: &GenericGFPoly, + ) -> Result, IllegalArgumentException> { + if !self.field.equals(other.field) { + return Err(IllegalArgumentException::new( + "GenericGFPolys do not have same GenericGF field", + )); + } + if other.is_zero() { + return Err(IllegalArgumentException::new("Divide by 0")); + } let mut quotient: GenericGFPoly = self.field.get_zero(); let mut remainder: GenericGFPoly = self; let denominator_leading_term: i32 = other.get_coefficient(&other.get_degree()); 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 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 iteration_quotient: GenericGFPoly = self.field.build_monomial(degree_difference, scale); - quotient = quotient.add_or_subtract(&iteration_quotient); - remainder = remainder.add_or_subtract(&term); - } - return Ok(vec![quotient, remainder, ]); - } + let iteration_quotient: GenericGFPoly = + self.field.build_monomial(degree_difference, scale); + quotient = quotient.add_or_subtract(&iteration_quotient); + remainder = remainder.add_or_subtract(&term); + } + return Ok(vec![quotient, remainder]); + } - pub fn to_string(&self) -> String { - if self.is_zero() { - return "0".to_owned(); - } + pub fn to_string(&self) -> String { + if self.is_zero() { + return "0".to_owned(); + } let result: StringBuilder = StringBuilder::new(8 * self.get_degree()); { let mut degree: i32 = self.get_degree(); - while degree >= 0 { - { + while degree >= 0 { + { let mut coefficient: i32 = self.get_coefficient(degree); - if coefficient != 0 { - if coefficient < 0 { - if degree == self.get_degree() { - result.append("-"); - } else { - result.append(" - "); - } - coefficient = -coefficient; - } else { - if result.length() > 0 { - result.append(" + "); - } - } - if degree == 0 || coefficient != 1 { + if coefficient != 0 { + if coefficient < 0 { + if degree == self.get_degree() { + result.append("-"); + } else { + result.append(" - "); + } + coefficient = -coefficient; + } else { + if result.length() > 0 { + result.append(" + "); + } + } + if degree == 0 || coefficient != 1 { let alpha_power: i32 = self.field.log(coefficient); - if alpha_power == 0 { - result.append('1'); - } else if alpha_power == 1 { - result.append('a'); - } else { - result.append("a^"); - result.append(alpha_power); - } - } - if degree != 0 { - if degree == 1 { - result.append('x'); - } else { - result.append("x^"); - result.append(degree); - } - } - } - } - degree -= 1; + if alpha_power == 0 { + result.append('1'); + } else if alpha_power == 1 { + result.append('a'); + } else { + result.append("a^"); + result.append(alpha_power); + } + } + if degree != 0 { + if degree == 1 { + result.append('x'); + } else { + result.append("x^"); + result.append(degree); + } + } + } + } + degree -= 1; } } - return result.to_string(); - } + return result.to_string(); + } } // GenericGF.java @@ -311,64 +337,62 @@ impl GenericGFPoly { const AZTEC_DATA_12: GenericGF = GenericGF::new(0x1069, 4096, 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 - const AZTEC_DATA_6: GenericGF = GenericGF::new(0x43, 64, 1); +const AZTEC_DATA_6: GenericGF = GenericGF::new(0x43, 64, 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 - 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 - 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 { + exp_table: Vec, - exp_table: Vec, + log_table: Vec, - log_table: Vec, + zero: GenericGFPoly, - zero: GenericGFPoly, + one: GenericGFPoly, - one: GenericGFPoly, + size: i32, - size: i32, + primitive: i32, - primitive: i32, - - generator_base: i32 + generator_base: i32, } impl GenericGF { - /** - * Create a representation of GF(size) using the given primitive polynomial. - * - * @param primitive irreducible polynomial whose coefficients are represented by - * the bits of an int, where the least-significant bit represents the constant - * coefficient - * @param size the size of the field - * @param b the factor b in the generator polynomial can be 0- or 1-based - * (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. - */ - pub fn new( primitive: i32, size: i32, b: i32) -> Self { - let mut new_generic_gf : GenericGF; - new_generic_gf .primitive = primitive; - new_generic_gf .size = size; - new_generic_gf .generatorBase = b; - exp_table = [0; size]; - log_table = [0; size]; - let mut x: i32 = 1; - { - let mut i: i32 = 0; + * Create a representation of GF(size) using the given primitive polynomial. + * + * @param primitive irreducible polynomial whose coefficients are represented by + * the bits of an int, where the least-significant bit represents the constant + * coefficient + * @param size the size of the field + * @param b the factor b in the generator polynomial can be 0- or 1-based + * (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. + */ + pub fn new(primitive: i32, size: i32, b: i32) -> Self { + let mut new_generic_gf: GenericGF; + new_generic_gf.primitive = primitive; + new_generic_gf.size = size; + new_generic_gf.generatorBase = b; + exp_table = [0; size]; + log_table = [0; size]; + let mut x: i32 = 1; + { + let mut i: i32 = 0; while i < size { { exp_table[i] = x; @@ -380,105 +404,113 @@ impl GenericGF { } } i += 1; - } - } + } + } - { - let mut i: i32 = 0; + { + let mut i: i32 = 0; while i < size - 1 { { log_table[exp_table[i]] = i; } i += 1; - } - } + } + } // logTable[0] == 0 but this should never be used - new_generic_gf.zero = GenericGFPoly::new( 0, &vec![0, ]); - new_generic_gf.one = GenericGFPoly::new( 0, &vec![1, ]); + new_generic_gf.zero = GenericGFPoly::new(0, &vec![0]); + new_generic_gf.one = GenericGFPoly::new(0, &vec![1]); new_generic_gf } - fn get_zero(&self) -> GenericGFPoly { + fn get_zero(&self) -> GenericGFPoly { return self.zero; } - fn get_one(&self) -> GenericGFPoly { + fn get_one(&self) -> GenericGFPoly { return self.one; } /** - * @return the monomial representing coefficient * x^degree - */ - fn build_monomial(&self, degree: i32, coefficient: i32) -> Result { + * @return the monomial representing coefficient * x^degree + */ + fn build_monomial( + &self, + degree: i32, + coefficient: i32, + ) -> Result { if degree < 0 { - return Err( IllegalArgumentException::new()); + return Err(IllegalArgumentException::new()); } if coefficient == 0 { return Ok(self.zero); } - let mut coefficients: [i32; degree + 1] = [0; degree + 1]; + let mut coefficients: [i32; degree + 1] = [0; degree + 1]; coefficients[0] = coefficient; return GenericGFPoly::new(self, &coefficients); } /** - * Implements both addition and subtraction -- they are the same in GF(size). - * - * @return sum/difference of a and b - */ - fn add_or_subtract( a: i32, b: i32) -> i32 { + * Implements both addition and subtraction -- they are the same in GF(size). + * + * @return sum/difference of a and b + */ + fn add_or_subtract(a: i32, b: i32) -> i32 { return a ^ b; } /** - * @return 2 to the power of a in GF(size) - */ - fn exp(&self, a: i32) -> i32 { + * @return 2 to the power of a in GF(size) + */ + fn exp(&self, a: i32) -> i32 { return self.exp_table[a]; } /** - * @return base 2 log of a in GF(size) - */ - fn log(&self, a: i32) -> Result { + * @return base 2 log of a in GF(size) + */ + fn log(&self, a: i32) -> Result { if a == 0 { - return Err( IllegalArgumentException::new()); + return Err(IllegalArgumentException::new()); } return self.log_table[a]; } /** - * @return multiplicative inverse of a - */ - fn inverse(&self, a: i32) -> Result { + * @return multiplicative inverse of a + */ + fn inverse(&self, a: i32) -> Result { if a == 0 { - return Err( ArithmeticException::new()); + return Err(ArithmeticException::new()); } return self.exp_table[self.size - self.log_table[a] - 1]; } /** - * @return product of a and b in GF(size) - */ - fn multiply(&self, a: i32, b: i32) -> i32 { + * @return product of a and b in GF(size) + */ + fn multiply(&self, a: i32, b: i32) -> i32 { if a == 0 || b == 0 { return 0; } return self.exp_table[(self.log_table[a] + self.log_table[b]) % (self.size - 1)]; } - pub fn get_size(&self) -> i32 { + pub fn get_size(&self) -> i32 { return self.size; } - pub fn get_generator_base(&self) -> i32 { + pub fn get_generator_base(&self) -> i32 { return self.generator_base; } - pub fn to_string(&self) -> String { - return format!("GF(0x{},{})", Integer::to_hex_string(self.primitive), self.size); + pub fn to_string(&self) -> String { + return format!( + "GF(0x{},{})", + Integer::to_hex_string(self.primitive), + self.size + ); } } @@ -506,183 +538,210 @@ impl GenericGF { * @author sanfordsquires */ pub struct ReedSolomonDecoder { - - field: GenericGF + field: GenericGF, } impl ReedSolomonDecoder { + pub fn new(field: &GenericGF) -> Self { + Self { field } + } - pub fn new( field: &GenericGF) -> Self { - Self{ field } - } - - /** - *

Decodes given set of received codewords, which include both data and error-correction - * codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place, - * in the input.

- * - * @param received data and error-correction codewords - * @param twoS number of error-correction codewords available - * @throws ReedSolomonException if decoding fails for any reason - */ - pub fn decode(&self, received: &Vec, two_s: i32) -> Result<(), ReedSolomonException> { + /** + *

Decodes given set of received codewords, which include both data and error-correction + * codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place, + * in the input.

+ * + * @param received data and error-correction codewords + * @param twoS number of error-correction codewords available + * @throws ReedSolomonException if decoding fails for any reason + */ + pub fn decode(&self, received: &Vec, two_s: i32) -> Result<(), ReedSolomonException> { let poly: GenericGFPoly = GenericGFPoly::new(&self.field, &received); let syndrome_coefficients: [i32; two_s] = [0; two_s]; let no_error: bool = true; { let mut i: i32 = 0; - while i < two_s { - { - let eval: i32 = poly.evaluate_at(&self.field.exp(i + self.field.get_generator_base())); - syndrome_coefficients[syndrome_coefficients.len() - 1 - i] = eval; - if eval != 0 { - no_error = false; - } - } - i += 1; + while i < two_s { + { + let eval: i32 = + poly.evaluate_at(&self.field.exp(i + self.field.get_generator_base())); + syndrome_coefficients[syndrome_coefficients.len() - 1 - i] = eval; + if eval != 0 { + no_error = false; + } + } + i += 1; } } - if no_error { - return; - } + if no_error { + return; + } let syndrome: GenericGFPoly = GenericGFPoly::new(&self.field, &syndrome_coefficients); - let sigma_omega: Vec = self.run_euclidean_algorithm(&self.field.build_monomial(two_s, 1), &syndrome, two_s); + let sigma_omega: Vec = + self.run_euclidean_algorithm(&self.field.build_monomial(two_s, 1), &syndrome, two_s); let sigma: GenericGFPoly = sigma_omega[0]; let omega: GenericGFPoly = sigma_omega[1]; let error_locations: Vec = self.find_error_locations(&sigma); let error_magnitudes: Vec = self.find_error_magnitudes(&omega, &error_locations); { let mut i: i32 = 0; - while i < error_locations.len() { - { + while i < error_locations.len() { + { let mut position: i32 = received.len() - 1 - self.field.log(error_locations[i]); - if position < 0 { - return Err( ReedSolomonException::new("Bad error location")); - } - received[position] = GenericGF::add_or_subtract(received[position], error_magnitudes[i]); - } - i += 1; + if position < 0 { + return Err(ReedSolomonException::new("Bad error location")); + } + received[position] = + GenericGF::add_or_subtract(received[position], error_magnitudes[i]); + } + i += 1; } } Ok(()) + } - } - - fn run_euclidean_algorithm(&self, a: &GenericGFPoly, b: &GenericGFPoly, R: i32) -> Result, ReedSolomonException+IllegalStateException> { - // Assume a's degree is >= b's - if a.get_degree() < b.get_degree() { + fn run_euclidean_algorithm( + &self, + a: &GenericGFPoly, + b: &GenericGFPoly, + R: i32, + ) -> Result, ReedSolomonException + IllegalStateException> { + // Assume a's degree is >= b's + if a.get_degree() < b.get_degree() { let temp: GenericGFPoly = a; - a = b; - b = &temp; - } + a = b; + b = &temp; + } let r_last: GenericGFPoly = a; let mut r: GenericGFPoly = b; let t_last: GenericGFPoly = self.field.get_zero(); let mut t: GenericGFPoly = self.field.get_one(); - // Run Euclidean algorithm until r's degree is less than R/2 - while 2 * r.get_degree() >= R { + // Run Euclidean algorithm until r's degree is less than R/2 + while 2 * r.get_degree() >= R { let r_last_last: GenericGFPoly = r_last; let t_last_last: GenericGFPoly = t_last; - r_last = r; - t_last = t; - // Divide rLastLast by rLast, with quotient in q and remainder in r - if r_last.is_zero() { - // Oops, Euclidean algorithm already terminated? - return Err( ReedSolomonException::new("r_{i-1} was zero")); - } - r = r_last_last; + r_last = r; + t_last = t; + // Divide rLastLast by rLast, with quotient in q and remainder in r + if r_last.is_zero() { + // Oops, Euclidean algorithm already terminated? + return Err(ReedSolomonException::new("r_{i-1} was zero")); + } + r = r_last_last; let mut q: GenericGFPoly = self.field.get_zero(); let denominator_leading_term: i32 = r_last.get_coefficient(&r_last.get_degree()); 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 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)); - r = r.add_or_subtract(&r_last.multiply_by_monomial(degree_diff, scale)); - } - t = q.multiply(&t_last).add_or_subtract(t_last_last); - if r.get_degree() >= r_last.get_degree() { - return Err( IllegalStateException::new(format!("Division algorithm failed to reduce polynomial? r: {}, rLast: {}", r, r_last))); - } - } + 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)); + r = r.add_or_subtract(&r_last.multiply_by_monomial(degree_diff, scale)); + } + t = q.multiply(&t_last).add_or_subtract(t_last_last); + if r.get_degree() >= r_last.get_degree() { + 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); - if sigma_tilde_at_zero == 0 { - return Err( ReedSolomonException::new("sigmaTilde(0) was zero")); - } + if sigma_tilde_at_zero == 0 { + return Err(ReedSolomonException::new("sigmaTilde(0) was zero")); + } let inverse: i32 = self.field.inverse(sigma_tilde_at_zero); let sigma: GenericGFPoly = t.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, ReedSolomonException> { - // This is a direct application of Chien's search + fn find_error_locations( + &self, + error_locator: &GenericGFPoly, + ) -> Result, ReedSolomonException> { + // This is a direct application of Chien's search let num_errors: i32 = error_locator.get_degree(); - if num_errors == 1 { - // shortcut - return Ok( vec![error_locator.get_coefficient(1), ]); - } + if num_errors == 1 { + // shortcut + return Ok(vec![error_locator.get_coefficient(1)]); + } let mut result: [i32; num_errors] = [0; num_errors]; let mut e: i32 = 0; { let mut i: i32 = 1; - while i < self.field.get_size() && e < num_errors { - { - if error_locator.evaluate_at(i) == 0 { - result[e] = self.field.inverse(i); - e += 1; - } - } - i += 1; + while i < self.field.get_size() && e < num_errors { + { + if error_locator.evaluate_at(i) == 0 { + result[e] = self.field.inverse(i); + e += 1; + } + } + i += 1; } } - if e != num_errors { - return Err( ReedSolomonException::new("Error locator degree does not match number of roots")); - } - return Ok(result); - } + if e != num_errors { + return Err(ReedSolomonException::new( + "Error locator degree does not match number of roots", + )); + } + return Ok(result); + } - fn find_error_magnitudes(&self, error_evaluator: &GenericGFPoly, error_locations: &Vec) -> Vec { - // This is directly applying Forney's Formula + fn find_error_magnitudes( + &self, + error_evaluator: &GenericGFPoly, + error_locations: &Vec, + ) -> Vec { + // This is directly applying Forney's Formula let s: i32 = error_locations.len(); let mut result: [i32; s] = [0; s]; { let mut i: i32 = 0; - while i < s { - { + while i < s { + { let xi_inverse: i32 = self.field.inverse(error_locations[i]); let mut denominator: i32 = 1; { let mut j: i32 = 0; - while j < s { - { - if i != j { - //denominator = field.multiply(denominator, - // GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse))); - // 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 - let term: i32 = 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); - } - } - j += 1; + while j < s { + { + if i != j { + //denominator = field.multiply(denominator, + // GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse))); + // 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 + let term: i32 = + 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); + } + } + j += 1; } } - result[i] = self.field.multiply(&error_evaluator.evaluate_at(xi_inverse), &self.field.inverse(denominator)); - if self.field.get_generator_base() != 0 { - result[i] = self.field.multiply(result[i], xi_inverse); - } - } - i += 1; + result[i] = self.field.multiply( + &error_evaluator.evaluate_at(xi_inverse), + &self.field.inverse(denominator), + ); + if self.field.get_generator_base() != 0 { + result[i] = self.field.multiply(result[i], xi_inverse); + } + } + i += 1; } } - return result; - } + return result; + } } // ReedSolomonEncoder.java @@ -693,70 +752,83 @@ impl ReedSolomonDecoder { * @author William Rucklidge */ pub struct ReedSolomonEncoder { - field: GenericGF, - cached_generators: Vector + cached_generators: Vector, } impl ReedSolomonEncoder { + pub fn new(field: &GenericGF) -> Self { + let mut new_rse; + new_rse.field = field; + new_rse.cachedGenerators = Vector::new(); + cached_generators.add(GenericGFPoly::new(field, &vec![1])); + new_rse + } - pub fn new( field: &GenericGF) -> Self { - let mut new_rse; - new_rse .field = field; - new_rse .cachedGenerators = Vector::new(); - cached_generators.add(GenericGFPoly::new(field, &vec![1, ])); - new_rse - } - - fn build_generator(&self, degree: i32) -> GenericGFPoly { - if degree >= self.cached_generators.size() { - let last_generator: GenericGFPoly = self.cached_generators.get(self.cached_generators.size() - 1); + fn build_generator(&self, degree: i32) -> GenericGFPoly { + if degree >= self.cached_generators.size() { + let last_generator: GenericGFPoly = self + .cached_generators + .get(self.cached_generators.size() - 1); { let mut d: i32 = self.cached_generators.size(); - 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()), ])); - self.cached_generators.add(next_generator); - last_generator = next_generator; - } - d += 1; + 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())], + )); + self.cached_generators.add(next_generator); + last_generator = next_generator; + } + d += 1; } } + } + return self.cached_generators.get(degree); + } - } - return self.cached_generators.get(degree); - } - - pub fn encode(&self, to_encode: &Vec, ec_bytes: i32) -> Result<(),IllegalArgumentException> { - if ec_bytes == 0 { - return Err( IllegalArgumentException::new("No error correction bytes")); - } + pub fn encode( + &self, + to_encode: &Vec, + ec_bytes: i32, + ) -> Result<(), IllegalArgumentException> { + if ec_bytes == 0 { + return Err(IllegalArgumentException::new("No error correction bytes")); + } let data_bytes: i32 = to_encode.len() - ec_bytes; - if data_bytes <= 0 { - return Err( IllegalArgumentException::new("No data bytes provided")); - } + if data_bytes <= 0 { + return Err(IllegalArgumentException::new("No data bytes provided")); + } let generator: GenericGFPoly = self.build_generator(ec_bytes); let info_coefficients: [i32; data_bytes] = [0; data_bytes]; - System::arraycopy(&to_encode, 0, &info_coefficients, 0, data_bytes); + System::arraycopy(&to_encode, 0, &info_coefficients, 0, data_bytes); let mut info: GenericGFPoly = GenericGFPoly::new(&self.field, &info_coefficients); - info = info.multiply_by_monomial(ec_bytes, 1); + info = info.multiply_by_monomial(ec_bytes, 1); let remainder: GenericGFPoly = info.divide(&generator)[1]; let coefficients: Vec = remainder.get_coefficients(); let num_zero_coefficients: i32 = ec_bytes - coefficients.len(); { let mut i: i32 = 0; - while i < num_zero_coefficients { - { - to_encode[data_bytes + i] = 0; - } - i += 1; + while i < num_zero_coefficients { + { + to_encode[data_bytes + i] = 0; + } + i += 1; } } - System::arraycopy(&coefficients, 0, &to_encode, data_bytes + num_zero_coefficients, coefficients.len()); - Ok(()) - } + System::arraycopy( + &coefficients, + 0, + &to_encode, + data_bytes + num_zero_coefficients, + coefficients.len(), + ); + Ok(()) + } } // ReedSolomonException.java @@ -767,12 +839,11 @@ impl ReedSolomonEncoder { * @author Sean Owen */ pub struct ReedSolomonException { - message: String + message: String, } impl ReedSolomonException { - - pub fn new( message: &String) -> Self { - ReedSolomonException{message} + pub fn new(message: &String) -> Self { + ReedSolomonException { message } } -} \ No newline at end of file +}