画像そっくりのオートシェイプを作成するには

Excelで資料を作るときに画像やオートシェイプなどを利用することがあります。

その際によくあるのが、ネットから画像を拝借して資料に載せる、というところですが、著作権の問題もありますのでそのまま使うのはさすがに気が引ける、というのがあります。

そこで、マクロで画像を基にオートシェイプを作って、それを加工すればいいじゃん、と思ったのがこのマクロを作ったきっかけです。

が。画像を直接加工した方が速いというのにすぐ気が付いてしまい。うーん。用途があるとは思えなくなりました。

それ以外にもいろいろと問題があるのですが、せっかく作ったので載せます。

とは言いつつも、完全にお遊びプログラムです。実用性があるかどうかは不明です


実行例

完全に元画像をコピーするため、絵画のような味わいは皆無です。こんな感じ。下の絵がオートシェイプで作成されてます。

400倍した元画像。元々画質がよくないですが。。

400倍したオートシェイプ。ドット絵みたいになってます。



考え方とか実現方法とか

シートに写真でもなんでもいいので画像を配置します。どうやってこのオートシェイプを作っているかというと、元画像の縦と横のピクセル数を計測して、全ピクセルの色を1ピクセルずつ取得し、それを1ポイント(ピクセルじゃなくてExcelでのポイント単位)ごとの四角のオートシェイプを作って背景色を元画像の通りに配色しています。

Windowsのウィンドウ上の座標や「ピクセル」と、Excelのシート上の「ポイント」は単位が異なるため、それを調整する必要があります。

ウィンドウ上の座標を取得するために、WindowオブジェクトのPointsToScreenPixelsXメソッドとPointsToScreenPixelsYメソッドを使って、ピクセルとポイントの差を吸収するような演算をやってたりします。このあたりは「ポイント、ピクセル、インチ、センチ、ミリの相互変換」をご参照ください。


難点

このプログラムと実行結果には以下の難点があります。

  • 処理が遅い。Win32APIのGetPixelで1ピクセルずつ取得しているのが原因。
  • 縦横1ポイントの四角オートシェイプを縦×横の数だけ作成するため、小さい画像でも数万個のオートシェイプが作成され、当然重くなる。
  • ってのを分かってるけど、どうにかするつもりがない。(実用性を感じないのでよりよくする気にならない。。。)

GetPixelが遅いのは別の方法で解決できますが、オートシェイプが多いのを解決するにはちょっと面倒なので、もうこのままにします。


コード

シートに写真でもなんでもいいのでjpegとかpngとかの画像を配置します。

それを選択して、以下のStartMain()関数を実行すると、元画像の5セルぐらい下にオートシェイプを作成します。

ただ、5分とか10分とかめちゃくちゃ時間がかかるため、動かす場合は1cm四方程度の小さい画像をお勧めします。



コード説明

Win32APIのGetDC()、GetPixel()、ReleaseDC()を使ってます。ウィンドウ上の色を取得するのに使ってます。詳細は省略します。

Win32APIは32bit版と64bit版で定義が異なるため、コード内では32bit版をコメントアウトし、64bit版を利用するようにしています。もし32bit版を利用する場合はコメント化を外して、64bit版のコードを削除(もしくはコメントアウト)してください。対象は4か所あり、そのうちの3か所はコード先頭のGetDC()、GetPixel()、ReleaseDC()で、残りの1か所はGetPictureColor関数の中で定義しているLongPtr型の変数hDCです。

Win32APIの32bit版を64bit版にしたい場合の詳細については「VBAでWin32API(WindowsAPI)を64bit対応する方法」をご参照ください。

やりたいことは、選択した画像のウィンドウ上の座標をとって、そこにある色を1ピクセルずつとって、それをオートシェイプとして作成する、という内容です。

「* 4 / 3」とか「0.75」とかはExcelのポイント単位とWindowsのピクセル単位の違いを吸収するための調整値です。1インチは72ポイントであり、また、96ピクセルでもあります。それらの単位の相関関係については「ポイント、ピクセル、インチ、センチ、ミリの相互変換」をご参照ください。