[リストへもどる]
一括表示

投稿時間:2003/05/22(Thu) 14:17
投稿者名:だいすけ
Eメール:daisuke-k@vanskg.jp
URL :
タイトル:
表示の拡大縮小について
今、ペイントのようなものをつくろうとしているんですが、
表示の拡大・縮小機能(虫眼鏡の機能)の作り方が分かりません。

まず、描画用のキャンバスと表示用のキャンバスを分けて考えて、
描画を行うのは100%のキャンバスに対してだけにし、
キャンバスの4倍表示の画像を出したいときは、その100%の
画像に対して、4倍表示を行い、その後、描画された絵を拡大表示
という形をとっているんですが、拡大するときや、描画を行うとき、
処理をとろうとするときに、キャンバスのサイズが大きければ大きいほど
処理が鈍く、最後には動かなくなってしまいます。

そういうわけで、描画をおこなったところだけ、行おうとしてるとこだけを
表示してやればいいわけだから、4倍表示は100%の描画したい場所を
拡大して表示という形をとればいいと考えたんですが、
その100%の絵の座標と4倍した絵の座標の取り方が分かりません。
どうやったらうまくいくのでしょうか?誰か助けて下さい。

投稿時間:2003/05/22(Thu) 15:08
投稿者名:Say
Eメール:
URL :
タイトル:
Re: 表示の拡大縮小について
質問の意味がつかみづらいのですが、こういうことでしょうか?

Option Explicit

Private Sub Form_Load()
    Picture1.AutoSize = True
    Picture1.Picture = LoadPicture("C:\WinNT\winnt.bmp")
    Picture2.Width = Picture1.Width
    Picture2.Height = Picture1.Height
End Sub


Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Picture2.Cls
    Picture2.PaintPicture Picture1, _
                          0, _
                          0, _
                          Picture1.Width, _
                          Picture1.Height, _
                          X, _
                          Y, _
                          Picture1.Width / 4, _
                          Picture1.Height / 4

                          
End Sub

投稿時間:2003/05/22(Thu) 15:40
投稿者名:だいすけ
Eメール:daisuke-k@vanskg.jp
URL :
タイトル:
表示の拡大縮小について
そういうことなんですけどね。 

それだと、1/4倍したPictureBoxに対しての描画はなんら問題ないかも知れないですが、
その1/4倍した画像を2倍、4倍していくと、その画像は段だん劣化していっちゃいますよね?

だから、拡大や縮小を行ったPictureBoxに対しては描画は行っても
意味のないことになりますよね?

おそらく、拡大縮小を行っただけで画像がきたなくなる
ペイントなんで誰も使いたくないですもの。。。

だから、画像を描画するためだけのPictureBoxと描画してるように見えるようにするための
表示する用のPictureBoxを用意し、100%以外の画像に描画が行われようとしたときは、
今のキャンバスが100%に対して何%か調べ、MouseDown-Move-Upされた座標に対して、
その比率をかけてかけてやります。

その比率をかけてやることで、100%のPictureBoxの座標系にかわりますよね?

それで100%の縮尺のPictureboxに対して描画を行い、StretchBltで表示用のキャンバスに返してやるという作業をしてるわけです。

でも、このとき。PictureBox(描画用)のleft-top,left+width,top+heightの位置を全てStretchBlt
すると、転送しようとしてる画像が大きすぎるため、処理が遅く、最後にはとまってしまうわけです。

だから、100%のキャンバスに対して描画を行い、拡大縮小の表示用のキャンバスにデータを転送するときに、描画を行った部位のみ転送してやれば、問題は解消されると考えたのですが、
表示用のキャンバスの座標と描画用のキャンバスの座標をどうやってとっていいのかわからないんです。

やっぱ、まだ分かりにくいですかね。。。

投稿時間:2003/05/22(Thu) 17:29
投稿者名:Say
Eメール:
URL :
タイトル:
Re: 表示の拡大縮小について
> それだと、1/4倍したPictureBoxに対しての描画はなんら問題ないかも知れないですが、
> その1/4倍した画像を2倍、4倍していくと、その画像は段だん劣化していっちゃいますよね?

?
ピクセルの整数倍は原理的に劣化はありません。

> だから、拡大や縮小を行ったPictureBoxに対しては描画は行っても
> 意味のないことになりますよね?

それは個人の価値観の問題です。

> おそらく、拡大縮小を行っただけで画像がきたなくなる
> ペイントなんで誰も使いたくないですもの。。。

原理的に拡大縮小は劣化を伴います。
劣化しないのは、ピクセルを整数倍に拡大し、
同じ倍率で縮小した場合のみです。
ただし、拡大画面に変更を加えるとき、変更の加え方が
元画面のピクセルの整数倍単位でなかった場合、縮小したときに劣化します。


拡大画面つきペイントのようなソフトを作ろうとしているのではありませんか?
描画が発生するたびにStretchBltで画像転送しまくっていたら遅くなるのは当然です。

画像読み込みのときはともかく、画像編集処理はライン描画やフィルタ処理などになるのではありませんか?
それならば、両方のPictureBoxに描画すればいいだけではないでしょうか?
たとえば、自由曲線の場合こんな感じ。
(手抜きですから縮小画面のほうがちょっとだけ劣化します。それがいやなら、
ブレセンハムのアルゴリズムなど用いて、Lineルーチンを自作する必要があります。)

Option Explicit
Dim x_bai As Long
Dim y_bai As Long
Dim x0 As Single
Dim y0 As Single

Dim lngDrawFlg1 As Long
Dim lngDrawFlg2 As Long
Private Sub Form_Load()
    Picture1.AutoRedraw = True
    Picture2.AutoRedraw = True
    Picture1.ScaleMode = vbPixels
    Picture2.ScaleMode = vbPixels
    x_bai = 2
    y_bai = 2
    Picture2.Width = Picture1.Width * x_bai
    Picture2.Height = Picture1.Height * y_bai
    lngDrawFlg1 = 0
    lngDrawFlg2 = 0
End Sub

Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    lngDrawFlg1 = 1
    x0 = X
    y0 = Y
End Sub

Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Dim x1 As Single
    Dim y1 As Single
    Dim x2 As Single
    Dim y2 As Single
    Dim x3 As Single
    Dim y3 As Single
    If lngDrawFlg1 = 1 Then
        x1 = X
        y1 = Y
        x2 = x0 * x_bai
        y2 = y0 * y_bai
        x3 = x1 * x_bai
        y3 = y1 * y_bai
        Picture2.Line (x2, y2)-(x3, y3)
        Picture2.Line (x2 + 1, y2)-(x3 + 1, y3)
        Picture2.Line (x2, y2 + 1)-(x3, y3 + 1)
        Picture2.Line (x2 + 1, y2 + 1)-(x3 + 1, y3 + 1)
        Picture1.Line (x0, y0)-(x1, y1)
        x0 = x1
        y0 = y1
    End If
End Sub

Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    lngDrawFlg1 = 0
End Sub

Private Sub Picture2_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    lngDrawFlg2 = 1
    x0 = X \ x_bai
    y0 = Y \ y_bai
End Sub

Private Sub Picture2_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Dim x1 As Single
    Dim y1 As Single
    Dim x2 As Single
    Dim y2 As Single
    Dim x3 As Single
    Dim y3 As Single
    If lngDrawFlg2 = 1 Then
        x1 = X \ x_bai
        y1 = Y \ y_bai
        x2 = x0 * x_bai
        y2 = y0 * y_bai
        x3 = x1 * x_bai
        y3 = y1 * y_bai
        Picture2.Line (x2, y2)-(x3, y3)
        Picture2.Line (x2 + 1, y2)-(x3 + 1, y3)
        Picture2.Line (x2, y2 + 1)-(x3, y3 + 1)
        Picture2.Line (x2 + 1, y2 + 1)-(x3 + 1, y3 + 1)
        Picture1.Line (x0, y0)-(x1, y1)
        x0 = x1
        y0 = y1
    End If
End Sub

Private Sub Picture2_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    lngDrawFlg2 = 0
End Sub

投稿時間:2003/05/22(Thu) 18:22
投稿者名:だいすけ
Eメール:daisuke-k@vanskg.jp
URL :
タイトル:
表示の拡大縮小について
わざわざソースまで作って頂きまして本当に有難う御座います。
本当に助かります。

この方法をとれば、拡大・縮小してる画像に描きこまれたときは
100%のほうにも描画されますし、100%のほうに描かれた時は
拡大・縮小を行ったキャンバスに対しても描画が行えますね^^;

でも、ちなみに、このときなんですが、
線の太さはどうやって判断させることができるんですかね??

単純に
Picture1.DrawWidth=Picture1.DrawWidth * Percentみたいにやってできたりしちゃうんですか?

あと、直線・円などを描画するときはどうやって描画したらいいんですかね^^;

ご教授お願いします。

投稿時間:2003/05/22(Thu) 18:51
投稿者名:Say
Eメール:
URL :
タイトル:
Re: 表示の拡大縮小について
> 線の太さはどうやって判断させることができるんですかね??
> 単純に
> Picture1.DrawWidth=Picture1.DrawWidth * Percentみたいにやってできたりしちゃうんですか?
>
> あと、直線・円などを描画するときはどうやって描画したらいいんですかね^^;
>

人の「作る楽しみ」を奪うほど、私は野暮ではありません。
基本的な描画命令はご存知でしょうから、いろいろ試してみてください。
描画系のプログラムは、結果が目に見えますので、試してみて
失敗したら失敗したでなかなか楽しいものです。(変な図が描けたりして)

自分で苦労して作ったほうが、出来上がった喜びもまたひとしおです。

いろいろやって、どうしてもわからないところだけ、具体的に質問してはいかがでしょう?

投稿時間:2003/05/22(Thu) 18:57
投稿者名:だいすけ
Eメール:daisuke-k@vanskg.jp
URL :
タイトル:
表示の拡大縮小について
そうですね。

自分の考えが怪しいので、確認してみたかったんですけど
とりあえず試しまくってみることが先決ですね。

色々教えてくださって有難うございました。

p.s.自分で立てたスレを読み返してみて、
失言をしてしまってた部位がありましたことを
深くお詫び申しあげます。すいませんでした。
また何かあったときは是非ともよろしくお願いします。