VB6 GDI+で軸指定の画像回転をするには?

解決


ノリスケ  2004-11-08 20:03:09  No: 86553

VB6の環境で、GDI+を使用した画像の回転に挑戦しています。
現状、画像の回転までは成功したんですが、任意の回転軸の座標を指定
し、そこを中心に回転させる場合、GdipDrawImageRectI関数に渡す
描画始点の座標が解からずにいます。

その解決策についてアドバイスをお願いします。
回転軸の座標を引き数にしたGDI+のGraphics関数があればベストなんですが
MSDNを調べても該当する関数の解説が見つかりません。
以下は、現状のテストコードです。

Option Explicit
Private Type GdiplusStartupInput
    GdiplusVersion           As Long
    DebugEventCallback       As Long
    SuppressBackgroundThread As Long
    SuppressExternalCodecs   As Long
End Type
Private Declare Function GdiplusStartup Lib "gdiplus" (token As Long, inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As Long = 0) As Long
Private Declare Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As Long
Private Declare Function GdipLoadImageFromFile Lib "gdiplus" (ByVal FileName As Long, image As Long) As Long
Private Declare Function GdipDisposeImage Lib "gdiplus" (ByVal image As Long) As Long
Private Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hdc As Long, Graphics As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "gdiplus" (ByVal Graphics As Long) As Long
Enum MatrixOrder
    MatrixOrderPrepend = 0
    MatrixOrderAppend = 1
End Enum
Private Declare Function GdipRotateWorldTransform Lib "GDIPlus" (ByVal Graphics As Long, ByVal Angle As Single, ByVal Order As MatrixOrder) As Long
Private Declare Function GdipGetImageWidth Lib "gdiplus" (ByVal image As Long, Width As Long) As Long
Private Declare Function GdipGetImageHeight Lib "gdiplus" (ByVal image As Long, Height As Long) As Long
Private Declare Function GdipDrawImageRectI Lib "gdiplus" (ByVal Graphics As Long, ByVal image As Long, ByVal X As Long, ByVal Y As Long, ByVal Width As Long, ByVal Height As Long) As Long

Private Sub Command1_Click()
    Dim sfilename As String
    sfilename = App.Path & "\test.bmp"
    With Picture1
        .AutoRedraw = True
        .Picture = LoadPicture()
        ' とりあえず、45度で回転してみる。
        Call RotatedImageFromFile(sfilename, Picture1.hdc, 45)
        .Picture = .image
    End With
End Sub

Private Sub RotatedImageFromFile(ByVal sfilename As String, _
                ByVal hdc As Long, ByVal angle As Single)

' sfilename - bmp, jpg, gif, emf, wmf, tif, png, ico ファイルのパス名
' hdc - Form1.hdc または Picture1.hdc
' angle - 回転角度(degrees)

Dim pstat As GdiplusStartupInput
Dim ltoken As Long, lstatus As Long
Dim lgraphics As Long, limage As Long
Dim x As Long, y As Long
Dim lwidth As Long, lheight As Long

    pstat.GdiplusVersion = 1
    If (GdiplusStartup(ltoken, pstat) <> 0) Then Exit Sub

    lstatus = GdipLoadImageFromFile(StrPtr(sfilename), limage)
    If (lstatus = 0) Then
        lstatus = GdipCreateFromHDC(hdc, lgraphics)
        If (lstatus = 0) Then
            Call GdipRotateWorldTransform(lgraphics, angle, MatrixOrderAppend)
            Call GdipGetImageWidth(limage, lwidth)
            Call GdipGetImageHeight(limage, lheight)
'-------------------------------
' 回転軸の座標(x0, y0)を指定した場合、GdipDrawImageRectI関数
' に渡す正しい描画始点(x, y)座標を求めることができていません。

Const pi = 3.14159
Dim r As Single
Dim x0 As Single, y0 As Single   ' 回転軸のx, y座標

Dim theta As Single
x0 = CSng(lwidth) / 2
y0 = CSng(lheight) / 2
r = Sqr(x0 * x0 + y0 * y0)
theta = Atn(y0 / x0)
theta = theta + (angle * pi / 180)
x = x0 - r * Cos(theta)
y = y0 - r * Sin(theta)
'-------------------------------
            Call GdipDrawImageRectI(lgraphics, limage, x, y, lwidth, lheight)
            Call GdipDeleteGraphics(lgraphics)
        End If
        Call GdipDisposeImage(limage)
    End If
    Call GdiplusShutdown(ltoken)
End Sub


ノリスケ  2004-11-09 08:04:39  No: 86554

以下のラインを修正すると、うまくいく様です。

> theta = theta + (angle * pi / 180)
> x = x0 - r * Cos(theta)
> y = y0 - r * Sin(theta)

theta = theta - (angle * pi / 180)
x = r * Cos(theta) - x0
y = r * Sin(theta) - y0


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加