Migaro. 技術Tips

                       

ミガロ. 製品の技術情報
IBMiの活用に役立つ情報を掲載!


Delphi 図形と文字の描画機能を使った電子印鑑画像生成

弊社テクニカルサポート宛てに、

「ミガロ.テクニカルレポートの
 『FastReportを活用した電子帳票作成テクニック』(以下「レポート」)
 を発展させて、シンプルな印鑑画像を作成したい」

というご質問がありました。

今回はDelphiの標準ロジックを使用して、印鑑画像を生成する方法をご紹介します。


弊社テクニカルレポート(先述のレポート)では、
申請者や承認者の日付印画像を作成するロジックを公開しております。

今回はこれを基に、以下の例(右側)のようなシンプルな印鑑画像を
シンプルなロジックで作成する手順を紹介します。

 

まず、新しいフォームを作成したら、以下のようにコンポーネントを配置します。
(すべてDelphiの標準コンポーネントです)

  • edtEnnoSize(TEdit)出力する円のサイズを設定
  • edtMyNameM(TEdit)出力する文字列を設定
  • Image1(TImage)出力結果の画像表示
  • SaveDialog1(TSaveDialog)画像保存時に使用
  • Button1(TButton)出力ボタン
  • Button2(TButton)画像保存ボタン
  • その他、画面表示用のTLabel

 

以下のようにロジックを記述します。

  • 画面生成時処理
  • 出力ボタン 押下時処理
  • 画像保存ボタン 押下時処理

の3つのイベントより構成されています。
今回のロジックでは「円のサイズ」という項目からもわかるように
印鑑のサイズが可変になっています。

{*******************************************************************************
 目的: 画面生成時処理(※それぞれオブジェクトインスペクタでも設定可)
 引数:
 戻値:
*******************************************************************************}
procedure TForm6.FormCreate(Sender: TObject);
begin
  Image1.AutoSize := True;  // 画像サイズを可変にする
  Button2.Enabled := False; // 保存ボタン押下不可

  // 保存ダイアログの設定
  with SaveDialog1 do
  begin
    DefaultExt := '.bmp';                     // 拡張子なしで保存した時の拡張子
    Filter  := 'BMP ファイル(*.bmp)|*.bmp'; // 保存拡張子の選択
    Options := Options + [ofOverwritePrompt]; // 同名ファイルの上書き確認オン
  end;
end;

{*******************************************************************************
 目的: 出力ボタン 押下時処理
 引数:
 戻値:
*******************************************************************************}
procedure TForm6.Button1Click(Sender: TObject);
var
  i: Integer;      // for文用
  iWidth: Integer; // 円のサイズ
  iChSiz: Integer; // 文字列の文字数
  iFtSiz: Integer; // フォントサイズ
  iX, iY: Integer; // 出力位置計算用
  sT: String;      // 描画文字の保持
  bmpBase1m: TBitmap;
  bmpOver1m: TBitmap;
begin

  // 文字数(文字数に制限を設ける場合、最初に行う)
  edtMyNameM.Text := Trim(edtMyNameM.Text);
  iChSiz := Length(edtMyNameM.Text);
  if (iChSiz = 0) then
  begin
    ShowMessage('文字列が入力されていません。');
    edtMyNameM.SetFocus;
    Abort;
  end;

  // 文字数(半角文字のチェック)
  if (Length(edtMyNameM.Text) * 2 <> Length(AnsiString(edtMyNameM.Text))) then
  begin
    if (Application.MessageBox('半角文字が含まれているため、' +
      '文字がずれる場合があります。よろしいですか?', '確認', 36) <> mrYes) then
    begin
      edtMyNameM.SetFocus;
      Abort;
    end;
  end;

  // 円のサイズ(画像サイズはこの値+2)
  iWidth := StrToIntDef(edtEnnoSize.Text, 0);
  if (iWidth < iChSiz * 10) then
  begin
    ShowMessage('文字数に対して円のサイズが小さすぎます。');
    edtEnnoSize.SetFocus;
    Abort;
  end;

 // 描画処理 ここから
  bmpBase1m := TBitmap.Create;
  bmpOver1m := TBitmap.Create;

  try
    bmpBase1m.PixelFormat := pf24bit;
    bmpOver1m.PixelFormat := pf24bit;

    // 印鑑の幅設定
    bmpBase1m.Width  := iWidth + 2;
    bmpBase1m.Height := iWidth + 2;

    // 枠線の描画処理
    bmpBase1m.Canvas.Pen.Color := clRed;           // 枠線の色
    bmpBase1m.Canvas.Pen.Width := 3;               // 枠線の太さ(今回は固定)
    bmpBase1m.Canvas.Ellipse(1, 1, iWidth, iWidth);// 円のサイズ ※1

    // 文字列の描画処理
    bmpOver1m.Width  := bmpBase1m.Width;
    bmpOver1m.Height := bmpBase1m.Height;
    bmpOver1m.Canvas.Font.Name := 'HG正楷書体-PRO';// フォント名の指定(例:楷書体)
    bmpOver1m.Transparent := True;

    // 文字数によってフォントサイズを計算(好みで微調整する)
    case iChSiz of // 文字列の長さによって位置を決定 ※2
      1:   iFtSiz := Trunc(iWidth * 0.6);          // 1文字の場合
      2:   iFtSiz := Trunc(iWidth * 0.4);          // 2文字の場合
      else iFtSiz := Trunc((iWidth - 4) / iChSiz); // 3文字以上の場合
    end;

    // フォントサイズを文字の大きさから決定する
    bmpOver1m.Canvas.Font.Height := iFtSiz;
    // フォント色=赤色
    bmpOver1m.Canvas.Font.Color  := clRed;
    if (Abs(bmpOver1m.Canvas.Font.Size) > 10) then
    begin
      // 太字(フォントサイズが極小の場合を除く)
      bmpOver1m.Canvas.Font.Style  := [fsBold];
    end;

    // 位置を判定して1文字ずつ描画する
    for i := 1 to iChSiz do
    begin
      sT := edtMyNameM.Text[i];
      iX := Trunc((iWidth - iFtSiz) / 2);  // 横位置
      case iChSiz of                       // 文字列の長さによって縦位置を決定 ※2
        1:   iY := iX;                     // 1文字の場合
        2:   iY := Trunc(iWidth / 2) - (iFtSiz * (2 - i)); // 2文字の場合
        else iY := 4 + ((i - 1) * iFtSiz); // 3文字以上の場合
      end;

      bmpOver1m.Canvas.TextOut(iX, iY, sT);
    end;

    bmpOver1m.Transparent := True;

    // 印鑑の枠線と文字列を融合する
    bmpBase1m.Canvas.StretchDraw(
                      Rect(0, 0, bmpOver1m.Width, bmpOver1m.Height), bmpOver1m);

    // 画面のImage1にセットする
    Image1.Picture.Assign(bmpBase1m);

  finally
    FreeAndNil(bmpBase1m);
    FreeAndNil(bmpOver1m);
  end;

  Button2.Enabled := True; // 保存ボタン押下可能
end;
{*******************************************************************************
 目的: 画像保存ボタン 押下時処理
 引数:
 戻値:
*******************************************************************************}
procedure TForm6.Button2Click(Sender: TObject);
var
  sFile: String;
begin
  sFile := 'stamp_' + edtMyNameM.Text + '_' + IntToStr(Image1.Width);
  SaveDialog1.FileName := sFile; // 保存ファイル名の初期値(例)

  if (SaveDialog1.Execute) then  // ダイアログで「保存」が押されたら保存する
  begin
    Image1.Picture.SaveToFile(SaveDialog1.FileName);
    ShowMessage('保存しました。');
  end;
end;
 

※1:この部分で円を描画しています。
   このサンプルでは正円を描画していますが、楕円にしたい場合は
   「Ellipse」の第1引数と第3引数を変更して調整します。
   例:『 bmpBase1m.Canvas.Ellipse(10, 1, iWidth – 10, iWidth);

※2:このcase文(2箇所)によって、出力文字が「1文字」「2文字」「3文字以上」
   それぞれの場合でフォントサイズや描画位置を微調整できます。

※3:今回のロジックは横向きの文字を1文字ずつ描画しているため、
   長音(「ー」)など縦横に依存する文字には対応していません。

 

出力された画像は、TImageに読み込ませて画面内に表示したり、
FastReport・VB-Report等の帳票ツールに読み込ませて印刷したり、活用方法は様々です。


=======================================
【免責事項】
本ページに掲載しているソースコードは情報提供の為のサンプルプログラムとなります。
お客様作成アプリケーション内で自由にご利用いただけます。
ただし、これらのソースコードやサンプルプログラムを使用したことによって生じた、
いかなる障害・損失に関しても一切の責を負いかねますので、ご了承下さい。
=======================================