dd9fd62dcb
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>
195 lines
5.0 KiB
ObjectPascal
195 lines
5.0 KiB
ObjectPascal
{
|
|
* Copyright 2008 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.
|
|
|
|
* Delphi Implementation by K. Gossens
|
|
}
|
|
|
|
unit ZXing.OneD.UPCEANExtension2Support;
|
|
|
|
interface
|
|
|
|
uses
|
|
System.SysUtils,
|
|
System.Generics.Collections,
|
|
System.Math,
|
|
ZXing.Reader,
|
|
ZXing.BarcodeFormat,
|
|
ZXing.BinaryBitmap,
|
|
ZXing.ReadResult,
|
|
ZXing.DecodeHintType,
|
|
ZXing.ResultMetadataType,
|
|
ZXing.ResultPoint,
|
|
ZXing.Common.BitArray;
|
|
|
|
type
|
|
/// <summary>
|
|
/// @see UPCEANExtension5Support
|
|
/// </summary>
|
|
TUPCEANExtension2Support = class sealed
|
|
private
|
|
class var
|
|
decodeMiddleCounters : TArray<Integer>;
|
|
decodeRowStringBuffer : TStringBuilder;
|
|
|
|
class procedure InitializeClass; static;
|
|
class procedure FinalizeClass; static;
|
|
|
|
class function decodeMiddle(const row: IBitArray;
|
|
const startRange: TArray<Integer>;
|
|
const resultString: TStringBuilder): Integer;
|
|
|
|
/// <summary>
|
|
/// Parses the extension string.
|
|
/// </summary>
|
|
/// <param name="raw">raw content of extension</param>
|
|
/// <returns>formatted interpretation of raw content as a {@link TMap} mapping
|
|
class function parseExtensionString(const raw: String): TResultMetadata; static;
|
|
public
|
|
class function decodeRow(const rowNumber: Integer; const row: IBitArray;
|
|
const extensionStartRange: TArray<Integer>): TReadResult;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
ZXing.OneD.UPCEANReader;
|
|
|
|
{ TUPCEANExtension2Support }
|
|
|
|
class procedure TUPCEANExtension2Support.InitializeClass;
|
|
begin
|
|
decodeMiddleCounters := TArray<Integer>.Create(0, 0, 0, 0);
|
|
decodeRowStringBuffer := TStringBuilder.Create;
|
|
end;
|
|
|
|
class procedure TUPCEANExtension2Support.FinalizeClass;
|
|
begin
|
|
decodeMiddleCounters := nil;
|
|
decodeRowStringBuffer.Free;
|
|
end;
|
|
|
|
class function TUPCEANExtension2Support.decodeRow(const rowNumber: Integer;
|
|
const row: IBitArray; const extensionStartRange: TArray<Integer>): TReadResult;
|
|
var
|
|
res : TStringBuilder;
|
|
ending : Integer;
|
|
resultString : String;
|
|
extensionResult : TReadResult;
|
|
extensionData : TResultMetadata;
|
|
resultPoints : TArray<IResultPoint>;
|
|
begin
|
|
Result := nil;
|
|
|
|
res := decodeRowStringBuffer;
|
|
res.Length := 0;
|
|
ending := decodeMiddle(row, extensionStartRange, res);
|
|
if (ending < 0)
|
|
then
|
|
exit;
|
|
|
|
resultString := res.ToString;
|
|
extensionData := TUPCEANExtension2Support.parseExtensionString(resultString);
|
|
|
|
resultPoints := TArray<IResultPoint>.Create(
|
|
TResultPointHelpers.CreateResultPoint((extensionStartRange[0] + extensionStartRange[1]) div 2, rowNumber),
|
|
TResultPointHelpers.CreateResultPoint(ending, rowNumber));
|
|
|
|
extensionResult := TReadResult.Create(resultString, nil, resultPoints, TBarcodeFormat.UPC_EAN_EXTENSION);
|
|
if (extensionData <> nil)
|
|
then
|
|
begin
|
|
extensionResult.putAllMetadata(extensionData);
|
|
FreeAndNil(extensionData);
|
|
end;
|
|
Result := extensionResult;
|
|
end;
|
|
|
|
class function TUPCEANExtension2Support.decodeMiddle(const row: IBitArray;
|
|
const startRange: TArray<Integer>; const resultString: TStringBuilder): Integer;
|
|
var
|
|
bestMatch: Integer;
|
|
counter: Integer;
|
|
ending: Integer;
|
|
counters : TArray<Integer>;
|
|
rowOffset, x,
|
|
checkParity: Integer;
|
|
begin
|
|
Result := -1;
|
|
|
|
counters := decodeMiddleCounters;
|
|
counters[0] := 0;
|
|
counters[1] := 0;
|
|
counters[2] := 0;
|
|
counters[3] := 0;
|
|
ending := row.Size;
|
|
rowOffset := startRange[1];
|
|
checkParity := 0;
|
|
x := 0;
|
|
while ((x < 2) and (rowOffset < ending)) do
|
|
begin
|
|
if (not TUPCEANReader.decodeDigit(row, counters, rowOffset, TUPCEANReader.L_AND_G_PATTERNS, bestMatch))
|
|
then
|
|
exit;
|
|
|
|
resultString.Append(IntToStr(bestMatch mod 10));
|
|
|
|
for counter in counters do
|
|
Inc(rowOffset, counter);
|
|
|
|
if (bestMatch >= 10)
|
|
then
|
|
checkParity := checkParity or (1 shl (1 - x));
|
|
|
|
if (x <> 1) then
|
|
begin
|
|
// Read off separator if not last
|
|
rowOffset := row.getNextSet(rowOffset);
|
|
rowOffset := row.getNextUnset(rowOffset);
|
|
end;
|
|
Inc(x);
|
|
end;
|
|
|
|
if (resultString.Length <> 2)
|
|
then
|
|
exit;
|
|
|
|
if ((Integer.Parse(resultString.ToString) mod 4) <> checkParity)
|
|
then
|
|
exit;
|
|
|
|
Result := rowOffset;
|
|
end;
|
|
|
|
class function TUPCEANExtension2Support.parseExtensionString(const raw: String): TResultMetadata;
|
|
var
|
|
dictionary1: TResultMetadata;
|
|
begin
|
|
Result := nil;
|
|
|
|
if (Length(raw) <> 2)
|
|
then
|
|
exit;
|
|
|
|
dictionary1 := TResultMetadata.Create;
|
|
dictionary1.Add(ZXing.ResultMetadataType.ISSUE_NUMBER, TResultMetaData.CreateStringMetadata(raw));
|
|
Result := dictionary1;
|
|
end;
|
|
|
|
initialization
|
|
TUPCEANExtension2Support.InitializeClass;
|
|
finalization
|
|
TUPCEANExtension2Support.FinalizeClass;
|
|
end.
|