由DelphiZXingQRCode编码的QR码无法解码,错误校正级别>低

kq0g1dla  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(272)

我正在使用这个Delphi单元。我不得不使用这个老的Delphi实现,所以不要问这个问题:https://github.com/foxitsoftware/DelphiZXingQRCode
它产生的QR码被任何解码器解码都很好,只要我把纠错级别保持在“低”。如果我增加纠错级别,产生的代码就不能被我迄今为止尝试过的任何解码器解码。但我被迫(根据一个标准)使用中纠错级别,不多不少。
但是,如何提高纠错级别(从现在开始是ecl)还不清楚。我假设它被硬编码在文件DelphiZXingQRCode的第3491行:Level.FBits:= 1.我找到了一些关于十六进制数表示ecl的信息,但现在找不到了。但我尝试将这些十六进制数作为位,QR码上的ecl位也相应地发生了变化。所以我假设这些十六进制数是正确的(1=低,0=中,2=高,3=四分位)。
下面是一个QRcode的例子,Level.FBits:= 2,意思是我希望ecl是“High”。内容是“Hello world”。中间的十字图像是我必须实现的标准的一部分,所以不要问这个。

有人知道如何修复这个问题吗?我试过......嗯......我试过理解代码,但是代码太多了。我就是无法修复它。如果我无法让其他人修复它,我将不得不......找到其他解决方案。这将是一个问题。

bvpmtnay

bvpmtnay1#

已解决。请参阅下面的代码。方法GenerateQRCode()现在需要ErrorCorrectionLevel的参数:整数0-3。看起来有效。我不得不删除一些未更改的行,因为文件对于StackOverflow来说太大了。请自己合并。

unit DelphiZXingQRCode;

    // ZXing QRCode port to Delphi, by Debenu Pty Ltd
    // www.debenu.com

    // Original copyright notice
    (*
     * 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.
     *)

    interface

    type
      TQRCodeEncoding = (qrAuto, qrNumeric, qrAlphanumeric, qrISO88591, qrUTF8NoBOM, qrUTF8BOM);
      T2DBooleanArray = array of array of Boolean;

      TDelphiZXingQRCode = class
      protected
        FData: WideString;
        FRows: Integer;
        FColumns: Integer;
        FEncoding: TQRCodeEncoding;
        FQuietZone: Integer;
        FElements: T2DBooleanArray;
        FErrorCorrectionLevel: integer;
        procedure SetEncoding(NewEncoding: TQRCodeEncoding);
        procedure SetData(const NewData: WideString);
        procedure SetQuietZone(NewQuietZone: Integer);
        procedure SetErrorCorrectionLevel(value: integer);
        function GetIsBlack(Row, Column: Integer): Boolean;
        procedure Update;
      public
        constructor Create;
        property Data: WideString read FData write SetData;
        property Encoding: TQRCodeEncoding read FEncoding write SetEncoding;
        property ErrorCorrectionLevel: integer read fErrorCorrectionLevel write SetErrorCorrectionLevel;
        property QuietZone: Integer read FQuietZone write SetQuietZone;
        property Rows: Integer read FRows;
        property Columns: Integer read FColumns;
        property IsBlack[Row, Column: Integer]: Boolean read GetIsBlack;
      end;

    implementation

    uses
      SysUtils,
      contnrs, Math, Classes;

    type
      TByteArray = array of Byte;
      T2DByteArray = array of array of Byte;
      TIntegerArray = array of Integer;

    // File too large for Stackoverflow: Deleted unchanged lines.

    { TErrorCorrectionLevel }

    procedure TErrorCorrectionLevel.Assign(Source: TErrorCorrectionLevel);
    begin
      Self.fOrdinal := Source.FOrdinal;
    end;

    constructor TErrorCorrectionLevel.Create(ordinalValue: integer);
    begin

      fOrdinal:=0;
      if (ordinalValue >= 0) and (ordinalValue <=3) then
        fOrdinal:=ordinalValue;
    end;

    function TErrorCorrectionLevel.GetBits: integer;
    begin
      if fOrdinal = 0 then  // level L
        result:=1
      else
      if fOrdinal = 1 then  // level M
        result:=0
      else
      if fOrdinal = 2 then  // level Q
        result:=3
      else
      if fOrdinal = 3 then  // level H
        result:=2
      else
        result:=1;
    end;

    // File too large for Stackoverflow: Deleted unchanged lines.

    procedure TDelphiZXingQRCode.SetErrorCorrectionLevel(value: integer);
    begin
      if (value < 0) or (value > 3) then
        raise Exception.Create('invalid error correction value. must be in range 0..3.');

      if value <> fErrorCorrectionLevel then
      begin
        FErrorCorrectionLevel:=value;
        Update;
      end;
    end;

    procedure TDelphiZXingQRCode.SetQuietZone(NewQuietZone: Integer);
    begin
      if ((FQuietZone <> NewQuietZone) and (NewQuietZone >= 0) and (NewQuietZone <= 100)) then
      begin
        FQuietZone := NewQuietZone;
        Update;
      end;
    end;

    procedure TDelphiZXingQRCode.Update;
    begin
      FElements := GenerateQRCode(FData, Ord(FEncoding), FErrorCorrectionLevel);
      FRows := Length(FElements) + FQuietZone * 2;
      FColumns := FRows;
    end;
    end.

相关问题