ぼかしの高速化

<戻る

ここに載せてあるソースコードは、参考のために載せてあります

サンプルコードは、一番下にLZHとしてあります




Option Explicit

'ピクセル色を取得する
Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long) As Long

'ピクセル色を描画する
Private Declare Function SetPixel Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal crColor As Long) As Long

'画像の転送する
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nheight As Long, ByVal hdcSrc As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long

'オブジェクトを選択する
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long

'オブジェクトを開放する
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long

'指定したDCとコンパチなDCを作る
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long

'DCを削除する
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long

'指定したDCに割り当てられているものと互換のBitmapオブジェクトを作る
Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nheight As Long) As Long

'キャンセルフラグです
Private mCancel As Boolean

Public Event mPer(ByVal Per As Integer)

'処理をキャンセルします
Sub Cancel()
    mCancel = True
End Sub

'ぼかし関数です
Sub Shade(ByVal srcDC As Long, ByVal srcWidth As Long, ByVal srcHeight As Long, ByVal dstDC As Long, ByVal Influence As Integer)
    Dim lngRet          As Long
    Dim lngSrcHDC       As Long
    Dim lngDstHDC       As Long
    Dim lngSrcHBITMAP   As Long
    Dim lngDstHBITMAP   As Long
    
    '仮想hDCの収得
    lngSrcHDC = CreateCompatibleDC(srcDC)
    lngDstHDC = CreateCompatibleDC(srcDC)
    
    '仮想ビットマップを作成します
    lngSrcHBITMAP = CreateCompatibleBitmap(srcDC, srcWidth, srcHeight)
    lngDstHBITMAP = CreateCompatibleBitmap(srcDC, srcWidth, srcHeight)
    
    'lngSrcHDCへ仮想ビットマップを割付します
    lngRet = SelectObject(lngSrcHDC, lngSrcHBITMAP)
    'lngDstHDCへ仮想ビットマップを割付します
    lngRet = SelectObject(lngDstHDC, lngDstHBITMAP)
    
    'lngSrcHDCへ画像をコピーします
    lngRet = BitBlt(lngSrcHDC, 0, 0, srcWidth, srcHeight, srcDC, 0, 0, vbSrcCopy)
    
    QuickShade lngSrcHDC, srcWidth, srcHeight, lngDstHDC, Influence
    
    '処理がキャンセルされていれば
    '処理中の画像を反映しないようにします
    If mCancel = False Then
        lngRet = BitBlt(dstDC, 0, 0, srcWidth, srcHeight, lngDstHDC, 0, 0, vbSrcCopy)
    Else
        mCancel = False
    End If
    
    '仮想DCを削除します
    lngRet = DeleteDC(lngSrcHDC)
    lngRet = DeleteDC(lngDstHDC)
    '仮想ビットマップを削除します
    lngRet = DeleteObject(lngSrcHBITMAP)
    lngRet = DeleteObject(lngDstHBITMAP)
    
End Sub

'ぼかし処理をします
Private Sub QuickShade(ByVal srcHDC As Long, ByVal srcWidth As Long, ByVal srcHeight As Long, ByVal dstHDC As Long, ByVal inf As Integer)
    Dim jx              As Integer
    Dim jy              As Integer
    Dim jxMax           As Integer
    Dim jyMax           As Integer
    Dim lngBuffer(2)    As Long
    Dim lngRefColor     As Long
    Dim lngSetColor     As Long
    Dim kx              As Integer
    Dim ky              As Integer
    Dim cnt             As Long
    
    Dim flg             As Integer
    Dim kx2             As Long
    Dim kx2Max          As Long
    Dim lngSaveRed      As Long
    Dim lngSaveGreen    As Long
    Dim lngSaveBlue     As Long
    Dim lngSaveCount    As Long
    
    'ピクチャボックスのサイズを設定します
    jxMax = srcWidth
    jyMax = srcHeight
    
    'ぼかし処理をします
    For jy = 0 To jyMax
        For jx = 0 To jxMax
            
            'インクリメント用の変数なので
            'ここで初期化しておきます
            lngBuffer(0) = 0: lngBuffer(1) = 0: lngBuffer(2) = 0
            
            If jx = inf And jy >= inf And jy <= jyMax - inf Then
                '内側の処理へ入る前の処理です
                '左側のエリアの平均色を求めます
                flg = 1
                GoSub SubShade
                GoSub SubShade2
                
            ElseIf jx >= inf And jx <= jxMax - inf And jy >= inf And jy <= jyMax - inf Then
                '内側の処理です
                '右側のピクセルの平均色を求めます
                flg = 2
                GoSub SubShade
                GoSub SubShade2
                
            Else
                '外側の処理です
                '通常のぼかし処理をします
                flg = 0
                GoSub SubShade
            End If
            
            '最終的にlngSetColorの色を描画します
            SetPixel dstHDC, jx, jy, lngSetColor
        Next jx
        DoEvents
        RaiseEvent mPer((jy / jyMax) * 100)
        If mCancel = True Then Exit Sub
    Next jy
        
    Exit Sub
    
SubShade:
    cnt = 0
    
    'フラグに応じて
    'ピクセル色を取得するエリアを限定します
    If flg = 0 Then
        kx2 = -inf
        kx2Max = inf
    ElseIf flg = 1 Then
        kx2 = -inf
        kx2Max = inf - 1
    ElseIf flg = 2 Then
        kx2 = inf - 1
        kx2Max = inf
    End If
    
    'ピクセル色の取得をします
    For ky = -inf To inf
        For kx = kx2 To kx2Max
            If (jx >= kx And jx <= jxMax - kx) And (jy >= ky And jy <= jyMax - ky) Then
                lngRefColor = GetPixel(srcHDC, jx + kx, jy + ky)
                If Not (lngRefColor <= -1) Then
                    lngBuffer(0) = lngBuffer(0) + lngRefColor Mod &H100
                    lngBuffer(1) = lngBuffer(1) + (lngRefColor Mod &H10000) \ &H100
                    lngBuffer(2) = lngBuffer(2) + lngRefColor \ &H10000
                    cnt = cnt + 1
                End If
            End If
    Next kx, ky
    If cnt = 0 Then Stop
    
    '取得したピクセルを保存しておきます
    If Not (flg = 0) Then
        lngSaveRed = lngBuffer(0)
        lngSaveGreen = lngBuffer(1)
        lngSaveBlue = lngBuffer(2)
        lngSaveCount = cnt
    End If
    
    '描画するピクセル色を決定します
    lngSetColor = RGB(lngBuffer(0) ¥ cnt, lngBuffer(1) ¥ cnt, lngBuffer(2) ¥ cnt)
    Return
    
SubShade2:
    
    '右端ピクセルだけを取得します
    cnt = 0
    For ky = -inf To inf
        lngRefColor = GetPixel(srcHDC, jx + inf, jy + ky)
        lngBuffer(0) = lngBuffer(0) + lngRefColor Mod &H100
        lngBuffer(1) = lngBuffer(1) + (lngRefColor Mod &H10000) \ &H100
        lngBuffer(2) = lngBuffer(2) + lngRefColor \ &H10000
        cnt = cnt + 1
    Next
    If cnt = 0 Then Stop
    
    '保存しておいた値と、
    '今取得した値の平均値を出してRGBに変換します
    lngSetColor = RGB( _
              (lngBuffer(0) ¥ cnt + lngSaveRed) ¥ (lngSaveCount + 1) _
            , (lngBuffer(1) ¥ cnt + lngSaveGreen) ¥ (lngSaveCount + 1) _
            , (lngBuffer(2) ¥ cnt + lngSaveBlue) ¥ (lngSaveCount + 1))
    
    '次に使用するときのために保存しておきます
    lngSaveRed = lngBuffer(0)
    lngSaveGreen = lngBuffer(1)
    lngSaveBlue = lngBuffer(2)
    lngSaveCount = cnt
    Return
    
End Sub





<戻る

Sample62.lzh


http://hp.vector.co.jp/authors/VA015521/