Jump to content

GDI+ Question Regarding a ScreenCapture->Blur->ReturnBitmapHandle sequence...


tip
 Share

Recommended Posts

Hi to all,

     Recently I've been trying to create a routine to ScreenCapture a window, apply a blur effect to the captured image, return the blurred image bitmap handle and finally apply that bitmap to a PicCtrl using _SetBitmapToCtrl function. (I believe it is written by Zedna.) But I'm having hard time understanding how the GDI+ functions exactly work.

     I had found several blur effect scripts on the forum. One script has very gaussian-blur-like effect but it applies final bitmap directly to window(_WinAPI_GetDC etc.), the other one returns final bitmaps handle but the effect isn't as realistic imho. First one is written by Siao, can be found here: and the second one is written by UEZ, can be found here

     I've tried to integrate these two script and failed :graduated: Here is the last draft:

#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#Include <ScreenCapture.au3>
 
_Main()
 
Func _WindowCapture_Blurred($i_HWND1)
 
Local $sRatio = 3, $iInterMode = 7, $iPixOffsetMode = 2, $iSmoothMode = 7
 
Local $tip_WindowClientInfo = _WinGetClientPos_Ex($i_HWND1,True)
 
_GDIPlus_Startup()
 
Local $hScreenCapture = _ScreenCapture_Capture("", $tip_WindowClientInfo[0],$tip_WindowClientInfo[1],$tip_WindowClientInfo[0]+$tip_WindowClientInfo[2],$tip_WindowClientInfo[1]+$tip_WindowClientInfo[3], False)
Local $hBitmapBig = _GDIPlus_BitmapCreateFromHBITMAP($hScreenCapture)
Local $hBitmapSmall = _GDIPlus_BitmapCloneArea($hBitmapBig, 0, 0, $tip_WindowClientInfo[2]/$sRatio, $tip_WindowClientInfo[3]/$sRatio)
Local $hGraphicSmall = _GDIPlus_ImageGetGraphicsContext($hBitmapSmall)
 
Local $hGraphicBig = _GDIPlus_GraphicsCreateFromHWND(_WinAPI_GetDesktopWindow())
 
;~  ;http://msdn2.microsoft.com/en-us/library/ms534141(VS.85).aspx
;~  ;InterpolationModeDefault = 0
;~  ;InterpolationModeLowQuality = 1
;~  ;InterpolationModeHighQuality = 2
;~  ;InterpolationModeBilinear = 3
;~  ;InterpolationModeBicubic = 4
;~  ;InterpolationModeNearestNeighbor = 5
;~  ;InterpolationModeHighQualityBilinear = 6
;~  ;InterpolationModeHighQualityBicubic = 7
    DllCall("gdiplus.dll", "int", "GdipSetInterpolationMode", "hwnd", $hGraphicBig, "int", $iInterMode)
    DllCall("gdiplus.dll", "int", "GdipSetInterpolationMode", "hwnd", $hGraphicSmall, "int", $iInterMode)
;~  ;http://msdn2.microsoft.com/en-us/library/ms534169(VS.85).aspx
;~  ;PixelOffsetModeDefault = 0 = PixelOffsetModeNone
;~  ;PixelOffsetModeHighSpeed = 1 = PixelOffsetModeNone
;~  ;PixelOffsetModeHighQuality = 2 = PixelOffsetModeHalf
;~  ;PixelOffsetModeNone = 3
;~  ;PixelOffsetModeHalf = 4
    DllCall("gdiplus.dll", "int", "GdipSetPixelOffsetMode", "hwnd", $hGraphicBig, "int", $iPixOffsetMode)
   DllCall("gdiplus.dll", "int", "GdipSetPixelOffsetMode", "hwnd", $hGraphicSmall, "int", $iPixOffsetMode)
;~  ;http://msdn2.microsoft.com/en-us/library/ms534173(VS.85).aspx
;~  ;SmoothingModeDefault = 0 = SmoothingModeNone
;~  ;SmoothingModeHighSpeed = 1 = SmoothingModeNone
;~  ;SmoothingModeHighQuality = 2 = SmoothingModeAntiAlias8x4
;~  ;SmoothingModeNone
;~  ;SmoothingModeAntiAlias8x4
;~  ;SmoothingModeAntiAlias = SmoothingModeAntiAlias8x4
;~  ;SmoothingModeAntiAlias8x8
    DllCall("gdiplus.dll", "int", "GdipSetSmoothingMode", "hwnd", $hGraphicBig, "int", $iSmoothMode)
    DllCall("gdiplus.dll", "int", "GdipSetSmoothingMode", "hwnd", $hGraphicSmall, "int", $iSmoothMode)
 
_GDIPlus_GraphicsDrawImageRect($hGraphicSmall, $hBitmapBig, 0, 0, $tip_WindowClientInfo[2], $tip_WindowClientInfo[3])
    _GDIPlus_GraphicsDrawImageRect($hGraphicBig, $hBitmapSmall, 0, 0, $tip_WindowClientInfo[2] / $sRatio, $tip_WindowClientInfo[3] / $sRatio)
 
$aRet = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmapBig)
 
_WinAPI_DeleteObject($hScreenCapture)
_GDIPlus_GraphicsDispose($hGraphicSmall)
_GDIPlus_GraphicsDispose($hGraphicBig)
_GDIPlus_BitmapDispose($hBitmapSmall)
_GDIPlus_BitmapDispose($hBitmapBig)
_GDIPlus_Shutdown()
    Return $aRet
EndFunc
 
Func _Main()
$Form1 = GUICreate("WindowCapture_Blurred Tryout", 640, 540, (@DesktopWidth-640)/2, (@DesktopHeight-560)/2)
    GUISetFont(10, 400, 0, "Segoe UI" ,$Form1,5)
    GUICtrlSetDefBkColor(-2,$Form1)
    GUISetBkColor(0x000000,$Form1)
$MenuItem1 = GUICtrlCreateMenu("&File")
$MenuItem2 = GUICtrlCreateMenuItem("Exit", $MenuItem1)
$Label1 = GUICtrlCreateLabel("     Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." _
     & " Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute" _
     & " irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat" _
     & " cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." & @CRLF & @CRLF & "    Suspendisse potenti. Fusce semper consequat suscipit. Quisque porttitor est eu felis pharetra lacinia. Donec mauris massa, aliquet " _
     & "vitae consectetur quis, laoreet in dolor. Cras fermentum vestibulum nulla, eget sollicitudin elit porttitor id. Nunc sapien nulla, blandit " _
     & "pellentesque sollicitudin et, dignissim non justo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. " _
     & "Vivamus congue ligula sed diam vehicula suscipit.", 30, 60, 580, 200)
GUICtrlSetColor(-1, 0xFFFFFF)
$Button1 = GUICtrlCreateButton("Try", 240, 300, 120, 25)
GUISetState(@SW_SHOW)
While 1
  $nMsg = GUIGetMsg()
  Switch $nMsg
   Case -3, $MenuItem2            ;   -3=$GUI_EVENT_CLOSE
    ExitLoop
   Case $Button1
    $a = _WinGetClientPos_Ex($Form1,True)
    $GUI2 = GUICreate("",$a[2],$a[3],$a[0]+$a[2],$a[1])
    $PicCtl = GUICtrlCreatePic("",0,0,$a[2],$a[3])
    $BlurredSS = _WindowCapture_Blurred($Form1)
     GUISetState()
    _SetBitmapToCtrl($PicCtl,$BlurredSS)
   EndSwitch
  WEnd
EndFunc
 
Func _SetBitmapToCtrl($CtrlId, $hBitmap)
    Local Const $STM_SETIMAGE = 0x0172
    Local Const $IMAGE_BITMAP = 0
    Local Const $SS_BITMAP = 0xE
    Local Const $GWL_STYLE = -16
    Local $hWnd = GUICtrlGetHandle($CtrlId)
    If $hWnd = 0 Then Return SetError(1, 0, 0)
        ; set SS_BITMAP style to control
    Local $oldStyle = DllCall("user32.dll", "long", "GetWindowLong", "hwnd", $hWnd, "int", $GWL_STYLE)
    If @error Then Return SetError(2, 0, 0)
    DllCall("user32.dll", "long", "SetWindowLong", "hwnd", $hWnd, "int", $GWL_STYLE, "long", BitOR($oldStyle[0], $SS_BITMAP))
    If @error Then Return SetError(3, 0, 0)
        Local $oldBmp = DllCall("user32.dll", "hwnd", "SendMessage", "hwnd", $hWnd, "int", $STM_SETIMAGE, "int", $IMAGE_BITMAP, "int", $hBitmap)
    If @error Then Return SetError(4, 0, 0)
    If $oldBmp[0] <> 0 Then _WinAPI_DeleteObject($oldBmp[0])
    Return 1
EndFunc
 
Func _WinGetClientPos_Ex($i_tip_Hwnd, $i_tip_ConsiderMenu = False)
If Not WinExists($i_tip_Hwnd) Or Not IsHWnd($i_tip_Hwnd) Then Return SetError(1,0,-1)
Local $i_tip_WinPos, $i_tip_ClientSize, $i_tip_BorderThickness, $i_tip_aRet
$i_tip_WinPos = WinGetPos($i_tip_Hwnd)
$i_tip_ClientSize = _WinGetClientSize_Ex($i_tip_Hwnd)
$i_tip_BorderThickness = ($i_tip_WinPos[2] - $i_tip_ClientSize[0])/2
Dim $i_tip_aRet[4] = [$i_tip_WinPos[0] + $i_tip_BorderThickness, $i_tip_WinPos[1] + ($i_tip_WinPos[3] - $i_tip_ClientSize[1]) - $i_tip_BorderThickness, $i_tip_ClientSize[0], $i_tip_ClientSize[1]]
If $i_tip_ConsiderMenu = True And $i_tip_ClientSize[2] > 0 Then
  $i_tip_aRet[1] -= $i_tip_ClientSize[2]
  $i_tip_aRet[3] = $i_tip_ClientSize[3]
EndIf
Return $i_tip_aRet
EndFunc ;==>_WinGetClientPos_Ex
 
Func _WinGetClientSize_Ex($i_tip_Hwnd)
If Not WinExists($i_tip_Hwnd) Or Not IsHWnd($i_tip_Hwnd) Then Return SetError(1,0,-1)
Local $i_tip_MenuExists, $i_tip_MenuExists, $i_tip_aRet
$i_tip_MenuExists = DllCall("User32.dll", "handle", "GetMenu", "hwnd", $i_tip_Hwnd)   ; We are checking if parent gui has a menu.
If @error Then
  $i_tip_MenuExists = 0
Else
  $i_tip_MenuExists = $i_tip_MenuExists[0]
  If $i_tip_MenuExists  > 0 Then
   $i_tip_MenuExists  = 20
  Else
   $i_tip_MenuExists  = 0
  EndIf
EndIf
$i_tip_aRet = WinGetClientSize($i_tip_Hwnd)
If IsArray($i_tip_aRet) = 0 Then
  Return SetError(2,0,-1)
Else
  ReDim $i_tip_aRet[4]
  $i_tip_aRet[2] = $i_tip_MenuExists
  $i_tip_aRet[3] = $i_tip_aRet[1] + $i_tip_aRet[2]
  Return $i_tip_aRet
EndIf
EndFunc ;==>_WinGetClientSize_Ex

     If you can point me to right direction I'd be very glad.

Sincerely

Tip

Edited by tip

[center]MsgBox_Tipped: Eye candy msgboxes/inputboxes/loginboxes. | CreateBlankBox: Semi-transparent layers with borders and rounded corners.[/center]

Link to comment
Share on other sites

Try this one:

#include <ScreenCapture.au3>
#include <GUIConstantsEx.au3>
Opt("MustDeclareVars", 1)

Global Const $IMAGE_BITMAP = 0
Global Const $STM_SETIMAGE = 0x0172

_GDIPlus_Startup()
Global Const $hGUI = GUICreate("Blur Image and send to Pic Control", 285, 402)
Global Const $idPic = GUICtrlCreatePic("", 28, 40, 228, 322)
GUISetState()

Global Const $pid = Run("calc.exe")
ProcessWait($pid)


Global $hHBITMAP = _ScreenCapture_CaptureWnd("", WinGetHandle("[CLASS:CalcFrame]")) ;capture screen
Sleep(500)
ProcessClose($pid)

Global $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hHBITMAP) ;convert to GDI+ bitmap
_WinAPI_DeleteObject($hHBITMAP) ;delete image object because not needed anymore
Global Const $hBitmap_Blur = _Blur($hBitmap, 228, 322) ;blur GDI+ image
_GDIPlus_BitmapDispose($hBitmap) ;dispose bitmap because not needed anymore
$hHBITMAP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap_Blur) ;convert GDI+ bitmap to WinAPI bitmap (reuse of same variable)
_GDIPlus_BitmapDispose($hBitmap_Blur) ;dispose bitmap because not needed anymore
_WinAPI_DeleteObject(GUICtrlSendMsg($idPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBITMAP)) ;send bitmap to picture control

Global $msg

Do
    $msg = GUIGetMsg()
Until $msg = $GUI_EVENT_CLOSE

_WinAPI_DeleteObject($hHBITMAP)
_GDIPlus_Shutdown()
GUIDelete($hGUI)

Exit

Func _Blur($hBitmap, $iW, $iH, $fScale = 0.666666, $qual = 6); by eukalyptus
    Local $hGraphics = _GDIPlus_GraphicsCreateFromHWND(_WinAPI_GetDesktopWindow())
    Local $hBmpSmall = _GDIPlus_BitmapCreateFromGraphics($iW, $iH, $hGraphics)
    Local $hGfxSmall = _GDIPlus_ImageGetGraphicsContext($hBmpSmall)
    DllCall($ghGDIPDll, "uint", "GdipSetPixelOffsetMode", "hwnd", $hGfxSmall, "int", 2)
    Local $hBmpBig = _GDIPlus_BitmapCreateFromGraphics($iW, $iH, $hGraphics)
    Local $hGfxBig = _GDIPlus_ImageGetGraphicsContext($hBmpBig)
    DllCall($ghGDIPDll, "uint", "GdipSetPixelOffsetMode", "hwnd", $hGfxBig, "int", 2)
    DllCall($ghGDIPDll, "uint", "GdipScaleWorldTransform", "hwnd", $hGfxSmall, "float", $fScale, "float", $fScale, "int", 0)
    DllCall($ghGDIPDll, "uint", "GdipSetInterpolationMode", "hwnd", $hGfxSmall, "int", $qual)
    DllCall($ghGDIPDll, "uint", "GdipScaleWorldTransform", "hwnd", $hGfxBig, "float", 1 / $fScale, "float",  1 / $fScale, "int", 0)
    DllCall($ghGDIPDll, "uint", "GdipSetInterpolationMode", "hwnd", $hGfxBig, "int", $qual)
    _GDIPlus_GraphicsDrawImageRect($hGfxSmall, $hBitmap, 0, 0, $iW, $iH)
    _GDIPlus_GraphicsDrawImageRect($hGfxBig, $hBmpSmall, 0, 0, $iW, $iH)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_BitmapDispose($hBmpSmall)
    _GDIPlus_GraphicsDispose($hGfxSmall)
    _GDIPlus_GraphicsDispose($hGfxBig)
    Return $hBmpBig
EndFunc   ;==>_Blur

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

UEZ, thanks for the quick reply. I had used your function but the blur effect is a bit distorted in comparison to Siao's. (I get that you didn't read the whole post :graduated:)

That's why I've tried to combine your code and his. Can you look at the code in the first post and help me to figure out what is wrong ;)

[center]MsgBox_Tipped: Eye candy msgboxes/inputboxes/loginboxes. | CreateBlankBox: Semi-transparent layers with borders and rounded corners.[/center]

Link to comment
Share on other sites

Just play with the $fScale value :graduated:

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

  • 4 weeks later...

Thank you very much UEZ.

Finally I've figured out how to make blur effect more like gaussian blur. "GdipSetSmoothingMode" dllcall is what I needed. :D

Here is the code.

Func _GDIPlus_ImageBlur($hBitmap, $iStrenght = 3, $i_WinAPIBMP = False)
    If $iStrenght <= 1 Then $iStrenght = 1.01
    $iStrenght = 1/$iStrenght

    Local $hGraphics = _GDIPlus_GraphicsCreateFromHWND(_WinAPI_GetDesktopWindow())
    $hBitmapWidth = _GDIPlus_ImageGetWidth($hBitmap)
    $hBitmapHeight = _GDIPlus_ImageGetHeight($hBitmap)
    Local $hBmpSmall = _GDIPlus_BitmapCreateFromGraphics($hBitmapWidth, $hBitmapHeight, $hGraphics)
    Local $hGfxSmall = _GDIPlus_ImageGetGraphicsContext($hBmpSmall)
    DllCall($ghGDIPDll, "uint", "GdipSetPixelOffsetMode", "hwnd", $hGfxSmall, "int", 2)
    Local $hBmpBig = _GDIPlus_BitmapCreateFromGraphics($hBitmapWidth, $hBitmapHeight, $hGraphics)
    Local $hGfxBig = _GDIPlus_ImageGetGraphicsContext($hBmpBig)
    DllCall($ghGDIPDll, "uint", "GdipSetSmoothingMode", "hwnd", $hGfxBig, "int", 7)
    DllCall($ghGDIPDll, "uint", "GdipSetSmoothingMode", "hwnd", $hGfxSmall, "int", 7)
    DllCall($ghGDIPDll, "uint", "GdipSetPixelOffsetMode", "hwnd", $hGfxBig, "int", 2)
    DllCall($ghGDIPDll, "uint", "GdipScaleWorldTransform", "hwnd", $hGfxSmall, "float", $iStrenght, "float", $iStrenght, "int", 0)
    DllCall($ghGDIPDll, "uint", "GdipSetInterpolationMode", "hwnd", $hGfxSmall, "int", 7)
    DllCall($ghGDIPDll, "uint", "GdipScaleWorldTransform", "hwnd", $hGfxBig, "float", 1 / $iStrenght, "float",  1 / $iStrenght, "int", 0)
    DllCall($ghGDIPDll, "uint", "GdipSetInterpolationMode", "hwnd", $hGfxBig, "int", 7)
    _GDIPlus_GraphicsDrawImageRect($hGfxSmall, $hBitmap, 0, 0, $hBitmapWidth, $hBitmapHeight)
    _GDIPlus_GraphicsDrawImageRect($hGfxBig, $hBmpSmall, 0, 0, $hBitmapWidth, $hBitmapHeight)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_BitmapDispose($hBmpSmall)
    _GDIPlus_GraphicsDispose($hGfxSmall)
    _GDIPlus_GraphicsDispose($hGfxBig)

    If $i_WinAPIBMP = True Then
        Local $hHBITMAP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmpBig) ;convert GDI+ bitmap to WinAPI hbitmap
        _GDIPlus_BitmapDispose($hBmpBig)
        Return $hHBITMAP
    Else
        Return $hBmpBig
    EndIf
EndFunc   ;==>_GDIPlus_ImageBlur

Thanks again. Both UEZ and Siao...

Regards,

Tip

[center]MsgBox_Tipped: Eye candy msgboxes/inputboxes/loginboxes. | CreateBlankBox: Semi-transparent layers with borders and rounded corners.[/center]

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...