2025/07/01

Notes - Excel 連携:#54)指定した Pixel 数で画像が出力できない !?

#52)画像のリサイズ』で、既存の画像ファイルをリサイズして再保存する方法を紹介しました。出力画像の縦横のサイズを Pixel で指定する仕様だったのですが、先日、希望通りのサイズにならない現象に出くわしました。誤差が原因だろうと、『#40)訂正 - 名前アイコン生成 』で紹介した、0.5 Point ずらす技を使いましたが、それでも、100% 改善することができませんでした。

そこで改めて、希望の Pixel と出力される画像サイズを検証してみました。想定外の結果になったので、検証してよかったのですが、#40 で訂正した内容のさらなる訂正記事のような状態となります...。ご了承ください。

 

検証方法

まずは、改めて Excel の挙動を確認します。

1000 x 1000 Pixel の画像を用意して、それをリサイズして再保存し、保存された画像ファイルのサイズをチェックします。リサイズは 760 Point から 770 Point まで 0.1 刻みで変化させます。Pixel で言うと 0.075 刻みとなるので、今回の症状を確実に捕まえられるという算段です。なお、縦横とも同じ Point を指定した正方形の画像が出力し、縦横の挙動の違いも調査します。

Notes - Excel 連携の連載ですので、参考までではありますが、検証プログラムを掲載します。調査対象の画像形式は、asFmt にセットしている通り、jpg, gif, png の 3 種類です。

Option Declare
Use "lsXls"

Public Const DXL_Image_Unknown = 0
Public Const DXL_Image_JPEG = 1
Public Const DXL_Image_GIF = 2
Public Const DXL_Image_PNG = 3

Sub Initialize
   Dim oXls As Variant
   Dim oSheet As Variant
   Dim oShape As Variant
   Dim oImage As Variant
   Dim sFN As String
   Dim ns As New NotesSession
   Dim nst As NotesStream
   Dim iType As Integer
   Dim iSizeX As Integer
   Dim iSizeY As Integer
   Dim asFmt(2) As String
   Dim i As Integer
   Dim iRow As Integer

   asFmt(0) = "jpg"
   asFmt(1) = "gif"
   asFmt(2) = "png"

   'Excel の準備
   Set oXls = CreateObject("Excel.Application")
   Call oXls.Workbooks.Add
   Set oSheet = oXls.Workbooks(1).WorkSheets(1)

   '画像サイズ取得
   Dim dX As Double '画像のサイズ(ポイント)

   'Chart オブジェクトを画像の大きさで作成
   Set oShape = xAddChart(oSheet, 750, 750)

   'Chart 上に画像ファイルを読み込み
   sFN = "C:\Sample.jpg"
   Set oImage = oShape.Chart.Shapes.AddPicture(sFN, msoFalse, msoTrue, 0, 0, -1, -1)

   'リサイズのテスト
   oSheet.Cells(1, 1).Value = "Point"
   oSheet.Cells(1, 2).Value = "Pixcel"
   For i = 0 To UBound(asFmt)
      oSheet.Cells(1, (i*2)+3).Value = "x(" & asFmt(i) & ")"
      oSheet.Cells(1, (i*2)+4).Value = "y(" & asFmt(i) & ")"

      iRow = 1
      For dX = 760 To 770 Step 0.1
         iRow = iRow + 1

         '初回のループのみ Point と 単純変換した Pixel を記録
         If i = 0 Then
            oSheet.Cells(iRow, 1).Value = dX
            oSheet.Cells(iRow, 2).Value = dX / 0.75
         End If

         'リサイズ
         oShape.Width = dX
         oShape.Height = dX

         'リサイズ画像の保存
         sFN = "C:\Resized_" & CStr(CInt(dX*10)) & "." & asFmt(i)
         Call xSaveAsPicture(oShape, sFN)

         '保存した画像サイズの確認
         Set nst = ns.CreateStream()
         Call nst.Open(sFN)
         iType = xGetImageFileInfo(nst, iSizeX, iSizeY)
         Call nst.Close()

         '画像サイズを Excel シートに記録
         oSheet.Cells(iRow, (i*2)+3).Value = iSizeX
         oSheet.Cells(iRow, (i*2)+4).Value = iSizeY
      Next
   Next

   oXls.Visible = True
End Sub

lsXls ライブラリはこれまでの連載で使用してきたライブラリです。また、画像サイズの取得方法として、別の連載『DXL Step-by-Step:#13)イメージの形式とサイズの取得』で掲載した、定数と xGetImageFileInfo、xGetImageFileType の 2 つの関数を流用しています。


実行結果の確認

検証プログラムを実行すると Excel シート上に結果が表示されます(図はセル書式セット後)。

このままでは傾向がつかめないので、Excel でグラフ化します。まずは、jpg 画像の結果は次の通りです。横軸が Point で、縦軸が Pixel です。

この結果より、2 つのことがわかります。

まず、リサイズ後の画像の横幅が青で縦が赤なのですが、ずれていることがわかります。縦横で同じ Point を指定したにもかかわらず、結果に差が出るということは、Pixel に丸める際に、縦横で仕様に差があるということです。

2 点目は少々厄介です。グレーの線は Point を単純に Pixel に変換したもので、実数なので直線になっています。その ± 0.5 が上下の薄いグレーの線です。この範囲内に入っているなら、四捨五入など丸め誤差の範囲と判断できるのですが、上側にはみ出ている箇所があります。この結果より、丸め処理だけで解決できる問題ではないと判定できます。また、グラフの波形が特定のパターンを示しているので、論理的な ”仕様” と考えられます。

続いて、別の画像形式の結果をグラフ化してみました。gif は jpg と同じ傾向だったのですが、png 形式では横幅の結果だけ微妙に違っていました。


対策は次回

これらの結果より、指定した Pixel 数で正確に画像を出力するためには、出力画像タイプごとの特性を把握したうえで、それに応じた微調整を行う必要があります。なぜこういった仕様になっているかは不明ですが、コーティングする上で大変悩ましい状況になりました。

ただ、少々長くなったので、その対策については次回にまとめます。


前回 Notes - Excel 連携 次回


0 件のコメント:

コメントを投稿