From 0061fdd9004208e5dead656918f35b995ab36264 Mon Sep 17 00:00:00 2001 From: Henry Schimke Date: Mon, 26 Dec 2022 12:22:28 -0600 Subject: [PATCH] pdf_417_reader port --- src/pdf417/PDF417Reader.java | 139 ------------------ src/pdf417/detector/detector.rs | 2 +- src/pdf417/mod.rs | 3 + src/pdf417/pdf_417_reader.rs | 200 ++++++++++++++++++++++++++ src/pdf417/pdf_417_result_metadata.rs | 1 + src/rxing_result_metadata.rs | 6 +- 6 files changed, 210 insertions(+), 141 deletions(-) delete mode 100644 src/pdf417/PDF417Reader.java create mode 100644 src/pdf417/pdf_417_reader.rs diff --git a/src/pdf417/PDF417Reader.java b/src/pdf417/PDF417Reader.java deleted file mode 100644 index 0de9d55..0000000 --- a/src/pdf417/PDF417Reader.java +++ /dev/null @@ -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 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 hints) throws NotFoundException { - try { - return decode(image, hints, true); - } catch (FormatException | ChecksumException ignored) { - throw NotFoundException.getNotFoundInstance(); - } - } - - private static RXingResult[] decode(BinaryBitmap image, Map hints, boolean multiple) - throws NotFoundException, FormatException, ChecksumException { - List 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 - } - -} diff --git a/src/pdf417/detector/detector.rs b/src/pdf417/detector/detector.rs index 87e8e1f..2f7baed 100644 --- a/src/pdf417/detector/detector.rs +++ b/src/pdf417/detector/detector.rs @@ -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; 8]> { +pub fn detect(multiple: bool, bitMatrix: &BitMatrix) -> Vec<[Option; 8]> { let mut barcodeCoordinates: Vec<[Option; 8]> = Vec::new(); let mut row = 0; let mut column = 0; diff --git a/src/pdf417/mod.rs b/src/pdf417/mod.rs index 2b9f2da..836db32 100644 --- a/src/pdf417/mod.rs +++ b/src/pdf417/mod.rs @@ -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::*; diff --git a/src/pdf417/pdf_417_reader.rs b/src/pdf417/pdf_417_reader.rs new file mode 100644 index 0000000..95cdce0 --- /dev/null +++ b/src/pdf417/pdf_417_reader.rs @@ -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 { + self.decode_with_hints(image, &HashMap::new()) + } + + fn decode_with_hints( + &mut self, + image: &crate::BinaryBitmap, + hints: &crate::DecodingHintDictionary, + ) -> Result { + 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, crate::Exceptions> { + self.decodeMultipleWithHints(image, &HashMap::new()) + } + + fn decodeMultipleWithHints( + &mut self, + image: &crate::BinaryBitmap, + hints: &crate::DecodingHintDictionary, + ) -> Result, 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, 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::() { + let data = RXingResultMetadataValue::Pdf417ExtraMetadata( + pdf417RXingResultMetadata + .clone() + .downcast::() + .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, p2: &Option) -> 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, p2: &Option) -> 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]) -> 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]) -> 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, + )) + } +} diff --git a/src/pdf417/pdf_417_result_metadata.rs b/src/pdf417/pdf_417_result_metadata.rs index 183d516..7256eee 100644 --- a/src/pdf417/pdf_417_result_metadata.rs +++ b/src/pdf417/pdf_417_result_metadata.rs @@ -17,6 +17,7 @@ /** * @author Guenther Grau */ +#[derive(Debug, PartialEq, Eq)] pub struct PDF417RXingResultMetadata { segmentIndex: usize, fileId: String, diff --git a/src/rxing_result_metadata.rs b/src/rxing_result_metadata.rs index 5c36a3f..4e02d0b 100644 --- a/src/rxing_result_metadata.rs +++ b/src/rxing_result_metadata.rs @@ -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), /** * If the code format supports structured append and the current scanned code is part of one then the