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:
r-zakarya
2026-09-17 18:38:41 +01:00
parent 780eecc11b
commit dd9fd62dcb
81 changed files with 22141 additions and 19 deletions
+185
View File
@@ -0,0 +1,185 @@
unit ZXing.ScanManager;
interface
uses
System.SysUtils,
System.Generics.Collections,
{$IFDEF FRAMEWORK_FMX}
FMX.Graphics,
{$ENDIF}
{$IFDEF FRAMEWORK_VCL}
VCL.Graphics,
{$ENDIF}
ZXing.LuminanceSource,
ZXing.RGBLuminanceSource,
ZXing.InvertedLuminanceSource,
ZXing.HybridBinarizer,
ZXing.BinaryBitmap,
ZXing.MultiFormatReader,
ZXing.BarcodeFormat,
ZXing.ResultPoint,
ZXing.ReadResult,
ZXing.DecodeHintType;
type
TScanManager = class
private
FEnableInversion: Boolean;
FHints: TDictionary<TDecodeHintType, TObject>;
FResultPointEvent: TResultPointCallback;
FMultiFormatReader: TMultiFormatReader;
listFormats: TList<TBarcodeFormat>;
function GetMultiFormatReader(const format: TBarcodeFormat)
: TMultiFormatReader;
procedure SetResultPointEvent(const AValue: TResultPointCallback);
public
destructor Destroy; override;
function Scan(const pBitmapForScan: TBitmap): TReadResult;
constructor Create(const format: TBarcodeFormat;
Hints: TDictionary<TDecodeHintType, TObject>);
property OnResultPoint: TResultPointCallback read FResultPointEvent
write SetResultPointEvent;
end;
implementation
constructor TScanManager.Create(const format: TBarcodeFormat;
Hints: TDictionary<TDecodeHintType, TObject>);
begin
inherited Create;
FEnableInversion := False;
FHints := Hints;
FMultiFormatReader := GetMultiFormatReader(format);
end;
destructor TScanManager.Destroy;
var
hint: TPair<TDecodeHintType, TObject>;
o: TObject;
begin
if Assigned(FHints) then
begin
for hint in FHints do
begin
o := hint.Value;
if Assigned(o) then
o.Free;
end;
FHints.Clear();
FreeAndNil(FHints);
end;
FreeAndNil(FMultiFormatReader);
inherited;
end;
procedure TScanManager.SetResultPointEvent(const AValue: TResultPointCallback);
var
ahKey: TDecodeHintType;
ahValue: TObject;
begin
FResultPointEvent := AValue;
ahKey := TDecodeHintType.NEED_RESULT_POINT_CALLBACK;
if Assigned(FResultPointEvent) then
begin
ahValue := TResultPointEventObject.Create(FResultPointEvent);
FHints.AddOrSetValue(ahKey, ahValue);
end
else
begin
if Fhints.TryGetValue(ahKey, ahValue) then
begin
ahValue.Free;
ahValue := nil;
FHints.Remove(ahKey);
end;
end;
end;
function TScanManager.GetMultiFormatReader(const format: TBarcodeFormat)
: TMultiFormatReader;
var
o: TObject;
begin
Result := TMultiFormatReader.Create;
listFormats := nil;
if FHints = nil then
FHints := TDictionary<TDecodeHintType, TObject>.Create();
if FHints.ContainsKey(ZXing.DecodeHintType.ENABLE_INVERSION) then
FEnableInversion := true;
if format <> TBarcodeFormat.Auto then
begin
if (FHints.TryGetValue(ZXing.DecodeHintType.POSSIBLE_FORMATS, o)) then
listFormats := o as TList<TBarcodeFormat>
else
begin
listFormats := TList<TBarcodeFormat>.Create();
FHints.Add(ZXing.DecodeHintType.POSSIBLE_FORMATS, listFormats);
end;
if (listFormats.Count = 0) then
listFormats.Add(format)
else
listFormats.Insert(0, format); // favor the format parameter
end;
Result.Hints := FHints;
end;
function TScanManager.Scan(const pBitmapForScan: TBitmap): TReadResult;
var
LuminanceSource, InvLuminanceSource: TLuminanceSource;
HybridBinarizer: THybridBinarizer;
BinaryBitmap: TBinaryBitmap;
begin
InvLuminanceSource := nil;
LuminanceSource := nil;
HybridBinarizer := nil;
BinaryBitmap := nil;
try
LuminanceSource := TRGBLuminanceSource.CreateFromBitmap(pBitmapForScan,
pBitmapForScan.Width, pBitmapForScan.Height);
HybridBinarizer := THybridBinarizer.Create(LuminanceSource);
BinaryBitmap := TBinaryBitmap.Create(HybridBinarizer);
Result := FMultiFormatReader.Decode(BinaryBitmap, true);
if (Result = nil) then
begin
if (FEnableInversion) then
begin
if (BinaryBitmap <> nil) then
FreeAndNil(BinaryBitmap);
if (HybridBinarizer <> nil) then
FreeAndNil(HybridBinarizer);
InvLuminanceSource := LuminanceSource.invert();
HybridBinarizer := THybridBinarizer.Create(InvLuminanceSource);
BinaryBitmap := TBinaryBitmap.Create(HybridBinarizer);
Result := FMultiFormatReader.Decode(BinaryBitmap, true);
end;
end;
finally
BinaryBitmap.Free;
HybridBinarizer.Free;
InvLuminanceSource.Free;
LuminanceSource.Free;
end;
end;
end.