遅い→起動時

http://d.hatena.ne.jp/pmint/

画像の拡大・縮小、回転、そしてスクロール

ペイントツールの試作に必要だった画像の拡大・縮小、回転、スクロール処理のサンプル。
いずれの処理もGDI+の機能にあるので、それを使うだけ。


こちらがプロジェクトファイル一式。

画像の拡大・縮小、回転、スクロールサンプル
WindowsApplication2154.zip


主要部分の抜粋。

Private Sub Panel_見える_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel_見える.Paint
With e.Graphics
    Dim origin As PointF = New PointF(PictureBox_見えない.Image.Width / 2, PictureBox_見えない.Image.Height / 2)
    Dim scale As Single = Me.HScrollBar_拡大縮小.Value / 10
    Dim angle As Single = Me.HScrollBar_回転.Value
    Dim scrollOffset As PointF = New PointF(Me.HScrollBar_そしてスクロールX.Value, Me.HScrollBar_そしてスクロールY.Value)

    ' 変換ルール(逆順に適用される。上から順に適用するには各アクセサーにSystem.Drawing.Drawing2D.MatrixOrder.Appendを与える)
    .TranslateTransform(scrollOffset.X, scrollOffset.Y)             ' 4. スクロール
    .TranslateTransform(origin.X, origin.Y)                         ' 3. 中心が本来の位置になるよう移動
    .ScaleTransform(scale, scale)                                   ' 2. 拡大・縮小
    .RotateTransform(angle)                                         ' 1. (0, 0)を中心に回転
    .DrawImage(Me.PictureBox_見えない.Image, -origin.X, -origin.Y)  ' 0. (0, 0)に回転と拡大の中心を合わせるように描画
End With
End Sub


コード内のオブジェクト名は、このスクリーンショットでご想像頂ける通り。


Forms.PictureBox → Forms.Panelへ描画する際に座標変換。
そのとき拡大・縮小、回転、スクロールを一度に行なってる。

改良案
  • ちらつき防止のため、出力先を非表示Bitmapへ。それ以降の表示はPaintイベントで。
  • 対象Graphicsの設定を変えて画質調整。
  • 回転の中心(= 拡大縮小の中心)を入力可能にする。
  • 画像が大きい場合、表示する分だけクリッピングして、処理量軽量化。
  • ペンタブレットに適切なUIを実装する。
    • スクロールはドラッグ中の移動量から。
    • 回転は中心との位置関係から。Math.Atan2()を使用して。
    • 拡大・縮小はドラッグ中のポインター位置 ─ 中心間の距離から。