pdf_417_reader port

This commit is contained in:
Henry Schimke
2022-12-26 12:22:28 -06:00
parent 9d215d9f99
commit 0061fdd900
6 changed files with 210 additions and 141 deletions

View File

@@ -1,139 +0,0 @@
/*
* 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.pdf417;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.DecodeHintType;
import com.google.zxing.FormatException;
import com.google.zxing.NotFoundException;
import com.google.zxing.Reader;
import com.google.zxing.RXingResult;
import com.google.zxing.RXingResultMetadataType;
import com.google.zxing.RXingResultPoint;
import com.google.zxing.common.DecoderRXingResult;
import com.google.zxing.multi.MultipleBarcodeReader;
import com.google.zxing.pdf417.decoder.PDF417ScanningDecoder;
import com.google.zxing.pdf417.detector.Detector;
import com.google.zxing.pdf417.detector.PDF417DetectorRXingResult;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* This implementation can detect and decode PDF417 codes in an image.
*
* @author Guenther Grau
*/
public final class PDF417Reader implements Reader, MultipleBarcodeReader {
private static final RXingResult[] EMPTY_RESULT_ARRAY = new RXingResult[0];
/**
* Locates and decodes a PDF417 code in an image.
*
* @return a String representing the content encoded by the PDF417 code
* @throws NotFoundException if a PDF417 code cannot be found,
* @throws FormatException if a PDF417 cannot be decoded
*/
@Override
public RXingResult decode(BinaryBitmap image) throws NotFoundException, FormatException, ChecksumException {
return decode(image, null);
}
@Override
public RXingResult decode(BinaryBitmap image, Map<DecodeHintType,?> hints) throws NotFoundException, FormatException,
ChecksumException {
RXingResult[] result = decode(image, hints, false);
if (result.length == 0 || result[0] == null) {
throw NotFoundException.getNotFoundInstance();
}
return result[0];
}
@Override
public RXingResult[] decodeMultiple(BinaryBitmap image) throws NotFoundException {
return decodeMultiple(image, null);
}
@Override
public RXingResult[] decodeMultiple(BinaryBitmap image, Map<DecodeHintType,?> hints) throws NotFoundException {
try {
return decode(image, hints, true);
} catch (FormatException | ChecksumException ignored) {
throw NotFoundException.getNotFoundInstance();
}
}
private static RXingResult[] decode(BinaryBitmap image, Map<DecodeHintType, ?> hints, boolean multiple)
throws NotFoundException, FormatException, ChecksumException {
List<RXingResult> results = new ArrayList<>();
PDF417DetectorRXingResult detectorRXingResult = Detector.detect(image, hints, multiple);
for (RXingResultPoint[] points : detectorRXingResult.getPoints()) {
DecoderRXingResult decoderRXingResult = PDF417ScanningDecoder.decode(detectorRXingResult.getBits(), points[4], points[5],
points[6], points[7], getMinCodewordWidth(points), getMaxCodewordWidth(points));
RXingResult result = new RXingResult(decoderRXingResult.getText(), decoderRXingResult.getRawBytes(), points, BarcodeFormat.PDF_417);
result.putMetadata(RXingResultMetadataType.ERROR_CORRECTION_LEVEL, decoderRXingResult.getECLevel());
PDF417RXingResultMetadata pdf417RXingResultMetadata = (PDF417RXingResultMetadata) decoderRXingResult.getOther();
if (pdf417RXingResultMetadata != null) {
result.putMetadata(RXingResultMetadataType.PDF417_EXTRA_METADATA, pdf417RXingResultMetadata);
}
result.putMetadata(RXingResultMetadataType.ORIENTATION, detectorRXingResult.getRotation());
result.putMetadata(RXingResultMetadataType.SYMBOLOGY_IDENTIFIER, "]L" + decoderRXingResult.getSymbologyModifier());
results.add(result);
}
return results.toArray(EMPTY_RESULT_ARRAY);
}
private static int getMaxWidth(RXingResultPoint p1, RXingResultPoint p2) {
if (p1 == null || p2 == null) {
return 0;
}
return (int) Math.abs(p1.getX() - p2.getX());
}
private static int getMinWidth(RXingResultPoint p1, RXingResultPoint p2) {
if (p1 == null || p2 == null) {
return Integer.MAX_VALUE;
}
return (int) Math.abs(p1.getX() - p2.getX());
}
private static int getMaxCodewordWidth(RXingResultPoint[] p) {
return Math.max(
Math.max(getMaxWidth(p[0], p[4]), getMaxWidth(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD /
PDF417Common.MODULES_IN_STOP_PATTERN),
Math.max(getMaxWidth(p[1], p[5]), getMaxWidth(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD /
PDF417Common.MODULES_IN_STOP_PATTERN));
}
private static int getMinCodewordWidth(RXingResultPoint[] p) {
return Math.min(
Math.min(getMinWidth(p[0], p[4]), getMinWidth(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD /
PDF417Common.MODULES_IN_STOP_PATTERN),
Math.min(getMinWidth(p[1], p[5]), getMinWidth(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD /
PDF417Common.MODULES_IN_STOP_PATTERN));
}
@Override
public void reset() {
// nothing needs to be reset
}
}

View File

@@ -114,7 +114,7 @@ fn applyRotation(matrix: &BitMatrix, rotation: u32) -> BitMatrix {
* @param bitMatrix bit matrix to detect barcodes in
* @return List of RXingResultPoint arrays containing the coordinates of found barcodes
*/
fn detect(multiple: bool, bitMatrix: &BitMatrix) -> Vec<[Option<RXingResultPoint>; 8]> {
pub fn detect(multiple: bool, bitMatrix: &BitMatrix) -> Vec<[Option<RXingResultPoint>; 8]> {
let mut barcodeCoordinates: Vec<[Option<RXingResultPoint>; 8]> = Vec::new();
let mut row = 0;
let mut column = 0;

View File

@@ -6,3 +6,6 @@ pub mod pdf_417_common;
mod pdf_417_result_metadata;
pub use pdf_417_result_metadata::*;
mod pdf_417_reader;
pub use pdf_417_reader::*;

View File

@@ -0,0 +1,200 @@
/*
* 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.
*/
use std::collections::HashMap;
use crate::{
multi::MultipleBarcodeReader, BarcodeFormat, BinaryBitmap, DecodingHintDictionary, Exceptions,
RXingResult, RXingResultMetadataType, RXingResultMetadataValue, RXingResultPoint, Reader,
ResultPoint,
};
use super::{
decoder::pdf_417_scanning_decoder, detector::detector, pdf_417_common,
PDF417RXingResultMetadata,
};
/**
* This implementation can detect and decode PDF417 codes in an image.
*
* @author Guenther Grau
*/
pub struct PDF417Reader;
impl Reader for PDF417Reader {
/**
* Locates and decodes a PDF417 code in an image.
*
* @return a String representing the content encoded by the PDF417 code
* @throws NotFoundException if a PDF417 code cannot be found,
* @throws FormatException if a PDF417 cannot be decoded
*/
fn decode(
&mut self,
image: &crate::BinaryBitmap,
) -> Result<crate::RXingResult, crate::Exceptions> {
self.decode_with_hints(image, &HashMap::new())
}
fn decode_with_hints(
&mut self,
image: &crate::BinaryBitmap,
hints: &crate::DecodingHintDictionary,
) -> Result<crate::RXingResult, crate::Exceptions> {
let result = Self::decode(image, hints, false)?;
if result.is_empty() {
// if (result.length == 0 || result[0] == null) {
return Err(Exceptions::NotFoundException("".to_owned()));
}
Ok(result[0].clone())
}
}
impl MultipleBarcodeReader for PDF417Reader {
fn decodeMultiple(
&mut self,
image: &crate::BinaryBitmap,
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
self.decodeMultipleWithHints(image, &HashMap::new())
}
fn decodeMultipleWithHints(
&mut self,
image: &crate::BinaryBitmap,
hints: &crate::DecodingHintDictionary,
) -> Result<Vec<crate::RXingResult>, crate::Exceptions> {
//try {
Self::decode(image, hints, true)
//} catch (FormatException | ChecksumException ignored) {
// throw NotFoundException.getNotFoundInstance();
//}
}
}
impl PDF417Reader {
fn decode(
image: &BinaryBitmap,
hints: &DecodingHintDictionary,
multiple: bool,
) -> Result<Vec<RXingResult>, Exceptions> {
let mut results = Vec::new(); //new ArrayList<>();
let detectorRXingResult = detector::detect_with_hints(image, hints, multiple)?;
for points in detectorRXingResult.getPoints() {
let points_filtered = points.iter().filter_map(|e| e.clone()).collect();
// for (RXingResultPoint[] points : detectorRXingResult.getPoints()) {
let decoderRXingResult = pdf_417_scanning_decoder::decode(
detectorRXingResult.getBits(),
points[4],
points[5],
points[6],
points[7],
Self::getMinCodewordWidth(points),
Self::getMaxCodewordWidth(points),
)?;
let mut result = RXingResult::new(
decoderRXingResult.getText().clone(),
decoderRXingResult.getRawBytes().clone(),
points_filtered,
BarcodeFormat::PDF_417,
);
result.putMetadata(
RXingResultMetadataType::ERROR_CORRECTION_LEVEL,
RXingResultMetadataValue::ErrorCorrectionLevel(
decoderRXingResult.getECLevel().to_owned(),
),
);
if let Some(pdf417RXingResultMetadata) = decoderRXingResult.getOther() {
if pdf417RXingResultMetadata.is::<PDF417RXingResultMetadata>() {
let data = RXingResultMetadataValue::Pdf417ExtraMetadata(
pdf417RXingResultMetadata
.clone()
.downcast::<PDF417RXingResultMetadata>()
.unwrap(),
);
result.putMetadata(RXingResultMetadataType::PDF417_EXTRA_METADATA, data);
}
}
// PDF417RXingResultMetadata pdf417RXingResultMetadata = (PDF417RXingResultMetadata) decoderRXingResult.getOther();
// if (pdf417RXingResultMetadata != null) {
// result.putMetadata(RXingResultMetadataType.PDF417_EXTRA_METADATA, pdf417RXingResultMetadata);
// }
result.putMetadata(
RXingResultMetadataType::ORIENTATION,
RXingResultMetadataValue::Orientation(detectorRXingResult.getRotation() as i32),
);
result.putMetadata(
RXingResultMetadataType::SYMBOLOGY_IDENTIFIER,
RXingResultMetadataValue::SymbologyIdentifier(format!(
"]L{}",
decoderRXingResult.getSymbologyModifier()
)),
);
results.push(result);
}
Ok(results)
}
fn getMaxWidth(p1: &Option<RXingResultPoint>, p2: &Option<RXingResultPoint>) -> u32 {
if let (Some(p1), Some(p2)) = (p1, p2) {
(p1.getX() - p2.getX()).abs() as u32
} else {
0
}
// if p1 == null || p2 == null {
// return 0;
// }
// return (int) Math.abs(p1.getX() - p2.getX());
}
fn getMinWidth(p1: &Option<RXingResultPoint>, p2: &Option<RXingResultPoint>) -> u32 {
if let (Some(p1), Some(p2)) = (p1, p2) {
(p1.getX() - p2.getX()).abs() as u32
} else {
u32::MAX
}
// if (p1 == null || p2 == null) {
// return Integer.MAX_VALUE;
// }
// return (int) Math.abs(p1.getX() - p2.getX());
}
fn getMaxCodewordWidth(p: &[Option<RXingResultPoint>]) -> u32 {
Self::getMaxWidth(&p[0], &p[4])
.max(
Self::getMaxWidth(&p[6], &p[2]) * pdf_417_common::MODULES_IN_CODEWORD
/ pdf_417_common::MODULES_IN_STOP_PATTERN,
)
.max(Self::getMaxWidth(&p[1], &p[5]).max(
Self::getMaxWidth(&p[7], &p[3]) * pdf_417_common::MODULES_IN_CODEWORD
/ pdf_417_common::MODULES_IN_STOP_PATTERN,
))
}
fn getMinCodewordWidth(p: &[Option<RXingResultPoint>]) -> u32 {
Self::getMinWidth(&p[0], &p[4])
.min(
Self::getMinWidth(&p[6], &p[2]) * pdf_417_common::MODULES_IN_CODEWORD
/ pdf_417_common::MODULES_IN_STOP_PATTERN,
)
.min(Self::getMinWidth(&p[1], &p[5]).min(
Self::getMinWidth(&p[7], &p[3]) * pdf_417_common::MODULES_IN_CODEWORD
/ pdf_417_common::MODULES_IN_STOP_PATTERN,
))
}
}

View File

@@ -17,6 +17,7 @@
/**
* @author Guenther Grau
*/
#[derive(Debug, PartialEq, Eq)]
pub struct PDF417RXingResultMetadata {
segmentIndex: usize,
fileId: String,

View File

@@ -16,6 +16,10 @@
//package com.google.zxing;
use std::{any::Any, rc::Rc};
use crate::pdf417::PDF417RXingResultMetadata;
/**
* Represents some type of metadata about the result of the decoding that the decoder
* wishes to communicate back to the caller.
@@ -180,7 +184,7 @@ pub enum RXingResultMetadataValue {
/**
* PDF417-specific metadata
*/
Pdf417ExtraMetadata(String),
Pdf417ExtraMetadata(Rc<PDF417RXingResultMetadata>),
/**
* If the code format supports structured append and the current scanned code is part of one then the