Merge branch 'main' into thiserror

# Conflicts:
#	src/aztec/decoder.rs
#	src/datamatrix/decoder/decoded_bit_stream_parser.rs
This commit is contained in:
Steve Cook
2023-03-01 13:39:30 -05:00
36 changed files with 1452 additions and 145 deletions

View File

@@ -17,8 +17,8 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Check - name: Check
run: cargo check --release --verbose run: cargo check --workspace --release --verbose
- name: Build - name: Build
run: cargo build --release --verbose run: cargo build --workspace --release --verbose
- name: Run tests - name: Run tests
run: cargo test --release --verbose run: cargo test --workspace --release --verbose

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "rxing" name = "rxing"
version = "0.3.1" version = "0.3.2"
description="A rust port of the zxing barcode library." description="A rust port of the zxing barcode library."
license="Apache-2.0" license="Apache-2.0"
repository="https://github.com/rxing-core/rxing" repository="https://github.com/rxing-core/rxing"
@@ -13,9 +13,9 @@ exclude = [
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
regex = "1.7.0" regex = "1.7.1"
fancy-regex = "0.10" fancy-regex = "0.11"
once_cell = "1.17.0" once_cell = "1.17.1"
encoding = "0.2" encoding = "0.2"
urlencoding = "2.1.2" urlencoding = "2.1.2"
uriparse = "0.6.4" uriparse = "0.6.4"
@@ -25,8 +25,7 @@ image = {version = "0.24", optional = true}
imageproc = {version = "0.23", optional = true} imageproc = {version = "0.23", optional = true}
unicode-segmentation = "1.10" unicode-segmentation = "1.10"
codepage-437 = "0.1.0" codepage-437 = "0.1.0"
rxing-one-d-proc-derive = "0.3" rxing-one-d-proc-derive = {version = "0.3", path ="./crates/one-d-proc-derive"}
#rxing-one-d-proc-derive = {path ="../rxing-one-d-proc-derive"}
num = "0.4.0" num = "0.4.0"
svg = {version = "0.13", optional = true} svg = {version = "0.13", optional = true}
resvg = {version = "0.28.0", optional = true, default-features=false} resvg = {version = "0.28.0", optional = true, default-features=false}
@@ -63,4 +62,10 @@ experimental_features = []
serde = ["dep:serde"] serde = ["dep:serde"]
#/// Adds otsu binarizer support using imageproc #/// Adds otsu binarizer support using imageproc
otsu_level = ["image"] otsu_level = ["image"]
[workspace]
members = [
"crates/one-d-proc-derive",
"crates/cli"
]

25
crates/cli/.gitignore vendored Normal file
View File

@@ -0,0 +1,25 @@
# Generated by Cargo
# will have compiled files and executables
/target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
# Added by cargo
/target
*.jpg
*.jpeg
*.png
*.tif
*.svg
*.webp
*.tiff
.DS_Store
/.vscode

14
crates/cli/Cargo.toml Normal file
View File

@@ -0,0 +1,14 @@
[package]
name = "rxing-cli"
version = "0.1.12"
edition = "2021"
description = "A command line interface for rxing supporting encoding and decoding of multiple barcode formats"
license="Apache-2.0"
repository="https://github.com/rxing-core/rxing/tree/main/crates/cli"
keywords = ["barcode", "2d_barcode", "1d_barcode", "barcode_reader", "barcode_writer"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap = { version = "4.1.1", features = ["derive"] }
rxing = {path = "../../", version = "~0.3.2", features = ["image", "svg_read", "svg_write"] }

201
crates/cli/LICENSE Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

19
crates/cli/README.md Normal file
View File

@@ -0,0 +1,19 @@
# rxing-cli
A command line interface for rxing supporting encoding and decoding of barcode data.
## Full documentation
`rxing-cli help`
`rxing-cli help encode`
`rxing-cli help decode`
## Instalation
`cargo install rxing-cli`
## Example Encode
`rxing-cli test_image.jpg encode --width 500 --height 500 --data "Sample Data and TEST Data" qrcode`
## Example Decode
`rxing-cli test_image.jpg decode`
## Example Multi Barcode Decode
`rxing-cli test_image.jpg decode --decode-multi`

654
crates/cli/src/main.rs Normal file
View File

@@ -0,0 +1,654 @@
use std::{
collections::{HashMap, HashSet},
path::PathBuf,
};
use clap::{ArgGroup, Parser, Subcommand};
use rxing::{BarcodeFormat, MultiFormatWriter, Writer};
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Args {
file_name: String,
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
#[command(group(
ArgGroup::new("advanced_display_group")
.required(false)
.args(["detailed_results","parsed_results","raw_bytes"]),
))]
Decode {
/// Try much harder to detect barcodes.
#[arg(short, long)]
try_harder: bool,
/// Search for multiple barcodes in an image instead of just one, this can be much slower.
#[arg(short, long)]
decode_multi: bool,
/// Can be specified multiple times with different barcode formats, only listed formats are searched for.
#[arg(short, long, value_enum)]
barcode_types: Option<Vec<BarcodeFormat>>,
/// Print detailed results data
#[arg(long)]
detailed_results: bool,
/// Print parsed results (exclusive with --detailed-results and --raw-bytes)
#[arg(long)]
parsed_results: bool,
/// Print raw bytes (exclusive with --detailed-results and --raw-bytes)
#[arg(long)]
raw_bytes: bool,
/// Unspecified, application-specific hint.
#[arg(long)]
other: Option<String>,
/// Image is a pure monochrome image of a barcode.
#[arg(long)]
pure_barcode: Option<bool>,
/// Specifies what character encoding to use when decoding, where applicable.
#[arg(long)]
character_set: Option<String>,
/// Allowed lengths of encoded data -- reject anything else..
#[arg(long)]
allowed_lengths: Option<Vec<u32>>,
/// Assume Code 39 codes employ a check digit.
#[arg(long)]
assume_code_39_check_digit: Option<bool>,
/// Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed.
/// For example this affects FNC1 handling for Code 128 (aka GS1-128).
#[arg(long, verbatim_doc_comment)]
assume_gs1: Option<bool>,
/// If true, return the start and end digits in a Codabar barcode instead of stripping them. They
/// are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them
/// to not be.
#[arg(long, verbatim_doc_comment)]
return_codabar_start_end: Option<bool>,
/// Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this.
/// Maps to an {@code int[]} of the allowed extension lengths, for example [2], [5], or [2, 5].
/// If it is optional to have an extension, do not set this hint. If this is set,
/// and a UPC or EAN barcode is found but an extension is not, then no result will be returned
/// at all.
#[arg(long, verbatim_doc_comment)]
allowed_ean_extensions: Option<Vec<u32>>,
/// If true, also tries to decode as inverted image. All configured decoders are simply called a
/// second time with an inverted image.
#[arg(long, verbatim_doc_comment)]
also_inverted: Option<bool>,
},
#[command(group(
ArgGroup::new("code_set_rules")
.required(false)
.args(["code_128_compact", "force_code_set"]),
))]
#[command(group(
ArgGroup::new("data_source")
.required(true)
.args(["data", "data_file"]),
))]
#[command(group(
ArgGroup::new("data_matrix_encoding")
.required(false)
.args(["data_matrix_compact","force_c40"]),
))]
Encode {
barcode_type: BarcodeFormat,
#[arg(long)]
width: u32,
#[arg(long)]
height: u32,
/// String input for the encoder.
#[arg(short, long)]
data: Option<String>,
/// A file containing the text to be encoded.
#[arg(long)]
data_file: Option<PathBuf>,
/// Specifies what degree of error correction to use, for example in QR Codes.
/// Type depends on the encoder. For example for QR codes it's (L,M,Q,H).
/// For Aztec it is of type u32, representing the minimal percentage of error correction words.
/// For PDF417 it is of type u8, valid values being 0 to 8.
/// Note: an Aztec symbol should have a minimum of 25% EC words.
#[arg(long, verbatim_doc_comment)]
error_correction: Option<String>,
/// Specifies what character encoding to use where applicable.
#[arg(long)]
character_set: Option<String>,
/// Specifies whether to use compact mode for Data Matrix.
/// The compact encoding mode also supports the encoding of characters that are not in the ISO-8859-1
/// character set via ECIs.
/// Please note that in that case, the most compact character encoding is chosen for characters in
/// the input that are not in the ISO-8859-1 character set. Based on experience, some scanners do not
/// support encodings like cp-1256 (Arabic). In such cases the encoding can be forced to UTF-8 by
/// means of the #CHARACTER_SET encoding hint.
/// Compact encoding also provides GS1-FNC1 support when #GS1_FORMAT is selected. In this case
/// group-separator character (ASCII 29 decimal) can be used to encode the positions of FNC1 codewords
/// for the purpose of delimiting AIs.
#[arg(long, verbatim_doc_comment)]
data_matrix_compact: Option<bool>,
/// Specifies margin, in pixels, to use when generating the barcode.
/// The meaning can vary
/// by format; for example it controls margin before and after the barcode horizontally for
/// most 1D formats.
#[arg(long, verbatim_doc_comment)]
margin: Option<String>,
/**
Specifies whether to use compact mode for PDF417.
*/
#[arg(long)]
pdf_417_compact: Option<bool>,
/**
Specifies what compaction mode to use for PDF417
AUTO = 0,
TEXT = 1,
BYTE = 2,
NUMERIC = 3
*/
#[arg(long)]
pdf_417_compaction: Option<String>,
/// Specifies whether to automatically insert ECIs when encoding PDF417.
/// Please note that in that case, the most compact character encoding is chosen for characters in
/// the input that are not in the ISO-8859-1 character set. Based on experience, some scanners do not
/// support encodings like cp-1256 (Arabic). In such cases the encoding can be forced to UTF-8 by
/// means of the #CHARACTER_SET encoding hint.
#[arg(long, verbatim_doc_comment)]
pdf_417_auto_eci: Option<bool>,
/// Specifies the required number of layers for an Aztec code.
/// A negative number (-1, -2, -3, -4) specifies a compact Aztec code.
/// 0 indicates to use the minimum number of layers (the default).
/// A positive number (1, 2, .. 32) specifies a normal (non-compact) Aztec code.
#[arg(long, verbatim_doc_comment)]
aztec_layers: Option<i32>,
/**
Specifies the exact version of QR code to be encoded.
*/
#[arg(long)]
qr_version: Option<String>,
/// Specifies the QR code mask pattern to be used. Allowed values are
/// 0..8. By default the code will automatically select
/// the optimal mask pattern.
#[arg(long, verbatim_doc_comment)]
qr_mask_pattern: Option<String>,
/// Specifies whether to use compact mode for QR code.
/// Please note that when compaction is performed, the most compact character encoding is chosen
/// for characters in the input that are not in the ISO-8859-1 character set. Based on experience,
/// some scanners do not support encodings like cp-1256 (Arabic). In such cases the encoding can
/// be forced to UTF-8 by means of the #CHARACTER_SET encoding hint.
#[arg(long, verbatim_doc_comment)]
qr_compact: Option<bool>,
/**
Specifies whether the data should be encoded to the GS1 standard/
*/
#[arg(long)]
gs1_format: Option<bool>,
/// Forces which encoding will be used. Currently only used for Code-128 code sets.
/// Valid values are "A", "B", "C".
#[arg(long, verbatim_doc_comment)]
force_code_set: Option<String>,
/**
Forces C40 encoding for data-matrix. This
*/
#[arg(long)]
force_c40: Option<bool>,
/**
Specifies whether to use compact mode for Code-128 code.
This can yield slightly smaller bar codes.
*/
#[arg(long)]
code_128_compact: Option<bool>,
},
}
fn main() {
let cli = Args::parse();
match &cli.command {
Commands::Decode {
try_harder,
decode_multi,
barcode_types,
other,
pure_barcode,
character_set,
allowed_lengths,
assume_code_39_check_digit,
assume_gs1,
return_codabar_start_end,
allowed_ean_extensions,
also_inverted,
detailed_results,
parsed_results,
raw_bytes,
} => decode_command(
&cli.file_name,
try_harder,
decode_multi,
barcode_types,
other,
pure_barcode,
character_set,
allowed_lengths,
assume_code_39_check_digit,
assume_gs1,
return_codabar_start_end,
allowed_ean_extensions,
also_inverted,
detailed_results,
parsed_results,
raw_bytes,
),
Commands::Encode {
barcode_type,
width,
height,
data,
data_file,
error_correction,
character_set,
data_matrix_compact,
margin,
pdf_417_compact,
pdf_417_compaction,
pdf_417_auto_eci,
aztec_layers,
qr_version,
qr_mask_pattern,
qr_compact,
gs1_format,
force_code_set,
force_c40,
code_128_compact,
} => encode_command(
&cli.file_name,
barcode_type,
width,
height,
data,
data_file,
error_correction,
character_set,
data_matrix_compact,
margin,
pdf_417_compact,
pdf_417_compaction,
pdf_417_auto_eci,
aztec_layers,
qr_version,
qr_mask_pattern,
qr_compact,
gs1_format,
force_code_set,
force_c40,
code_128_compact,
),
}
}
fn decode_command(
file_name: &str,
try_harder: &bool,
decode_multi: &bool,
barcode_types: &Option<Vec<BarcodeFormat>>,
other: &Option<String>,
pure_barcode: &Option<bool>,
character_set: &Option<String>,
allowed_lengths: &Option<Vec<u32>>,
assume_code_39_check_digit: &Option<bool>,
assume_gs1: &Option<bool>,
return_codabar_start_end: &Option<bool>,
allowed_ean_extensions: &Option<Vec<u32>>,
also_inverted: &Option<bool>,
detailed_result: &bool,
parsed_bytes: &bool,
raw_bytes: &bool,
) {
let mut hints: rxing::DecodingHintDictionary = HashMap::new();
if let Some(other) = other {
hints.insert(
rxing::DecodeHintType::OTHER,
rxing::DecodeHintValue::Other(other.to_owned()),
);
}
if let Some(pure_barcode) = pure_barcode {
hints.insert(
rxing::DecodeHintType::PURE_BARCODE,
rxing::DecodeHintValue::PureBarcode(*pure_barcode),
);
}
if let Some(character_set) = character_set {
hints.insert(
rxing::DecodeHintType::CHARACTER_SET,
rxing::DecodeHintValue::CharacterSet(character_set.to_owned()),
);
}
if let Some(allowed_lengths) = allowed_lengths {
hints.insert(
rxing::DecodeHintType::ALLOWED_LENGTHS,
rxing::DecodeHintValue::AllowedLengths(allowed_lengths.to_vec()),
);
}
if let Some(assume_code_39_check_digit) = assume_code_39_check_digit {
hints.insert(
rxing::DecodeHintType::ASSUME_CODE_39_CHECK_DIGIT,
rxing::DecodeHintValue::AssumeCode39CheckDigit(*assume_code_39_check_digit),
);
}
if let Some(assume_gs1) = assume_gs1 {
hints.insert(
rxing::DecodeHintType::ASSUME_GS1,
rxing::DecodeHintValue::AssumeGs1(*assume_gs1),
);
}
if let Some(return_codabar_start_end) = return_codabar_start_end {
hints.insert(
rxing::DecodeHintType::RETURN_CODABAR_START_END,
rxing::DecodeHintValue::ReturnCodabarStartEnd(*return_codabar_start_end),
);
}
if let Some(allowed_ean_extensions) = allowed_ean_extensions {
hints.insert(
rxing::DecodeHintType::ALLOWED_EAN_EXTENSIONS,
rxing::DecodeHintValue::AllowedEanExtensions(allowed_ean_extensions.to_vec()),
);
}
if let Some(also_inverted) = also_inverted {
hints.insert(
rxing::DecodeHintType::ALSO_INVERTED,
rxing::DecodeHintValue::AlsoInverted(*also_inverted),
);
}
// println!(
// "Decode '{}' with: try_harder: {}, decode_multi: {}, barcode_types: {:?}",
// file_name, try_harder, decode_multi, barcode_types
// );
if !try_harder {
hints.insert(
rxing::DecodeHintType::TRY_HARDER,
rxing::DecodeHintValue::TryHarder(false),
);
}
if let Some(barcode_type) = barcode_types {
hints.insert(
rxing::DecodeHintType::POSSIBLE_FORMATS,
rxing::DecodeHintValue::PossibleFormats(HashSet::from_iter(
barcode_type.iter().copied(),
)),
);
}
let path = PathBuf::from(file_name);
let extension = if let Some(ext) = path.extension() {
ext.to_string_lossy().to_string()
} else {
String::default()
};
if *decode_multi {
let results = if extension == "svg" {
rxing::helpers::detect_multiple_in_svg_with_hints(file_name, &mut hints)
} else {
rxing::helpers::detect_multiple_in_file_with_hints(file_name, &mut hints)
};
match results {
Ok(result_array) => {
println!("Found {} results", result_array.len());
for (i, result) in result_array.into_iter().enumerate() {
println!(
"Result {}:\n{}",
i,
print_result(&result, *detailed_result, *raw_bytes, *parsed_bytes)
);
}
}
Err(search_err) => {
println!(
"Error while attempting to locate multiple barcodes in '{file_name}': {search_err}"
);
}
}
} else {
let result = if extension == "svg" {
rxing::helpers::detect_in_svg_with_hints(file_name, None, &mut hints)
} else {
rxing::helpers::detect_in_file_with_hints(file_name, None, &mut hints)
};
match result {
Ok(result) => {
println!(
"Detection result: \n{}",
print_result(&result, *detailed_result, *raw_bytes, *parsed_bytes)
);
}
Err(search_err) => {
println!("Error while attempting to locate barcode in '{file_name}': {search_err}");
}
}
}
}
fn encode_command(
file_name: &str,
barcode_type: &BarcodeFormat,
width: &u32,
height: &u32,
data: &Option<String>,
data_file: &Option<PathBuf>,
error_correction: &Option<String>,
character_set: &Option<String>,
data_matrix_compact: &Option<bool>,
margin: &Option<String>,
pdf_417_compact: &Option<bool>,
pdf_417_compaction: &Option<String>,
pdf_417_auto_eci: &Option<bool>,
aztec_layers: &Option<i32>,
qr_version: &Option<String>,
qr_mask_pattern: &Option<String>,
qr_compact: &Option<bool>,
gs1_format: &Option<bool>,
force_code_set: &Option<String>,
force_c40: &Option<bool>,
code_128_compact: &Option<bool>,
) {
// if data.is_none() && data_file.is_none() {
// println!("must provide either data string or data file");
// return;
// }
// if data.is_some() && data_file.is_some() {
// println!("provide only data string or data file");
// return;
// }
let input_data = if let Some(path_from) = data_file {
if path_from.exists() {
let Ok(fl) = std::fs::File::open(path_from) else {
println!("file cannot be opened");
return;
};
std::io::read_to_string(fl).expect("file should read")
} else {
println!("{} does not exist", path_from.to_string_lossy());
return;
}
} else if let Some(ds) = data {
ds.to_owned()
} else {
println!("Unknown error getting data");
return;
};
let mut hints: rxing::EncodingHintDictionary = HashMap::new();
if let Some(ec) = error_correction {
hints.insert(
rxing::EncodeHintType::ERROR_CORRECTION,
rxing::EncodeHintValue::ErrorCorrection(ec.to_owned()),
);
}
if let Some(character_set) = character_set {
hints.insert(
rxing::EncodeHintType::CHARACTER_SET,
rxing::EncodeHintValue::CharacterSet(character_set.to_owned()),
);
}
if let Some(data_matrix_compact) = data_matrix_compact {
hints.insert(
rxing::EncodeHintType::DATA_MATRIX_COMPACT,
rxing::EncodeHintValue::DataMatrixCompact(*data_matrix_compact),
);
}
if let Some(margin) = margin {
hints.insert(
rxing::EncodeHintType::MARGIN,
rxing::EncodeHintValue::Margin(margin.to_owned()),
);
}
if let Some(pdf_417_compact) = pdf_417_compact {
hints.insert(
rxing::EncodeHintType::PDF417_COMPACT,
rxing::EncodeHintValue::Pdf417Compact(pdf_417_compact.to_string()),
);
}
if let Some(pdf_417_compaction) = pdf_417_compaction {
hints.insert(
rxing::EncodeHintType::PDF417_COMPACTION,
rxing::EncodeHintValue::Pdf417Compaction(pdf_417_compaction.to_owned()),
);
}
if let Some(pdf_417_auto_eci) = pdf_417_auto_eci {
hints.insert(
rxing::EncodeHintType::PDF417_AUTO_ECI,
rxing::EncodeHintValue::Pdf417AutoEci(pdf_417_auto_eci.to_string()),
);
}
if let Some(aztec_layers) = aztec_layers {
hints.insert(
rxing::EncodeHintType::AZTEC_LAYERS,
rxing::EncodeHintValue::AztecLayers(*aztec_layers),
);
}
if let Some(qr_version) = qr_version {
hints.insert(
rxing::EncodeHintType::QR_VERSION,
rxing::EncodeHintValue::QrVersion(qr_version.to_owned()),
);
}
if let Some(qr_mask_pattern) = qr_mask_pattern {
hints.insert(
rxing::EncodeHintType::QR_MASK_PATTERN,
rxing::EncodeHintValue::QrMaskPattern(qr_mask_pattern.to_owned()),
);
}
if let Some(qr_compact) = qr_compact {
println!("Warning, QRCompact can generate unreadable barcodes");
hints.insert(
rxing::EncodeHintType::QR_COMPACT,
rxing::EncodeHintValue::QrCompact(qr_compact.to_string()),
);
}
if let Some(gs1_format) = gs1_format {
hints.insert(
rxing::EncodeHintType::GS1_FORMAT,
rxing::EncodeHintValue::Gs1Format(*gs1_format),
);
}
if let Some(force_code_set) = force_code_set {
hints.insert(
rxing::EncodeHintType::FORCE_CODE_SET,
rxing::EncodeHintValue::ForceCodeSet(force_code_set.to_owned()),
);
}
if let Some(force_c40) = force_c40 {
hints.insert(
rxing::EncodeHintType::FORCE_C40,
rxing::EncodeHintValue::ForceC40(*force_c40),
);
}
if let Some(code_128_compact) = code_128_compact {
hints.insert(
rxing::EncodeHintType::CODE128_COMPACT,
rxing::EncodeHintValue::Code128Compact(*code_128_compact),
);
}
// println!("Encode: file_name: {}, barcode_type: {}, width: {:?}, height: {:?}, data: '{:?}', data_file: {:?}", file_name, barcode_type, width, height, data, data_file);
let writer = MultiFormatWriter::default();
match writer.encode_with_hints(
&input_data,
barcode_type,
*width as i32,
*height as i32,
&hints,
) {
Ok(result) => {
println!("Encode successful, saving...");
match rxing::helpers::save_file(file_name, &result) {
Ok(_) => println!("Saved to '{file_name}'"),
Err(error) => println!("Could not save '{file_name}': {error}"),
}
}
Err(encode_error) => println!("Couldn't encode: {encode_error}"),
}
}
fn print_result(result: &rxing::RXingResult, detailed: bool, raw: bool, parsed: bool) -> String {
let result_data = result.getText().escape_default().collect::<String>();
if detailed {
format!("[Barcode Format] {}\n[Metadata] {:?}\n[Points] {:?}\n[Number of Bits] {}\n[Timestamp] {}\n[Data] {}", result.getBarcodeFormat(),result.getRXingResultMetadata(), result.getRXingResultPoints(), result.getNumBits(), result.getTimestamp(), result_data)
} else if raw {
result
.getRawBytes()
.iter()
.fold(String::from(""), |acc, b| acc + " " + &b.to_string())
} else if parsed {
let parsed_data = rxing::client::result::parseRXingResult(result);
parsed_data.to_string()
} else {
format!("({}) {}", result.getBarcodeFormat(), result_data)
}
}

10
crates/one-d-proc-derive/.gitignore vendored Normal file
View File

@@ -0,0 +1,10 @@
# Generated by Cargo
# will have compiled files and executables
/target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk

View File

@@ -0,0 +1,16 @@
[package]
name = "rxing-one-d-proc-derive"
repository = "https://github.com/rxing-core/rxing/tree/main/crates/one-d-proc-derive"
version = "0.3.1"
edition = "2021"
description = "proc macros to simplify the development of one-d barcode symbologies in rxing (https://github.com/rxing-core/rxing)"
license = "Apache-2.0"
[lib]
proc-macro = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
syn = "1.0"
quote = "1.0"

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,2 @@
# rxing-one-d-proc-derive
one dimensional barcode macros for rxing

View File

@@ -0,0 +1,181 @@
use proc_macro::TokenStream;
use quote::quote;
use syn;
#[proc_macro_derive(OneDReader)]
pub fn one_d_reader_derive(input: TokenStream) -> TokenStream {
// Construct a representation of Rust code as a syntax tree
// that we can manipulate
let ast = syn::parse(input).unwrap();
// Build the trait implementation
impl_one_d_reader_macro(&ast)
}
fn impl_one_d_reader_macro(ast: &syn::DeriveInput) -> TokenStream {
let name = &ast.ident;
let gen = quote! {
use std::collections::HashMap;
use crate::result_point::ResultPoint;
use crate::DecodeHintType;
use crate::DecodingHintDictionary;
use crate::RXingResultMetadataType;
use crate::RXingResultMetadataValue;
use crate::RXingResultPoint;
use crate::Reader;
impl Reader for #name {
fn decode(&mut self, image: &mut crate::BinaryBitmap) -> Result<crate::RXingResult, Exceptions> {
self.decode_with_hints(image, &HashMap::new())
}
// Note that we don't try rotation without the try harder flag, even if rotation was supported.
fn decode_with_hints(
&mut self,
image: &mut crate::BinaryBitmap,
hints: &DecodingHintDictionary,
) -> Result<crate::RXingResult, Exceptions> {
if let Ok(res) = self.doDecode(image, hints) {
Ok(res)
}else {
let tryHarder = hints.contains_key(&DecodeHintType::TRY_HARDER);
if tryHarder && image.isRotateSupported() {
let mut rotatedImage = image.rotateCounterClockwise();
let mut result = self.doDecode(&mut rotatedImage, hints)?;
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
let metadata = result.getRXingResultMetadata();
let mut orientation = 270;
if metadata.contains_key(&RXingResultMetadataType::ORIENTATION) {
// But if we found it reversed in doDecode(), add in that result here:
orientation = (orientation +
if let Some(crate::RXingResultMetadataValue::Orientation(or)) = metadata.get(&RXingResultMetadataType::ORIENTATION) {
*or
}else {
0
}) % 360;
}
result.putMetadata(RXingResultMetadataType::ORIENTATION, RXingResultMetadataValue::Orientation(orientation));
// Update result points
// let points = result.getRXingResultPoints();
// if points != null {
let height = rotatedImage.getHeight();
// for point in result.getRXingResultPointsMut().iter_mut() {
let total_points = result.getRXingResultPoints().len();
let points = result.getRXingResultPointsMut();
for i in 0..total_points{
// for (int i = 0; i < points.length; i++) {
points[i] = RXingResultPoint::new(height as f32- points[i].getY() - 1.0, points[i].getX());
}
// }
Ok(result)
} else {
return Err(Exceptions::NotFoundException(None))
}
}
}
}
};
gen.into()
}
#[proc_macro_derive(EANReader)]
pub fn ean_reader_derive(input: TokenStream) -> TokenStream {
// Construct a representation of Rust code as a syntax tree
// that we can manipulate
let ast = syn::parse(input).unwrap();
// Build the trait implementation
impl_ean_reader_macro(&ast)
}
fn impl_ean_reader_macro(ast: &syn::DeriveInput) -> TokenStream {
let name = &ast.ident;
let gen = quote! {
impl super::OneDReader for #name {
fn decodeRow(
&mut self,
rowNumber: u32,
row: &crate::common::BitArray,
hints: &crate::DecodingHintDictionary,
) -> Result<crate::RXingResult, crate::Exceptions> {
self.decodeRowWithGuardRange(rowNumber, row, &self.findStartGuardPattern(row)?, hints)
}
}
};
gen.into()
}
#[proc_macro_derive(OneDWriter)]
pub fn one_d_writer_derive(input: TokenStream) -> TokenStream {
// Construct a representation of Rust code as a syntax tree
// that we can manipulate
let ast = syn::parse(input).unwrap();
// Build the trait implementation
impl_one_d_writer_macro(&ast)
}
fn impl_one_d_writer_macro(ast: &syn::DeriveInput) -> TokenStream {
let name = &ast.ident;
let gen = quote! {
use crate::{
EncodeHintType, EncodeHintValue, Exceptions, Writer,
};
use std::collections::HashMap;
impl Writer for #name {
fn encode(
&self,
contents: &str,
format: &crate::BarcodeFormat,
width: i32,
height: i32,
) -> Result<crate::common::BitMatrix, crate::Exceptions> {
self.encode_with_hints(contents, format, width, height, &HashMap::new())
}
fn encode_with_hints(
&self,
contents: &str,
format: &crate::BarcodeFormat,
width: i32,
height: i32,
hints: &crate::EncodingHintDictionary,
) -> Result<crate::common::BitMatrix, crate::Exceptions> {
if contents.is_empty() {
return Err(Exceptions::IllegalArgumentException(
Some("Found empty contents".to_owned()),
));
}
if width < 0 || height < 0 {
return Err(Exceptions::IllegalArgumentException(Some(format!(
"Negative size is not allowed. Input: {}x{}",
width, height
))));
}
if let Some(supportedFormats) = self.getSupportedWriteFormats() {
if !supportedFormats.contains(format) {
return Err(Exceptions::IllegalArgumentException(Some(format!(
"Can only encode {:?}, but got {:?}",
supportedFormats, format
))));
}
}
let mut sidesMargin = self.getDefaultMargin();
if let Some(EncodeHintValue::Margin(margin)) = hints.get(&EncodeHintType::MARGIN) {
sidesMargin = margin.parse::<u32>().unwrap();
}
// if hints.contains_key(&EncodeHintType::MARGIN) {
// sidesMargin = Integer.parseInt(hints.get(EncodeHintType.MARGIN).toString());
// }
let code = self.encode_oned_with_hints(contents, hints)?;
Self::renderRXingResult(&code, width, height, sidesMargin)
}
}
};
gen.into()
}

View File

@@ -162,7 +162,7 @@ fn get_encoded_data(corrected_bits: &[bool]) -> Result<String> {
result.push_str( result.push_str(
&encdr &encdr
.decode(&decoded_bytes, encoding::DecoderTrap::Strict) .decode(&decoded_bytes, encoding::DecoderTrap::Strict)
.map_err(|a| Exceptions::illegal_state_with(a))?, .map_err(Exceptions::illegal_state_with)?,
); );
decoded_bytes.clear(); decoded_bytes.clear();
@@ -342,7 +342,7 @@ fn correct_bits(
} }
let mut offset = rawbits.len() % codeword_size; let mut offset = rawbits.len() % codeword_size;
let mut data_words = vec![0i32; num_codewords]; let mut data_words = vec![0; num_codewords];
for word in data_words.iter_mut().take(num_codewords) { for word in data_words.iter_mut().take(num_codewords) {
// for i in 0..num_codewords { // for i in 0..num_codewords {
// for (int i = 0; i < numCodewords; i++, offset += codewordSize) { // for (int i = 0; i < numCodewords; i++, offset += codewordSize) {

View File

@@ -142,7 +142,7 @@ impl<'a> Detector<'_> {
self.shift = Self::get_rotation(&sides, length)?; self.shift = Self::get_rotation(&sides, length)?;
// Flatten the parameter bits into a single 28- or 40-bit long // Flatten the parameter bits into a single 28- or 40-bit long
let mut parameter_data = 0u64; let mut parameter_data: u64 = 0;
for i in 0..4 { for i in 0..4 {
// for (int i = 0; i < 4; i++) { // for (int i = 0; i < 4; i++) {
let side = sides[(self.shift + i) as usize % 4]; let side = sides[(self.shift + i) as usize % 4];
@@ -230,7 +230,7 @@ impl<'a> Detector<'_> {
} }
let num_eccodewords = num_codewords - num_data_codewords; let num_eccodewords = num_codewords - num_data_codewords;
let mut parameterWords = vec![0i32; num_codewords as usize]; let mut parameterWords = vec![0; num_codewords as usize];
for i in (0..num_codewords).rev() { for i in (0..num_codewords).rev() {
// for (int i = numCodewords - 1; i >= 0; --i) { // for (int i = numCodewords - 1; i >= 0; --i) {
parameterWords[i as usize] = (parameter_data & 0xF) as i32; parameterWords[i as usize] = (parameter_data & 0xF) as i32;
@@ -245,7 +245,7 @@ impl<'a> Detector<'_> {
//throw NotFoundException.getNotFoundInstance(); //throw NotFoundException.getNotFoundInstance();
//} //}
// Toss the error correction. Just return the data as an integer // Toss the error correction. Just return the data as an integer
let mut result = 0u32; let mut result: u32 = 0;
for i in 0..num_data_codewords { for i in 0..num_data_codewords {
// for (int i = 0; i < numDataCodewords; i++) { // for (int i = 0; i < numDataCodewords; i++) {
result = (result << 4) + parameterWords[i as usize] as u32; result = (result << 4) + parameterWords[i as usize] as u32;
@@ -321,10 +321,10 @@ impl<'a> Detector<'_> {
// Expand the square by .5 pixel in each direction so that we're on the border // Expand the square by .5 pixel in each direction so that we're on the border
// between the white square and the black square // between the white square and the black square
let pinax = point(pina.get_x() as f32 + 0.5f32, pina.get_y() as f32 - 0.5f32); let pinax = point(pina.get_x() as f32 + 0.5, pina.get_y() as f32 - 0.5);
let pinbx = point(pinb.get_x() as f32 + 0.5f32, pinb.get_y() as f32 + 0.5f32); let pinbx = point(pinb.get_x() as f32 + 0.5, pinb.get_y() as f32 + 0.5);
let pincx = point(pinc.get_x() as f32 - 0.5f32, pinc.get_y() as f32 + 0.5f32); let pincx = point(pinc.get_x() as f32 - 0.5, pinc.get_y() as f32 + 0.5);
let pindx = point(pind.get_x() as f32 - 0.5f32, pind.get_y() as f32 - 0.5f32); let pindx = point(pind.get_x() as f32 - 0.5, pind.get_y() as f32 - 0.5);
// Expand the square so that its corners are the centers of the points // Expand the square so that its corners are the centers of the points
// just outside the bull's eye. // just outside the bull's eye.
@@ -483,8 +483,8 @@ impl<'a> Detector<'_> {
let sampler = DefaultGridSampler::default(); let sampler = DefaultGridSampler::default();
let dimension = self.get_dimension(); let dimension = self.get_dimension();
let low = dimension as f32 / 2.0f32 - self.nb_center_layers as f32; let low = dimension as f32 / 2.0 - self.nb_center_layers as f32;
let high = dimension as f32 / 2.0f32 + self.nb_center_layers as f32; let high = dimension as f32 / 2.0 + self.nb_center_layers as f32;
sampler.sample_grid_detailed( sampler.sample_grid_detailed(
image, image,
@@ -601,7 +601,7 @@ impl<'a> Detector<'_> {
*/ */
fn get_color(&self, p1: AztecPoint, p2: AztecPoint) -> i32 { fn get_color(&self, p1: AztecPoint, p2: AztecPoint) -> i32 {
let d = Self::distance_points(p1, p2); let d = Self::distance_points(p1, p2);
if d == 0.0f32 { if d == 0.0 {
return 0; return 0;
} }
let dx = (p2.get_x() - p1.get_x()) as f32 / d; let dx = (p2.get_x() - p1.get_x()) as f32 / d;
@@ -626,11 +626,11 @@ impl<'a> Detector<'_> {
let err_ratio = error as f32 / d; let err_ratio = error as f32 / d;
if err_ratio > 0.1f32 && err_ratio < 0.9f32 { if err_ratio > 0.1 && err_ratio < 0.9 {
return 0; return 0;
} }
if (err_ratio <= 0.1f32) == color_model { if (err_ratio <= 0.1) == color_model {
1 1
} else { } else {
-1 -1
@@ -674,7 +674,7 @@ impl<'a> Detector<'_> {
* @return the corners of the expanded square * @return the corners of the expanded square
*/ */
fn expand_square(corner_points: &[Point], old_side: u32, new_side: u32) -> [Point; 4] { fn expand_square(corner_points: &[Point], old_side: u32, new_side: u32) -> [Point; 4] {
let ratio = new_side as f32 / (2.0f32 * old_side as f32); let ratio = new_side as f32 / (2.0 * old_side as f32);
let d = corner_points[0] - corner_points[2]; let d = corner_points[0] - corner_points[2];
let middle = corner_points[0].middle(corner_points[2]); let middle = corner_points[0].middle(corner_points[2]);

View File

@@ -446,7 +446,7 @@ fn generateCheckWords(bitArray: &BitArray, totalBits: usize, wordSize: usize) ->
} }
fn bitsToWords(stuffedBits: &BitArray, wordSize: usize, totalWords: usize) -> Vec<i32> { fn bitsToWords(stuffedBits: &BitArray, wordSize: usize, totalWords: usize) -> Vec<i32> {
let mut message = vec![0i32; totalWords]; let mut message = vec![0; totalWords];
let mut i = 0; let mut i = 0;
let n = stuffedBits.getSize() / wordSize; let n = stuffedBits.getSize() / wordSize;
while i < n { while i < n {

View File

@@ -196,7 +196,7 @@ impl HighLevelEncoder {
// shown // shown
pub const SHIFT_TABLE: [[i32; 6]; 6] = { pub const SHIFT_TABLE: [[i32; 6]; 6] = {
// mode shift codes, per table // mode shift codes, per table
let mut shift_table = [[-1i32; 6]; 6]; let mut shift_table = [[-1; 6]; 6];
shift_table[Self::MODE_UPPER][Self::MODE_PUNCT] = 0; shift_table[Self::MODE_UPPER][Self::MODE_PUNCT] = 0;

View File

@@ -40,11 +40,11 @@ use super::{maybe_append_multiple, maybe_append_string, ParsedRXingResult, Parse
// const RFC2445_DURATION: &'static str = // const RFC2445_DURATION: &'static str =
// "P(?:(\\d+)W)?(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?)?"; // "P(?:(\\d+)W)?(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?)?";
const RFC2445_DURATION_FIELD_UNITS: [i64; 5] = [ const RFC2445_DURATION_FIELD_UNITS: [i64; 5] = [
7 * 24 * 60 * 60 * 1000i64, // 1 week 7 * 24 * 60 * 60 * 1000, // 1 week
24 * 60 * 60 * 1000i64, // 1 day 24 * 60 * 60 * 1000, // 1 day
60 * 60 * 1000i64, // 1 hour 60 * 60 * 1000, // 1 hour
60 * 1000i64, // 1 minute 60 * 1000, // 1 minute
1000i64, // 1 second 1000, // 1 second
]; ];
static DATE_TIME: Lazy<Regex> = Lazy::new(|| Regex::new("[0-9]{8}(T[0-9]{6}Z?)?").unwrap()); static DATE_TIME: Lazy<Regex> = Lazy::new(|| Regex::new("[0-9]{8}(T[0-9]{6}Z?)?").unwrap());
@@ -114,8 +114,8 @@ impl CalendarParsedRXingResult {
let start = Self::parseDate(startString.clone())?; let start = Self::parseDate(startString.clone())?;
let end = if endString.is_empty() { let end = if endString.is_empty() {
let durationMS = Self::parseDurationMS(&durationString)?; let durationMS = Self::parseDurationMS(&durationString)?;
if durationMS < 0i64 { if durationMS < 0 {
-1i64 -1
} else { } else {
start + (durationMS / 1000) start + (durationMS / 1000)
} }
@@ -240,7 +240,7 @@ impl CalendarParsedRXingResult {
} }
// let regex = Regex::new(RFC2445_DURATION).unwrap(); // let regex = Regex::new(RFC2445_DURATION).unwrap();
if let Some(m) = RFC2445_DURATION.captures(durationString) { if let Some(m) = RFC2445_DURATION.captures(durationString) {
let mut durationMS = 0i64; let mut durationMS: i64 = 0;
for (i, unit) in RFC2445_DURATION_FIELD_UNITS.iter().enumerate() { for (i, unit) in RFC2445_DURATION_FIELD_UNITS.iter().enumerate() {
// for i in 0..RFC2445_DURATION_FIELD_UNITS.len() { // for i in 0..RFC2445_DURATION_FIELD_UNITS.len() {
// for (int i = 0; i < RFC2445_DURATION_FIELD_UNITS.length; i++) { // for (int i = 0; i < RFC2445_DURATION_FIELD_UNITS.length; i++) {

View File

@@ -224,7 +224,7 @@ fn doTest(
); );
assert_eq!( assert_eq!(
endString, endString,
if calRXingResult.getEndTimestamp() < 0i64 { if calRXingResult.getEndTimestamp() < 0 {
String::default() String::default()
} else { } else {
format_date_string(calRXingResult.getEndTimestamp(), dateFormat) format_date_string(calRXingResult.getEndTimestamp(), dateFormat)

View File

@@ -29,9 +29,7 @@ static EPSILON: f32 = 1.0E-4f32;
#[test] #[test]
fn test_square_to_quadrilateral() { fn test_square_to_quadrilateral() {
let pt = PerspectiveTransform::squareToQuadrilateral( let pt = PerspectiveTransform::squareToQuadrilateral(2.0, 3.0, 10.0, 4.0, 16.0, 15.0, 4.0, 9.0);
2.0f32, 3.0f32, 10.0, 4.0, 16.0, 15.0, 4.0, 9.0,
);
assert_point_equals(2.0, 3.0, 0.0, 0.0, &pt); assert_point_equals(2.0, 3.0, 0.0, 0.0, &pt);
assert_point_equals(10.0, 4.0, 1.0, 0.0, &pt); assert_point_equals(10.0, 4.0, 1.0, 0.0, &pt);
assert_point_equals(4.0, 9.0, 0.0, 1.0, &pt); assert_point_equals(4.0, 9.0, 0.0, 1.0, &pt);

View File

@@ -23,7 +23,7 @@ use std::{cmp, fmt};
use crate::common::Result; use crate::common::Result;
use crate::Exceptions; use crate::Exceptions;
static LOAD_FACTOR: f32 = 0.75f32; static LOAD_FACTOR: f32 = 0.75;
/** /**
* <p>A simple, fast array of bits, represented compactly by an array of ints internally.</p> * <p>A simple, fast array of bits, represented compactly by an array of ints internally.</p>

View File

@@ -335,7 +335,7 @@ impl<'a> WhiteRectangleDetector<'_> {
let ti = t.x; let ti = t.x;
let tj = t.y; let tj = t.y;
if yi < self.width as f32 / 2.0f32 { if yi < self.width as f32 / 2.0 {
[ [
point(ti - CORR as f32, tj + CORR as f32), point(ti - CORR as f32, tj + CORR as f32),
point(zi + CORR as f32, zj + CORR as f32), point(zi + CORR as f32, zj + CORR as f32),

View File

@@ -241,7 +241,7 @@ impl GlobalHistogramBinarizer {
// Find a valley between them that is low and closer to the white peak. // Find a valley between them that is low and closer to the white peak.
let mut bestValley = secondPeak - 1; let mut bestValley = secondPeak - 1;
let mut bestValleyScore = -1i32; let mut bestValleyScore = -1;
let mut x = secondPeak; let mut x = secondPeak;
while x > firstPeak { while x > firstPeak {
// for (int x = secondPeak - 1; x > firstPeak; x--) { // for (int x = secondPeak - 1; x > firstPeak; x--) {

View File

@@ -179,7 +179,7 @@ impl HybridBinarizer {
} }
let left = Self::cap(x, sub_width - 3); let left = Self::cap(x, sub_width - 3);
let mut sum = 0; let mut sum = 0;
for z in -2i32..=2 { for z in -2..=2 {
// for (int z = -2; z <= 2; z++) { // for (int z = -2; z <= 2; z++) {
let blackRow = &black_points[(top as i32 + z) as usize]; let blackRow = &black_points[(top as i32 + z) as usize];
sum += blackRow[(left - 2) as usize] sum += blackRow[(left - 2) as usize]
@@ -255,7 +255,7 @@ impl HybridBinarizer {
if xoffset > maxXOffset as u32 { if xoffset > maxXOffset as u32 {
xoffset = maxXOffset as u32; xoffset = maxXOffset as u32;
} }
let mut sum = 0u32; let mut sum: u32 = 0;
let mut min = 0xff; let mut min = 0xff;
let mut max = 0; let mut max = 0;

View File

@@ -133,19 +133,9 @@ impl PerspectiveTransform {
) -> Self { ) -> Self {
let dx3 = x0 - x1 + x2 - x3; let dx3 = x0 - x1 + x2 - x3;
let dy3 = y0 - y1 + y2 - y3; let dy3 = y0 - y1 + y2 - y3;
if dx3 == 0.0f32 && dy3 == 0.0f32 { if dx3 == 0.0 && dy3 == 0.0 {
// Affine // Affine
PerspectiveTransform::new( PerspectiveTransform::new(x1 - x0, x2 - x1, x0, y1 - y0, y2 - y1, y0, 0.0, 0.0, 1.0)
x1 - x0,
x2 - x1,
x0,
y1 - y0,
y2 - y1,
y0,
0.0f32,
0.0f32,
1.0f32,
)
} else { } else {
let dx1 = x1 - x2; let dx1 = x1 - x2;
let dx2 = x3 - x2; let dx2 = x3 - x2;
@@ -163,7 +153,7 @@ impl PerspectiveTransform {
y0, y0,
a13, a13,
a23, a23,
1.0f32, 1.0,
) )
} }
} }

View File

@@ -348,7 +348,7 @@ pub(crate) fn corrupt(
) { ) {
let mut corrupted = vec![false; received.len()]; let mut corrupted = vec![false; received.len()];
//BitSet corrupted = new BitSet(received.length); //BitSet corrupted = new BitSet(received.length);
let mut j = 0isize; let mut j: isize = 0;
while j < howMany as isize { while j < howMany as isize {
// for (int j = 0; j < howMany; j++) { // for (int j = 0; j < howMany; j++) {
let location: usize = random.gen_range(0..received.len()); let location: usize = random.gen_range(0..received.len());
@@ -477,7 +477,7 @@ fn test_decoder(field: GenericGFRef, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
}; };
for _j in 0..iterations { for _j in 0..iterations {
//for (int j = 0; j < iterations; j++) { //for (int j = 0; j < iterations; j++) {
let mut i = 0isize; let mut i: isize = 0;
while i < ecWords.len() as isize { while i < ecWords.len() as isize {
//for (int i = 0; i < ecWords.length; i++) { //for (int i = 0; i < ecWords.length; i++) {
if i > 10 && i < ecWords.len() as isize / 2 - 10 { if i > 10 && i < ecWords.len() as isize / 2 - 10 {

View File

@@ -153,7 +153,7 @@ impl Decoder {
fn correctErrors(&self, codewordBytes: &mut [u8], numDataCodewords: u32) -> Result<()> { fn correctErrors(&self, codewordBytes: &mut [u8], numDataCodewords: u32) -> Result<()> {
let _numCodewords = codewordBytes.len(); let _numCodewords = codewordBytes.len();
// First read into an array of ints // First read into an array of ints
// let codewordsInts = vec![0i32;numCodewords]; // let codewordsInts = vec![0;numCodewords];
// for i in 0..numCodewords { // for i in 0..numCodewords {
// // for (int i = 0; i < numCodewords; i++) { // // for (int i = 0; i < numCodewords; i++) {
// codewordsInts[i] = codewordBytes[i]; // codewordsInts[i] = codewordBytes[i];

View File

@@ -732,7 +732,7 @@ fn decodeBase256Segment(
result.append_string( result.append_string(
&encoding::all::ISO_8859_1 &encoding::all::ISO_8859_1
.decode(&bytes, encoding::DecoderTrap::Strict) .decode(&bytes, encoding::DecoderTrap::Strict)
.map_err(|e| Exceptions::parse_with(e))?, .map_err(Exceptions::parse_with)?,
); );
byteSegments.push(bytes); byteSegments.push(bytes);

View File

@@ -375,7 +375,7 @@ fn addEdges(
//We create 4 EDF edges, with 1, 2 3 or 4 characters length. The fourth normally doesn't have a latch to ASCII //We create 4 EDF edges, with 1, 2 3 or 4 characters length. The fourth normally doesn't have a latch to ASCII
//unless it is 2 characters away from the end of the input. //unless it is 2 characters away from the end of the input.
let mut i = 0u32; let mut i: u32 = 0;
while i < 3 { while i < 3 {
// for (i = 0; i < 3; i++) { // for (i = 0; i < 3; i++) {
let pos = from + i; let pos = from + i;

View File

@@ -136,7 +136,7 @@ fn getBit(bit: u8, bytes: &[u8]) -> u8 {
} }
fn getInt(bytes: &[u8], x: &[u8]) -> u32 { fn getInt(bytes: &[u8], x: &[u8]) -> u32 {
let mut val = 0u32; let mut val: u32 = 0;
for i in 0..x.len() { for i in 0..x.len() {
// for (int i = 0; i < x.length; i++) { // for (int i = 0; i < x.length; i++) {
val += (getBit(x[i], bytes) as u32) << ((x.len() - i - 1) as u32); val += (getBit(x[i], bytes) as u32) << ((x.len() - i - 1) as u32);

View File

@@ -95,7 +95,7 @@ fn correctErrors(
let divisor = if mode == ALL { 1 } else { 2 }; let divisor = if mode == ALL { 1 } else { 2 };
// First read into an array of ints // First read into an array of ints
let mut codewordsInts = vec![0i32; (codewords / divisor) as usize]; let mut codewordsInts = vec![0; (codewords / divisor) as usize];
for i in 0..codewords { for i in 0..codewords {
if (mode == ALL) || (i % 2 == (mode - 1)) { if (mode == ALL) || (i % 2 == (mode - 1)) {
codewordsInts[(i / divisor) as usize] = codewordBytes[(i + start) as usize] as i32; codewordsInts[(i / divisor) as usize] = codewordBytes[(i + start) as usize] as i32;

View File

@@ -134,8 +134,8 @@ impl Circle<'_> {
let point_3 = self.find_width_at_degree(97.0).1[0]; let point_3 = self.find_width_at_degree(97.0).1[0];
let guessed_center_point = Self::find_center(point_1, point_2, point_3); let guessed_center_point = Self::find_center(point_1, point_2, point_3);
self.center = ( self.center = (
guessed_center_point.0.round() as u32, guessed_center_point.x.round() as u32,
guessed_center_point.1.round() as u32, guessed_center_point.y.round() as u32,
) )
} }
@@ -143,7 +143,7 @@ impl Circle<'_> {
/// returns (ellipse, center, semi_major, semi_minor, linear_eccentricity) /// returns (ellipse, center, semi_major, semi_minor, linear_eccentricity)
pub fn detect_ellipse(&self) -> (bool, (u32, u32), u32, u32, u32) { pub fn detect_ellipse(&self) -> (bool, (u32, u32), u32, u32, u32) {
// find semi-major and semi-minor axi // find semi-major and semi-minor axi
let mut lengths = [(0, 0.0, [(0.0_f32, 0.0); 2]); 72]; let mut lengths = [(0, 0.0, [Point::default(); 2]); 72];
let mut circle_points = Vec::new(); let mut circle_points = Vec::new();
// for i_rotation in 0..72 { // for i_rotation in 0..72 {
for (i_rotation, length_set) in lengths.iter_mut().enumerate() { for (i_rotation, length_set) in lengths.iter_mut().enumerate() {
@@ -193,7 +193,7 @@ impl Circle<'_> {
let guessed_center_point = Self::find_center(point_1, point_2, point_3); let guessed_center_point = Self::find_center(point_1, point_2, point_3);
( (
false, false,
(guessed_center_point.0 as u32, guessed_center_point.1 as u32), (guessed_center_point.x as u32, guessed_center_point.y as u32),
self.radius, self.radius,
self.radius, self.radius,
0, 0,
@@ -213,7 +213,7 @@ impl Circle<'_> {
); );
( (
true, true,
(ellipse_center.0 as u32, ellipse_center.1 as u32), (ellipse_center.x as u32, ellipse_center.y as u32),
major_axis.0 / 2, major_axis.0 / 2,
minor_axis.0 / 2, minor_axis.0 / 2,
linear_eccentricity, linear_eccentricity,
@@ -222,10 +222,10 @@ impl Circle<'_> {
} }
} }
fn find_center(p1: (f32, f32), p2: (f32, f32), p3: (f32, f32)) -> (f32, f32) { fn find_center(p1: Point, p2: Point, p3: Point) -> Point {
let (x1, y1) = p1; let Point { x: x1, y: y1 } = p1;
let (x2, y2) = p2; let Point { x: x2, y: y2 } = p2;
let (x3, y3) = p3; let Point { x: x3, y: y3 } = p3;
let a = x1 * (y2 - y3) - y1 * (x2 - x3) + (x2 * y3 - x3 * y2); let a = x1 * (y2 - y3) - y1 * (x2 - x3) + (x2 * y3 - x3 * y2);
let bx = (x1 * x1 + y1 * y1) * (y3 - y2) let bx = (x1 * x1 + y1 * y1) * (y3 - y2)
@@ -238,22 +238,16 @@ impl Circle<'_> {
let x = bx / (2.0 * a); let x = bx / (2.0 * a);
let y = by / (2.0 * a); let y = by / (2.0 * a);
(x.abs(), y.abs()) (x.abs(), y.abs()).into()
} }
fn calculate_ellipse_center( fn calculate_ellipse_center(a: f32, _b: f32, p1: Point, p2: Point, p3: Point) -> Point {
a: f32, let x1 = p1.x;
_b: f32, let y1 = p1.y;
p1: (f32, f32), let x2 = p2.x;
p2: (f32, f32), let y2 = p2.y;
p3: (f32, f32), let x3 = p3.x;
) -> (f32, f32) { let y3 = p3.y;
let x1 = p1.0;
let y1 = p1.1;
let x2 = p2.0;
let y2 = p2.1;
let x3 = p3.0;
let y3 = p3.1;
let ma = (x1 * x1 + y1 * y1 - a * a) / 2.0; let ma = (x1 * x1 + y1 * y1 - a * a) / 2.0;
let mb = (x2 * x2 + y2 * y2 - a * a) / 2.0; let mb = (x2 * x2 + y2 * y2 - a * a) / 2.0;
@@ -264,20 +258,20 @@ impl Circle<'_> {
let x = (ma * y2 + mb * y3 + mc * y1) / determinant; let x = (ma * y2 + mb * y3 + mc * y1) / determinant;
let y = (x1 * mb + x2 * mc + x3 * ma) / determinant; let y = (x1 * mb + x2 * mc + x3 * ma) / determinant;
(x, y) (x, y).into()
} }
fn check_ellipse_point( fn check_ellipse_point(
center: (u32, u32), center: (u32, u32),
point: &(f32, f32), point: &Point,
semi_major_axis: u32, semi_major_axis: u32,
semi_minor_axis: u32, semi_minor_axis: u32,
) -> f64 { ) -> f64 {
((point.0 as f64 - center.0 as f64).powf(2.0) / (semi_major_axis as f64).powf(2.0)) ((point.x as f64 - center.0 as f64).powf(2.0) / (semi_major_axis as f64).powf(2.0))
+ ((point.1 as f64 - center.1 as f64).powf(2.0) / (semi_minor_axis as f64).powf(2.0)) + ((point.y as f64 - center.1 as f64).powf(2.0) / (semi_minor_axis as f64).powf(2.0))
} }
fn find_width_at_degree(&self, rotation: f32) -> (u32, [(f32, f32); 2]) { fn find_width_at_degree(&self, rotation: f32) -> (u32, [Point; 2]) {
let mut x = self.center.0; let mut x = self.center.0;
let y = self.center.1; let y = self.center.1;
let mut length = 0; let mut length = 0;
@@ -285,7 +279,7 @@ impl Circle<'_> {
// count left // count left
while { while {
let point = get_point(self.center, (x, y), rotation); let point = get_point(self.center, (x, y), rotation);
!self.image.get(point.0 as u32, point.1 as u32) && x > 0 !self.image.get(point.x as u32, point.y as u32) && x > 0
} { } {
x -= 1; x -= 1;
length += 1; length += 1;
@@ -297,7 +291,7 @@ impl Circle<'_> {
// count right // count right
while { while {
let point = get_point(self.center, (x, y), rotation); let point = get_point(self.center, (x, y), rotation);
!self.image.get(point.0 as u32, point.1 as u32) !self.image.get(point.x as u32, point.y as u32)
} { } {
x += 1; x += 1;
length += 1; length += 1;
@@ -344,10 +338,10 @@ pub fn detect(image: &BitMatrix, try_harder: bool) -> Result<MaxicodeDetectionRe
}; };
let grid_sampler = DefaultGridSampler::default(); let grid_sampler = DefaultGridSampler::default();
let [tl, bl, tr, br] = &symbol_box.0; let [tl, bl, tr, br] = symbol_box.0;
let target_width = Point::distance(tl.into(), tr.into()); let target_width = Point::distance(tl, tr);
let target_height = Point::distance(br.into(), tr.into()); let target_height = Point::distance(br, tr);
// let target_width = (tr.0 - tl.0).round().abs() as u32; // let target_width = (tr.0 - tl.0).round().abs() as u32;
// let target_height = (br.1 - tr.1).round().abs() as u32; // let target_height = (br.1 - tr.1).round().abs() as u32;
@@ -364,14 +358,14 @@ pub fn detect(image: &BitMatrix, try_harder: bool) -> Result<MaxicodeDetectionRe
target_height, target_height,
0.0, 0.0,
target_height, target_height,
tl.0, tl.x,
tl.1, tl.y,
tr.0, tr.x,
tr.1, tr.y,
br.0, br.x,
br.1, br.y,
bl.0, bl.x,
bl.1, bl.y,
) else { ) else {
if try_harder { if try_harder {
continue; continue;
@@ -382,10 +376,7 @@ pub fn detect(image: &BitMatrix, try_harder: bool) -> Result<MaxicodeDetectionRe
return Ok(MaxicodeDetectionResult { return Ok(MaxicodeDetectionResult {
bits, bits,
points: symbol_box points: symbol_box
.0 .0.to_vec(),
.iter()
.map(|p| Point { x: p.0, y: p.1 })
.collect(),
rotation: symbol_box.1, rotation: symbol_box.1,
}); });
} }
@@ -709,7 +700,7 @@ const LEFT_SHIFT_PERCENT_ADJUST: f32 = 0.03;
const RIGHT_SHIFT_PERCENT_ADJUST: f32 = 0.03; const RIGHT_SHIFT_PERCENT_ADJUST: f32 = 0.03;
const ACCEPTED_SCALES: [f64; 5] = [0.065, 0.069, 0.07, 0.075, 0.08]; const ACCEPTED_SCALES: [f64; 5] = [0.065, 0.069, 0.07, 0.075, 0.08];
fn box_symbol(image: &BitMatrix, circle: &mut Circle) -> Result<([(f32, f32); 4], f32)> { fn box_symbol(image: &BitMatrix, circle: &mut Circle) -> Result<([Point; 4], f32)> {
let (left_boundary, right_boundary, top_boundary, bottom_boundary) = let (left_boundary, right_boundary, top_boundary, bottom_boundary) =
calculate_simple_boundary(circle, Some(image), None, false); calculate_simple_boundary(circle, Some(image), None, false);
@@ -743,10 +734,10 @@ fn box_symbol(image: &BitMatrix, circle: &mut Circle) -> Result<([(f32, f32); 4]
Ok(( Ok((
[ [
(result_box[0].x, result_box[0].y), (result_box[0].x, result_box[0].y).into(),
(result_box[1].x, result_box[1].y), (result_box[1].x, result_box[1].y).into(),
(result_box[2].x, result_box[2].y), (result_box[2].x, result_box[2].y).into(),
(result_box[3].x, result_box[3].y), (result_box[3].x, result_box[3].y).into(),
], ],
final_rotation, final_rotation,
)) ))
@@ -845,9 +836,9 @@ fn attempt_rotation_box(
let p1_rot = get_point(circle.center, topl_p1, rotation); let p1_rot = get_point(circle.center, topl_p1, rotation);
let p2_rot = get_point(circle.center, topl_p2, rotation); let p2_rot = get_point(circle.center, topl_p2, rotation);
let p3_rot = get_point(circle.center, topl_p3, rotation); let p3_rot = get_point(circle.center, topl_p3, rotation);
let found_tl = image.try_get_area(p1_rot.0 as u32, p1_rot.1 as u32, 3)? let found_tl = image.try_get_area(p1_rot.x as u32, p1_rot.y as u32, 3)?
&& image.try_get_area(p2_rot.0 as u32, p2_rot.1 as u32, 3)? && image.try_get_area(p2_rot.x as u32, p2_rot.y as u32, 3)?
&& image.try_get_area(p3_rot.0 as u32, p3_rot.1 as u32, 3)?; && image.try_get_area(p3_rot.x as u32, p3_rot.y as u32, 3)?;
if !found_tl { if !found_tl {
continue; continue;
} }
@@ -858,9 +849,9 @@ fn attempt_rotation_box(
let p1_rot = get_point(circle.center, topr_p1, rotation); let p1_rot = get_point(circle.center, topr_p1, rotation);
let p2_rot = get_point(circle.center, topr_p2, rotation); let p2_rot = get_point(circle.center, topr_p2, rotation);
let p3_rot = get_point(circle.center, topr_p3, rotation); let p3_rot = get_point(circle.center, topr_p3, rotation);
let found_tr = !image.try_get_area(p1_rot.0 as u32, p1_rot.1 as u32, 3)? let found_tr = !image.try_get_area(p1_rot.x as u32, p1_rot.y as u32, 3)?
&& !image.try_get_area(p2_rot.0 as u32, p2_rot.1 as u32, 3)? && !image.try_get_area(p2_rot.x as u32, p2_rot.y as u32, 3)?
&& !image.try_get_area(p3_rot.0 as u32, p3_rot.1 as u32, 3)?; && !image.try_get_area(p3_rot.x as u32, p3_rot.y as u32, 3)?;
if !found_tr { if !found_tr {
continue; continue;
} }
@@ -871,9 +862,9 @@ fn attempt_rotation_box(
let p1_rot = get_point(circle.center, l_p1, rotation); let p1_rot = get_point(circle.center, l_p1, rotation);
let p2_rot = get_point(circle.center, l_p2, rotation); let p2_rot = get_point(circle.center, l_p2, rotation);
let p3_rot = get_point(circle.center, l_p3, rotation); let p3_rot = get_point(circle.center, l_p3, rotation);
let found_l = image.try_get_area(p1_rot.0 as u32, p1_rot.1 as u32, 3)? let found_l = image.try_get_area(p1_rot.x as u32, p1_rot.y as u32, 3)?
&& !image.try_get_area(p2_rot.0 as u32, p2_rot.1 as u32, 3)? && !image.try_get_area(p2_rot.x as u32, p2_rot.y as u32, 3)?
&& image.try_get_area(p3_rot.0 as u32, p3_rot.1 as u32, 3)?; && image.try_get_area(p3_rot.x as u32, p3_rot.y as u32, 3)?;
if !found_l { if !found_l {
continue; continue;
} }
@@ -884,9 +875,9 @@ fn attempt_rotation_box(
let p1_rot = get_point(circle.center, r_p1, rotation); let p1_rot = get_point(circle.center, r_p1, rotation);
let p2_rot = get_point(circle.center, r_p2, rotation); let p2_rot = get_point(circle.center, r_p2, rotation);
let p3_rot = get_point(circle.center, r_p3, rotation); let p3_rot = get_point(circle.center, r_p3, rotation);
let found_r = image.try_get_area(p1_rot.0 as u32, p1_rot.1 as u32, 3)? let found_r = image.try_get_area(p1_rot.x as u32, p1_rot.y as u32, 3)?
&& !image.try_get_area(p2_rot.0 as u32, p2_rot.1 as u32, 3)? && !image.try_get_area(p2_rot.x as u32, p2_rot.y as u32, 3)?
&& image.try_get_area(p3_rot.0 as u32, p3_rot.1 as u32, 3)?; && image.try_get_area(p3_rot.x as u32, p3_rot.y as u32, 3)?;
if !found_r { if !found_r {
continue; continue;
} }
@@ -897,9 +888,9 @@ fn attempt_rotation_box(
let p1_rot = get_point(circle.center, bottoml_p1, rotation); let p1_rot = get_point(circle.center, bottoml_p1, rotation);
let p2_rot = get_point(circle.center, bottoml_p2, rotation); let p2_rot = get_point(circle.center, bottoml_p2, rotation);
let p3_rot = get_point(circle.center, bottoml_p3, rotation); let p3_rot = get_point(circle.center, bottoml_p3, rotation);
let found_bl = image.try_get_area(p1_rot.0 as u32, p1_rot.1 as u32, 3)? let found_bl = image.try_get_area(p1_rot.x as u32, p1_rot.y as u32, 3)?
&& !image.try_get_area(p2_rot.0 as u32, p2_rot.1 as u32, 3)? && !image.try_get_area(p2_rot.x as u32, p2_rot.y as u32, 3)?
&& image.try_get_area(p3_rot.0 as u32, p3_rot.1 as u32, 3)?; && image.try_get_area(p3_rot.x as u32, p3_rot.y as u32, 3)?;
if !found_bl { if !found_bl {
continue; continue;
} }
@@ -910,9 +901,9 @@ fn attempt_rotation_box(
let p1_rot = get_point(circle.center, bottomr_p1, rotation); let p1_rot = get_point(circle.center, bottomr_p1, rotation);
let p2_rot = get_point(circle.center, bottomr_p2, rotation); let p2_rot = get_point(circle.center, bottomr_p2, rotation);
let p3_rot = get_point(circle.center, bottomr_p3, rotation); let p3_rot = get_point(circle.center, bottomr_p3, rotation);
let found_br = image.try_get_area(p1_rot.0 as u32, p1_rot.1 as u32, 3)? let found_br = image.try_get_area(p1_rot.x as u32, p1_rot.y as u32, 3)?
&& !image.try_get_area(p2_rot.0 as u32, p2_rot.1 as u32, 3)? && !image.try_get_area(p2_rot.x as u32, p2_rot.y as u32, 3)?
&& image.try_get_area(p3_rot.0 as u32, p3_rot.1 as u32, 3)?; && image.try_get_area(p3_rot.x as u32, p3_rot.y as u32, 3)?;
if !found_br { if !found_br {
continue; continue;
} }
@@ -952,10 +943,10 @@ fn attempt_rotation_box(
Some(( Some((
[ [
point(new_1.0, new_1.1), point(new_1.x, new_1.y),
point(new_2.0, new_2.1), point(new_2.x, new_2.y),
point(new_3.0, new_3.1), point(new_3.x, new_3.y),
point(new_4.0, new_4.1), point(new_4.x, new_4.y),
], ],
final_rotation, final_rotation,
)) ))
@@ -977,7 +968,7 @@ fn get_adjusted_points(
) )
} }
fn get_point(center: (u32, u32), original: (u32, u32), angle: f32) -> (f32, f32) { fn get_point(center: (u32, u32), original: (u32, u32), angle: f32) -> Point {
let radians = angle.to_radians(); let radians = angle.to_radians();
let x = radians.cos() * (original.0 as f32 - center.0 as f32) let x = radians.cos() * (original.0 as f32 - center.0 as f32)
- radians.sin() * (original.1 as f32 - center.1 as f32) - radians.sin() * (original.1 as f32 - center.1 as f32)
@@ -986,7 +977,7 @@ fn get_point(center: (u32, u32), original: (u32, u32), angle: f32) -> (f32, f32)
+ radians.cos() * (original.1 as f32 - center.1 as f32) + radians.cos() * (original.1 as f32 - center.1 as f32)
+ center.1 as f32; + center.1 as f32;
(x.abs(), y.abs()) Point::new(x.abs(), y.abs())
} }
fn adjust_point_alternate(point: (u32, u32), circle: &Circle, center_scale: f64) -> (u32, u32) { fn adjust_point_alternate(point: (u32, u32), circle: &Circle, center_scale: f64) -> (u32, u32) {

View File

@@ -91,7 +91,7 @@ impl OneDReader for CodaBarReader {
// Look for whitespace after pattern: // Look for whitespace after pattern:
let trailingWhitespace = self.counters[nextStart - 1]; let trailingWhitespace = self.counters[nextStart - 1];
let mut lastPatternSize = 0; let mut lastPatternSize = 0;
for i in -8isize..-1 { for i in -8..-1 {
lastPatternSize += self.counters[(nextStart as isize + i) as usize]; lastPatternSize += self.counters[(nextStart as isize + i) as usize];
} }
@@ -283,7 +283,7 @@ impl CodaBarReader {
.nth(i) .nth(i)
.ok_or(Exceptions::INDEX_OUT_OF_BOUNDS)? .ok_or(Exceptions::INDEX_OUT_OF_BOUNDS)?
as usize]; as usize];
for j in (0usize..=6).rev() { for j in (0..=6).rev() {
// Even j = bars, while odd j = spaces. Categories 2 and 3 are for // Even j = bars, while odd j = spaces. Categories 2 and 3 are for
// long stripes, while 0 and 1 are for short stripes. // long stripes, while 0 and 1 are for short stripes.
let category = (j & 1) + ((pattern as usize) & 1) * 2; let category = (j & 1) + ((pattern as usize) & 1) * 2;

View File

@@ -28,7 +28,7 @@ fn testBitsDiffering() {
assert_eq!(0, FormatInformation::numBitsDiffering(1, 1)); assert_eq!(0, FormatInformation::numBitsDiffering(1, 1));
assert_eq!(1, FormatInformation::numBitsDiffering(0, 2)); assert_eq!(1, FormatInformation::numBitsDiffering(0, 2));
assert_eq!(2, FormatInformation::numBitsDiffering(1, 2)); assert_eq!(2, FormatInformation::numBitsDiffering(1, 2));
assert_eq!(32, FormatInformation::numBitsDiffering(-1i32 as u32, 0)); assert_eq!(32, FormatInformation::numBitsDiffering(u32::MAX, 0));
} }
#[test] #[test]

View File

@@ -48,8 +48,8 @@ pub fn decode(
let mut bits = BitSource::new(bytes.to_owned()); let mut bits = BitSource::new(bytes.to_owned());
let mut result = String::with_capacity(50); let mut result = String::with_capacity(50);
let mut byteSegments = vec![vec![0u8; 0]; 0]; let mut byteSegments = vec![vec![0u8; 0]; 0];
let mut symbolSequence = -1i32; let mut symbolSequence = -1;
let mut parityData = -1i32; let mut parityData = -1;
let mut currentCharacterSetECI = None; let mut currentCharacterSetECI = None;
let mut fc1InEffect = false; let mut fc1InEffect = false;

View File

@@ -22,7 +22,7 @@ use crate::common::BitArray;
*/ */
fn getUnsignedInt(v: &BitArray) -> u64 { fn getUnsignedInt(v: &BitArray) -> u64 {
let mut result = 0u64; let mut result: u64 = 0;
const OFFSET: usize = 0; const OFFSET: usize = 0;
for i in 0..32 { for i in 0..32 {
// for (int i = 0, offset = 0; i < 32; i++) { // for (int i = 0, offset = 0; i < 32; i++) {

View File

@@ -132,7 +132,7 @@ impl RXingResult {
/** Currently necessary because the external OneDReader proc macro uses it. */ /** Currently necessary because the external OneDReader proc macro uses it. */
pub fn getRXingResultPoints(&self) -> &Vec<Point> { pub fn getRXingResultPoints(&self) -> &Vec<Point> {
&&self.resultPoints &self.resultPoints
} }
/** Currently necessary because the external OneDReader proc macro uses it. */ /** Currently necessary because the external OneDReader proc macro uses it. */