feat(apk): scanner le QR du poste depuis l'app (ZXing.Delphi, Apache 2.0)
Le scanner du systeme demandait avec quoi ouvrir le lien. L'app ouvre la camera arriere, decode une image sur quatre et remplit URL + jeton des qu'un lien pmserver://sync est lu. Rien n'est enregistre avant Save. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,350 @@
|
||||
{
|
||||
* 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.
|
||||
|
||||
* Original Authors: Sean Owen and dswitkin@google.com (Daniel Switkin)
|
||||
* Ported from ZXING Java Source: www.Redivivus.in (suraj.supekar@redivivus.in)
|
||||
* Delphi Implementation by E. Spelt and K. Gossens
|
||||
}
|
||||
|
||||
unit ZXing.MultiFormatReader;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
System.SysUtils,
|
||||
System.Rtti,
|
||||
System.Generics.Collections,
|
||||
System.RegularExpressions,
|
||||
ZXing.ReadResult,
|
||||
ZXing.Reader,
|
||||
ZXing.DecodeHintType,
|
||||
ZXing.BinaryBitmap,
|
||||
ZXing.BarcodeFormat,
|
||||
ZXing.ResultPoint,
|
||||
|
||||
// 1D Barcodes
|
||||
ZXing.OneD.OneDReader,
|
||||
ZXing.OneD.Code128Reader,
|
||||
ZXing.OneD.Code93Reader,
|
||||
ZXing.OneD.ITFReader,
|
||||
ZXing.OneD.EAN13Reader,
|
||||
ZXing.OneD.EAN8Reader,
|
||||
ZXing.OneD.UPCAReader,
|
||||
ZXing.OneD.UPCEReader,
|
||||
ZXing.OneD.Code39Reader,
|
||||
|
||||
// 2D Codes
|
||||
ZXing.QrCode.QRCodeReader,
|
||||
ZXing.Datamatrix.DataMatrixReader;
|
||||
|
||||
/// <summary>
|
||||
/// MultiFormatReader is a convenience class and the main entry point into the library for most uses.
|
||||
/// By default it attempts to decode all barcode formats that the library supports. Optionally, you
|
||||
/// can provide a hints object to request different behavior, for example only decoding QR codes.
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
/// <author>dswitkin@google.com (Daniel Switkin)</author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source</author>
|
||||
type
|
||||
|
||||
TMultiFormatReader = class(TInterfacedObject, IReader)
|
||||
private
|
||||
|
||||
FHints: TDictionary<TDecodeHintType, TObject>;
|
||||
readers: TList<IReader>;
|
||||
|
||||
function DecodeInternal(image: TBinaryBitmap): TReadResult;
|
||||
procedure Set_Hints(const Value: TDictionary<TDecodeHintType, TObject>);
|
||||
function Get_Hints: TDictionary<TDecodeHintType, TObject>;
|
||||
|
||||
/// <summary> This version of decode honors the intent of Reader.decode(BinaryBitmap) in that it
|
||||
/// passes null as a hint to the decoders. However, that makes it inefficient to call repeatedly.
|
||||
/// Use setHints() followed by decodeWithState() for continuous scan applications.
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="image">The pixel data to decode
|
||||
/// </param>
|
||||
/// <returns> The contents of the image
|
||||
/// </returns>
|
||||
/// <throws> ReaderException Any errors which occurred </throws>
|
||||
public
|
||||
function decode(const image: TBinaryBitmap): TReadResult; overload;
|
||||
function decode(const image: TBinaryBitmap; WithHints: Boolean)
|
||||
: TReadResult; overload;
|
||||
/// <summary> Decode an image using the hints provided. Does not honor existing state.
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="image">The pixel data to decode
|
||||
/// </param>
|
||||
/// <param name="hints">The hints to use, clearing the previous state.
|
||||
/// </param>
|
||||
/// <returns> The contents of the image
|
||||
/// </returns>
|
||||
/// <throws> ReaderException Any errors which occurred </throws>
|
||||
function decode(const image: TBinaryBitmap;
|
||||
hints: TDictionary<TDecodeHintType, TObject>): TReadResult; overload;
|
||||
|
||||
/// <summary> Decode an image using the state set up by calling setHints() previously. Continuous scan
|
||||
/// clients will get a <b>large</b> speed increase by using this instead of decode().
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="image">The pixel data to decode
|
||||
/// </param>
|
||||
/// <returns> The contents of the image
|
||||
/// </returns>
|
||||
/// <throws> ReaderException Any errors which occurred </throws>
|
||||
function DecodeWithState(image: TBinaryBitmap): TReadResult;
|
||||
destructor Destroy; override;
|
||||
|
||||
/// <summary> This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls
|
||||
/// to decodeWithState(image) can reuse the same set of readers without reallocating memory. This
|
||||
/// is important for performance in continuous scan clients.
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="hints">The set of hints to use for subsequent calls to decode(image)
|
||||
/// </param>
|
||||
property hints: TDictionary<TDecodeHintType, TObject> read Get_Hints
|
||||
write Set_Hints;
|
||||
|
||||
procedure Reset;
|
||||
procedure FreeReaders();
|
||||
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function TMultiFormatReader.decode(const image: TBinaryBitmap): TReadResult;
|
||||
begin
|
||||
hints := nil;
|
||||
result := DecodeInternal(image)
|
||||
end;
|
||||
|
||||
function TMultiFormatReader.decode(const image: TBinaryBitmap;
|
||||
WithHints: Boolean): TReadResult;
|
||||
begin
|
||||
result := DecodeInternal(image)
|
||||
end;
|
||||
|
||||
function TMultiFormatReader.decode(const image: TBinaryBitmap;
|
||||
hints: TDictionary<TDecodeHintType, TObject>): TReadResult;
|
||||
begin
|
||||
FHints := hints;
|
||||
result := DecodeInternal(image)
|
||||
end;
|
||||
|
||||
function TMultiFormatReader.DecodeWithState(image: TBinaryBitmap): TReadResult;
|
||||
begin
|
||||
// Make sure to set up the default state so we don't crash
|
||||
if readers = nil then
|
||||
begin
|
||||
hints := nil
|
||||
end;
|
||||
|
||||
result := DecodeInternal(image);
|
||||
|
||||
end;
|
||||
|
||||
destructor TMultiFormatReader.Destroy;
|
||||
begin
|
||||
FreeReaders;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TMultiFormatReader.FreeReaders;
|
||||
begin
|
||||
if readers <> nil then
|
||||
readers.Clear();
|
||||
|
||||
readers.Free;
|
||||
readers := nil;
|
||||
end;
|
||||
|
||||
function TMultiFormatReader.Get_Hints: TDictionary<TDecodeHintType, TObject>;
|
||||
begin
|
||||
result := FHints;
|
||||
end;
|
||||
|
||||
procedure TMultiFormatReader.Set_Hints(const Value: TDictionary<TDecodeHintType,
|
||||
TObject>);
|
||||
var
|
||||
useCode39CheckDigit, useCode39ExtendedMode: Boolean;
|
||||
formats: TList<TBarcodeFormat>;
|
||||
begin
|
||||
FHints := Value;
|
||||
|
||||
// tryHarder := (Value <> nil) and
|
||||
// (Value.ContainsKey(ZXing.DecodeHintType.TRY_HARDER));
|
||||
|
||||
if ((Value = nil) or
|
||||
(not Value.ContainsKey(ZXing.DecodeHintType.POSSIBLE_FORMATS))) then
|
||||
begin
|
||||
formats := nil;
|
||||
end
|
||||
else
|
||||
begin
|
||||
formats := Value[ZXing.DecodeHintType.POSSIBLE_FORMATS]
|
||||
as TList<TBarcodeFormat>
|
||||
end;
|
||||
|
||||
// add readers from the hints
|
||||
readers := TList<IReader>.Create;
|
||||
if formats <> nil then
|
||||
begin
|
||||
|
||||
// 1D readers
|
||||
|
||||
if (formats.Contains(TBarcodeFormat.CODE_128)) then
|
||||
begin
|
||||
readers.Add(TCode128Reader.Create())
|
||||
end;
|
||||
|
||||
if (formats.Contains(TBarcodeFormat.CODE_93)) then
|
||||
begin
|
||||
readers.Add(TCode93Reader.Create())
|
||||
end;
|
||||
|
||||
if (formats.Contains(TBarcodeFormat.ITF)) then
|
||||
begin
|
||||
readers.Add(TITFReader.Create())
|
||||
end;
|
||||
|
||||
// 2D readers
|
||||
if (formats.Contains(TBarcodeFormat.QR_CODE)) then
|
||||
begin
|
||||
readers.Add(TQRCodeReader.Create())
|
||||
end;
|
||||
|
||||
if formats.Contains(TBarcodeFormat.DATA_MATRIX) then
|
||||
readers.Add(TDataMatrixReader.Create);
|
||||
|
||||
if (formats.Contains(TBarcodeFormat.EAN_13)) then
|
||||
readers.Add(TEAN13Reader.Create());
|
||||
|
||||
if (formats.Contains(TBarcodeFormat.EAN_8)) then
|
||||
readers.Add(TEAN8Reader.Create());
|
||||
|
||||
if (formats.Contains(TBarcodeFormat.UPC_A)) then
|
||||
readers.Add(TUPCAReader.Create());
|
||||
|
||||
if (formats.Contains(TBarcodeFormat.UPC_E)) then
|
||||
readers.Add(TUPCEReader.Create());
|
||||
|
||||
if (formats.Contains(TBarcodeFormat.CODE_39)) then
|
||||
begin
|
||||
useCode39CheckDigit := hints.ContainsKey
|
||||
(TDecodeHintType.ASSUME_CODE_39_CHECK_DIGIT) and
|
||||
hints.ContainsKey(TDecodeHintType.ASSUME_CODE_39_CHECK_DIGIT);
|
||||
|
||||
useCode39ExtendedMode := hints.ContainsKey
|
||||
(TDecodeHintType.USE_CODE_39_EXTENDED_MODE) and
|
||||
hints.ContainsKey(TDecodeHintType.USE_CODE_39_EXTENDED_MODE);
|
||||
|
||||
readers.Add(TCode39Reader.Create(useCode39CheckDigit,
|
||||
useCode39ExtendedMode));
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
if (readers.Count = 0) then // must be auto, add them all
|
||||
begin
|
||||
|
||||
// 1D readers
|
||||
readers.Add(TCode128Reader.Create());
|
||||
readers.Add(TUPCAReader.Create());
|
||||
readers.Add(TUPCEReader.Create());
|
||||
readers.Add(TEAN13Reader.Create());
|
||||
readers.Add(TEAN8Reader.Create());
|
||||
readers.Add(TCode93Reader.Create());
|
||||
readers.Add(TITFReader.Create());
|
||||
useCode39CheckDigit := hints.ContainsKey
|
||||
(TDecodeHintType.ASSUME_CODE_39_CHECK_DIGIT) and hints.ContainsKey
|
||||
(TDecodeHintType.ASSUME_CODE_39_CHECK_DIGIT);
|
||||
|
||||
useCode39ExtendedMode := hints.ContainsKey
|
||||
(TDecodeHintType.USE_CODE_39_EXTENDED_MODE) and hints.ContainsKey
|
||||
(TDecodeHintType.USE_CODE_39_EXTENDED_MODE);
|
||||
|
||||
readers.Add(TCode39Reader.Create(useCode39CheckDigit,
|
||||
useCode39ExtendedMode));
|
||||
|
||||
|
||||
// 2D readers
|
||||
readers.Add(TQRCodeReader.Create());
|
||||
readers.Add(TDataMatrixReader.Create)
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TMultiFormatReader.Reset;
|
||||
var
|
||||
Reader: IReader;
|
||||
begin
|
||||
if readers <> nil then
|
||||
begin
|
||||
for Reader in readers do
|
||||
begin
|
||||
Reader.Reset();
|
||||
end
|
||||
end
|
||||
end;
|
||||
|
||||
function TMultiFormatReader.DecodeInternal(image: TBinaryBitmap): TReadResult;
|
||||
var
|
||||
rpCallBack: TResultPointCallback;
|
||||
i: integer;
|
||||
Reader: IReader;
|
||||
begin
|
||||
|
||||
result := nil;
|
||||
if (readers = nil) then
|
||||
begin
|
||||
Exit;
|
||||
end;
|
||||
|
||||
rpCallBack := nil;
|
||||
if ((FHints <> nil) and
|
||||
(FHints.ContainsKey(ZXing.DecodeHintType.NEED_RESULT_POINT_CALLBACK))) then
|
||||
begin
|
||||
// rpCallBack := FHints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]
|
||||
// as TResultPointCallback(nil);
|
||||
end;
|
||||
|
||||
for i := 0 to readers.Count - 1 do
|
||||
begin
|
||||
|
||||
Reader := readers[i];
|
||||
Reader.Reset();
|
||||
result := Reader.decode(image, FHints);
|
||||
if result <> nil then
|
||||
begin
|
||||
|
||||
// found a barcode, pushing the successful reader up front
|
||||
// I assume that the same type of barcode is read multiple times
|
||||
// so the reordering of the readers list should speed up the next reading
|
||||
// a little bit
|
||||
|
||||
readers.Delete(i);
|
||||
readers.Insert(0, Reader);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
// if rpCallBack <> nil then
|
||||
// rpCallBack(nil)
|
||||
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
Reference in New Issue
Block a user