【VBA×画像処理】ビットマップ画像の回転

本ページでは、VBAで読み込んだビットマップ(BMP)画像を内部的に処理し、各ピクセルの配置を操作して画像を90度単位で回転させる方法を解説していきます。画像の回転とは、ある中心点を基準として画像を所定の角度で回転させる処理のことを指します。本ページでは画像処理で頻繁に利用される、右90度回転(時計回り)と左90度回転(反時計回り)の処理について解説します。

icon-warning 注意事項

本ページではビットマップ(BMP)画像の読み込みと書き出しページで実装したクラスに画像処理を追加していきます。前提の機能となる画像の入出力機能を実装しているため事前に一読ください。

画像の回転

画像の90度回転は、上下・左右反転と同様にピクセルのRGB情報を座標変換でインデックスを入れ替えるだけで実現できます。ただし90度回転を行うと元画像の縦と横のサイズが入れ替わるため、出力画像の配列サイズは元画像の縦横を入れ替えたサイズで確保する必要がある点に注意が必要です。式で表すと下記の通りです。(※ここで \( H \) は画像の高さ \( W \) は画像の幅)
\[
\begin{cases}
1.\,\, (y, x) \to (x,\, H – 1 – y) \\
2.\,\, (y, x) \to (W – 1 – x,\, y)
\end{cases}
\]

右90度回転(時計回り)を行う場合は1.の式を、左90度回転(反時計回り)を行う場合は2.の式を適用することでそれぞれ回転が可能です。右回転を2回連続で適用すれば180度回転(上下左右反転と同等)、右回転を3回連続で適用すれば左回転と同等の結果となるため、これらを組み合わせることで任意の90度単位の回転が実現できます。このように、画像の90度回転も座標変換による単純なインデックスの入れ替え処理で構成されます。
   

サンプルコード

以下は画像を右回転・左回転するためのコードです。事前に用意しておいたclsBitmap内に下記コードをコピペすることで利用可能になります。

クラスモジュール (clsBitmapに追記)

'****************************************************************************
'*  画像の右回転(時計回り90度)
'****************************************************************************
Public Sub RotateRight()
 
    Dim rgbDataOrg() As RGBTRIPLE '元画像RGBデータ
    Dim rgbDataRot() As RGBTRIPLE '回転画像RGBデータ

    Dim lHeight As Long
    Dim lWidth  As Long
    Dim lX      As Long
    Dim lY      As Long
    
    '元画像情報を取得
    rgbDataOrg = m_rgbImageData
    lHeight = UBound(rgbDataOrg, 1) + 1  '配列は0始まりなので+1で補正
    lWidth = UBound(rgbDataOrg, 2) + 1   '配列は0始まりなので+1で補正
    
    '配列サイズを定義(元画像の縦横を入れ替えた2次元配列)
    ReDim rgbDataRot(UBound(rgbDataOrg, 2), UBound(rgbDataOrg, 1))

    '右回転
    For lY = 0 To lHeight - 1
        For lX = 0 To lWidth - 1
            rgbDataRot(lX, (lHeight - 1) - lY).rgbRed = rgbDataOrg(lY, lX).rgbRed
            rgbDataRot(lX, (lHeight - 1) - lY).rgbGreen = rgbDataOrg(lY, lX).rgbGreen
            rgbDataRot(lX, (lHeight - 1) - lY).rgbBlue = rgbDataOrg(lY, lX).rgbBlue
        Next
    Next
    
    'RGBデータを更新
    m_rgbImageData = rgbDataRot

End Sub
'****************************************************************************
'*  画像の左回転(反時計回り90度)
'****************************************************************************
Public Sub RotateLeft()
 
    Dim rgbDataOrg() As RGBTRIPLE '元画像RGBデータ
    Dim rgbDataRot() As RGBTRIPLE '回転画像RGBデータ

    Dim lHeight As Long
    Dim lWidth  As Long
    Dim lX      As Long
    Dim lY      As Long
    
    '元画像情報を取得
    rgbDataOrg = m_rgbImageData
    lHeight = UBound(rgbDataOrg, 1) + 1  '配列は0始まりなので+1で補正
    lWidth = UBound(rgbDataOrg, 2) + 1   '配列は0始まりなので+1で補正
    
    '配列サイズを定義(元画像の縦横を入れ替えた2次元配列)
    ReDim rgbDataRot(UBound(rgbDataOrg, 2), UBound(rgbDataOrg, 1))

    '左回転
    For lY = 0 To lHeight - 1
        For lX = 0 To lWidth - 1
            rgbDataRot((lWidth - 1) - lX, lY).rgbRed = rgbDataOrg(lY, lX).rgbRed
            rgbDataRot((lWidth - 1) - lX, lY).rgbGreen = rgbDataOrg(lY, lX).rgbGreen
            rgbDataRot((lWidth - 1) - lX, lY).rgbBlue = rgbDataOrg(lY, lX).rgbBlue
        Next
    Next
    
    'RGBデータを更新
    m_rgbImageData = rgbDataRot

End Sub

 
標準モジュール

Option Explicit
Sub main()

    Dim sPathBmpSrc As String
    Dim sPathBmpExport As String
    Dim oBitmap As clsBitmap

    sPathBmpSrc = "C:\...\source.bmp"
    sPathBmpExport = "C:\...\output.bmp"

    Set oBitmap = New clsBitmap
    Call oBitmap.LoadBitmap(sPathBmpSrc)        '画像読み込み
    Call oBitmap.RotateRight                    '右回転(時計回り90度)
    'Call oBitmap.RotateLeft                    '左回転(反時計回り90度)
    Call oBitmap.ExportBitmap24(sPathBmpExport) '画像出力

End Sub

使い方は非常にシンプルで上記コードのように既に用意しておいた画像の入出力処理の間に、回転処理を呼び出すだけです。右回転を複数回連続で呼び出すことで180度回転や270度回転(左回転と同等)も実現でき、他の画像処理と組み合わせることも可能です。
 

関連情報

VBA×画像処理ページ

次回 >> 指定位置に長方形を描画する
前回 >> 画像の上下・左右反転
画像処理のメインページへ戻る

参考

外部リンク:Rotation (mathematics) – Wikipedia
     :Rotation matrix – Wikipedia

Excel,VBA,画像処理