mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-25 20:02:34 +00:00
cleaned up many warnings
This commit is contained in:
@@ -26,13 +26,13 @@
|
||||
|
||||
use crate::{RGBLuminanceSource, LuminanceSource};
|
||||
|
||||
static src_data : [u32;9] = [0x000000, 0x7F7F7F, 0xFFFFFF,
|
||||
const SRC_DATA : [u32;9] = [0x000000, 0x7F7F7F, 0xFFFFFF,
|
||||
0xFF0000, 0x00FF00, 0x0000FF,
|
||||
0x0000FF, 0x00FF00, 0xFF0000];
|
||||
|
||||
#[test]
|
||||
fn testCrop() {
|
||||
let SOURCE = RGBLuminanceSource::new_with_width_height_pixels(3,3,&src_data.to_vec());
|
||||
let SOURCE = RGBLuminanceSource::new_with_width_height_pixels(3,3,&SRC_DATA.to_vec());
|
||||
|
||||
assert!(SOURCE.isCropSupported());
|
||||
let cropped = SOURCE.crop(1, 1, 1, 1).unwrap();
|
||||
@@ -43,7 +43,7 @@ use crate::{RGBLuminanceSource, LuminanceSource};
|
||||
|
||||
#[test]
|
||||
fn testMatrix() {
|
||||
let SOURCE = RGBLuminanceSource::new_with_width_height_pixels(3,3,&src_data.to_vec());
|
||||
let SOURCE = RGBLuminanceSource::new_with_width_height_pixels(3,3,&SRC_DATA.to_vec());
|
||||
|
||||
assert_eq!(vec![ 0x00, 0x7F, 0xFF, 0x3F, 0x7F, 0x3F, 0x3F, 0x7F, 0x3F ],
|
||||
SOURCE.getMatrix());
|
||||
@@ -57,7 +57,7 @@ use crate::{RGBLuminanceSource, LuminanceSource};
|
||||
|
||||
#[test]
|
||||
fn testGetRow() {
|
||||
let SOURCE = RGBLuminanceSource::new_with_width_height_pixels(3,3,&src_data.to_vec());
|
||||
let SOURCE = RGBLuminanceSource::new_with_width_height_pixels(3,3,&SRC_DATA.to_vec());
|
||||
|
||||
assert_eq!(vec![ 0x3F, 0x7F, 0x3F ], SOURCE.getRow(2, &vec![0;3]));
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ use crate::{
|
||||
shared_test_methods::{stripSpace, toBitArray, toBooleanArray},
|
||||
AztecDetectorResult::AztecDetectorRXingResult,
|
||||
},
|
||||
common::{BitArray, BitMatrix},
|
||||
BarcodeFormat, EncodeHintType, EncodeHintValue, RXingResultPoint,
|
||||
};
|
||||
|
||||
@@ -49,8 +48,8 @@ const UTF_8: EncodingRef = encoding::all::UTF_8; //StandardCharsets.UTF_8;
|
||||
const ISO_8859_15: EncodingRef = encoding::all::ISO_8859_15; //Charset.forName("ISO-8859-15");
|
||||
const WINDOWS_1252: EncodingRef = encoding::all::WINDOWS_1252; //Charset.forName("Windows-1252");
|
||||
|
||||
const DOTX: &str = "[^.X]";
|
||||
const SPACES: &str = "\\s+";
|
||||
// const DOTX: &str = "[^.X]";
|
||||
// const SPACES: &str = "\\s+";
|
||||
const NO_POINTS: Vec<RXingResultPoint> = Vec::new();
|
||||
|
||||
// real life tests
|
||||
|
||||
@@ -14,12 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use encoding::Encoding;
|
||||
|
||||
use crate::{
|
||||
common::{
|
||||
reedsolomon::{
|
||||
get_predefined_genericgf, GenericGF, PredefinedGenericGF, ReedSolomonDecoder, GenericGFRef,
|
||||
get_predefined_genericgf, PredefinedGenericGF, ReedSolomonDecoder, GenericGFRef,
|
||||
},
|
||||
BitMatrix, CharacterSetECI, DecoderRXingResult, DetectorRXingResult,
|
||||
},
|
||||
|
||||
@@ -19,7 +19,7 @@ use std::fmt;
|
||||
use crate::{
|
||||
common::{
|
||||
detector::{MathUtils, WhiteRectangleDetector},
|
||||
reedsolomon::{self, GenericGF, ReedSolomonDecoder},
|
||||
reedsolomon::{self, ReedSolomonDecoder},
|
||||
BitMatrix, DefaultGridSampler, GridSampler,
|
||||
},
|
||||
exceptions::Exceptions,
|
||||
|
||||
@@ -19,7 +19,7 @@ use encoding::Encoding;
|
||||
use crate::{
|
||||
common::{
|
||||
reedsolomon::{
|
||||
get_predefined_genericgf, GenericGF, PredefinedGenericGF, ReedSolomonEncoder, GenericGFRef,
|
||||
get_predefined_genericgf, PredefinedGenericGF, ReedSolomonEncoder, GenericGFRef,
|
||||
},
|
||||
BitArray, BitMatrix,
|
||||
},
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::common::BitArray;
|
||||
|
||||
use super::{BinaryShiftToken, SimpleToken};
|
||||
|
||||
77
src/barcode_format.rs
Normal file
77
src/barcode_format.rs
Normal file
@@ -0,0 +1,77 @@
|
||||
|
||||
/*
|
||||
* Copyright 2007 ZXing authors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//package com.google.zxing;
|
||||
|
||||
/**
|
||||
* Enumerates barcode formats known to this package. Please keep alphabetized.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||
pub enum BarcodeFormat {
|
||||
/** Aztec 2D barcode format. */
|
||||
AZTEC,
|
||||
|
||||
/** CODABAR 1D format. */
|
||||
CODABAR,
|
||||
|
||||
/** Code 39 1D format. */
|
||||
CODE_39,
|
||||
|
||||
/** Code 93 1D format. */
|
||||
CODE_93,
|
||||
|
||||
/** Code 128 1D format. */
|
||||
CODE_128,
|
||||
|
||||
/** Data Matrix 2D barcode format. */
|
||||
DATA_MATRIX,
|
||||
|
||||
/** EAN-8 1D format. */
|
||||
EAN_8,
|
||||
|
||||
/** EAN-13 1D format. */
|
||||
EAN_13,
|
||||
|
||||
/** ITF (Interleaved Two of Five) 1D format. */
|
||||
ITF,
|
||||
|
||||
/** MaxiCode 2D barcode format. */
|
||||
MAXICODE,
|
||||
|
||||
/** PDF417 format. */
|
||||
PDF_417,
|
||||
|
||||
/** QR Code 2D barcode format. */
|
||||
QR_CODE,
|
||||
|
||||
/** RSS 14 */
|
||||
RSS_14,
|
||||
|
||||
/** RSS EXPANDED */
|
||||
RSS_EXPANDED,
|
||||
|
||||
/** UPC-A 1D format. */
|
||||
UPC_A,
|
||||
|
||||
/** UPC-E 1D format. */
|
||||
UPC_E,
|
||||
|
||||
/** UPC/EAN extension format. Not a stand-alone format. */
|
||||
UPC_EAN_EXTENSION,
|
||||
}
|
||||
76
src/binarizer.rs
Normal file
76
src/binarizer.rs
Normal file
@@ -0,0 +1,76 @@
|
||||
|
||||
/*
|
||||
* Copyright 2009 ZXing authors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//package com.google.zxing;
|
||||
|
||||
use crate::{common::{BitArray, BitMatrix}, Exceptions, LuminanceSource};
|
||||
|
||||
/**
|
||||
* This class hierarchy provides a set of methods to convert luminance data to 1 bit data.
|
||||
* It allows the algorithm to vary polymorphically, for example allowing a very expensive
|
||||
* thresholding technique for servers and a fast one for mobile. It also permits the implementation
|
||||
* to vary, e.g. a JNI version for Android and a Java fallback version for other platforms.
|
||||
*
|
||||
* @author dswitkin@google.com (Daniel Switkin)
|
||||
*/
|
||||
pub trait Binarizer {
|
||||
//private final LuminanceSource source;
|
||||
//fn new(source:dyn LuminanceSource) -> Self;
|
||||
|
||||
fn getLuminanceSource(&self) -> &Box<dyn LuminanceSource>;
|
||||
|
||||
/**
|
||||
* Converts one row of luminance data to 1 bit data. May actually do the conversion, or return
|
||||
* cached data. Callers should assume this method is expensive and call it as seldom as possible.
|
||||
* This method is intended for decoding 1D barcodes and may choose to apply sharpening.
|
||||
* For callers which only examine one row of pixels at a time, the same BitArray should be reused
|
||||
* and passed in with each call for performance. However it is legal to keep more than one row
|
||||
* at a time if needed.
|
||||
*
|
||||
* @param y The row to fetch, which must be in [0, bitmap height)
|
||||
* @param row An optional preallocated array. If null or too small, it will be ignored.
|
||||
* If used, the Binarizer will call BitArray.clear(). Always use the returned object.
|
||||
* @return The array of bits for this row (true means black).
|
||||
* @throws NotFoundException if row can't be binarized
|
||||
*/
|
||||
fn getBlackRow(&self, y: usize, row: &mut BitArray) -> Result<BitArray, Exceptions>;
|
||||
|
||||
/**
|
||||
* Converts a 2D array of luminance data to 1 bit data. As above, assume this method is expensive
|
||||
* and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or
|
||||
* may not apply sharpening. Therefore, a row from this matrix may not be identical to one
|
||||
* fetched using getBlackRow(), so don't mix and match between them.
|
||||
*
|
||||
* @return The 2D array of bits for the image (true means black).
|
||||
* @throws NotFoundException if image can't be binarized to make a matrix
|
||||
*/
|
||||
fn getBlackMatrix(&self) -> Result<BitMatrix, Exceptions>;
|
||||
|
||||
/**
|
||||
* Creates a new object with the same type as this Binarizer implementation, but with pristine
|
||||
* state. This is needed because Binarizer implementations may be stateful, e.g. keeping a cache
|
||||
* of 1 bit data. See Effective Java for why we can't use Java's clone() method.
|
||||
*
|
||||
* @param source The LuminanceSource this Binarizer will operate on.
|
||||
* @return A new concrete Binarizer implementation object.
|
||||
*/
|
||||
fn createBinarizer(&self, source: Box<dyn LuminanceSource>) -> Box<dyn Binarizer>;
|
||||
|
||||
fn getWidth(&self) -> usize;
|
||||
|
||||
fn getHeight(&self) -> usize;
|
||||
}
|
||||
164
src/binary_bitmap.rs
Normal file
164
src/binary_bitmap.rs
Normal file
@@ -0,0 +1,164 @@
|
||||
|
||||
/*
|
||||
* Copyright 2009 ZXing authors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//package com.google.zxing;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use crate::{common::{BitMatrix, BitArray}, Exceptions, Binarizer};
|
||||
|
||||
/**
|
||||
* This class is the core bitmap class used by ZXing to represent 1 bit data. Reader objects
|
||||
* accept a BinaryBitmap and attempt to decode it.
|
||||
*
|
||||
* @author dswitkin@google.com (Daniel Switkin)
|
||||
*/
|
||||
pub struct BinaryBitmap {
|
||||
binarizer: Box<dyn Binarizer>,
|
||||
matrix: BitMatrix,
|
||||
}
|
||||
|
||||
impl BinaryBitmap {
|
||||
pub fn new(binarizer: Box<dyn Binarizer>) -> Self {
|
||||
Self {
|
||||
matrix: binarizer.getBlackMatrix().unwrap(),
|
||||
binarizer: binarizer,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The width of the bitmap.
|
||||
*/
|
||||
pub fn getWidth(&self) -> usize {
|
||||
return self.binarizer.getWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The height of the bitmap.
|
||||
*/
|
||||
pub fn getHeight(&self) -> usize {
|
||||
return self.binarizer.getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts one row of luminance data to 1 bit data. May actually do the conversion, or return
|
||||
* cached data. Callers should assume this method is expensive and call it as seldom as possible.
|
||||
* This method is intended for decoding 1D barcodes and may choose to apply sharpening.
|
||||
*
|
||||
* @param y The row to fetch, which must be in [0, bitmap height)
|
||||
* @param row An optional preallocated array. If null or too small, it will be ignored.
|
||||
* If used, the Binarizer will call BitArray.clear(). Always use the returned object.
|
||||
* @return The array of bits for this row (true means black).
|
||||
* @throws NotFoundException if row can't be binarized
|
||||
*/
|
||||
pub fn getBlackRow(&self, y: usize, row: &mut BitArray) -> Result<BitArray, Exceptions> {
|
||||
return self.binarizer.getBlackRow(y, row);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a 2D array of luminance data to 1 bit. As above, assume this method is expensive
|
||||
* and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or
|
||||
* may not apply sharpening. Therefore, a row from this matrix may not be identical to one
|
||||
* fetched using getBlackRow(), so don't mix and match between them.
|
||||
*
|
||||
* @return The 2D array of bits for the image (true means black).
|
||||
* @throws NotFoundException if image can't be binarized to make a matrix
|
||||
*/
|
||||
pub fn getBlackMatrix(&self) -> Result<&BitMatrix, Exceptions> {
|
||||
// The matrix is created on demand the first time it is requested, then cached. There are two
|
||||
// reasons for this:
|
||||
// 1. This work will never be done if the caller only installs 1D Reader objects, or if a
|
||||
// 1D Reader finds a barcode before the 2D Readers run.
|
||||
// 2. This work will only be done once even if the caller installs multiple 2D Readers.
|
||||
return Ok(&self.matrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether this bitmap can be cropped.
|
||||
*/
|
||||
pub fn isCropSupported(&self) -> bool {
|
||||
let b = &self.binarizer;
|
||||
let r = &b.getLuminanceSource();
|
||||
let isCropOk = r.isCropSupported();
|
||||
return isCropOk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new object with cropped image data. Implementations may keep a reference to the
|
||||
* original data rather than a copy. Only callable if isCropSupported() is true.
|
||||
*
|
||||
* @param left The left coordinate, which must be in [0,getWidth())
|
||||
* @param top The top coordinate, which must be in [0,getHeight())
|
||||
* @param width The width of the rectangle to crop.
|
||||
* @param height The height of the rectangle to crop.
|
||||
* @return A cropped version of this object.
|
||||
*/
|
||||
pub fn crop(&self, left: usize, top: usize, width: usize, height: usize) -> BinaryBitmap {
|
||||
let newSource = self
|
||||
.binarizer
|
||||
.getLuminanceSource()
|
||||
.crop(left, top, width, height);
|
||||
return BinaryBitmap::new(
|
||||
self.binarizer
|
||||
.createBinarizer(newSource.expect("new lum source expected")),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether this bitmap supports counter-clockwise rotation.
|
||||
*/
|
||||
pub fn isRotateSupported(&self) -> bool {
|
||||
return self.binarizer.getLuminanceSource().isRotateSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new object with rotated image data by 90 degrees counterclockwise.
|
||||
* Only callable if {@link #isRotateSupported()} is true.
|
||||
*
|
||||
* @return A rotated version of this object.
|
||||
*/
|
||||
pub fn rotateCounterClockwise(&self) -> BinaryBitmap {
|
||||
let newSource = self.binarizer.getLuminanceSource().rotateCounterClockwise();
|
||||
return BinaryBitmap::new(
|
||||
self.binarizer
|
||||
.createBinarizer(newSource.expect("new lum source expected")),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new object with rotated image data by 45 degrees counterclockwise.
|
||||
* Only callable if {@link #isRotateSupported()} is true.
|
||||
*
|
||||
* @return A rotated version of this object.
|
||||
*/
|
||||
pub fn rotateCounterClockwise45(&self) -> BinaryBitmap {
|
||||
let newSource = self
|
||||
.binarizer
|
||||
.getLuminanceSource()
|
||||
.rotateCounterClockwise45();
|
||||
return BinaryBitmap::new(
|
||||
self.binarizer
|
||||
.createBinarizer(newSource.expect("new lum source expected")),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for BinaryBitmap {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.getBlackMatrix().unwrap())
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
// import java.awt.image.BufferedImage;
|
||||
// import java.awt.image.WritableRaster;
|
||||
|
||||
use image::{DynamicImage, EncodableLayout, GenericImage, GrayImage, ImageBuffer, Luma};
|
||||
use image::{DynamicImage, ImageBuffer, Luma};
|
||||
use imageproc::geometric_transformations::rotate_about_center;
|
||||
|
||||
use crate::LuminanceSource;
|
||||
|
||||
@@ -62,10 +62,10 @@ pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
Vec::new()
|
||||
},
|
||||
Vec::new(),
|
||||
"".to_owned(),
|
||||
pronunciation.unwrap_or_default(),//"".to_owned(),
|
||||
phoneNumbers,
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
emails, //Vec::new(),
|
||||
Vec::new(),
|
||||
"".to_owned(),
|
||||
note,
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
use crate::RXingResult;
|
||||
|
||||
use super::{
|
||||
ParsedClientResult, ResultParser, URIParsedRXingResult, URIParsedResult, URIResultParser,
|
||||
ParsedClientResult, ResultParser, URIParsedRXingResult, URIResultParser,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
// import java.util.regex.Matcher;
|
||||
// import java.util.regex.Pattern;
|
||||
|
||||
use chrono::{Date, DateTime, Local, NaiveDateTime, TimeZone, Utc};
|
||||
use chrono::{ DateTime, NaiveDateTime, TimeZone, Utc};
|
||||
use chrono_tz::Tz;
|
||||
use regex::Regex;
|
||||
use lazy_static::lazy_static;
|
||||
@@ -35,8 +35,7 @@ use lazy_static::lazy_static;
|
||||
use crate::exceptions::Exceptions;
|
||||
|
||||
use super::{
|
||||
maybe_append_multiple, maybe_append_string, ParsedRXingResult, ParsedRXingResultType,
|
||||
ResultParser,
|
||||
maybe_append_multiple, maybe_append_string, ParsedRXingResult, ParsedRXingResultType
|
||||
};
|
||||
|
||||
// const RFC2445_DURATION: &'static str =
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
// */
|
||||
// public final class CalendarParsedRXingResultTestCase extends Assert {
|
||||
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use chrono::{NaiveDateTime};
|
||||
|
||||
use crate::{
|
||||
client::result::{ParsedClientResult, ParsedRXingResultType},
|
||||
@@ -44,7 +44,7 @@ use crate::{
|
||||
use super::{ParsedRXingResult, ResultParser};
|
||||
|
||||
const EPSILON: f64 = 1.0E-10;
|
||||
const DATE_FORMAT_STRING: &'static str = "yyyyMMdd'T'HHmmss'Z'";
|
||||
// const DATE_FORMAT_STRING: &'static str = "yyyyMMdd'T'HHmmss'Z'";
|
||||
|
||||
// private static DateFormat makeGMTFormat() {
|
||||
// DateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'", Locale.ENGLISH);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
// package com.google.zxing.client.result;
|
||||
|
||||
use super::{maybe_append_string, ParsedRXingResult, ParsedRXingResultType, ResultParser};
|
||||
use super::{ ParsedRXingResult, ParsedRXingResultType, ResultParser};
|
||||
|
||||
/**
|
||||
* Represents a parsed result that encodes an email message including recipients, subject
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
// import java.util.Map;
|
||||
// import java.util.Objects;
|
||||
|
||||
use std::{collections::HashMap, hash::Hash};
|
||||
use std::{collections::HashMap};
|
||||
|
||||
use super::{ParsedRXingResult, ParsedRXingResultType};
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
client::result::{ParsedClientResult, ProductParsedResult},
|
||||
client::result::{ParsedClientResult},
|
||||
RXingResult, BarcodeFormat,
|
||||
};
|
||||
|
||||
|
||||
@@ -85,7 +85,6 @@ pub fn parse(result: &crate::RXingResult) -> Option<super::ParsedClientResult> {
|
||||
"00" => sscc = value,
|
||||
"01" => productID = value,
|
||||
"10" => lotNumber = value,
|
||||
"10" => lotNumber = value,
|
||||
"11" => productionDate = value,
|
||||
"13" => packagingDate = value,
|
||||
"15" => bestBeforeDate = value,
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
// import com.google.zxing.BarcodeFormat;
|
||||
// import com.google.zxing.RXingResult;
|
||||
|
||||
use std::result;
|
||||
|
||||
use crate::BarcodeFormat;
|
||||
|
||||
use super::{ ResultParser, ISBNParsedRXingResult, ParsedClientResult};
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
// import java.util.Locale;
|
||||
// import java.util.TimeZone;
|
||||
|
||||
use chrono::{Local, TimeZone, Utc};
|
||||
use chrono::{TimeZone, Utc};
|
||||
|
||||
use crate::{client::result::ParsedRXingResult, BarcodeFormat, RXingResult};
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
// package com.google.zxing.client.result;
|
||||
|
||||
use std::any::Any;
|
||||
|
||||
use super::ParsedRXingResultType;
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
*/
|
||||
// public final class ProductParsedRXingResultTestCase extends Assert {
|
||||
|
||||
use crate::{BarcodeFormat, RXingResult, client::result::{ParsedRXingResult, ParsedRXingResultType, ProductParsedResult, ParsedClientResult}};
|
||||
use crate::{BarcodeFormat, RXingResult, client::result::{ParsedRXingResult, ParsedRXingResultType, ParsedClientResult}};
|
||||
|
||||
use super::ResultParser;
|
||||
|
||||
|
||||
@@ -38,8 +38,7 @@ use crate::{exceptions::Exceptions, RXingResult};
|
||||
use super::{
|
||||
AddressBookAUResultParser, AddressBookDoCoMoResultParser, BizcardResultParser,
|
||||
BookmarkDoCoMoResultParser, EmailAddressResultParser, EmailDoCoMoResultParser,
|
||||
ExpandedProductResultParser, GeoResultParser, ISBNResultParser, ParsedClientResult,
|
||||
ParsedRXingResult, ProductResultParser, SMSMMSResultParser, SMTPResultParser, TelResultParser,
|
||||
ExpandedProductResultParser, GeoResultParser, ISBNResultParser, ParsedClientResult, ProductResultParser, SMSMMSResultParser, SMTPResultParser, TelResultParser,
|
||||
TextParsedRXingResult, URIResultParser, URLTOResultParser, VCardResultParser,
|
||||
VEventResultParser, VINResultParser, WifiResultParser, SMSTOMMSTOResultParser,
|
||||
};
|
||||
@@ -101,7 +100,7 @@ const AMPERSAND: &'static str = "&"; // private static final Pattern AMPERSAND =
|
||||
const EQUALS: &'static str = "="; //private static final Pattern EQUALS = Pattern.compile("=");
|
||||
const BYTE_ORDER_MARK: &'static str = "\u{feff}"; //private static final String BYTE_ORDER_MARK = "\ufeff";
|
||||
|
||||
const EMPTY_STR_ARRAY: &'static str = "";
|
||||
// const EMPTY_STR_ARRAY: &'static str = "";
|
||||
|
||||
pub fn getMassagedText(result: &RXingResult) -> String {
|
||||
let mut text = result.getText().clone();
|
||||
|
||||
@@ -27,12 +27,11 @@
|
||||
* @author Sean Owen
|
||||
*/
|
||||
// public final class TelParsedRXingResultTestCase extends Assert {
|
||||
use std::any::Any;
|
||||
|
||||
use crate::{
|
||||
client::result::{
|
||||
ParsedClientResult, ParsedRXingResult, ParsedRXingResultType,
|
||||
TelParsedRXingResult,
|
||||
|
||||
},
|
||||
BarcodeFormat, RXingResult,
|
||||
};
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
// import com.google.zxing.RXingResult;
|
||||
|
||||
use super::{TelParsedRXingResult, ParsedRXingResult, ParsedClientResult, ResultParser};
|
||||
use super::{TelParsedRXingResult, ParsedClientResult, ResultParser};
|
||||
|
||||
/**
|
||||
* Parses a "tel:" URI result, which specifies a phone number.
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use encoding::all::encodings;
|
||||
use regex::Regex;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
@@ -111,16 +111,16 @@ use rand::Rng;
|
||||
#[test]
|
||||
fn test_get_next_set5() {
|
||||
let mut r = rand::thread_rng();
|
||||
for i in 0 .. 10 {
|
||||
for _i in 0 .. 10 {
|
||||
// for (int i = 0; i < 10; i++) {
|
||||
let mut array = BitArray::with_size(1 + r.gen_range(0..100));
|
||||
let numSet = r.gen_range(0..20);
|
||||
for j in 0..numSet {
|
||||
for _j in 0..numSet {
|
||||
// for (int j = 0; j < numSet; j++) {
|
||||
array.set(r.gen_range(0..array.getSize()));
|
||||
}
|
||||
let numQueries = r.gen_range(0..20);
|
||||
for j in 0..numQueries {
|
||||
for _j in 0..numQueries {
|
||||
// for (int j = 0; j < numQueries; j++) {
|
||||
let query = r.gen_range(0..array.getSize());
|
||||
let mut expected = query;
|
||||
@@ -151,7 +151,7 @@ use rand::Rng;
|
||||
#[test]
|
||||
fn test_append_bit(){
|
||||
let mut array = BitArray::new();
|
||||
array.appendBits(0x000001E, 6);
|
||||
array.appendBits(0x000001E, 6).expect("must append)");
|
||||
let mut array_2 = BitArray::new();
|
||||
array_2.appendBit(false);
|
||||
array_2.appendBit(true);
|
||||
|
||||
@@ -58,7 +58,7 @@ use super::BitMatrix;
|
||||
#[test]
|
||||
fn test_set_region() {
|
||||
let mut matrix = BitMatrix::with_single_dimension(5);
|
||||
matrix.setRegion(1, 1, 3, 3);
|
||||
matrix.setRegion(1, 1, 3, 3).expect("must set");
|
||||
for y in 0..5 {
|
||||
// for (int y = 0; y < 5; y++) {
|
||||
for x in 0..5{
|
||||
@@ -72,11 +72,11 @@ use super::BitMatrix;
|
||||
fn test_enclosing() {
|
||||
let mut matrix = BitMatrix::with_single_dimension(5);
|
||||
assert!(matrix.getEnclosingRectangle().is_none());
|
||||
matrix.setRegion(1, 1, 1, 1);
|
||||
matrix.setRegion(1, 1, 1, 1).expect("must set");
|
||||
assert_eq!(vec![ 1, 1, 1, 1 ], matrix.getEnclosingRectangle().unwrap());
|
||||
matrix.setRegion(1, 1, 3, 2);
|
||||
matrix.setRegion(1, 1, 3, 2).expect("must set");
|
||||
assert_eq!(vec![ 1, 1, 3, 2 ], matrix.getEnclosingRectangle().unwrap());
|
||||
matrix.setRegion(0, 0, 5, 5);
|
||||
matrix.setRegion(0, 0, 5, 5).expect("must set");
|
||||
assert_eq!(vec![ 0, 0, 5, 5 ], matrix.getEnclosingRectangle().unwrap());
|
||||
}
|
||||
|
||||
@@ -85,13 +85,13 @@ use super::BitMatrix;
|
||||
let mut matrix = BitMatrix::with_single_dimension(5);
|
||||
assert!(matrix.getTopLeftOnBit().is_none());
|
||||
assert!(matrix.getBottomRightOnBit().is_none());
|
||||
matrix.setRegion(1, 1, 1, 1);
|
||||
matrix.setRegion(1, 1, 1, 1).expect("must set");
|
||||
assert_eq!(vec![ 1, 1 ], matrix.getTopLeftOnBit().unwrap());
|
||||
assert_eq!(vec![ 1, 1 ], matrix.getBottomRightOnBit().unwrap());
|
||||
matrix.setRegion(1, 1, 3, 2);
|
||||
matrix.setRegion(1, 1, 3, 2).expect("must set");
|
||||
assert_eq!(vec![ 1, 1 ], matrix.getTopLeftOnBit().unwrap());
|
||||
assert_eq!(vec![ 3, 2 ], matrix.getBottomRightOnBit().unwrap());
|
||||
matrix.setRegion(0, 0, 5, 5);
|
||||
matrix.setRegion(0, 0, 5, 5).expect("must set");
|
||||
assert_eq!(vec![ 0, 0 ], matrix.getTopLeftOnBit().unwrap());
|
||||
assert_eq!(vec![ 4, 4 ], matrix.getBottomRightOnBit().unwrap());
|
||||
}
|
||||
@@ -128,7 +128,7 @@ use super::BitMatrix;
|
||||
let mut matrix = BitMatrix::new(320, 240).unwrap();
|
||||
assert_eq!(320, matrix.getWidth());
|
||||
assert_eq!(240, matrix.getHeight());
|
||||
matrix.setRegion(105, 22, 80, 12);
|
||||
matrix.setRegion(105, 22, 80, 12).expect("must set");
|
||||
|
||||
// Only bits in the region should be on
|
||||
for y in 0..240 {
|
||||
@@ -217,9 +217,9 @@ use super::BitMatrix;
|
||||
fn test_parse() {
|
||||
let emptyMatrix = BitMatrix::new(3, 3).unwrap();
|
||||
let mut fullMatrix = BitMatrix::new(3, 3).unwrap();
|
||||
fullMatrix.setRegion(0, 0, 3, 3);
|
||||
fullMatrix.setRegion(0, 0, 3, 3).expect("must set");
|
||||
let mut centerMatrix = BitMatrix::new(3, 3).unwrap();
|
||||
centerMatrix.setRegion(1, 1, 1, 1);
|
||||
centerMatrix.setRegion(1, 1, 1, 1).expect("must set");
|
||||
let emptyMatrix24 = BitMatrix::new(2, 4).unwrap();
|
||||
|
||||
assert_eq!(emptyMatrix, BitMatrix::parse_strings(" \n \n \n", "x", " ").unwrap());
|
||||
@@ -243,9 +243,9 @@ use super::BitMatrix;
|
||||
fn test_parse_boolean() {
|
||||
let emptyMatrix = BitMatrix::new(3, 3).unwrap();
|
||||
let mut fullMatrix = BitMatrix::new(3, 3).unwrap();
|
||||
fullMatrix.setRegion(0, 0, 3, 3);
|
||||
fullMatrix.setRegion(0, 0, 3, 3).expect("must set");
|
||||
let mut centerMatrix = BitMatrix::new(3, 3).unwrap();
|
||||
centerMatrix.setRegion(1, 1, 1, 1);
|
||||
centerMatrix.setRegion(1, 1, 1, 1).expect("must set");
|
||||
let emptyMatrix24 = BitMatrix::new(2, 4).unwrap();
|
||||
|
||||
let mut matrix = vec![vec![false;3];3];
|
||||
@@ -276,9 +276,9 @@ use super::BitMatrix;
|
||||
fn test_xor_case() {
|
||||
let emptyMatrix = BitMatrix::new(3, 3).unwrap();
|
||||
let mut fullMatrix = BitMatrix::new(3, 3).unwrap();
|
||||
fullMatrix.setRegion(0, 0, 3, 3);
|
||||
fullMatrix.setRegion(0, 0, 3, 3).expect("must set");
|
||||
let mut centerMatrix = BitMatrix::new(3, 3).unwrap();
|
||||
centerMatrix.setRegion(1, 1, 1, 1);
|
||||
centerMatrix.setRegion(1, 1, 1, 1).expect("must set");
|
||||
let mut invertedCenterMatrix = fullMatrix.clone();
|
||||
invertedCenterMatrix.unset(1, 1);
|
||||
let badMatrix = BitMatrix::new(4, 4).unwrap();
|
||||
@@ -328,7 +328,7 @@ use super::BitMatrix;
|
||||
|
||||
fn test_XOR( dataMatrix: &BitMatrix, flipMatrix: &BitMatrix, expectedMatrix: &BitMatrix) {
|
||||
let mut matrix = dataMatrix.clone();
|
||||
matrix.xor(flipMatrix);
|
||||
matrix.xor(flipMatrix).expect("must set");
|
||||
assert_eq!(*expectedMatrix, matrix);
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ pub fn sum(array: &[i32]) -> i32 {
|
||||
mod tests {
|
||||
use crate::common::detector::MathUtils;
|
||||
|
||||
static EPSILON: f32 = 1.0E-8f32;
|
||||
// static EPSILON: f32 = 1.0E-8f32;
|
||||
|
||||
#[test]
|
||||
fn testRound() {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
pub mod MathUtils;
|
||||
use crate::common::BitMatrix;
|
||||
use crate::{Exceptions, RXingResultPoint, ResultPoint};
|
||||
|
||||
mod monochrome_rectangle_detector;
|
||||
pub use monochrome_rectangle_detector::*;
|
||||
|
||||
@@ -245,7 +245,7 @@ impl MonochromeRectangleDetector {
|
||||
|
||||
// Scan left/up first
|
||||
let mut start = center;
|
||||
while (start >= minDim) {
|
||||
while start >= minDim {
|
||||
if if horizontal {
|
||||
self.image.get(start as u32, fixedDimension as u32)
|
||||
} else {
|
||||
@@ -275,7 +275,7 @@ impl MonochromeRectangleDetector {
|
||||
|
||||
// Then try right/down
|
||||
let mut end = center;
|
||||
while (end < maxDim) {
|
||||
while end < maxDim {
|
||||
if if horizontal {
|
||||
self.image.get(end as u32, fixedDimension as u32)
|
||||
} else {
|
||||
|
||||
@@ -171,7 +171,7 @@ impl ECIEncoderSet {
|
||||
// In this case we append a UTF-8 and UTF-16 encoder to the list
|
||||
// encoders = [] new CharsetEncoder[neededEncoders.size() + 2];
|
||||
encoders = Vec::new();
|
||||
let index = 0;
|
||||
// let index = 0;
|
||||
|
||||
for encoder in neededEncoders {
|
||||
// for (CharsetEncoder encoder : neededEncoders) {
|
||||
|
||||
@@ -81,7 +81,7 @@ impl ECIStringBuilder {
|
||||
* @param value string to append
|
||||
*/
|
||||
pub fn append_string(&mut self, value: &str) {
|
||||
value.as_bytes().iter().map(|b| self.current_bytes.push(*b));
|
||||
value.as_bytes().iter().map(|b| self.current_bytes.push(*b)).count();
|
||||
// self.current_bytes.push(value.as_bytes());
|
||||
}
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ impl GlobalHistogramBinarizer {
|
||||
const LUMINANCE_BITS: usize = 5;
|
||||
const LUMINANCE_SHIFT: usize = 8 - GlobalHistogramBinarizer::LUMINANCE_BITS;
|
||||
const LUMINANCE_BUCKETS: usize = 1 << GlobalHistogramBinarizer::LUMINANCE_BITS;
|
||||
const EMPTY: [u8; 0] = [0; 0];
|
||||
// const EMPTY: [u8; 0] = [0; 0];
|
||||
|
||||
pub fn new(source: Box<dyn LuminanceSource>) -> Self {
|
||||
Self {
|
||||
|
||||
@@ -160,7 +160,7 @@ pub trait GridSampler {
|
||||
if y == -1 {
|
||||
points[offset + 1] = 0.0f32;
|
||||
nudged = true;
|
||||
} else if (y == height.try_into().unwrap()) {
|
||||
} else if y == height.try_into().unwrap() {
|
||||
points[offset + 1] = height as f32 - 1f32;
|
||||
nudged = true;
|
||||
}
|
||||
|
||||
@@ -1,26 +1,7 @@
|
||||
pub mod detector;
|
||||
pub mod reedsolomon;
|
||||
|
||||
use core::num;
|
||||
use std::any::Any;
|
||||
use std::cmp;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::Binarizer;
|
||||
use crate::DecodeHintType;
|
||||
use crate::DecodeHintValue;
|
||||
use crate::DecodingHintDictionary;
|
||||
use crate::Exceptions;
|
||||
use crate::LuminanceSource;
|
||||
use crate::RXingResultPoint;
|
||||
use encoding::Encoding;
|
||||
use encoding::EncodingRef;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
#[cfg(test)]
|
||||
mod StringUtilsTestCase;
|
||||
@@ -118,9 +99,6 @@ pub use eci_encoder_set::*;
|
||||
mod minimal_eci_input;
|
||||
pub use minimal_eci_input::*;
|
||||
|
||||
mod input_edge;
|
||||
pub use input_edge::*;
|
||||
|
||||
|
||||
mod global_histogram_binarizer;
|
||||
pub use global_histogram_binarizer::*;
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
//import org.junit.Assert;
|
||||
//import org.junit.Test;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::{GenericGF, GenericGFPoly};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use rand::Rng;
|
||||
|
||||
use super::{GenericGF, GenericGFRef, ReedSolomonDecoder, ReedSolomonEncoder};
|
||||
use super::{GenericGFRef, ReedSolomonDecoder, ReedSolomonEncoder};
|
||||
/*
|
||||
* Copyrigh&t 2013 ZXing authors
|
||||
*
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
use std::fmt;
|
||||
|
||||
use crate::Exceptions;
|
||||
use std::hash::Hash;
|
||||
|
||||
#[cfg(test)]
|
||||
mod GenericGFPolyTestCase;
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -53,8 +53,8 @@ pub struct StringUtils {
|
||||
// encoding::label::encoding_from_whatwg_label("GB2312").unwrap();
|
||||
// const EUC_JP: &dyn Encoding = encoding::label::encoding_from_whatwg_label("EUC_JP").unwrap();
|
||||
const ASSUME_SHIFT_JIS: bool = false;
|
||||
static SHIFT_JIS: &'static str = "SJIS";
|
||||
static GB2312: &'static str = "GB2312";
|
||||
// static SHIFT_JIS: &'static str = "SJIS";
|
||||
// static GB2312: &'static str = "GB2312";
|
||||
lazy_static! {
|
||||
pub static ref SHIFT_JIS_CHARSET: EncodingRef =
|
||||
encoding::label::encoding_from_whatwg_label("SJIS").unwrap();
|
||||
|
||||
204
src/decode_hints.rs
Normal file
204
src/decode_hints.rs
Normal file
@@ -0,0 +1,204 @@
|
||||
|
||||
/*
|
||||
* Copyright 2007 ZXing authors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//package com.google.zxing;
|
||||
|
||||
use crate::{BarcodeFormat, RXingResultPointCallback};
|
||||
|
||||
/**
|
||||
* Encapsulates a type of hint that a caller may pass to a barcode reader to help it
|
||||
* more quickly or accurately decode it. It is up to implementations to decide what,
|
||||
* if anything, to do with the information that is supplied.
|
||||
*
|
||||
* @author Sean Owen
|
||||
* @author dswitkin@google.com (Daniel Switkin)
|
||||
* @see Reader#decode(BinaryBitmap,java.util.Map)
|
||||
*/
|
||||
#[derive(Eq, PartialEq, Hash, Debug, Clone, Copy)]
|
||||
pub enum DecodeHintType {
|
||||
/**
|
||||
* Unspecified, application-specific hint. Maps to an unspecified {@link Object}.
|
||||
*/
|
||||
OTHER,
|
||||
|
||||
/**
|
||||
* Image is a pure monochrome image of a barcode. Doesn't matter what it maps to;
|
||||
* use {@link Boolean#TRUE}.
|
||||
*/
|
||||
PURE_BARCODE,
|
||||
|
||||
/**
|
||||
* Image is known to be of one of a few possible formats.
|
||||
* Maps to a {@link List} of {@link BarcodeFormat}s.
|
||||
*/
|
||||
POSSIBLE_FORMATS,
|
||||
|
||||
/**
|
||||
* Spend more time to try to find a barcode; optimize for accuracy, not speed.
|
||||
* Doesn't matter what it maps to; use {@link Boolean#TRUE}.
|
||||
*/
|
||||
TRY_HARDER,
|
||||
|
||||
/**
|
||||
* Specifies what character encoding to use when decoding, where applicable (type String)
|
||||
*/
|
||||
CHARACTER_SET,
|
||||
|
||||
/**
|
||||
* Allowed lengths of encoded data -- reject anything else. Maps to an {@code int[]}.
|
||||
*/
|
||||
ALLOWED_LENGTHS,
|
||||
|
||||
/**
|
||||
* Assume Code 39 codes employ a check digit. Doesn't matter what it maps to;
|
||||
* use {@link Boolean#TRUE}.
|
||||
*/
|
||||
ASSUME_CODE_39_CHECK_DIGIT,
|
||||
|
||||
/**
|
||||
* 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). Doesn't matter what it maps to;
|
||||
* use {@link Boolean#TRUE}.
|
||||
*/
|
||||
ASSUME_GS1,
|
||||
|
||||
/**
|
||||
* 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. Doesn't matter what it maps to; use {@link Boolean#TRUE}.
|
||||
*/
|
||||
RETURN_CODABAR_START_END,
|
||||
|
||||
/**
|
||||
* The caller needs to be notified via callback when a possible {@link RXingResultPoint}
|
||||
* is found. Maps to a {@link RXingResultPointCallback}.
|
||||
*/
|
||||
NEED_RESULT_POINT_CALLBACK,
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
ALLOWED_EAN_EXTENSIONS,
|
||||
|
||||
/**
|
||||
* If true, also tries to decode as inverted image. All configured decoders are simply called a
|
||||
* second time with an inverted image. Doesn't matter what it maps to; use {@link Boolean#TRUE}.
|
||||
*/
|
||||
ALSO_INVERTED,
|
||||
// End of enumeration values.
|
||||
|
||||
/*
|
||||
* Data type the hint is expecting.
|
||||
* Among the possible values the {@link Void} stands out as being used for
|
||||
* hints that do not expect a value to be supplied (flag hints). Such hints
|
||||
* will possibly have their value ignored, or replaced by a
|
||||
* {@link Boolean#TRUE}. Hint suppliers should probably use
|
||||
* {@link Boolean#TRUE} as directed by the actual hint documentation.
|
||||
*/
|
||||
/*
|
||||
private final Class<?> valueType;
|
||||
|
||||
DecodeHintType(Class<?> valueType) {
|
||||
this.valueType = valueType;
|
||||
}
|
||||
|
||||
public Class<?> getValueType() {
|
||||
return valueType;
|
||||
}*/
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum DecodeHintValue {
|
||||
/**
|
||||
* Unspecified, application-specific hint. Maps to an unspecified {@link Object}.
|
||||
*/
|
||||
Other(String),
|
||||
|
||||
/**
|
||||
* Image is a pure monochrome image of a barcode. Doesn't matter what it maps to;
|
||||
* use {@link Boolean#TRUE}.
|
||||
*/
|
||||
PureBarcode(bool),
|
||||
|
||||
/**
|
||||
* Image is known to be of one of a few possible formats.
|
||||
* Maps to a {@link List} of {@link BarcodeFormat}s.
|
||||
*/
|
||||
PossibleFormats(BarcodeFormat),
|
||||
|
||||
/**
|
||||
* Spend more time to try to find a barcode; optimize for accuracy, not speed.
|
||||
* Doesn't matter what it maps to; use {@link Boolean#TRUE}.
|
||||
*/
|
||||
TryHarder(bool),
|
||||
|
||||
/**
|
||||
* Specifies what character encoding to use when decoding, where applicable (type String)
|
||||
*/
|
||||
CharacterSet(String),
|
||||
|
||||
/**
|
||||
* Allowed lengths of encoded data -- reject anything else. Maps to an {@code int[]}.
|
||||
*/
|
||||
AllowedLengths(Vec<u32>),
|
||||
|
||||
/**
|
||||
* Assume Code 39 codes employ a check digit. Doesn't matter what it maps to;
|
||||
* use {@link Boolean#TRUE}.
|
||||
*/
|
||||
AssumeCode39CheckDigit(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). Doesn't matter what it maps to;
|
||||
* use {@link Boolean#TRUE}.
|
||||
*/
|
||||
AssumeGs1(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. Doesn't matter what it maps to; use {@link Boolean#TRUE}.
|
||||
*/
|
||||
ReturnCodabarStartEnd(bool),
|
||||
|
||||
/**
|
||||
* The caller needs to be notified via callback when a possible {@link RXingResultPoint}
|
||||
* is found. Maps to a {@link RXingResultPointCallback}.
|
||||
*/
|
||||
NeedResultPointCallback(RXingResultPointCallback),
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
AllowedEanExtensions(Vec<u32>),
|
||||
|
||||
/**
|
||||
* If true, also tries to decode as inverted image. All configured decoders are simply called a
|
||||
* second time with an inverted image. Doesn't matter what it maps to; use {@link Boolean#TRUE}.
|
||||
*/
|
||||
AlsoInverted(bool),
|
||||
// End of enumeration values.
|
||||
}
|
||||
48
src/dimension.rs
Normal file
48
src/dimension.rs
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
/*
|
||||
* Copyright 2012 ZXing authors
|
||||
*
|
||||
* Licensed under the Apache Licens0rsion 2.0 (the "License");
|
||||
* you may not use this file except in1iance 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.
|
||||
*/
|
||||
|
||||
//package com.google.zxing;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use crate::Exceptions;
|
||||
|
||||
/**
|
||||
* Simply encapsulates a width and height.
|
||||
*/
|
||||
#[derive(Eq, PartialEq, Hash)]
|
||||
pub struct Dimension(usize, usize);
|
||||
|
||||
impl Dimension {
|
||||
pub fn new(width: usize, height: usize) -> Result<Self, Exceptions> {
|
||||
Ok(Self(width, height))
|
||||
}
|
||||
|
||||
pub fn getWidth(&self) -> usize {
|
||||
return self.0;
|
||||
}
|
||||
|
||||
pub fn getHeight(&self) -> usize {
|
||||
return self.1;
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Dimension {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}x{}", self.0, self.1)
|
||||
}
|
||||
}
|
||||
330
src/encode_hints.rs
Normal file
330
src/encode_hints.rs
Normal file
@@ -0,0 +1,330 @@
|
||||
|
||||
/*
|
||||
* Copyright 2008 ZXing authors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//package com.google.zxing;
|
||||
|
||||
use crate::Dimension;
|
||||
|
||||
/**
|
||||
* These are a set of hints that you may pass to Writers to specify their behavior.
|
||||
*
|
||||
* @author dswitkin@google.com (Daniel Switkin)
|
||||
*/
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||
pub enum EncodeHintType {
|
||||
/**
|
||||
* 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 type
|
||||
* {@link com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ErrorCorrectionLevel}.
|
||||
* For Aztec it is of type {@link Integer}, representing the minimal percentage of error correction words.
|
||||
* For PDF417 it is of type {@link Integer}, valid values being 0 to 8.
|
||||
* In all cases, it can also be a {@link String} representation of the desired value as well.
|
||||
* Note: an Aztec symbol should have a minimum of 25% EC words.
|
||||
*/
|
||||
ERROR_CORRECTION,
|
||||
|
||||
/**
|
||||
* Specifies what character encoding to use where applicable (type {@link String})
|
||||
*/
|
||||
CHARACTER_SET,
|
||||
|
||||
/**
|
||||
* Specifies the matrix shape for Data Matrix (type {@link com.google.zxing.datamatrix.encoder.SymbolShapeHint})
|
||||
*/
|
||||
DATA_MATRIX_SHAPE,
|
||||
|
||||
/**
|
||||
* Specifies whether to use compact mode for Data Matrix (type {@link Boolean}, or "true" or "false"
|
||||
* {@link String } value).
|
||||
* 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 {@link #CHARACTER_SET} encoding hint.
|
||||
* Compact encoding also provides GS1-FNC1 support when {@link #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.
|
||||
* This option and {@link #FORCE_C40} are mutually exclusive.
|
||||
*/
|
||||
DATA_MATRIX_COMPACT,
|
||||
|
||||
/**
|
||||
* Specifies a minimum barcode size (type {@link Dimension}). Only applicable to Data Matrix now.
|
||||
*
|
||||
* @deprecated use width/height params in
|
||||
* {@link com.google.zxing.datamatrix.DataMatrixWriter#encode(String, BarcodeFormat, int, int)}
|
||||
*/
|
||||
#[deprecated]
|
||||
MIN_SIZE,
|
||||
|
||||
/**
|
||||
* Specifies a maximum barcode size (type {@link Dimension}). Only applicable to Data Matrix now.
|
||||
*
|
||||
* @deprecated without replacement
|
||||
*/
|
||||
#[deprecated]
|
||||
MAX_SIZE,
|
||||
|
||||
/**
|
||||
* 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. (Type {@link Integer}, or {@link String} representation of the integer value).
|
||||
*/
|
||||
MARGIN,
|
||||
|
||||
/**
|
||||
* Specifies whether to use compact mode for PDF417 (type {@link Boolean}, or "true" or "false"
|
||||
* {@link String} value).
|
||||
*/
|
||||
PDF417_COMPACT,
|
||||
|
||||
/**
|
||||
* Specifies what compaction mode to use for PDF417 (type
|
||||
* {@link com.google.zxing.pdf417.encoder.Compaction Compaction} or {@link String} value of one of its
|
||||
* enum values).
|
||||
*/
|
||||
PDF417_COMPACTION,
|
||||
|
||||
/**
|
||||
* Specifies the minimum and maximum number of rows and columns for PDF417 (type
|
||||
* {@link com.google.zxing.pdf417.encoder.Dimensions Dimensions}).
|
||||
*/
|
||||
PDF417_DIMENSIONS,
|
||||
|
||||
/**
|
||||
* Specifies whether to automatically insert ECIs when encoding PDF417 (type {@link Boolean}, or "true" or "false"
|
||||
* {@link String} value).
|
||||
* 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 {@link #CHARACTER_SET} encoding hint.
|
||||
*/
|
||||
PDF417_AUTO_ECI,
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* (Type {@link Integer}, or {@link String} representation of the integer value).
|
||||
*/
|
||||
AZTEC_LAYERS,
|
||||
|
||||
/**
|
||||
* Specifies the exact version of QR code to be encoded.
|
||||
* (Type {@link Integer}, or {@link String} representation of the integer value).
|
||||
*/
|
||||
QR_VERSION,
|
||||
|
||||
/**
|
||||
* Specifies the QR code mask pattern to be used. Allowed values are
|
||||
* 0..QRCode.NUM_MASK_PATTERNS-1. By default the code will automatically select
|
||||
* the optimal mask pattern.
|
||||
* * (Type {@link Integer}, or {@link String} representation of the integer value).
|
||||
*/
|
||||
QR_MASK_PATTERN,
|
||||
|
||||
/**
|
||||
* Specifies whether to use compact mode for QR code (type {@link Boolean}, or "true" or "false"
|
||||
* {@link String } value).
|
||||
* 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 {@link #CHARACTER_SET} encoding hint.
|
||||
*/
|
||||
QR_COMPACT,
|
||||
|
||||
/**
|
||||
* Specifies whether the data should be encoded to the GS1 standard (type {@link Boolean}, or "true" or "false"
|
||||
* {@link String } value).
|
||||
*/
|
||||
GS1_FORMAT,
|
||||
|
||||
/**
|
||||
* Forces which encoding will be used. Currently only used for Code-128 code sets (Type {@link String}).
|
||||
* Valid values are "A", "B", "C".
|
||||
* This option and {@link #CODE128_COMPACT} are mutually exclusive.
|
||||
*/
|
||||
FORCE_CODE_SET,
|
||||
|
||||
/**
|
||||
* Forces C40 encoding for data-matrix (type {@link Boolean}, or "true" or "false") {@link String } value). This
|
||||
* option and {@link #DATA_MATRIX_COMPACT} are mutually exclusive.
|
||||
*/
|
||||
FORCE_C40,
|
||||
|
||||
/**
|
||||
* Specifies whether to use compact mode for Code-128 code (type {@link Boolean}, or "true" or "false"
|
||||
* {@link String } value).
|
||||
* This can yield slightly smaller bar codes. This option and {@link #FORCE_CODE_SET} are mutually
|
||||
* exclusive.
|
||||
*/
|
||||
CODE128_COMPACT,
|
||||
}
|
||||
|
||||
pub enum EncodeHintValue {
|
||||
/**
|
||||
* 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 type
|
||||
* {@link com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ErrorCorrectionLevel}.
|
||||
* For Aztec it is of type {@link Integer}, representing the minimal percentage of error correction words.
|
||||
* For PDF417 it is of type {@link Integer}, valid values being 0 to 8.
|
||||
* In all cases, it can also be a {@link String} representation of the desired value as well.
|
||||
* Note: an Aztec symbol should have a minimum of 25% EC words.
|
||||
*/
|
||||
ErrorCorrection(String),
|
||||
|
||||
/**
|
||||
* Specifies what character encoding to use where applicable (type {@link String})
|
||||
*/
|
||||
CharacterSet(String),
|
||||
|
||||
/**
|
||||
* Specifies the matrix shape for Data Matrix (type {@link com.google.zxing.datamatrix.encoder.SymbolShapeHint})
|
||||
*/
|
||||
DataMatrixShape,
|
||||
|
||||
/**
|
||||
* Specifies whether to use compact mode for Data Matrix (type {@link Boolean}, or "true" or "false"
|
||||
* {@link String } value).
|
||||
* 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 {@link #CHARACTER_SET} encoding hint.
|
||||
* Compact encoding also provides GS1-FNC1 support when {@link #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.
|
||||
* This option and {@link #FORCE_C40} are mutually exclusive.
|
||||
*/
|
||||
DataMatrixCompact(String),
|
||||
|
||||
/**
|
||||
* Specifies a minimum barcode size (type {@link Dimension}). Only applicable to Data Matrix now.
|
||||
*
|
||||
* @deprecated use width/height params in
|
||||
* {@link com.google.zxing.datamatrix.DataMatrixWriter#encode(String, BarcodeFormat, int, int)}
|
||||
*/
|
||||
#[deprecated]
|
||||
MinSize,
|
||||
|
||||
/**
|
||||
* Specifies a maximum barcode size (type {@link Dimension}). Only applicable to Data Matrix now.
|
||||
*
|
||||
* @deprecated without replacement
|
||||
*/
|
||||
#[deprecated]
|
||||
MaxSize(Dimension),
|
||||
|
||||
/**
|
||||
* 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. (Type {@link Integer}, or {@link String} representation of the integer value).
|
||||
*/
|
||||
Margin(String),
|
||||
|
||||
/**
|
||||
* Specifies whether to use compact mode for PDF417 (type {@link Boolean}, or "true" or "false"
|
||||
* {@link String} value).
|
||||
*/
|
||||
Pdf417Compact(String),
|
||||
|
||||
/**
|
||||
* Specifies what compaction mode to use for PDF417 (type
|
||||
* {@link com.google.zxing.pdf417.encoder.Compaction Compaction} or {@link String} value of one of its
|
||||
* enum values).
|
||||
*/
|
||||
Pdf417Compaction(String),
|
||||
|
||||
/**
|
||||
* Specifies the minimum and maximum number of rows and columns for PDF417 (type
|
||||
* {@link com.google.zxing.pdf417.encoder.Dimensions Dimensions}).
|
||||
*/
|
||||
Pdf417Dimensions,
|
||||
|
||||
/**
|
||||
* Specifies whether to automatically insert ECIs when encoding PDF417 (type {@link Boolean}, or "true" or "false"
|
||||
* {@link String} value).
|
||||
* 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 {@link #CHARACTER_SET} encoding hint.
|
||||
*/
|
||||
Pdf417AutoEci(String),
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* (Type {@link Integer}, or {@link String} representation of the integer value).
|
||||
*/
|
||||
AztecLayers(i32),
|
||||
|
||||
/**
|
||||
* Specifies the exact version of QR code to be encoded.
|
||||
* (Type {@link Integer}, or {@link String} representation of the integer value).
|
||||
*/
|
||||
QrVersion(String),
|
||||
|
||||
/**
|
||||
* Specifies the QR code mask pattern to be used. Allowed values are
|
||||
* 0..QRCode.NUM_MASK_PATTERNS-1. By default the code will automatically select
|
||||
* the optimal mask pattern.
|
||||
* * (Type {@link Integer}, or {@link String} representation of the integer value).
|
||||
*/
|
||||
QrMaskPattern(String),
|
||||
|
||||
/**
|
||||
* Specifies whether to use compact mode for QR code (type {@link Boolean}, or "true" or "false"
|
||||
* {@link String } value).
|
||||
* 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 {@link #CHARACTER_SET} encoding hint.
|
||||
*/
|
||||
QrCompact(String),
|
||||
|
||||
/**
|
||||
* Specifies whether the data should be encoded to the GS1 standard (type {@link Boolean}, or "true" or "false"
|
||||
* {@link String } value).
|
||||
*/
|
||||
Gs1Format(String),
|
||||
|
||||
/**
|
||||
* Forces which encoding will be used. Currently only used for Code-128 code sets (Type {@link String}).
|
||||
* Valid values are "A", "B", "C".
|
||||
* This option and {@link #CODE128_COMPACT} are mutually exclusive.
|
||||
*/
|
||||
ForceCodeSet(String),
|
||||
|
||||
/**
|
||||
* Forces C40 encoding for data-matrix (type {@link Boolean}, or "true" or "false") {@link String } value). This
|
||||
* option and {@link #DATA_MATRIX_COMPACT} are mutually exclusive.
|
||||
*/
|
||||
ForceC40(String),
|
||||
|
||||
/**
|
||||
* Specifies whether to use compact mode for Code-128 code (type {@link Boolean}, or "true" or "false"
|
||||
* {@link String } value).
|
||||
* This can yield slightly smaller bar codes. This option and {@link #FORCE_CODE_SET} are mutually
|
||||
* exclusive.
|
||||
*/
|
||||
Code128Compact(String),
|
||||
}
|
||||
2326
src/lib.rs
2326
src/lib.rs
File diff suppressed because it is too large
Load Diff
173
src/luminance_source.rs
Normal file
173
src/luminance_source.rs
Normal file
@@ -0,0 +1,173 @@
|
||||
|
||||
/*
|
||||
* Copyright 2009 ZXing authors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//package com.google.zxing;
|
||||
|
||||
use crate::Exceptions;
|
||||
|
||||
/**
|
||||
* The purpose of this class hierarchy is to abstract different bitmap implementations across
|
||||
* platforms into a standard interface for requesting greyscale luminance values. The interface
|
||||
* only provides immutable methods; therefore crop and rotation create copies. This is to ensure
|
||||
* that one Reader does not modify the original luminance source and leave it in an unknown state
|
||||
* for other Readers in the chain.
|
||||
*
|
||||
* @author dswitkin@google.com (Daniel Switkin)
|
||||
*/
|
||||
pub trait LuminanceSource {
|
||||
//private final int width;
|
||||
//private final int height;
|
||||
|
||||
//fn new( width:usize, height:usize) -> Self;
|
||||
|
||||
/**
|
||||
* Fetches one row of luminance data from the underlying platform's bitmap. Values range from
|
||||
* 0 (black) to 255 (white). Because Java does not have an unsigned byte type, callers will have
|
||||
* to bitwise and with 0xff for each value. It is preferable for implementations of this method
|
||||
* to only fetch this row rather than the whole image, since no 2D Readers may be installed and
|
||||
* getMatrix() may never be called.
|
||||
*
|
||||
* @param y The row to fetch, which must be in [0,getHeight())
|
||||
* @param row An optional preallocated array. If null or too small, it will be ignored.
|
||||
* Always use the returned object, and ignore the .length of the array.
|
||||
* @return An array containing the luminance data.
|
||||
*/
|
||||
fn getRow(&self, y: usize, row: &Vec<u8>) -> Vec<u8>;
|
||||
|
||||
/**
|
||||
* Fetches luminance data for the underlying bitmap. Values should be fetched using:
|
||||
* {@code int luminance = array[y * width + x] & 0xff}
|
||||
*
|
||||
* @return A row-major 2D array of luminance values. Do not use result.length as it may be
|
||||
* larger than width * height bytes on some platforms. Do not modify the contents
|
||||
* of the result.
|
||||
*/
|
||||
fn getMatrix(&self) -> Vec<u8>;
|
||||
|
||||
/**
|
||||
* @return The width of the bitmap.
|
||||
*/
|
||||
fn getWidth(&self) -> usize;
|
||||
|
||||
/**
|
||||
* @return The height of the bitmap.
|
||||
*/
|
||||
fn getHeight(&self) -> usize;
|
||||
|
||||
/**
|
||||
* @return Whether this subclass supports cropping.
|
||||
*/
|
||||
fn isCropSupported(&self) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new object with cropped image data. Implementations may keep a reference to the
|
||||
* original data rather than a copy. Only callable if isCropSupported() is true.
|
||||
*
|
||||
* @param left The left coordinate, which must be in [0,getWidth())
|
||||
* @param top The top coordinate, which must be in [0,getHeight())
|
||||
* @param width The width of the rectangle to crop.
|
||||
* @param height The height of the rectangle to crop.
|
||||
* @return A cropped version of this object.
|
||||
*/
|
||||
fn crop(
|
||||
&self,
|
||||
left: usize,
|
||||
top: usize,
|
||||
width: usize,
|
||||
height: usize,
|
||||
) -> Result<Box<dyn LuminanceSource>, Exceptions> {
|
||||
return Err(Exceptions::UnsupportedOperationException(
|
||||
"This luminance source does not support cropping.".to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether this subclass supports counter-clockwise rotation.
|
||||
*/
|
||||
fn isRotateSupported(&self) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a wrapper of this {@code LuminanceSource} which inverts the luminances it returns -- black becomes
|
||||
* white and vice versa, and each value becomes (255-value).
|
||||
*/
|
||||
fn invert(&mut self); /* {
|
||||
return InvertedLuminanceSource::new_with_delegate(self);
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Returns a new object with rotated image data by 90 degrees counterclockwise.
|
||||
* Only callable if {@link #isRotateSupported()} is true.
|
||||
*
|
||||
* @return A rotated version of this object.
|
||||
*/
|
||||
fn rotateCounterClockwise(&self) -> Result<Box<dyn LuminanceSource>, Exceptions> {
|
||||
return Err(Exceptions::UnsupportedOperationException(
|
||||
"This luminance source does not support rotation by 90 degrees.".to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new object with rotated image data by 45 degrees counterclockwise.
|
||||
* Only callable if {@link #isRotateSupported()} is true.
|
||||
*
|
||||
* @return A rotated version of this object.
|
||||
*/
|
||||
fn rotateCounterClockwise45(&self) -> Result<Box<dyn LuminanceSource>, Exceptions> {
|
||||
return Err(Exceptions::UnsupportedOperationException(
|
||||
"This luminance source does not support rotation by 45 degrees.".to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
fn invert_block_of_bytes(&self, vec_to_invert: Vec<u8>) -> Vec<u8> {
|
||||
let mut iv = vec_to_invert.clone();
|
||||
for itm in iv.iter_mut() {
|
||||
let z = *itm;
|
||||
*itm = 255 - (z & 0xFF);
|
||||
}
|
||||
iv
|
||||
}
|
||||
|
||||
/*
|
||||
@Override
|
||||
public final String toString() {
|
||||
byte[] row = new byte[width];
|
||||
StringBuilder result = new StringBuilder(height * (width + 1));
|
||||
for (int y = 0; y < height; y++) {
|
||||
row = getRow(y, row);
|
||||
for (int x = 0; x < width; x++) {
|
||||
int luminance = row[x] & 0xFF;
|
||||
char c;
|
||||
if (luminance < 0x40) {
|
||||
c = '#';
|
||||
} else if (luminance < 0x80) {
|
||||
c = '+';
|
||||
} else if (luminance < 0xC0) {
|
||||
c = '.';
|
||||
} else {
|
||||
c = ' ';
|
||||
}
|
||||
result.append(c);
|
||||
}
|
||||
result.append('\n');
|
||||
}
|
||||
return result.toString();
|
||||
}*/
|
||||
}
|
||||
@@ -40,7 +40,7 @@ const EVEN: u32 = 1;
|
||||
const ODD: u32 = 2;
|
||||
|
||||
lazy_static! {
|
||||
static ref rsDecoder: ReedSolomonDecoder = ReedSolomonDecoder::new(get_predefined_genericgf(
|
||||
static ref RS_DECODER: ReedSolomonDecoder = ReedSolomonDecoder::new(get_predefined_genericgf(
|
||||
PredefinedGenericGF::MaxicodeField64
|
||||
));
|
||||
}
|
||||
@@ -103,7 +103,7 @@ fn correctErrors(
|
||||
}
|
||||
}
|
||||
// try {
|
||||
rsDecoder.decode(&mut codewordsInts, (ecCodewords / divisor) as i32)?;
|
||||
RS_DECODER.decode(&mut codewordsInts, (ecCodewords / divisor) as i32)?;
|
||||
// } catch (ReedSolomonException ignored) {
|
||||
// throw ChecksumException.getChecksumInstance();
|
||||
// }
|
||||
|
||||
364
src/planar_yuv_luminance_source.rs
Normal file
364
src/planar_yuv_luminance_source.rs
Normal file
@@ -0,0 +1,364 @@
|
||||
|
||||
// /*
|
||||
// * Copyright 2013 ZXing authors
|
||||
// *
|
||||
// * 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.
|
||||
// */
|
||||
// //package com.google.zxing;
|
||||
|
||||
// /**
|
||||
// * A wrapper implementation of {@link LuminanceSource} which inverts the luminances it returns -- black becomes
|
||||
// * white and vice versa, and each value becomes (255-value).
|
||||
// *
|
||||
// * @author Sean Owen
|
||||
// */
|
||||
// pub struct InvertedLuminanceSource {
|
||||
// width: usize,
|
||||
// height: usize,
|
||||
// delegate: Box<dyn LuminanceSource>,
|
||||
// }
|
||||
|
||||
// impl InvertedLuminanceSource {
|
||||
// pub fn new_with_delegate(delegate: Box<dyn LuminanceSource>) -> Self {
|
||||
// Self {
|
||||
// width: delegate.getWidth(),
|
||||
// height: delegate.getHeight(),
|
||||
// delegate,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl LuminanceSource for InvertedLuminanceSource {
|
||||
// fn getRow(&self, y: usize, row: &Vec<u8>) -> Vec<u8> {
|
||||
// let mut new_row = self.delegate.getRow(y, row);
|
||||
// let width = self.getWidth();
|
||||
// for i in 0..width {
|
||||
// //for (int i = 0; i < width; i++) {
|
||||
// new_row[i] = 255 - (new_row[i] & 0xFF);
|
||||
// }
|
||||
// return new_row;
|
||||
// }
|
||||
|
||||
// fn getMatrix(&self) -> Vec<u8> {
|
||||
// let matrix = self.delegate.getMatrix();
|
||||
// let length = self.getWidth() * self.getHeight();
|
||||
// let mut invertedMatrix = Vec::with_capacity(length);
|
||||
// for i in 0..length {
|
||||
// //for (int i = 0; i < length; i++) {
|
||||
// invertedMatrix[i] = 255 - (matrix[i] & 0xFF);
|
||||
// }
|
||||
// return invertedMatrix;
|
||||
// }
|
||||
|
||||
// fn getWidth(&self) -> usize {
|
||||
// self.width
|
||||
// }
|
||||
|
||||
// fn getHeight(&self) -> usize {
|
||||
// self.height
|
||||
// }
|
||||
|
||||
// fn isCropSupported(&self) -> bool {
|
||||
// return self.delegate.isCropSupported();
|
||||
// }
|
||||
|
||||
// fn crop(
|
||||
// &self,
|
||||
// left: usize,
|
||||
// top: usize,
|
||||
// width: usize,
|
||||
// height: usize,
|
||||
// ) -> Result<Box<dyn LuminanceSource>, UnsupportedOperationException> {
|
||||
// let crop = self.delegate.crop(left, top, width, height)?;
|
||||
// return Ok(Box::new(InvertedLuminanceSource::new_with_delegate(crop)));
|
||||
// }
|
||||
|
||||
// fn isRotateSupported(&self) -> bool {
|
||||
// return self.delegate.isRotateSupported();
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * @return original delegate {@link LuminanceSource} since invert undoes itself
|
||||
// */
|
||||
// fn invert(&self) -> Box<dyn LuminanceSource> {
|
||||
// return self.delegate;
|
||||
// }
|
||||
|
||||
// fn rotateCounterClockwise(
|
||||
// &self,
|
||||
// ) -> Result<Box<dyn LuminanceSource>, UnsupportedOperationException> {
|
||||
// let rot = self.delegate.rotateCounterClockwise()?;
|
||||
// return Ok(Box::new(InvertedLuminanceSource::new_with_delegate(rot)));
|
||||
// }
|
||||
|
||||
// fn rotateCounterClockwise45(
|
||||
// &self,
|
||||
// ) -> Result<Box<dyn LuminanceSource>, UnsupportedOperationException> {
|
||||
// let rot_45 = self.delegate.rotateCounterClockwise45()?;
|
||||
// return Ok(Box::new(InvertedLuminanceSource::new_with_delegate(rot_45)));
|
||||
// }
|
||||
// }
|
||||
|
||||
/*
|
||||
* Copyright 2009 ZXing authors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//package com.google.zxing;
|
||||
|
||||
use crate::{Exceptions, LuminanceSource};
|
||||
|
||||
const THUMBNAIL_SCALE_FACTOR: usize = 2;
|
||||
|
||||
/**
|
||||
* This object extends LuminanceSource around an array of YUV data returned from the camera driver,
|
||||
* with the option to crop to a rectangle within the full data. This can be used to exclude
|
||||
* superfluous pixels around the perimeter and speed up decoding.
|
||||
*
|
||||
* It works for any pixel format where the Y channel is planar and appears first, including
|
||||
* YCbCr_420_SP and YCbCr_422_SP.
|
||||
*
|
||||
* @author dswitkin@google.com (Daniel Switkin)
|
||||
*/
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PlanarYUVLuminanceSource {
|
||||
yuv_data: Vec<u8>,
|
||||
data_width: usize,
|
||||
data_height: usize,
|
||||
left: usize,
|
||||
top: usize,
|
||||
width: usize,
|
||||
height: usize,
|
||||
invert: bool,
|
||||
}
|
||||
|
||||
impl PlanarYUVLuminanceSource {
|
||||
pub fn new_with_all(
|
||||
yuv_data: Vec<u8>,
|
||||
data_width: usize,
|
||||
data_height: usize,
|
||||
left: usize,
|
||||
top: usize,
|
||||
width: usize,
|
||||
height: usize,
|
||||
reverse_horizontal: bool,
|
||||
inverted: bool,
|
||||
) -> Result<Self, Exceptions> {
|
||||
if left + width > data_width || top + height > data_height {
|
||||
return Err(Exceptions::IllegalArgumentException(
|
||||
"Crop rectangle does not fit within image data.".to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
let mut new_s: Self = Self {
|
||||
yuv_data,
|
||||
data_width,
|
||||
data_height,
|
||||
left,
|
||||
top,
|
||||
width,
|
||||
height,
|
||||
invert: inverted,
|
||||
};
|
||||
|
||||
if reverse_horizontal {
|
||||
new_s.reverseHorizontal(width, height);
|
||||
}
|
||||
|
||||
Ok(new_s)
|
||||
}
|
||||
|
||||
pub fn renderThumbnail(&self) -> Vec<u8> {
|
||||
let width = self.getWidth() / THUMBNAIL_SCALE_FACTOR;
|
||||
let height = self.getHeight() / THUMBNAIL_SCALE_FACTOR;
|
||||
let mut pixels = vec![0; width * height];
|
||||
let yuv = &self.yuv_data;
|
||||
let mut input_offset = self.top * self.data_width + self.left;
|
||||
|
||||
for y in 0..height {
|
||||
//for (int y = 0; y < height; y++) {
|
||||
let output_offset = y * width;
|
||||
for x in 0..width {
|
||||
//for (int x = 0; x < width; x++) {
|
||||
let grey = yuv[input_offset + x * THUMBNAIL_SCALE_FACTOR] & 0xff;
|
||||
pixels[output_offset + x] = (0xFF000000 | (grey as u32 * 0x00010101)) as u8;
|
||||
}
|
||||
input_offset += self.data_width * THUMBNAIL_SCALE_FACTOR;
|
||||
}
|
||||
return pixels;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return width of image from {@link #renderThumbnail()}
|
||||
*/
|
||||
pub fn getThumbnailWidth(&self) -> usize {
|
||||
return self.getWidth() / THUMBNAIL_SCALE_FACTOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return height of image from {@link #renderThumbnail()}
|
||||
*/
|
||||
pub fn getThumbnailHeight(&self) -> usize {
|
||||
return self.getHeight() / THUMBNAIL_SCALE_FACTOR;
|
||||
}
|
||||
|
||||
fn reverseHorizontal(&mut self, width: usize, height: usize) {
|
||||
//let mut yuvData = self.yuvData;
|
||||
let mut rowStart = self.top * self.data_width + self.left;
|
||||
for _y in 0..height {
|
||||
let middle = rowStart + width / 2;
|
||||
let mut x2 = rowStart + width - 1;
|
||||
for x1 in rowStart..middle {
|
||||
//for (int x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) {
|
||||
let temp = self.yuv_data[x1];
|
||||
self.yuv_data[x1] = self.yuv_data[x2];
|
||||
self.yuv_data[x2] = temp;
|
||||
x2 -= 1;
|
||||
}
|
||||
rowStart += self.data_width;
|
||||
}
|
||||
//self.yuvData = yuvData;
|
||||
/*for (int y = 0, rowStart = top * dataWidth + left; y < height; y++, rowStart += dataWidth) {
|
||||
let middle = rowStart + width / 2;
|
||||
for (int x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) {
|
||||
let temp = yuvData[x1];
|
||||
yuvData[x1] = yuvData[x2];
|
||||
yuvData[x2] = temp;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
impl LuminanceSource for PlanarYUVLuminanceSource {
|
||||
fn getRow(&self, y: usize, row: &Vec<u8>) -> Vec<u8> {
|
||||
if y >= self.getHeight() {
|
||||
//throw new IllegalArgumentException("Requested row is outside the image: " + y);
|
||||
panic!("Requested row is outside the image: {}", y);
|
||||
}
|
||||
let width = self.getWidth();
|
||||
|
||||
let offset = (y + self.top) * self.data_width + self.left;
|
||||
|
||||
let mut row = if row.len() >= width {
|
||||
row.to_vec()
|
||||
} else {
|
||||
vec![0; width]
|
||||
};
|
||||
|
||||
row[..width].clone_from_slice(&self.yuv_data[offset..width + offset]);
|
||||
//System.arraycopy(yuvData, offset, row, 0, width);
|
||||
if self.invert {
|
||||
row = self.invert_block_of_bytes(row);
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
fn getMatrix(&self) -> Vec<u8> {
|
||||
let width = self.getWidth();
|
||||
let height = self.getHeight();
|
||||
|
||||
// If the caller asks for the entire underlying image, save the copy and give them the
|
||||
// original data. The docs specifically warn that result.length must be ignored.
|
||||
if width == self.data_width && height == self.data_height {
|
||||
let mut v = self.yuv_data.clone();
|
||||
if self.invert {
|
||||
v = self.invert_block_of_bytes(v);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
let area = width * height;
|
||||
let mut matrix = vec![0; area];
|
||||
let mut inputOffset = self.top * self.data_width + self.left;
|
||||
|
||||
// If the width matches the full width of the underlying data, perform a single copy.
|
||||
if width == self.data_width {
|
||||
matrix[0..area].clone_from_slice(&self.yuv_data[inputOffset..area]);
|
||||
//System.arraycopy(yuvData, inputOffset, matrix, 0, area);
|
||||
if self.invert {
|
||||
matrix = self.invert_block_of_bytes(matrix);
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
// Otherwise copy one cropped row at a time.
|
||||
for y in 0..height {
|
||||
//for (int y = 0; y < height; y++) {
|
||||
let outputOffset = y * width;
|
||||
matrix[outputOffset..outputOffset + width]
|
||||
.clone_from_slice(&self.yuv_data[inputOffset..inputOffset + width]);
|
||||
//System.arraycopy(yuvData, inputOffset, matrix, outputOffset, width);
|
||||
inputOffset += self.data_width;
|
||||
}
|
||||
|
||||
if self.invert {
|
||||
matrix = self.invert_block_of_bytes(matrix);
|
||||
}
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
fn getWidth(&self) -> usize {
|
||||
self.width
|
||||
}
|
||||
|
||||
fn getHeight(&self) -> usize {
|
||||
self.height
|
||||
}
|
||||
|
||||
fn isCropSupported(&self) -> bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
fn crop(
|
||||
&self,
|
||||
left: usize,
|
||||
top: usize,
|
||||
width: usize,
|
||||
height: usize,
|
||||
) -> Result<Box<dyn LuminanceSource>, Exceptions> {
|
||||
match PlanarYUVLuminanceSource::new_with_all(
|
||||
self.yuv_data.clone(),
|
||||
self.data_width,
|
||||
self.data_height,
|
||||
self.left + left,
|
||||
self.top + top,
|
||||
width,
|
||||
height,
|
||||
false,
|
||||
self.invert,
|
||||
) {
|
||||
Ok(new) => Ok(Box::new(new)),
|
||||
Err(_err) => Err(Exceptions::UnsupportedOperationException("".to_owned())),
|
||||
}
|
||||
}
|
||||
|
||||
fn isRotateSupported(&self) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
fn invert(&mut self) {
|
||||
self.invert = !self.invert;
|
||||
}
|
||||
}
|
||||
@@ -16,11 +16,10 @@
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
hash::Hash,
|
||||
path::{Path, PathBuf},
|
||||
path::{ PathBuf},
|
||||
};
|
||||
|
||||
use image::{DynamicImage, EncodableLayout};
|
||||
use image::{DynamicImage};
|
||||
|
||||
use crate::{
|
||||
common::BitMatrix, qrcode::QRCodeWriter, BarcodeFormat, EncodeHintType, EncodeHintValue, Writer,
|
||||
|
||||
@@ -18,12 +18,12 @@ use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
common::{
|
||||
detector::MathUtils, BitMatrix, DefaultGridSampler, DetectorRXingResult, GridSampler,
|
||||
detector::MathUtils, BitMatrix, DefaultGridSampler, GridSampler,
|
||||
PerspectiveTransform,
|
||||
},
|
||||
qrcode::decoder::Version,
|
||||
result_point_utils, DecodeHintType, DecodeHintValue, DecodingHintDictionary, Exceptions,
|
||||
RXingResultPoint, RXingResultPointCallback, ResultPoint,
|
||||
RXingResultPointCallback, ResultPoint,
|
||||
};
|
||||
|
||||
use super::{
|
||||
|
||||
@@ -14,11 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use std::{fs::File, io::Write};
|
||||
|
||||
use crate::{
|
||||
common::BitMatrix, result_point_utils, DecodeHintType, DecodingHintDictionary, Exceptions,
|
||||
RXingResultPoint, RXingResultPointCallback, ResultPoint,
|
||||
RXingResultPointCallback, ResultPoint,
|
||||
};
|
||||
|
||||
use super::{FinderPattern, FinderPatternInfo};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
common::{BitMatrix, DetectorRXingResult},
|
||||
RXingResultPoint, ResultPoint,
|
||||
RXingResultPoint,
|
||||
};
|
||||
|
||||
pub struct QRCodeDetectorResult {
|
||||
|
||||
@@ -23,10 +23,10 @@ use crate::common::BitArray;
|
||||
|
||||
fn getUnsignedInt(v: &BitArray) -> u64 {
|
||||
let mut result = 0u64;
|
||||
const offset: usize = 0;
|
||||
const OFFSET: usize = 0;
|
||||
for i in 0..32 {
|
||||
// for (int i = 0, offset = 0; i < 32; i++) {
|
||||
if v.get(offset + i) {
|
||||
if v.get(OFFSET + i) {
|
||||
result |= 1 << (31 - i);
|
||||
}
|
||||
}
|
||||
@@ -82,15 +82,15 @@ fn testAppendBit() {
|
||||
#[test]
|
||||
fn testAppendBits() {
|
||||
let mut v = BitArray::new();
|
||||
v.appendBits(0x1, 1);
|
||||
v.appendBits(0x1, 1).expect("append");
|
||||
assert_eq!(1, v.getSize());
|
||||
assert_eq!(0x80000000, getUnsignedInt(&v));
|
||||
let mut v = BitArray::new();
|
||||
v.appendBits(0xff, 8);
|
||||
v.appendBits(0xff, 8).expect("append");
|
||||
assert_eq!(8, v.getSize());
|
||||
assert_eq!(0xff000000, getUnsignedInt(&v));
|
||||
let mut v = BitArray::new();
|
||||
v.appendBits(0xff7, 12);
|
||||
v.appendBits(0xff7, 12).expect("append");
|
||||
assert_eq!(12, v.getSize());
|
||||
assert_eq!(0xff700000, getUnsignedInt(&v));
|
||||
}
|
||||
@@ -102,11 +102,11 @@ fn testNumBytes() {
|
||||
v.appendBit(false);
|
||||
// 1 bit was added in the vector, so 1 byte should be consumed.
|
||||
assert_eq!(1, v.getSizeInBytes());
|
||||
v.appendBits(0, 7);
|
||||
v.appendBits(0, 7).expect("append");
|
||||
assert_eq!(1, v.getSizeInBytes());
|
||||
v.appendBits(0, 8);
|
||||
v.appendBits(0, 8).expect("append");
|
||||
assert_eq!(2, v.getSizeInBytes());
|
||||
v.appendBits(0, 1);
|
||||
v.appendBits(0, 1).expect("append");
|
||||
// We now have 17 bits, so 3 bytes should be consumed.
|
||||
assert_eq!(3, v.getSizeInBytes());
|
||||
}
|
||||
@@ -114,9 +114,9 @@ fn testNumBytes() {
|
||||
#[test]
|
||||
fn testAppendBitVector() {
|
||||
let mut v1 = BitArray::new();
|
||||
v1.appendBits(0xbe, 8);
|
||||
v1.appendBits(0xbe, 8).expect("append");
|
||||
let mut v2 = BitArray::new();
|
||||
v2.appendBits(0xef, 8);
|
||||
v2.appendBits(0xef, 8).expect("append");
|
||||
v1.appendBitArray(v2);
|
||||
// beef = 1011 1110 1110 1111
|
||||
assert_eq!(" X.XXXXX. XXX.XXXX", v1.to_string());
|
||||
@@ -125,9 +125,9 @@ fn testAppendBitVector() {
|
||||
#[test]
|
||||
fn testXOR() {
|
||||
let mut v1 = BitArray::new();
|
||||
v1.appendBits(0x5555aaaa, 32);
|
||||
v1.appendBits(0x5555aaaa, 32).expect("append");
|
||||
let mut v2 = BitArray::new();
|
||||
v2.appendBits(0xaaaa5555, 32);
|
||||
v2.appendBits(0xaaaa5555, 32).expect("append");
|
||||
v1.xor(&v2);
|
||||
assert_eq!(0xffffffff, getUnsignedInt(&v1));
|
||||
}
|
||||
@@ -135,7 +135,7 @@ fn testXOR() {
|
||||
#[test]
|
||||
fn testXOR2() {
|
||||
let mut v1 = BitArray::new();
|
||||
v1.appendBits(0x2a, 7); // 010 1010
|
||||
v1.appendBits(0x2a, 7).expect("append"); // 010 1010
|
||||
let mut v2 = BitArray::new();
|
||||
v2.appendBits(0x55, 7); // 101 0101
|
||||
v1.xor(&v2);
|
||||
@@ -145,7 +145,7 @@ fn testXOR2() {
|
||||
#[test]
|
||||
fn testAt() {
|
||||
let mut v = BitArray::new();
|
||||
v.appendBits(0xdead, 16); // 1101 1110 1010 1101
|
||||
v.appendBits(0xdead, 16).expect("append"); // 1101 1110 1010 1101
|
||||
assert!(v.get(0));
|
||||
assert!(v.get(1));
|
||||
assert!(!v.get(2));
|
||||
@@ -170,6 +170,6 @@ fn testAt() {
|
||||
#[test]
|
||||
fn testToString() {
|
||||
let mut v = BitArray::new();
|
||||
v.appendBits(0xdead, 16); // 1101 1110 1010 1101
|
||||
v.appendBits(0xdead, 16).expect("append"); // 1101 1110 1010 1101
|
||||
assert_eq!(" XX.XXXX. X.X.XX.X", v.to_string());
|
||||
}
|
||||
|
||||
@@ -686,23 +686,23 @@ fn testInterleaveWithECBytes() {
|
||||
fn testAppendNumericBytes() {
|
||||
// 1 = 01 = 0001 in 4 bits.
|
||||
let mut bits = BitArray::new();
|
||||
encoder::appendNumericBytes("1", &mut bits);
|
||||
encoder::appendNumericBytes("1", &mut bits).expect("append");
|
||||
assert_eq!(" ...X", bits.to_string());
|
||||
// 12 = 0xc = 0001100 in 7 bits.
|
||||
let mut bits = BitArray::new();
|
||||
encoder::appendNumericBytes("12", &mut bits);
|
||||
encoder::appendNumericBytes("12", &mut bits).expect("append");
|
||||
assert_eq!(" ...XX..", bits.to_string());
|
||||
// 123 = 0x7b = 0001111011 in 10 bits.
|
||||
let mut bits = BitArray::new();
|
||||
encoder::appendNumericBytes("123", &mut bits);
|
||||
encoder::appendNumericBytes("123", &mut bits).expect("append");
|
||||
assert_eq!(" ...XXXX. XX", bits.to_string());
|
||||
// 1234 = "123" + "4" = 0001111011 + 0100
|
||||
let mut bits = BitArray::new();
|
||||
encoder::appendNumericBytes("1234", &mut bits);
|
||||
encoder::appendNumericBytes("1234", &mut bits).expect("append");
|
||||
assert_eq!(" ...XXXX. XX.X..", bits.to_string());
|
||||
// Empty.
|
||||
let mut bits = BitArray::new();
|
||||
encoder::appendNumericBytes("", &mut bits);
|
||||
encoder::appendNumericBytes("", &mut bits).expect("append");
|
||||
assert_eq!("", bits.to_string());
|
||||
}
|
||||
|
||||
@@ -710,19 +710,19 @@ fn testAppendNumericBytes() {
|
||||
fn testAppendAlphanumericBytes() {
|
||||
// A = 10 = 0xa = 001010 in 6 bits
|
||||
let mut bits = BitArray::new();
|
||||
encoder::appendAlphanumericBytes("A", &mut bits);
|
||||
encoder::appendAlphanumericBytes("A", &mut bits).expect("append");
|
||||
assert_eq!(" ..X.X.", bits.to_string());
|
||||
// AB = 10 * 45 + 11 = 461 = 0x1cd = 00111001101 in 11 bits
|
||||
let mut bits = BitArray::new();
|
||||
encoder::appendAlphanumericBytes("AB", &mut bits);
|
||||
encoder::appendAlphanumericBytes("AB", &mut bits).expect("append");
|
||||
assert_eq!(" ..XXX..X X.X", bits.to_string());
|
||||
// ABC = "AB" + "C" = 00111001101 + 001100
|
||||
let mut bits = BitArray::new();
|
||||
encoder::appendAlphanumericBytes("ABC", &mut bits);
|
||||
encoder::appendAlphanumericBytes("ABC", &mut bits).expect("append");
|
||||
assert_eq!(" ..XXX..X X.X..XX. .", bits.to_string());
|
||||
// Empty.
|
||||
let mut bits = BitArray::new();
|
||||
encoder::appendAlphanumericBytes("", &mut bits);
|
||||
encoder::appendAlphanumericBytes("", &mut bits).expect("append");
|
||||
assert_eq!("", bits.to_string());
|
||||
// Invalid data.
|
||||
// try {
|
||||
@@ -738,11 +738,11 @@ fn testAppendAlphanumericBytes() {
|
||||
fn testAppend8BitBytes() {
|
||||
// 0x61, 0x62, 0x63
|
||||
let mut bits = BitArray::new();
|
||||
encoder::append8BitBytes("abc", &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING);
|
||||
encoder::append8BitBytes("abc", &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING).expect("append");
|
||||
assert_eq!(" .XX....X .XX...X. .XX...XX", bits.to_string());
|
||||
// Empty.
|
||||
let mut bits = BitArray::new();
|
||||
encoder::append8BitBytes("", &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING);
|
||||
encoder::append8BitBytes("", &mut bits, encoder::DEFAULT_BYTE_MODE_ENCODING).expect("append");
|
||||
assert_eq!("", bits.to_string());
|
||||
}
|
||||
|
||||
@@ -750,9 +750,9 @@ fn testAppend8BitBytes() {
|
||||
#[test]
|
||||
fn testAppendKanjiBytes() {
|
||||
let mut bits = BitArray::new();
|
||||
encoder::appendKanjiBytes(&shiftJISString(&[0x93, 0x5f]), &mut bits);
|
||||
encoder::appendKanjiBytes(&shiftJISString(&[0x93, 0x5f]), &mut bits).expect("append");
|
||||
assert_eq!(" .XX.XX.. XXXXX", bits.to_string());
|
||||
encoder::appendKanjiBytes(&shiftJISString(&[0xe4, 0xaa]), &mut bits);
|
||||
encoder::appendKanjiBytes(&shiftJISString(&[0xe4, 0xaa]), &mut bits).expect("append");
|
||||
assert_eq!(" .XX.XX.. XXXXXXX. X.X.X.X. X.", bits.to_string());
|
||||
}
|
||||
|
||||
@@ -826,7 +826,7 @@ fn testBugInBitVectorNumBytes() {
|
||||
// 11745 bits = 1468.125 bytes are needed (i.e. cannot fit in 1468
|
||||
// bytes).
|
||||
let mut builder = String::with_capacity(3518);
|
||||
for x in 0..3518 {
|
||||
for _x in 0..3518 {
|
||||
// for (int x = 0; x < 3518; x++) {
|
||||
builder.push('0');
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ fn testEmbedDataBits() {
|
||||
)
|
||||
.expect("op ok");
|
||||
let bits = BitArray::new();
|
||||
matrix_util::embedDataBits(&bits, -1, &mut matrix);
|
||||
matrix_util::embedDataBits(&bits, -1, &mut matrix).expect("append");
|
||||
let expected = r" 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1
|
||||
1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1
|
||||
1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1
|
||||
@@ -254,7 +254,7 @@ fn testBuildMatrix() {
|
||||
Version::getVersionForNumber(1).expect("version"), // Version 1
|
||||
3, // Mask pattern 3
|
||||
&mut matrix,
|
||||
);
|
||||
).expect("append");
|
||||
let expected = r" 1 1 1 1 1 1 1 0 0 1 1 0 0 0 1 1 1 1 1 1 1
|
||||
1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1
|
||||
1 0 1 1 1 0 1 0 0 0 0 1 0 0 1 0 1 1 1 0 1
|
||||
@@ -344,6 +344,6 @@ fn testMakeVersionInfoBits() {
|
||||
fn testMakeTypeInfoInfoBits() {
|
||||
// From Appendix C in JISX0510:2004 (p 65)
|
||||
let mut bits = BitArray::new();
|
||||
matrix_util::makeTypeInfoBits(&ErrorCorrectionLevel::M, 5, &mut bits);
|
||||
matrix_util::makeTypeInfoBits(&ErrorCorrectionLevel::M, 5, &mut bits).expect("append");
|
||||
assert_eq!(" X......X X..XXX.", bits.to_string());
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ use unicode_segmentation::UnicodeSegmentation;
|
||||
use crate::{
|
||||
common::{
|
||||
reedsolomon::{get_predefined_genericgf, PredefinedGenericGF, ReedSolomonEncoder},
|
||||
BitArray, CharacterSetECI, StringUtils,
|
||||
BitArray, CharacterSetECI,
|
||||
},
|
||||
qrcode::decoder::{ErrorCorrectionLevel, Mode, Version, VersionRef},
|
||||
EncodeHintType, EncodeHintValue, EncodingHintDictionary, Exceptions,
|
||||
|
||||
@@ -24,7 +24,7 @@ use crate::{
|
||||
Exceptions,
|
||||
};
|
||||
|
||||
use unicode_segmentation::{Graphemes, UnicodeSegmentation};
|
||||
use unicode_segmentation::{ UnicodeSegmentation};
|
||||
|
||||
use super::encoder;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ use std::collections::HashMap;
|
||||
use crate::{
|
||||
common::{BitMatrix, DecoderRXingResult, DetectorRXingResult},
|
||||
BarcodeFormat, DecodeHintType, Exceptions, RXingResult, RXingResultMetadataType,
|
||||
RXingResultMetadataValue, RXingResultPoint, Reader, ResultPoint,
|
||||
RXingResultMetadataValue, RXingResultPoint, Reader,
|
||||
};
|
||||
|
||||
use super::{
|
||||
|
||||
71
src/reader.rs
Normal file
71
src/reader.rs
Normal file
@@ -0,0 +1,71 @@
|
||||
|
||||
/*
|
||||
* Copyright 2007 ZXing authors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//package com.google.zxing;
|
||||
|
||||
use crate::{BinaryBitmap, RXingResult, Exceptions, DecodingHintDictionary};
|
||||
|
||||
/**
|
||||
* Implementations of this interface can decode an image of a barcode in some format into
|
||||
* the String it encodes. For example, {@link com.google.zxing.qrcode.QRCodeReader} can
|
||||
* decode a QR code. The decoder may optionally receive hints from the caller which may help
|
||||
* it decode more quickly or accurately.
|
||||
*
|
||||
* See {@link MultiFormatReader}, which attempts to determine what barcode
|
||||
* format is present within the image as well, and then decodes it accordingly.
|
||||
*
|
||||
* @author Sean Owen
|
||||
* @author dswitkin@google.com (Daniel Switkin)
|
||||
*/
|
||||
pub trait Reader {
|
||||
/**
|
||||
* Locates and decodes a barcode in some format within an image.
|
||||
*
|
||||
* @param image image of barcode to decode
|
||||
* @return String which the barcode encodes
|
||||
* @throws NotFoundException if no potential barcode is found
|
||||
* @throws ChecksumException if a potential barcode is found but does not pass its checksum
|
||||
* @throws FormatException if a potential barcode is found but format is invalid
|
||||
*/
|
||||
fn decode(&self, image: &BinaryBitmap) -> Result<RXingResult, Exceptions>;
|
||||
|
||||
/**
|
||||
* Locates and decodes a barcode in some format within an image. This method also accepts
|
||||
* hints, each possibly associated to some data, which may help the implementation decode.
|
||||
*
|
||||
* @param image image of barcode to decode
|
||||
* @param hints passed as a {@link Map} from {@link DecodeHintType}
|
||||
* to arbitrary data. The
|
||||
* meaning of the data depends upon the hint type. The implementation may or may not do
|
||||
* anything with these hints.
|
||||
* @return String which the barcode encodes
|
||||
* @throws NotFoundException if no potential barcode is found
|
||||
* @throws ChecksumException if a potential barcode is found but does not pass its checksum
|
||||
* @throws FormatException if a potential barcode is found but format is invalid
|
||||
*/
|
||||
fn decode_with_hints(
|
||||
&self,
|
||||
image: &BinaryBitmap,
|
||||
hints: &DecodingHintDictionary,
|
||||
) -> Result<RXingResult, Exceptions>;
|
||||
|
||||
/**
|
||||
* Resets any internal state the implementation has after a decode, to prepare it
|
||||
* for reuse.
|
||||
*/
|
||||
fn reset(&self);
|
||||
}
|
||||
26
src/result_point.rs
Normal file
26
src/result_point.rs
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
/*
|
||||
* Copyright 2007 ZXing authors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//package com.google.zxing;
|
||||
|
||||
use crate::RXingResultPoint;
|
||||
|
||||
pub trait ResultPoint {
|
||||
fn getX(&self) -> f32;
|
||||
fn getY(&self) -> f32;
|
||||
fn into_rxing_result_point(self) -> RXingResultPoint;
|
||||
}
|
||||
89
src/result_point_utils.rs
Normal file
89
src/result_point_utils.rs
Normal file
@@ -0,0 +1,89 @@
|
||||
use crate::{common::detector::MathUtils, ResultPoint};
|
||||
|
||||
/**
|
||||
* Orders an array of three RXingResultPoints in an order [A,B,C] such that AB is less than AC
|
||||
* and BC is less than AC, and the angle between BC and BA is less than 180 degrees.
|
||||
*
|
||||
* @param patterns array of three {@code RXingResultPoint} to order
|
||||
*/
|
||||
pub fn orderBestPatterns<T: ResultPoint + Copy + Clone>(patterns: &mut [T; 3]) {
|
||||
// Find distances between pattern centers
|
||||
let zeroOneDistance = MathUtils::distance_float(
|
||||
patterns[0].getX(),
|
||||
patterns[0].getY(),
|
||||
patterns[1].getX(),
|
||||
patterns[1].getY(),
|
||||
);
|
||||
let oneTwoDistance = MathUtils::distance_float(
|
||||
patterns[1].getX(),
|
||||
patterns[1].getY(),
|
||||
patterns[2].getX(),
|
||||
patterns[2].getY(),
|
||||
);
|
||||
let zeroTwoDistance = MathUtils::distance_float(
|
||||
patterns[0].getX(),
|
||||
patterns[0].getY(),
|
||||
patterns[2].getX(),
|
||||
patterns[2].getY(),
|
||||
);
|
||||
|
||||
let mut pointA; //: &RXingResultPoint;
|
||||
let pointB; //: &RXingResultPoint;
|
||||
let mut pointC; //: &RXingResultPoint;
|
||||
// Assume one closest to other two is B; A and C will just be guesses at first
|
||||
if oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance {
|
||||
pointB = patterns[0];
|
||||
pointA = patterns[1];
|
||||
pointC = patterns[2];
|
||||
} else if zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance {
|
||||
pointB = patterns[1];
|
||||
pointA = patterns[0];
|
||||
pointC = patterns[2];
|
||||
} else {
|
||||
pointB = patterns[2];
|
||||
pointA = patterns[0];
|
||||
pointC = patterns[1];
|
||||
}
|
||||
|
||||
// Use cross product to figure out whether A and C are correct or flipped.
|
||||
// This asks whether BC x BA has a positive z component, which is the arrangement
|
||||
// we want for A, B, C. If it's negative, then we've got it flipped around and
|
||||
// should swap A and C.
|
||||
if crossProductZ(pointA, pointB, pointC) < 0.0f32 {
|
||||
let temp = pointA;
|
||||
pointA = pointC;
|
||||
pointC = temp;
|
||||
}
|
||||
|
||||
let pa = pointA;
|
||||
let pb = pointB;
|
||||
let pc = pointC;
|
||||
|
||||
patterns[0] = pa;
|
||||
patterns[1] = pb;
|
||||
patterns[2] = pc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pattern1 first pattern
|
||||
* @param pattern2 second pattern
|
||||
* @return distance between two points
|
||||
*/
|
||||
pub fn distance<T: ResultPoint>(pattern1: &T, pattern2: &T) -> f32 {
|
||||
return MathUtils::distance_float(
|
||||
pattern1.getX(),
|
||||
pattern1.getY(),
|
||||
pattern2.getX(),
|
||||
pattern2.getY(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the z component of the cross product between vectors BC and BA.
|
||||
*/
|
||||
pub fn crossProductZ<T: ResultPoint>(pointA: T, pointB: T, pointC: T) -> f32 {
|
||||
let bX = pointB.getX();
|
||||
let bY = pointB.getY();
|
||||
return ((pointC.getX() - bX) * (pointA.getY() - bY))
|
||||
- ((pointC.getY() - bY) * (pointA.getX() - bX));
|
||||
}
|
||||
207
src/rgb_luminance_source.rs
Normal file
207
src/rgb_luminance_source.rs
Normal file
@@ -0,0 +1,207 @@
|
||||
|
||||
/*
|
||||
* Copyright 2009 ZXing authors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//package com.google.zxing;
|
||||
|
||||
use crate::{Exceptions, LuminanceSource};
|
||||
|
||||
/**
|
||||
* This class is used to help decode images from files which arrive as RGB data from
|
||||
* an ARGB pixel array. It does not support rotation.
|
||||
*
|
||||
* @author dswitkin@google.com (Daniel Switkin)
|
||||
* @author Betaminos
|
||||
*/
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RGBLuminanceSource {
|
||||
luminances: Vec<u8>,
|
||||
dataWidth: usize,
|
||||
dataHeight: usize,
|
||||
left: usize,
|
||||
top: usize,
|
||||
width: usize,
|
||||
height: usize,
|
||||
invert: bool,
|
||||
}
|
||||
|
||||
impl LuminanceSource for RGBLuminanceSource {
|
||||
fn getRow(&self, y: usize, row: &Vec<u8>) -> Vec<u8> {
|
||||
if y >= self.getHeight() {
|
||||
panic!("Requested row is outside the image: {}", y);
|
||||
}
|
||||
let width = self.getWidth();
|
||||
|
||||
let offset = (y + self.top) * self.dataWidth + self.left;
|
||||
|
||||
let mut row = if row.len() >= width {
|
||||
row.to_vec()
|
||||
} else {
|
||||
vec![0; width]
|
||||
};
|
||||
|
||||
row[..width].clone_from_slice(&self.luminances[offset..offset + width]);
|
||||
//System.arraycopy(self.luminances, offset, row, 0, width);
|
||||
if self.invert {
|
||||
row = self.invert_block_of_bytes(row);
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
fn getMatrix(&self) -> Vec<u8> {
|
||||
let width = self.getWidth();
|
||||
let height = self.getHeight();
|
||||
|
||||
// If the caller asks for the entire underlying image, save the copy and give them the
|
||||
// original data. The docs specifically warn that result.length must be ignored.
|
||||
if width == self.dataWidth && height == self.dataHeight {
|
||||
let mut z = self.luminances.clone();
|
||||
if self.invert {
|
||||
z = self.invert_block_of_bytes(z);
|
||||
}
|
||||
return z;
|
||||
}
|
||||
|
||||
let area = width * height;
|
||||
let mut matrix = vec![0; area];
|
||||
let mut inputOffset = self.top * self.dataWidth + self.left;
|
||||
|
||||
// If the width matches the full width of the underlying data, perform a single copy.
|
||||
if width == self.dataWidth {
|
||||
matrix[..area].clone_from_slice(&self.luminances[inputOffset..area + inputOffset]);
|
||||
//System.arraycopy(self.luminances, inputOffset, matrix, 0, area);
|
||||
if self.invert {
|
||||
matrix = self.invert_block_of_bytes(matrix);
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
// Otherwise copy one cropped row at a time.
|
||||
for y in 0..height {
|
||||
//for (int y = 0; y < height; y++) {
|
||||
let outputOffset = y * width;
|
||||
matrix[outputOffset..width + outputOffset]
|
||||
.clone_from_slice(&self.luminances[inputOffset..width + inputOffset]);
|
||||
//System.arraycopy(luminances, inputOffset, matrix, outputOffset, width);
|
||||
inputOffset += self.dataWidth;
|
||||
}
|
||||
|
||||
if self.invert {
|
||||
matrix = self.invert_block_of_bytes(matrix);
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
fn getWidth(&self) -> usize {
|
||||
self.width
|
||||
}
|
||||
|
||||
fn getHeight(&self) -> usize {
|
||||
self.height
|
||||
}
|
||||
|
||||
fn isCropSupported(&self) -> bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
fn crop(
|
||||
&self,
|
||||
left: usize,
|
||||
top: usize,
|
||||
width: usize,
|
||||
height: usize,
|
||||
) -> Result<Box<dyn LuminanceSource>, Exceptions> {
|
||||
match RGBLuminanceSource::new_complex(
|
||||
&self.luminances,
|
||||
self.dataWidth,
|
||||
self.dataHeight,
|
||||
self.left + left,
|
||||
self.top + top,
|
||||
width,
|
||||
height,
|
||||
) {
|
||||
Ok(crop) => Ok(Box::new(crop)),
|
||||
Err(_error) => Err(Exceptions::UnsupportedOperationException("".to_owned())),
|
||||
}
|
||||
}
|
||||
|
||||
fn invert(&mut self) {
|
||||
self.invert = !self.invert;
|
||||
}
|
||||
}
|
||||
|
||||
impl RGBLuminanceSource {
|
||||
pub fn new_with_width_height_pixels(width: usize, height: usize, pixels: &Vec<u32>) -> Self {
|
||||
//super(width, height);
|
||||
|
||||
let dataWidth = width;
|
||||
let dataHeight = height;
|
||||
let left = 0;
|
||||
let top = 0;
|
||||
|
||||
// In order to measure pure decoding speed, we convert the entire image to a greyscale array
|
||||
// up front, which is the same as the Y channel of the YUVLuminanceSource in the real app.
|
||||
//
|
||||
// Total number of pixels suffices, can ignore shape
|
||||
let size = width * height;
|
||||
let mut luminances: Vec<u8> = vec![0; size];
|
||||
for offset in 0..size {
|
||||
//for (int offset = 0; offset < size; offset++) {
|
||||
let pixel = pixels[offset];
|
||||
let r = (pixel >> 16) & 0xff; // red
|
||||
let g2 = (pixel >> 7) & 0x1fe; // 2 * green
|
||||
let b = pixel & 0xff; // blue
|
||||
// Calculate green-favouring average cheaply
|
||||
luminances[offset] = ((r + g2 + b) / 4).try_into().unwrap();
|
||||
}
|
||||
Self {
|
||||
luminances,
|
||||
dataWidth,
|
||||
dataHeight,
|
||||
left: left,
|
||||
top: top,
|
||||
width,
|
||||
height,
|
||||
invert: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn new_complex(
|
||||
pixels: &Vec<u8>,
|
||||
data_width: usize,
|
||||
data_height: usize,
|
||||
left: usize,
|
||||
top: usize,
|
||||
width: usize,
|
||||
height: usize,
|
||||
) -> Result<Self, Exceptions> {
|
||||
if left + width > data_width || top + height > data_height {
|
||||
return Err(Exceptions::IllegalArgumentException(
|
||||
"Crop rectangle does not fit within image data.".to_owned(),
|
||||
));
|
||||
}
|
||||
Ok(Self {
|
||||
luminances: pixels.clone(),
|
||||
dataWidth: data_width,
|
||||
dataHeight: data_height,
|
||||
left,
|
||||
top,
|
||||
width,
|
||||
height,
|
||||
invert: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
180
src/rxing_result.rs
Normal file
180
src/rxing_result.rs
Normal file
@@ -0,0 +1,180 @@
|
||||
|
||||
/*
|
||||
* Copyright 2007 ZXing authors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//package com.google.zxing;
|
||||
|
||||
//import java.util.EnumMap;
|
||||
//import java.util.Map;
|
||||
|
||||
use std::{fmt, collections::HashMap, time::{SystemTime, UNIX_EPOCH}};
|
||||
|
||||
use crate::{RXingResultMetadataValue, RXingResultMetadataType, BarcodeFormat, RXingResultPoint};
|
||||
|
||||
/**
|
||||
* <p>Encapsulates the result of decoding a barcode within an image.</p>
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
pub struct RXingResult {
|
||||
text: String,
|
||||
rawBytes: Vec<u8>,
|
||||
numBits: usize,
|
||||
resultPoints: Vec<RXingResultPoint>,
|
||||
format: BarcodeFormat,
|
||||
resultMetadata: HashMap<RXingResultMetadataType, RXingResultMetadataValue>,
|
||||
timestamp: u128,
|
||||
}
|
||||
impl RXingResult {
|
||||
pub fn new(
|
||||
text: &str,
|
||||
rawBytes: Vec<u8>,
|
||||
resultPoints: Vec<RXingResultPoint>,
|
||||
format: BarcodeFormat,
|
||||
) -> Self {
|
||||
Self::new_timestamp(
|
||||
text,
|
||||
rawBytes,
|
||||
resultPoints,
|
||||
format,
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.expect("Time went backwards")
|
||||
.as_millis(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_timestamp(
|
||||
text: &str,
|
||||
rawBytes: Vec<u8>,
|
||||
resultPoints: Vec<RXingResultPoint>,
|
||||
format: BarcodeFormat,
|
||||
timestamp: u128,
|
||||
) -> Self {
|
||||
let l = rawBytes.len();
|
||||
Self::new_complex(text, rawBytes, 8 * l, resultPoints, format, timestamp)
|
||||
}
|
||||
|
||||
pub fn new_complex(
|
||||
text: &str,
|
||||
rawBytes: Vec<u8>,
|
||||
numBits: usize,
|
||||
resultPoints: Vec<RXingResultPoint>,
|
||||
format: BarcodeFormat,
|
||||
timestamp: u128,
|
||||
) -> Self {
|
||||
Self {
|
||||
text: text.to_owned(),
|
||||
rawBytes: rawBytes,
|
||||
numBits,
|
||||
resultPoints,
|
||||
format,
|
||||
resultMetadata: HashMap::new(),
|
||||
timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return raw text encoded by the barcode
|
||||
*/
|
||||
pub fn getText(&self) -> &String {
|
||||
return &self.text;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return raw bytes encoded by the barcode, if applicable, otherwise {@code null}
|
||||
*/
|
||||
pub fn getRawBytes(&self) -> &Vec<u8> {
|
||||
return &self.rawBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length
|
||||
* @since 3.3.0
|
||||
*/
|
||||
pub fn getNumBits(&self) -> usize {
|
||||
return self.numBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return points related to the barcode in the image. These are typically points
|
||||
* identifying finder patterns or the corners of the barcode. The exact meaning is
|
||||
* specific to the type of barcode that was decoded.
|
||||
*/
|
||||
pub fn getRXingResultPoints(&self) -> &Vec<RXingResultPoint> {
|
||||
return &self.resultPoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link BarcodeFormat} representing the format of the barcode that was decoded
|
||||
*/
|
||||
pub fn getBarcodeFormat(&self) -> &BarcodeFormat {
|
||||
return &self.format;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link Map} mapping {@link RXingResultMetadataType} keys to values. May be
|
||||
* {@code null}. This contains optional metadata about what was detected about the barcode,
|
||||
* like orientation.
|
||||
*/
|
||||
pub fn getRXingResultMetadata(
|
||||
&self,
|
||||
) -> &HashMap<RXingResultMetadataType, RXingResultMetadataValue> {
|
||||
return &self.resultMetadata;
|
||||
}
|
||||
|
||||
pub fn putMetadata(
|
||||
&mut self,
|
||||
md_type: RXingResultMetadataType,
|
||||
value: RXingResultMetadataValue,
|
||||
) {
|
||||
self.resultMetadata.insert(md_type, value);
|
||||
}
|
||||
|
||||
pub fn putAllMetadata(
|
||||
&mut self,
|
||||
metadata: HashMap<RXingResultMetadataType, RXingResultMetadataValue>,
|
||||
) {
|
||||
if self.resultMetadata.is_empty() {
|
||||
self.resultMetadata = metadata;
|
||||
} else {
|
||||
for (key, value) in metadata.into_iter() {
|
||||
self.resultMetadata.insert(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addRXingResultPoints(&mut self, newPoints: &mut Vec<RXingResultPoint>) {
|
||||
//RXingResultPoint[] oldPoints = resultPoints;
|
||||
if !newPoints.is_empty() {
|
||||
// let allPoints:Vec<RXingResultPoint>= Vec::with_capacity(oldPoints.len() + newPoints.len());
|
||||
//System.arraycopy(oldPoints, 0, allPoints, 0, oldPoints.length);
|
||||
//System.arraycopy(newPoints, 0, allPoints, oldPoints.length, newPoints.length);
|
||||
//resultPoints = allPoints;
|
||||
self.resultPoints.append(newPoints);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getTimestamp(&self) -> u128 {
|
||||
return self.timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for RXingResult {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.text)
|
||||
}
|
||||
}
|
||||
204
src/rxing_result_metadata.rs
Normal file
204
src/rxing_result_metadata.rs
Normal file
@@ -0,0 +1,204 @@
|
||||
|
||||
/*
|
||||
* Copyright 2008 ZXing authors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//package com.google.zxing;
|
||||
|
||||
/**
|
||||
* Represents some type of metadata about the result of the decoding that the decoder
|
||||
* wishes to communicate back to the caller.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
#[derive(Eq, PartialEq, Hash, Debug)]
|
||||
pub enum RXingResultMetadataType {
|
||||
/**
|
||||
* Unspecified, application-specific metadata. Maps to an unspecified {@link Object}.
|
||||
*/
|
||||
OTHER,
|
||||
|
||||
/**
|
||||
* Denotes the likely approximate orientation of the barcode in the image. This value
|
||||
* is given as degrees rotated clockwise from the normal, upright orientation.
|
||||
* For example a 1D barcode which was found by reading top-to-bottom would be
|
||||
* said to have orientation "90". This key maps to an {@link Integer} whose
|
||||
* value is in the range [0,360).
|
||||
*/
|
||||
ORIENTATION,
|
||||
|
||||
/**
|
||||
* <p>2D barcode formats typically encode text, but allow for a sort of 'byte mode'
|
||||
* which is sometimes used to encode binary data. While {@link RXingResult} makes available
|
||||
* the complete raw bytes in the barcode for these formats, it does not offer the bytes
|
||||
* from the byte segments alone.</p>
|
||||
*
|
||||
* <p>This maps to a {@link java.util.List} of byte arrays corresponding to the
|
||||
* raw bytes in the byte segments in the barcode, in order.</p>
|
||||
*/
|
||||
BYTE_SEGMENTS,
|
||||
|
||||
/**
|
||||
* Error correction level used, if applicable. The value type depends on the
|
||||
* format, but is typically a String.
|
||||
*/
|
||||
ERROR_CORRECTION_LEVEL,
|
||||
|
||||
/**
|
||||
* For some periodicals, indicates the issue number as an {@link Integer}.
|
||||
*/
|
||||
ISSUE_NUMBER,
|
||||
|
||||
/**
|
||||
* For some products, indicates the suggested retail price in the barcode as a
|
||||
* formatted {@link String}.
|
||||
*/
|
||||
SUGGESTED_PRICE,
|
||||
|
||||
/**
|
||||
* For some products, the possible country of manufacture as a {@link String} denoting the
|
||||
* ISO country code. Some map to multiple possible countries, like "US/CA".
|
||||
*/
|
||||
POSSIBLE_COUNTRY,
|
||||
|
||||
/**
|
||||
* For some products, the extension text
|
||||
*/
|
||||
UPC_EAN_EXTENSION,
|
||||
|
||||
/**
|
||||
* PDF417-specific metadata
|
||||
*/
|
||||
PDF417_EXTRA_METADATA,
|
||||
|
||||
/**
|
||||
* If the code format supports structured append and the current scanned code is part of one then the
|
||||
* sequence number is given with it.
|
||||
*/
|
||||
STRUCTURED_APPEND_SEQUENCE,
|
||||
|
||||
/**
|
||||
* If the code format supports structured append and the current scanned code is part of one then the
|
||||
* parity is given with it.
|
||||
*/
|
||||
STRUCTURED_APPEND_PARITY,
|
||||
|
||||
/**
|
||||
* Barcode Symbology Identifier.
|
||||
* Note: According to the GS1 specification the identifier may have to replace a leading FNC1/GS character
|
||||
* when prepending to the barcode content.
|
||||
*/
|
||||
SYMBOLOGY_IDENTIFIER,
|
||||
}
|
||||
|
||||
impl From<String> for RXingResultMetadataType {
|
||||
fn from(in_str: String) -> Self {
|
||||
match in_str.as_str() {
|
||||
"OTHER" => RXingResultMetadataType::OTHER,
|
||||
"ORIENTATION" => RXingResultMetadataType::ORIENTATION,
|
||||
"BYTE_SEGMENTS" => RXingResultMetadataType::BYTE_SEGMENTS,
|
||||
"ERROR_CORRECTION_LEVEL" => RXingResultMetadataType::ERROR_CORRECTION_LEVEL,
|
||||
"ISSUE_NUMBER" => RXingResultMetadataType::ISSUE_NUMBER,
|
||||
"SUGGESTED_PRICE" => RXingResultMetadataType::SUGGESTED_PRICE,
|
||||
"POSSIBLE_COUNTRY" => RXingResultMetadataType::POSSIBLE_COUNTRY,
|
||||
"UPC_EAN_EXTENSION" => RXingResultMetadataType::UPC_EAN_EXTENSION,
|
||||
"PDF417_EXTRA_METADATA" => RXingResultMetadataType::PDF417_EXTRA_METADATA,
|
||||
"STRUCTURED_APPEND_SEQUENCE" => RXingResultMetadataType::STRUCTURED_APPEND_SEQUENCE,
|
||||
"STRUCTURED_APPEND_PARITY" => RXingResultMetadataType::STRUCTURED_APPEND_PARITY,
|
||||
"SYMBOLOGY_IDENTIFIER" => RXingResultMetadataType::SYMBOLOGY_IDENTIFIER,
|
||||
_ => RXingResultMetadataType::OTHER,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum RXingResultMetadataValue {
|
||||
/**
|
||||
* Unspecified, application-specific metadata. Maps to an unspecified {@link Object}.
|
||||
*/
|
||||
OTHER(String),
|
||||
|
||||
/**
|
||||
* Denotes the likely approximate orientation of the barcode in the image. This value
|
||||
* is given as degrees rotated clockwise from the normal, upright orientation.
|
||||
* For example a 1D barcode which was found by reading top-to-bottom would be
|
||||
* said to have orientation "90". This key maps to an {@link Integer} whose
|
||||
* value is in the range [0,360).
|
||||
*/
|
||||
Orientation(i32),
|
||||
|
||||
/**
|
||||
* <p>2D barcode formats typically encode text, but allow for a sort of 'byte mode'
|
||||
* which is sometimes used to encode binary data. While {@link RXingResult} makes available
|
||||
* the complete raw bytes in the barcode for these formats, it does not offer the bytes
|
||||
* from the byte segments alone.</p>
|
||||
*
|
||||
* <p>This maps to a {@link java.util.List} of byte arrays corresponding to the
|
||||
* raw bytes in the byte segments in the barcode, in order.</p>
|
||||
*/
|
||||
ByteSegments(Vec<Vec<u8>>),
|
||||
|
||||
/**
|
||||
* Error correction level used, if applicable. The value type depends on the
|
||||
* format, but is typically a String.
|
||||
*/
|
||||
ErrorCorrectionLevel(String),
|
||||
|
||||
/**
|
||||
* For some periodicals, indicates the issue number as an {@link Integer}.
|
||||
*/
|
||||
IssueNumber(i32),
|
||||
|
||||
/**
|
||||
* For some products, indicates the suggested retail price in the barcode as a
|
||||
* formatted {@link String}.
|
||||
*/
|
||||
SuggestedPrice(String),
|
||||
|
||||
/**
|
||||
* For some products, the possible country of manufacture as a {@link String} denoting the
|
||||
* ISO country code. Some map to multiple possible countries, like "US/CA".
|
||||
*/
|
||||
PossibleCountry(String),
|
||||
|
||||
/**
|
||||
* For some products, the extension text
|
||||
*/
|
||||
UpcEanExtension(String),
|
||||
|
||||
/**
|
||||
* PDF417-specific metadata
|
||||
*/
|
||||
Pdf417ExtraMetadata(String),
|
||||
|
||||
/**
|
||||
* If the code format supports structured append and the current scanned code is part of one then the
|
||||
* sequence number is given with it.
|
||||
*/
|
||||
StructuredAppendSequence(i32),
|
||||
|
||||
/**
|
||||
* If the code format supports structured append and the current scanned code is part of one then the
|
||||
* parity is given with it.
|
||||
*/
|
||||
StructuredAppendParity(i32),
|
||||
|
||||
/**
|
||||
* Barcode Symbology Identifier.
|
||||
* Note: According to the GS1 specification the identifier may have to replace a leading FNC1/GS character
|
||||
* when prepending to the barcode content.
|
||||
*/
|
||||
SymbologyIdentifier(String),
|
||||
}
|
||||
54
src/rxing_result_point.rs
Normal file
54
src/rxing_result_point.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
use std::fmt;
|
||||
|
||||
use crate::ResultPoint;
|
||||
use std::hash::Hash;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Encapsulates a point of interest in an image containing a barcode. Typically, this
|
||||
* would be the location of a finder pattern or the corner of the barcode, for example.</p>
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct RXingResultPoint {
|
||||
pub(crate) x: f32,
|
||||
pub(crate)y: f32,
|
||||
}
|
||||
impl Hash for RXingResultPoint {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.x.to_string().hash(state);
|
||||
self.y.to_string().hash(state);
|
||||
}
|
||||
}
|
||||
impl PartialEq for RXingResultPoint {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.x.to_string() == other.x.to_string() && self.y.to_string() == other.y.to_string()
|
||||
}
|
||||
}
|
||||
impl Eq for RXingResultPoint {}
|
||||
impl RXingResultPoint {
|
||||
pub const fn new(x: f32, y: f32) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
impl ResultPoint for RXingResultPoint {
|
||||
fn getX(&self) -> f32 {
|
||||
return self.x;
|
||||
}
|
||||
|
||||
fn getY(&self) -> f32 {
|
||||
return self.y;
|
||||
}
|
||||
|
||||
fn into_rxing_result_point(self) -> RXingResultPoint {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for RXingResultPoint {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "({},{})", self.x, self.y)
|
||||
}
|
||||
}
|
||||
63
src/writer.rs
Normal file
63
src/writer.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
|
||||
/*
|
||||
* Copyright 2008 ZXing authors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//package com.google.zxing;
|
||||
|
||||
use crate::{BarcodeFormat, common::BitMatrix, Exceptions, EncodingHintDictionary};
|
||||
|
||||
/**
|
||||
* The base class for all objects which encode/generate a barcode image.
|
||||
*
|
||||
* @author dswitkin@google.com (Daniel Switkin)
|
||||
*/
|
||||
pub trait Writer {
|
||||
/**
|
||||
* Encode a barcode using the default settings.
|
||||
*
|
||||
* @param contents The contents to encode in the barcode
|
||||
* @param format The barcode format to generate
|
||||
* @param width The preferred width in pixels
|
||||
* @param height The preferred height in pixels
|
||||
* @return {@link BitMatrix} representing encoded barcode image
|
||||
* @throws WriterException if contents cannot be encoded legally in a format
|
||||
*/
|
||||
fn encode(
|
||||
&self,
|
||||
contents: &str,
|
||||
format: &BarcodeFormat,
|
||||
width: i32,
|
||||
height: i32,
|
||||
) -> Result<BitMatrix, Exceptions>;
|
||||
|
||||
/**
|
||||
* @param contents The contents to encode in the barcode
|
||||
* @param format The barcode format to generate
|
||||
* @param width The preferred width in pixels
|
||||
* @param height The preferred height in pixels
|
||||
* @param hints Additional parameters to supply to the encoder
|
||||
* @return {@link BitMatrix} representing encoded barcode image
|
||||
* @throws WriterException if contents cannot be encoded legally in a format
|
||||
*/
|
||||
fn encode_with_hints(
|
||||
&self,
|
||||
contents: &str,
|
||||
format: &BarcodeFormat,
|
||||
width: i32,
|
||||
height: i32,
|
||||
hints: &EncodingHintDictionary,
|
||||
) -> Result<BitMatrix, Exceptions>;
|
||||
}
|
||||
@@ -30,12 +30,12 @@ fn aztec_black_box1_test_case() {
|
||||
);
|
||||
|
||||
// super("src/test/resources/blackbox/aztec-1", AztecReader::new(), BarcodeFormat::AZTEC);
|
||||
tester.addTest(14, 14, 0.0);
|
||||
tester.addTest(14, 14, 90.0);
|
||||
tester.addTest(14, 14, 180.0);
|
||||
tester.addTest(14, 14, 270.0);
|
||||
tester.add_test(14, 14, 0.0);
|
||||
tester.add_test(14, 14, 90.0);
|
||||
tester.add_test(14, 14, 180.0);
|
||||
tester.add_test(14, 14, 270.0);
|
||||
|
||||
tester.testBlackBox();
|
||||
tester.test_black_box();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,10 +51,10 @@ fn aztec_black_box2_test_case() {
|
||||
BarcodeFormat::AZTEC,
|
||||
);
|
||||
// super(, new AztecReader(), BarcodeFormat.AZTEC);
|
||||
tester.addTest(5, 5, 0.0);
|
||||
tester.addTest(4, 4, 90.0);
|
||||
tester.addTest(6, 6, 180.0);
|
||||
tester.addTest(3, 3, 270.0);
|
||||
tester.add_test(5, 5, 0.0);
|
||||
tester.add_test(4, 4, 90.0);
|
||||
tester.add_test(6, 6, 180.0);
|
||||
tester.add_test(3, 3, 270.0);
|
||||
|
||||
tester.testBlackBox();
|
||||
tester.test_black_box();
|
||||
}
|
||||
|
||||
@@ -43,9 +43,9 @@ pub struct AbstractBlackBoxTestCase<T:Reader> {
|
||||
|
||||
impl<T:Reader> AbstractBlackBoxTestCase<T> {
|
||||
|
||||
pub fn buildTestBase(testBasePathSuffix: &str) -> Box<Path> {
|
||||
pub fn build_test_base(test_base_path_suffix: &str) -> Box<Path> {
|
||||
// A little workaround to prevent aggravation in my IDE
|
||||
let test_base = Path::new(testBasePathSuffix);
|
||||
let test_base = Path::new(test_base_path_suffix);
|
||||
// if !testBase.exists() {
|
||||
// // try starting with 'core' since the test base is often given as the project root
|
||||
// testBase = Paths.get("core").resolve(testBasePathSuffix);
|
||||
@@ -59,7 +59,7 @@ impl<T:Reader> AbstractBlackBoxTestCase<T> {
|
||||
expected_format: BarcodeFormat,
|
||||
) -> Self {
|
||||
Self {
|
||||
test_base: Self::buildTestBase(test_base_path_suffix),
|
||||
test_base: Self::build_test_base(test_base_path_suffix),
|
||||
barcode_reader,
|
||||
expected_format,
|
||||
test_rxing_results: Vec::new(),
|
||||
@@ -67,15 +67,15 @@ impl<T:Reader> AbstractBlackBoxTestCase<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getTestBase(&self) -> &Box<Path> {
|
||||
pub fn get_test_base(&self) -> &Box<Path> {
|
||||
&self.test_base
|
||||
}
|
||||
|
||||
pub fn addTest(&mut self, must_pass_count: u32, try_harder_count: u32, rotation: f32) {
|
||||
self.addTestComplex(must_pass_count, try_harder_count, 0, 0, rotation);
|
||||
pub fn add_test(&mut self, must_pass_count: u32, try_harder_count: u32, rotation: f32) {
|
||||
self.add_test_complex(must_pass_count, try_harder_count, 0, 0, rotation);
|
||||
}
|
||||
|
||||
pub fn addHint(&mut self, hint: DecodeHintType, value: DecodeHintValue) {
|
||||
pub fn add_hint(&mut self, hint: DecodeHintType, value: DecodeHintValue) {
|
||||
self.hints.insert(hint, value);
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ impl<T:Reader> AbstractBlackBoxTestCase<T> {
|
||||
* reading the wrong contents using the try harder flag
|
||||
* @param rotation The rotation in degrees clockwise to use for this test.
|
||||
*/
|
||||
pub fn addTestComplex(
|
||||
pub fn add_test_complex(
|
||||
&mut self,
|
||||
must_pass_count: u32,
|
||||
try_harder_count: u32,
|
||||
@@ -106,14 +106,14 @@ impl<T:Reader> AbstractBlackBoxTestCase<T> {
|
||||
));
|
||||
}
|
||||
|
||||
pub fn getImageFiles(&self) -> Vec<PathBuf> {
|
||||
pub fn get_image_files(&self) -> Vec<PathBuf> {
|
||||
assert!(
|
||||
self.test_base.exists(),
|
||||
"Please download and install test images, and run from the 'core' directory"
|
||||
);
|
||||
// let paths = Vec::new();
|
||||
let path_search = read_dir(&self.test_base);
|
||||
const possible_extensions: &str = "jpg,jpeg,gif,png,JPG,JPEG,GIF,PNG";
|
||||
const POSSIBLE_EXTENSIONS: &str = "jpg,jpeg,gif,png,JPG,JPEG,GIF,PNG";
|
||||
|
||||
let mut paths = path_search
|
||||
.unwrap()
|
||||
@@ -121,7 +121,7 @@ impl<T:Reader> AbstractBlackBoxTestCase<T> {
|
||||
.filter(|r| r.is_ok()) // Get rid of Err variants for Result<DirEntry>
|
||||
.map(|r| r.unwrap().path()) // This is safe, since we only have the Ok variants
|
||||
.filter(|r| r.is_file()) // Filter out non-folders
|
||||
.filter(|r| possible_extensions.contains(r.extension().unwrap().to_str().unwrap()))
|
||||
.filter(|r| POSSIBLE_EXTENSIONS.contains(r.extension().unwrap().to_str().unwrap()))
|
||||
// .map(|r| r.into_boxed_path())
|
||||
.collect::<Vec<PathBuf>>();
|
||||
|
||||
@@ -130,14 +130,14 @@ impl<T:Reader> AbstractBlackBoxTestCase<T> {
|
||||
paths
|
||||
}
|
||||
|
||||
pub fn getReader(&self) -> &T {
|
||||
pub fn get_reader(&self) -> &T {
|
||||
&self.barcode_reader
|
||||
}
|
||||
|
||||
pub fn testBlackBox(&self) {
|
||||
pub fn test_black_box(&self) {
|
||||
assert!(!self.test_rxing_results.is_empty());
|
||||
|
||||
let image_files = self.getImageFiles();
|
||||
let image_files = self.get_image_files();
|
||||
let test_count = self.test_rxing_results.len();
|
||||
|
||||
let mut passed_counts = vec![0usize; test_count];
|
||||
@@ -145,16 +145,16 @@ impl<T:Reader> AbstractBlackBoxTestCase<T> {
|
||||
let mut try_harder_counts = vec![0usize; test_count];
|
||||
let mut try_harder_misread_counts = vec![0usize; test_count];
|
||||
|
||||
for testImage in &image_files {
|
||||
for test_image in &image_files {
|
||||
// for (Path testImage : imageFiles) {
|
||||
log::info(format!("Starting {}", testImage.to_string_lossy()));
|
||||
log::info(format!("Starting {}", test_image.to_string_lossy()));
|
||||
|
||||
let image = image::open(testImage).unwrap(); //ImageIO.read(testImage.toFile());
|
||||
let image = image::open(test_image).unwrap(); //ImageIO.read(testImage.toFile());
|
||||
|
||||
//let testImageFileName = testImage.getFileName().toString();
|
||||
let file_base_name = testImage.file_stem().unwrap();
|
||||
let file_base_name = test_image.file_stem().unwrap();
|
||||
//let expectedTextFile = self.testBase.resolve(fileBaseName + ".txt");
|
||||
let mut expected_text_file = testImage.clone();
|
||||
let mut expected_text_file = test_image.clone();
|
||||
expected_text_file.set_extension("txt");
|
||||
let expected_text = if expected_text_file.exists() {
|
||||
Self::read_file_as_string(expected_text_file)
|
||||
@@ -171,7 +171,7 @@ impl<T:Reader> AbstractBlackBoxTestCase<T> {
|
||||
let mut expected_metadata_file: PathBuf = self.test_base.clone().to_path_buf();
|
||||
expected_metadata_file.push(format!("{}.metadata", file_base_name.to_str().unwrap()));
|
||||
expected_metadata_file.set_extension("txt");
|
||||
let expectedMetadata_unfinished = if expected_metadata_file.exists() {
|
||||
let expected_metadata_unfinished = if expected_metadata_file.exists() {
|
||||
java_properties::read(
|
||||
std::fs::File::open(expected_metadata_file)
|
||||
.expect("file exists, we already know that"),
|
||||
@@ -184,7 +184,7 @@ impl<T:Reader> AbstractBlackBoxTestCase<T> {
|
||||
HashMap::new()
|
||||
};
|
||||
let expected_metadata = HashMap::new();
|
||||
for (k, v) in expectedMetadata_unfinished {
|
||||
for (k, v) in expected_metadata_unfinished {
|
||||
let new_k = RXingResultMetadataType::from(k);
|
||||
let _new_v = match new_k {
|
||||
RXingResultMetadataType::OTHER => RXingResultMetadataValue::OTHER(v),
|
||||
@@ -230,7 +230,7 @@ impl<T:Reader> AbstractBlackBoxTestCase<T> {
|
||||
|
||||
for x in 0..test_count {
|
||||
// for (int x = 0; x < testCount; x++) {
|
||||
let rotation = self.test_rxing_results.get(x).unwrap().getRotation();
|
||||
let rotation = self.test_rxing_results.get(x).unwrap().get_rotation();
|
||||
let rotated_image = Self::rotate_image(&image, rotation);
|
||||
let source = BufferedImageLuminanceSource::new(rotated_image);
|
||||
let bitmap = BinaryBitmap::new(Box::new(HybridBinarizer::new(Box::new(source))));
|
||||
@@ -296,13 +296,13 @@ impl<T:Reader> AbstractBlackBoxTestCase<T> {
|
||||
let test_rxing_result = self.test_rxing_results.get(x).unwrap();
|
||||
log::info(format!(
|
||||
"Rotation {} degrees:",
|
||||
test_rxing_result.getRotation()
|
||||
test_rxing_result.get_rotation()
|
||||
));
|
||||
log::info(format!(
|
||||
" {} of {} images passed ({} required)",
|
||||
passed_counts[x],
|
||||
image_files.len(),
|
||||
test_rxing_result.getMustPassCount()
|
||||
test_rxing_result.get_must_pass_count()
|
||||
));
|
||||
let mut failed = image_files.len() - passed_counts[x];
|
||||
log::info(format!(
|
||||
@@ -314,7 +314,7 @@ impl<T:Reader> AbstractBlackBoxTestCase<T> {
|
||||
" {} of {} images passed with try harder ({} required)",
|
||||
try_harder_counts[x],
|
||||
image_files.len(),
|
||||
test_rxing_result.getTryHarderCount()
|
||||
test_rxing_result.get_try_harder_count()
|
||||
));
|
||||
failed = image_files.len() - try_harder_counts[x];
|
||||
log::info(format!(
|
||||
@@ -324,18 +324,18 @@ impl<T:Reader> AbstractBlackBoxTestCase<T> {
|
||||
));
|
||||
total_found += passed_counts[x] + try_harder_counts[x];
|
||||
total_must_pass +=
|
||||
test_rxing_result.getMustPassCount() + test_rxing_result.getTryHarderCount();
|
||||
test_rxing_result.get_must_pass_count() + test_rxing_result.get_try_harder_count();
|
||||
total_misread += misread_counts[x] + try_harder_misread_counts[x];
|
||||
total_max_misread +=
|
||||
test_rxing_result.getMaxMisreads() + test_rxing_result.getMaxTryHarderMisreads();
|
||||
test_rxing_result.get_max_misreads() + test_rxing_result.get_max_try_harder_misreads();
|
||||
}
|
||||
|
||||
let totalTests = image_files.len() * test_count * 2;
|
||||
let total_tests = image_files.len() * test_count * 2;
|
||||
log::info(format!(
|
||||
"Decoded {} images out of {} ({}, {} required)",
|
||||
total_found,
|
||||
totalTests,
|
||||
total_found * 100 / totalTests,
|
||||
total_tests,
|
||||
total_found * 100 / total_tests,
|
||||
total_must_pass
|
||||
));
|
||||
if total_found > total_must_pass as usize {
|
||||
@@ -365,32 +365,32 @@ impl<T:Reader> AbstractBlackBoxTestCase<T> {
|
||||
// Then run through again and assert if any failed
|
||||
for x in 0..test_count {
|
||||
// for (int x = 0; x < testCount; x++) {
|
||||
let testRXingResult = self.test_rxing_results.get(x).unwrap();
|
||||
let test_rxing_result = self.test_rxing_results.get(x).unwrap();
|
||||
let label = format!(
|
||||
"Rotation {} degrees: Too many images failed",
|
||||
testRXingResult.getRotation()
|
||||
test_rxing_result.get_rotation()
|
||||
);
|
||||
assert!(
|
||||
passed_counts[x] >= testRXingResult.getMustPassCount() as usize,
|
||||
passed_counts[x] >= test_rxing_result.get_must_pass_count() as usize,
|
||||
"{}",
|
||||
label
|
||||
);
|
||||
assert!(
|
||||
try_harder_counts[x] >= testRXingResult.getTryHarderCount() as usize,
|
||||
try_harder_counts[x] >= test_rxing_result.get_try_harder_count() as usize,
|
||||
"Try harder, {}",
|
||||
label,
|
||||
);
|
||||
let label = format!(
|
||||
"Rotation {} degrees: Too many images misread",
|
||||
testRXingResult.getRotation()
|
||||
test_rxing_result.get_rotation()
|
||||
);
|
||||
assert!(
|
||||
misread_counts[x] <= testRXingResult.getMaxMisreads() as usize,
|
||||
misread_counts[x] <= test_rxing_result.get_max_misreads() as usize,
|
||||
"{}",
|
||||
label
|
||||
);
|
||||
assert!(
|
||||
try_harder_misread_counts[x] <= testRXingResult.getMaxTryHarderMisreads() as usize,
|
||||
try_harder_misread_counts[x] <= test_rxing_result.get_max_try_harder_misreads() as usize,
|
||||
"Try harder, {}",
|
||||
label
|
||||
);
|
||||
@@ -419,13 +419,13 @@ impl<T:Reader> AbstractBlackBoxTestCase<T> {
|
||||
|
||||
// Try in 'pure' mode mostly to exercise PURE_BARCODE code paths for exceptions;
|
||||
// not expected to pass, generally
|
||||
let mut result = None;
|
||||
// let mut result = None;
|
||||
let mut pure_hints = HashMap::new();
|
||||
pure_hints.insert(
|
||||
DecodeHintType::PURE_BARCODE,
|
||||
DecodeHintValue::PureBarcode(true),
|
||||
);
|
||||
result = if let Ok(res) = self.barcode_reader.decode_with_hints(source, &pure_hints) {
|
||||
let mut result = if let Ok(res) = self.barcode_reader.decode_with_hints(source, &pure_hints) {
|
||||
Some(res)
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
mod TestResult;
|
||||
mod test_result;
|
||||
mod abstract_black_box_test_case;
|
||||
|
||||
pub use TestResult::*;
|
||||
pub use test_result::*;
|
||||
pub use abstract_black_box_test_case::*;
|
||||
@@ -42,23 +42,23 @@ impl TestRXingResult {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getMustPassCount(&self) -> u32 {
|
||||
pub fn get_must_pass_count(&self) -> u32 {
|
||||
self.must_pass_count
|
||||
}
|
||||
|
||||
pub fn getTryHarderCount(&self) -> u32 {
|
||||
pub fn get_try_harder_count(&self) -> u32 {
|
||||
self.try_harder_count
|
||||
}
|
||||
|
||||
pub fn getMaxMisreads(&self) -> u32 {
|
||||
pub fn get_max_misreads(&self) -> u32 {
|
||||
self.max_misreads
|
||||
}
|
||||
|
||||
pub fn getMaxTryHarderMisreads(&self) -> u32 {
|
||||
pub fn get_max_try_harder_misreads(&self) -> u32 {
|
||||
self.max_try_harder_misreads
|
||||
}
|
||||
|
||||
pub fn getRotation(&self) -> f32 {
|
||||
pub fn get_rotation(&self) -> f32 {
|
||||
self.rotation
|
||||
}
|
||||
}
|
||||
@@ -29,9 +29,9 @@ fn maxicode1_test_case() {
|
||||
BarcodeFormat::MAXICODE,
|
||||
);
|
||||
// super("src/test/resources/blackbox/maxicode-1", new MultiFormatReader(), BarcodeFormat.MAXICODE);
|
||||
tester.addTest(6, 6, 0.0);
|
||||
tester.add_test(6, 6, 0.0);
|
||||
|
||||
tester.testBlackBox();
|
||||
tester.test_black_box();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,12 +48,12 @@ fn maxi_code_black_box1_test_case() {
|
||||
BarcodeFormat::MAXICODE,
|
||||
);
|
||||
// super("src/test/resources/blackbox/maxicode-1", new MultiFormatReader(), BarcodeFormat.MAXICODE);
|
||||
tester.addHint(
|
||||
tester.add_hint(
|
||||
DecodeHintType::PURE_BARCODE,
|
||||
rxing::DecodeHintValue::PureBarcode(true),
|
||||
);
|
||||
|
||||
tester.addTest(1, 1, 0.0);
|
||||
tester.add_test(1, 1, 0.0);
|
||||
|
||||
tester.testBlackBox();
|
||||
tester.test_black_box();
|
||||
}
|
||||
|
||||
@@ -30,12 +30,12 @@ fn qrcode_black_box1_test_case() {
|
||||
rxing::BarcodeFormat::QR_CODE,
|
||||
);
|
||||
// super("src/test/resources/blackbox/qrcode-1", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
||||
tester.addTest(17, 17, 0.0);
|
||||
tester.addTest(14, 14, 90.0);
|
||||
tester.addTest(17, 17, 180.0);
|
||||
tester.addTest(14, 14, 270.0);
|
||||
tester.add_test(17, 17, 0.0);
|
||||
tester.add_test(14, 14, 90.0);
|
||||
tester.add_test(17, 17, 180.0);
|
||||
tester.add_test(14, 14, 270.0);
|
||||
|
||||
tester.testBlackBox();
|
||||
tester.test_black_box();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,12 +49,12 @@ fn qrcode_black_box2_test_case() {
|
||||
QRCodeReader {},
|
||||
BarcodeFormat::QR_CODE,
|
||||
);
|
||||
tester.addTest(31, 31, 0.0);
|
||||
tester.addTest(30, 30, 90.0);
|
||||
tester.addTest(30, 30, 180.0);
|
||||
tester.addTest(30, 30, 270.0);
|
||||
tester.add_test(31, 31, 0.0);
|
||||
tester.add_test(30, 30, 90.0);
|
||||
tester.add_test(30, 30, 180.0);
|
||||
tester.add_test(30, 30, 270.0);
|
||||
|
||||
tester.testBlackBox();
|
||||
tester.test_black_box();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,12 +68,12 @@ fn qrcode_black_box3_test_case() {
|
||||
QRCodeReader {},
|
||||
BarcodeFormat::QR_CODE,
|
||||
);
|
||||
tester.addTest(38, 38, 0.0);
|
||||
tester.addTest(39, 39, 90.0);
|
||||
tester.addTest(36, 36, 180.0);
|
||||
tester.addTest(39, 39, 270.0);
|
||||
tester.add_test(38, 38, 0.0);
|
||||
tester.add_test(39, 39, 90.0);
|
||||
tester.add_test(36, 36, 180.0);
|
||||
tester.add_test(39, 39, 270.0);
|
||||
|
||||
tester.testBlackBox();
|
||||
tester.test_black_box();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,12 +89,12 @@ fn qrcode_black_box4_test_case() {
|
||||
QRCodeReader {},
|
||||
BarcodeFormat::QR_CODE,
|
||||
);
|
||||
tester.addTest(36, 36, 0.0);
|
||||
tester.addTest(35, 35, 90.0);
|
||||
tester.addTest(35, 35, 180.0);
|
||||
tester.addTest(35, 35, 270.0);
|
||||
tester.add_test(36, 36, 0.0);
|
||||
tester.add_test(35, 35, 90.0);
|
||||
tester.add_test(35, 35, 180.0);
|
||||
tester.add_test(35, 35, 270.0);
|
||||
|
||||
tester.testBlackBox();
|
||||
tester.test_black_box();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,12 +112,12 @@ fn qrcode_black_box5_test_case() {
|
||||
QRCodeReader {},
|
||||
BarcodeFormat::QR_CODE,
|
||||
);
|
||||
tester.addTest(19, 19, 0.0);
|
||||
tester.addTest(19, 19, 90.0);
|
||||
tester.addTest(19, 19, 180.0);
|
||||
tester.addTest(19, 19, 270.0);
|
||||
tester.add_test(19, 19, 0.0);
|
||||
tester.add_test(19, 19, 90.0);
|
||||
tester.add_test(19, 19, 180.0);
|
||||
tester.add_test(19, 19, 270.0);
|
||||
|
||||
tester.testBlackBox();
|
||||
tester.test_black_box();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,10 +132,10 @@ fn qrcode_black_box6_test_case() {
|
||||
QRCodeReader {},
|
||||
BarcodeFormat::QR_CODE,
|
||||
);
|
||||
tester.addTest(15, 15, 0.0);
|
||||
tester.addTest(14, 14, 90.0);
|
||||
tester.addTest(13, 13, 180.0);
|
||||
tester.addTest(14, 14, 270.0);
|
||||
tester.add_test(15, 15, 0.0);
|
||||
tester.add_test(14, 14, 90.0);
|
||||
tester.add_test(13, 13, 180.0);
|
||||
tester.add_test(14, 14, 270.0);
|
||||
|
||||
tester.testBlackBox();
|
||||
tester.test_black_box();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user