-
-
Notifications
You must be signed in to change notification settings - Fork 564
Feature/multi qr code reader #376
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 8 commits
fc690ea
09c4ea3
9d0fae6
9a7527c
abeafd7
7e7c13f
abcff1a
e0ae737
9f073f9
f2a398d
384c84a
562277e
f5212ac
ebd9756
6efcdca
9e92e55
e3c15b6
e5aac7c
49a0363
07ec4e7
3599b38
7c0beab
fa890ef
9f32092
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,181 @@ | ||
| /* | ||
| * 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. | ||
| */ | ||
|
|
||
| import { int, List } from 'src/customTypings'; | ||
| import BarcodeFormat from '../../BarcodeFormat'; | ||
| import BinaryBitmap from '../../BinaryBitmap'; | ||
| import DecoderResult from '../../common/DecoderResult'; | ||
| import DetectorResult from '../../common/DetectorResult'; | ||
| import DecodeHintType from '../../DecodeHintType'; | ||
| import QRCodeDecoderMetaData from '../../qrcode/decoder/QRCodeDecoderMetaData'; | ||
| import QRCodeReader from '../../qrcode/QRCodeReader'; | ||
| import ReaderException from '../../ReaderException'; | ||
| import Result from '../../Result'; | ||
| import ResultMetadataType from '../../ResultMetadataType'; | ||
| import ResultPoint from '../../ResultPoint'; | ||
| import ByteArrayOutputStream from '../../util/ByteArrayOutputStream'; | ||
| import Collections from '../../util/Collections'; | ||
| import Comparator from '../../util/Comparator'; | ||
| import Integer from '../../util/Integer'; | ||
| import StringBuilder from '../../util/StringBuilder'; | ||
| import MultipleBarcodeReader from '../MultipleBarcodeReader'; | ||
| import MultiDetector from './detector/MultiDetector'; | ||
|
|
||
| // package com.google.zxing.multi.qrcode; | ||
|
|
||
| // import com.google.zxing.BarcodeFormat; | ||
| // import com.google.zxing.BinaryBitmap; | ||
| // import com.google.zxing.DecodeHintType; | ||
| // import com.google.zxing.NotFoundException; | ||
| // import com.google.zxing.ReaderException; | ||
| // import com.google.zxing.Result; | ||
| // import com.google.zxing.ResultMetadataType; | ||
| // import com.google.zxing.ResultPoint; | ||
| // import com.google.zxing.common.DecoderResult; | ||
| // import com.google.zxing.common.DetectorResult; | ||
| // import com.google.zxing.multi.MultipleBarcodeReader; | ||
| // import com.google.zxing.multi.qrcode.detector.MultiDetector; | ||
| // import com.google.zxing.qrcode.QRCodeReader; | ||
| // import com.google.zxing.qrcode.decoder.QRCodeDecoderMetaData; | ||
|
|
||
| // import java.io.ByteArrayOutputStream; | ||
| // import java.io.Serializable; | ||
| // import java.util.ArrayList; | ||
| // import java.util.List; | ||
| // import java.util.Map; | ||
| // import java.util.Collections; | ||
| // import java.util.Comparator; | ||
|
|
||
| /** | ||
| * This implementation can detect and decode multiple QR Codes in an image. | ||
| * | ||
| * @author Sean Owen | ||
| * @author Hannes Erven | ||
| */ | ||
| export default /*public final*/ class QRCodeMultiReader extends QRCodeReader implements MultipleBarcodeReader { | ||
|
|
||
| private static /* final */ EMPTY_RESULT_ARRAY: Result[] = []; | ||
| protected static /* final */ NO_POINTS = new Array<ResultPoint>(); | ||
|
|
||
| /** | ||
| * @throws NotFoundException | ||
| * @override decodeMultiple | ||
| */ | ||
| public decodeMultipleWithoutHints(image: BinaryBitmap): Result[] { | ||
| return this.decodeMultiple(image, null); | ||
| } | ||
|
|
||
| /** | ||
| * @override | ||
| * @throws NotFoundException | ||
| */ | ||
| public decodeMultiple(image: BinaryBitmap, hints: Map<DecodeHintType, any>): Result[] { | ||
| let results: List<Result> = []; | ||
| const detectorResults: DetectorResult[] = new MultiDetector(image.getBlackMatrix()).detectMulti(hints); | ||
| for (const detectorResult of detectorResults) { | ||
| try { | ||
| const decoderResult: DecoderResult = this.getDecoder().decodeBitMatrix(detectorResult.getBits(), hints); | ||
| const points: ResultPoint[] = detectorResult.getPoints(); | ||
| // If the code was mirrored: swap the bottom-left and the top-right points. | ||
| if (decoderResult.getOther() instanceof QRCodeDecoderMetaData) { | ||
| (<QRCodeDecoderMetaData> decoderResult.getOther()).applyMirroredCorrection(points); | ||
| } | ||
| const result: Result = Result.constructor4Args(decoderResult.getText(), decoderResult.getRawBytes(), points, | ||
| BarcodeFormat.QR_CODE); | ||
| const byteSegments: List<Uint8Array> = decoderResult.getByteSegments(); | ||
| if (byteSegments != null) { | ||
| result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); | ||
| } | ||
| const ecLevel: string = decoderResult.getECLevel(); | ||
| if (ecLevel != null) { | ||
| result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); | ||
| } | ||
| if (decoderResult.hasStructuredAppend()) { | ||
| result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE, | ||
| decoderResult.getStructuredAppendSequenceNumber()); | ||
| result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_PARITY, | ||
| decoderResult.getStructuredAppendParity()); | ||
| } | ||
| results.push(result); | ||
| } catch (re) { | ||
| if (re instanceof ReaderException) { | ||
| // ignore and continue | ||
| } else { | ||
| throw re; | ||
| } | ||
| } | ||
| } | ||
| if (results.length === 0) { | ||
| return QRCodeMultiReader.EMPTY_RESULT_ARRAY; | ||
| } else { | ||
| results = QRCodeMultiReader.processStructuredAppend(results); | ||
| return results/* .toArray(QRCodeMultiReader.EMPTY_RESULT_ARRAY) */; | ||
| } | ||
| } | ||
|
|
||
| static processStructuredAppend( results: List<Result>): List<Result> { | ||
| const newResults: List<Result> = []; | ||
| const saResults: List<Result> = []; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need to create multiple There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the tip!! Can you help me with some examples or a PR? |
||
| for (const result of results) { | ||
| if (result.getResultMetadata().has(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE)) { | ||
| saResults.push(result); | ||
| } else { | ||
| newResults.push(result); | ||
| } | ||
| } | ||
| if (saResults.length === 0) { | ||
| return results; | ||
| } | ||
|
|
||
| // sort and concatenate the SA list items | ||
| Collections.sort(saResults, new SAComparator()); | ||
| const newText: StringBuilder = new StringBuilder(); | ||
| const newRawBytes: ByteArrayOutputStream = new ByteArrayOutputStream(); | ||
| const newByteSegment: ByteArrayOutputStream = new ByteArrayOutputStream(); | ||
| for (const saResult of saResults) { | ||
| newText.append(saResult.getText()); | ||
| const saBytes: Uint8Array = saResult.getRawBytes(); | ||
| newRawBytes.writeBytesOffset(saBytes, 0, saBytes.length); | ||
| // @SuppressWarnings("unchecked") | ||
| const byteSegments: Iterable<Uint8Array> = | ||
| <Iterable<Uint8Array>> saResult.getResultMetadata().get(ResultMetadataType.BYTE_SEGMENTS); | ||
| if (byteSegments != null) { | ||
| for (const segment of byteSegments) { | ||
| newByteSegment.writeBytesOffset(segment, 0, segment.length); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| const newResult: Result = Result.constructor4Args(newText.toString(), newRawBytes.toByteArray(), QRCodeMultiReader.NO_POINTS, BarcodeFormat.QR_CODE); | ||
| if (newByteSegment.size() > 0) { | ||
| newResult.putMetadata(ResultMetadataType.BYTE_SEGMENTS, Collections.singletonList(newByteSegment.toByteArray())); | ||
| } | ||
| newResults.push(newResult); // TYPESCRIPTPORT: inserted element at the start of the array because it seems the Java version does that as well. | ||
| return newResults; | ||
| } | ||
|
|
||
| } | ||
|
|
||
| /* private static final*/ class SAComparator implements Comparator<Result>/*, Serializable*/ { | ||
| /** | ||
| * @override | ||
| */ | ||
| public compare(a: Result, b: Result): int { | ||
| const aNumber: int = <int> a.getResultMetadata().get(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE); | ||
| const bNumber: int = <int> b.getResultMetadata().get(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE); | ||
| return Integer.compare(aNumber, bNumber); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| /* | ||
| * 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. | ||
| */ | ||
|
|
||
| import BitMatrix from "src/core/common/BitMatrix"; | ||
| import DetectorResult from "src/core/common/DetectorResult"; | ||
| import DecodeHintType from "src/core/DecodeHintType"; | ||
| import NotFoundException from "src/core/NotFoundException"; | ||
| import Detector from "src/core/qrcode/detector/Detector"; | ||
| import FinderPatternInfo from "src/core/qrcode/detector/FinderPatternInfo"; | ||
| import ReaderException from "src/core/ReaderException"; | ||
| import ResultPointCallback from "src/core/ResultPointCallback"; | ||
| import { List } from "src/customTypings"; | ||
| import MultiFinderPatternFinder from "./MultiFinderPatternFinder"; | ||
|
|
||
| // package com.google.zxing.multi.qrcode.detector; | ||
|
|
||
| // import com.google.zxing.DecodeHintType; | ||
| // import com.google.zxing.NotFoundException; | ||
| // import com.google.zxing.ReaderException; | ||
| // import com.google.zxing.ResultPointCallback; | ||
| // import com.google.zxing.common.BitMatrix; | ||
| // import com.google.zxing.common.DetectorResult; | ||
| // import com.google.zxing.qrcode.detector.Detector; | ||
| // import com.google.zxing.qrcode.detector.FinderPatternInfo; | ||
|
|
||
| // import java.util.ArrayList; | ||
| // import java.util.List; | ||
| // import java.util.Map; | ||
|
|
||
| /** | ||
| * <p>Encapsulates logic that can detect one or more QR Codes in an image, even if the QR Code | ||
| * is rotated or skewed, or partially obscured.</p> | ||
| * | ||
| * @author Sean Owen | ||
| * @author Hannes Erven | ||
| */ | ||
| export default /* public final */ class MultiDetector extends Detector { | ||
|
|
||
| private static /* final */ EMPTY_DETECTOR_RESULTS: DetectorResult[] = []; | ||
|
|
||
| public constructor( image: BitMatrix) { | ||
| super(image); | ||
| } | ||
|
|
||
| /** @throws NotFoundException */ | ||
| public detectMulti( hints: Map<DecodeHintType, any>): DetectorResult[] { | ||
odahcam marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const image: BitMatrix = this.getImage(); | ||
| const resultPointCallback: ResultPointCallback = | ||
| hints == null ? null : <ResultPointCallback> hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK); | ||
| const finder: MultiFinderPatternFinder = new MultiFinderPatternFinder(image, resultPointCallback); | ||
| const infos: FinderPatternInfo[] = finder.findMulti(hints); | ||
|
|
||
| if (infos.length === 0) { | ||
| throw NotFoundException.getNotFoundInstance(); | ||
| } | ||
|
|
||
| const result: List<DetectorResult> = []; | ||
| for (const info of infos) { | ||
| try { | ||
| result.push(this.processFinderPatternInfo(info)); | ||
| } catch (e) { | ||
| if (e instanceof ReaderException) { | ||
| // ignore | ||
| } else { | ||
| throw e; | ||
| } | ||
| } | ||
| } | ||
| if (result.length === 0) { | ||
| return MultiDetector.EMPTY_DETECTOR_RESULTS; | ||
| } else { | ||
| return result/* .toArray(EMPTY_DETECTOR_RESULTS) */; | ||
| } | ||
| } | ||
|
|
||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.