fix(totp): scan QR ecran - indices Byte dans ZXing (boucle infinie a 100 % CPU)
ZXing.Delphi declarait rgbIndex/luminanceIndex en Byte dans les conversions octets bruts -> luminance : au-dela de 255 ils repassaient a 0, la boucle ne finissait jamais. L'APK n'y passait pas (CreateFromBitmap). Mesure apres correctif : 60 ms sur un ecran 1920x1080 avec TRY_HARDER, 86 ms sans QR. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -364,7 +364,7 @@ procedure TRGBLuminanceSource.CalculateLuminanceRGB24(
|
||||
const rgbRawBytes: TArray<Byte>);
|
||||
var
|
||||
rgbIndex,
|
||||
luminanceIndex,
|
||||
luminanceIndex : Integer; // pmserver: etaient Byte -> boucle infinie au-dela de 255 octets
|
||||
r, g, b : Integer;
|
||||
begin
|
||||
rgbIndex := 0;
|
||||
@@ -389,7 +389,7 @@ procedure TRGBLuminanceSource.CalculateLuminanceBGR24(
|
||||
const rgbRawBytes: TArray<Byte>);
|
||||
var
|
||||
rgbIndex,
|
||||
luminanceIndex,
|
||||
luminanceIndex : Integer; // pmserver: etaient Byte -> boucle infinie au-dela de 255 octets
|
||||
b, g, r : Byte;
|
||||
begin
|
||||
rgbIndex := 0;
|
||||
@@ -414,7 +414,7 @@ procedure TRGBLuminanceSource.CalculateLuminanceRGB32(
|
||||
const rgbRawBytes: TArray<Byte>);
|
||||
var
|
||||
rgbIndex,
|
||||
luminanceIndex,
|
||||
luminanceIndex : Integer; // pmserver: etaient Byte -> boucle infinie au-dela de 255 octets
|
||||
r, g, b : Byte;
|
||||
begin
|
||||
rgbIndex := 0;
|
||||
@@ -439,7 +439,7 @@ procedure TRGBLuminanceSource.CalculateLuminanceBGR32(
|
||||
const rgbRawBytes: TArray<Byte>);
|
||||
var
|
||||
rgbIndex,
|
||||
luminanceIndex,
|
||||
luminanceIndex : Integer; // pmserver: etaient Byte -> boucle infinie au-dela de 255 octets
|
||||
b, g, r : Byte;
|
||||
begin
|
||||
rgbIndex := 0;
|
||||
@@ -464,7 +464,7 @@ procedure TRGBLuminanceSource.CalculateLuminanceBGRA32(
|
||||
const rgbRawBytes: TArray<Byte>);
|
||||
var
|
||||
rgbIndex,
|
||||
luminanceIndex,
|
||||
luminanceIndex : Integer; // pmserver: etaient Byte -> boucle infinie au-dela de 255 octets
|
||||
b, g, r,
|
||||
alpha : Byte;
|
||||
luminance : Byte;
|
||||
@@ -495,7 +495,7 @@ procedure TRGBLuminanceSource.CalculateLuminanceRGBA32(
|
||||
const rgbRawBytes: TArray<Byte>);
|
||||
var
|
||||
rgbIndex,
|
||||
luminanceIndex,
|
||||
luminanceIndex : Integer; // pmserver: etaient Byte -> boucle infinie au-dela de 255 octets
|
||||
r, g, b,
|
||||
alpha : Byte;
|
||||
luminance : Byte;
|
||||
@@ -526,7 +526,7 @@ procedure TRGBLuminanceSource.CalculateLuminanceARGB32(
|
||||
const rgbRawBytes: TArray<Byte>);
|
||||
var
|
||||
rgbIndex,
|
||||
luminanceIndex,
|
||||
luminanceIndex : Integer; // pmserver: etaient Byte -> boucle infinie au-dela de 255 octets
|
||||
r, g, b,
|
||||
alpha : Byte;
|
||||
luminance : Byte;
|
||||
|
||||
@@ -13,6 +13,10 @@ interface
|
||||
|
||||
/// Texte du premier QR trouve a l'ecran, '' si aucun.
|
||||
function ScanScreenForQr: string;
|
||||
// Exposees pour le banc d'essai (mesure du temps de decodage).
|
||||
function CaptureVirtualScreen(out AWidth, AHeight: Integer): TArray<Byte>;
|
||||
function DecodeQrPixels(const APixels: TArray<Byte>; AW, AH: Integer;
|
||||
ATryHarder: Boolean): string;
|
||||
|
||||
implementation
|
||||
|
||||
@@ -65,10 +69,9 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function ScanScreenForQr: string;
|
||||
function DecodeQrPixels(const APixels: TArray<Byte>; AW, AH: Integer;
|
||||
ATryHarder: Boolean): string;
|
||||
var
|
||||
LPixels: TArray<Byte>;
|
||||
LW, LH: Integer;
|
||||
LSource: TLuminanceSource;
|
||||
LBinarizer: THybridBinarizer;
|
||||
LImage: TBinaryBitmap;
|
||||
@@ -78,19 +81,16 @@ var
|
||||
LRes: TReadResult;
|
||||
begin
|
||||
Result := '';
|
||||
LPixels := CaptureVirtualScreen(LW, LH);
|
||||
if LPixels = nil then Exit;
|
||||
|
||||
LFormats := TList<TBarcodeFormat>.Create;
|
||||
LFormats.Add(TBarcodeFormat.QR_CODE);
|
||||
LHints := TDictionary<TDecodeHintType, TObject>.Create;
|
||||
LHints.Add(TDecodeHintType.POSSIBLE_FORMATS, LFormats);
|
||||
LHints.Add(TDecodeHintType.TRY_HARDER, nil);
|
||||
if ATryHarder then LHints.Add(TDecodeHintType.TRY_HARDER, nil);
|
||||
LReader := TMultiFormatReader.Create;
|
||||
LReader.Hints := LHints;
|
||||
// BGR32 et non BGRA32 : le 4e octet d'une capture GDI vaut 0, et la
|
||||
// conversion BGRA le lirait comme une transparence totale - image blanche.
|
||||
LSource := TRGBLuminanceSource.Create(LPixels, LW, LH, TBitmapFormat.BGR32);
|
||||
LSource := TRGBLuminanceSource.Create(APixels, AW, AH, TBitmapFormat.BGR32);
|
||||
LBinarizer := THybridBinarizer.Create(LSource);
|
||||
LImage := TBinaryBitmap.Create(LBinarizer);
|
||||
LRes := nil;
|
||||
@@ -112,4 +112,14 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function ScanScreenForQr: string;
|
||||
var
|
||||
LPixels: TArray<Byte>;
|
||||
LW, LH: Integer;
|
||||
begin
|
||||
Result := '';
|
||||
LPixels := CaptureVirtualScreen(LW, LH);
|
||||
if LPixels <> nil then Result := DecodeQrPixels(LPixels, LW, LH, True);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
Reference in New Issue
Block a user