2025/07/02

Notes - Excel 連携:#55)指定した Pixel 数で画像を出力する方法

前回は Export メソッドで画像を出力した際に希望通りのサイズとならないことがある現象(以下、誤差といいます)に関して、詳細な調査を行いました。

発見できた事実は、

  1. 縦と横で誤差が発生する条件が違う
  2. Point(実数)とPixel(整数)間の変換で発生する丸め誤差ではない
  3. 出力画像形式により、誤差が発生する条件が違う

という結果になりました。なぜこのような仕様(?)になっているのかわかりませんが、画像ファイルフォーマットの仕様や画像形式ごとにプログラマが違うなどが原因ではないかと想定します。


対応方針

前回、掲載したグラフから誤差が発生するパターンがつかめそうなのですが、いつ仕様の調整が入るかわかりません。そこで、特性に合わせた対応にするのではなく、出力画像が希望通りのサイズとなっているか確認し、誤差があったら調整して再出力する方式とします。

あまり美しい対応とは言えませんが、ご了承ください...


サンプルプログラム

画像として保存する新しい関数を作成しました。引数は、

  1. 画像化する Chart が配置された Shape オブジェクト
  2. 保存ファイル名
  3. 画像サイズ横(Pixel)
  4. 画像サイズ縦(Pixel)

です。

Function xSaveAsPicture_Px(voShape As Variant, ByVal vsFileName As String, ByVal viX As Integer, ByVal viY As Integer)
   Dim ns As New NotesSession
   Dim nst As NotesStream
   Dim iX As Integer
   Dim iY As Integer
   Dim iType As Integer
   Dim bOK As Boolean

   Dim dX_Org As Double '元の画像の幅(ポイント)
   Dim dY_Org As Double '元の画像の高さ(ポイント)
   Dim dX_Out As Double '出力する画像の幅(ポイント)
   Dim dY_Out As Double '出力する画像の高さ(ポイント)

   '元のサイズ取得
   dX_Org = voShape.Width
   dY_Org = voShape.Height

   '希望の画素数にリサイズ
   dX_Out = dX_Org * (PixcelToPoint(viX)/dX_Org)
   dY_Out = dY_Org * (PixcelToPoint(viY)/dY_Org)
   voShape.Width = dX_Out
   voShape.Height = dY_Out

   '画像として保存し、サイズを検証
   bOK = False
   Do
      '画像として保存
      Call voShape.Chart.Export(vsFileName)

      '出力された画像の種類とサイズを取得
      Set nst = ns.CreateStream()
      Call nst.Open(vsFileName)
      iType = xGetImageFileInfo(nst, iX, iY)
      Call nst.Close()

      '出力された画像の検証
      If iType = DXL_Image_Unknown Then
         'サポートできない画像なのでこれで OK とする
         bOK = True
      Else
         'サイズの確認
         If iX = viX And iY = viY Then
            '希望通りのサイズ
            bOK = True
         Else
            'サイズが違う
            If iX < viX Then
               '小さい場合は 0.5 point 加算
               voShape.Width = voShape.Width + 0.5
            ElseIf iX > viX Then
               '大きい場合は 0.5 point 減算
               voShape.Width = voShape.Width - 0.5
            End If
            If iY < viY Then
               '小さい場合は 0.5 point 加算
               voShape.Height = voShape.Height + 0.5
            ElseIf iY > viY Then
               '大きい場合は 0.5 point 減算
               voShape.Height = voShape.Height - 0.5
            End If
         End If
      End If
   Loop Until bOK = True

   '元のサイズに戻す
   voShape.Width = dX_Org
   voShape.Height = dY_Org
End Function

ポイントは Do ~ Loop の中です。画像を出力し、そのサイズを確認、希望通りになっていなければサイズを微調整して再出力するようにしています。微調整は 1 Pixel 分の 0.75 Point でも問題ないとは思うのですが、特性が完全につかめていないので、0.5 Point と少し遠慮しています。

なお、今回のサンプルも前回同様に『DXL Step-by-Step:#13)イメージの形式とサイズの取得』で掲載した、定数と 2 つの関数を流用しています。また対応していない画像形式に対しては、サイズのチェックを行わず、初回の出力をそのまま採用しています。


テスト結果

この関数を利用して、ある画像を 32 ~ 48 Pixel まで変換してみました。結果は、対応している画像 jpg, gif, png では、指定通りのサイズが出力されるようになりました。そして、対応していない bmp では、一部希望通りとなっていないサイズが発生しています。

通常使用する画像形式は正しく出力できることが確認できました。今後新たな問題は発覚しないことを祈りつつ、指定した Pixel 数で画像を出力する関数はこれで完成とします。


前回 Notes - Excel 連携


0 件のコメント:

コメントを投稿