Sign in to follow this  
Followers 0
pixartist

Blurring the screen!?

16 posts in this topic

#1 ·  Posted (edited)

ok first, here is my script :

#include <GUIConstants.au3>
HotKeySet("{F10}", "blur")


Func blur()
    
    $dc = DllCall("user32.dll", "int", "GetDC", "hwnd", "")
    $memory_dc = DllCall("gdi32.dll", "hwnd", "CreateCompatibleDC", "hwnd", $dc[0])
    $memory_bm = DllCall("gdi32.dll", "hwnd", "CreateCompatibleBitmap", "ptr", $dc[0], "int", @DesktopWidth, "int", @DesktopHeight)
    DllCall("gdi32.dll", "hwnd", "SelectObject", "hwnd", $memory_dc[0], "hwnd", $memory_bm[0])
    DllCall("gdi32.dll", "int", "BitBlt", "hwnd", $memory_dc[0], "int", 0, "int", 0, "int", @DesktopWidth, "int", @DesktopHeight, "hwnd", $dc[0], "int", 0, "int", 0, "int", 0xCC0020)
    Dim $x, $y, $cc, $t, $b, $l, $r
    for $x = 1 to @DesktopWidth-1
        for $y = 1 to @DesktopHeight-1
        #cs $cc = PixelGetColor($x, $y )
            $t = PixelGetColor($x, $y -1)
            $b = PixelGetColor($x, $y +1)
            $l = PixelGetColor($x-1, $y )
            $r = PixelGetColor($x+1, $y )
        #ce
        
        $cc = DllCall("gdi32.dll", "long", "GetPixel", "long", $memory_dc[0], "long", $x, "long", $y)

        $t = DllCall("gdi32.dll", "long", "GetPixel", "long", $memory_dc[0], "long", $x, "long", $y - 1)

        $b = DllCall("gdi32.dll", "long", "GetPixel", "long", $memory_dc[0], "long", $x, "long", $y + 1)

        $l = DllCall("gdi32.dll", "long", "GetPixel", "long", $memory_dc[0], "long", $x - 1, "long", $y)

        $r = DllCall("gdi32.dll", "long", "GetPixel", "long", $memory_dc[0], "long", $x + 1, "long", $y)


        
        $rv = Floor(BitShift(BitAND(0xFF0000, $cc[0]), 16) / 5 + BitShift(BitAND(0xFF0000, $l[0]), 16) / 5 + BitShift(BitAND(0xFF0000, $r[0]), 16) / 5 + BitShift(BitAND(0xFF0000, $t[0]), 16) / 5 + BitShift(BitAND(0xFF0000, $b[0]), 16) / 5)
        ;MsgBox(0,"",$r[0]1&"-"&$r[0]2&"-"&$r[0]3&"-"&$r[0]4&"-"&$r[0]5&"-"&$r[0]v)
        $gv = Floor((BitShift(BitAND(0x00ff00, $cc[0]), 8) / 5 + BitShift(BitAND(0x00ff00, $l[0]), 8) / 5 + BitShift(BitAND(0x00ff00, $r[0]), 8) / 5 + BitShift(BitAND(0x00ff00, $t[0]), 8) / 5 + BitShift(BitAND(0x00ff00, $b[0]), 8) / 5))
        $bv = Floor((BitAND(0xFF, $cc[0]) / 5 + BitAND(0xFF, $l[0]) / 5 + BitAND(0xFF, $r[0]) / 5 + BitAND(0xFF, $t[0]) / 5 + BitAND(0xFF, $b[0]) / 5))
        DllCall("gdi32.dll", "long", "SetPixel", "long", $dc[0], "long", $x, "long", $y, "long", "0x" & Hex($rv, 2) & Hex($gv, 2) & Hex($bv, 2))
        ;MsgBox(0,"","0x"&hex($rv,2)&hex($gv,2)&hex($bv,2))
        Next
    Next
EndFunc



While 1
    
    Sleep(1)
WEnd

aso you see, i capture the screen and get the pixels from the dc in the memory, and i also use bitshift for the color-modification. how can this take like 5 minutes to blur my screen? how can i do it in < 500ms ^^ ?

edit: ok it's like 10 million dllcalls, but how should that be possible without calling dll's in the loop ?

edit2: if there was just a way to work with pixeldata in hbitmaps directly :)

Edited by pixartist

Share this post


Link to post
Share on other sites



I neatend up your code but couldn't speed it up.

If you are not creating a GUI you don't need GUIConstants.au3

HotKeySet("{F10}", "blur")

While 1
    Sleep(100)
WEnd

Func blur()
    ConsoleWrite("Going to blur!" & @CRLF)
    $dc = DllCall("user32.dll", "int", "GetDC", "hwnd", "")
    $memory_dc = DllCall("gdi32.dll", "hwnd", "CreateCompatibleDC", "hwnd", $dc[0])
    $memory_bm = DllCall("gdi32.dll", "hwnd", "CreateCompatibleBitmap", "ptr", $dc[0], "int", @DesktopWidth, "int", @DesktopHeight)
    DllCall("gdi32.dll", "hwnd", "SelectObject", "hwnd", $memory_dc[0], "hwnd", $memory_bm[0])
    DllCall("gdi32.dll", "int", "BitBlt", "hwnd", $memory_dc[0], "int", 0, "int", 0, "int", @DesktopWidth, "int", @DesktopHeight, "hwnd", $dc[0], "int", 0, "int", 0, "int", 0xCC0020)
    Dim $x, $y, $cc, $t, $b, $l, $r
    For $x = 1 To @DesktopWidth - 1
        For $y = 1 To @DesktopHeight - 1
            $cc = DllCall("gdi32.dll", "long", "GetPixel", "long", $memory_dc[0], "long", $x, "long", $y)
            $t = DllCall("gdi32.dll", "long", "GetPixel", "long", $memory_dc[0], "long", $x, "long", $y - 1)
            $b = DllCall("gdi32.dll", "long", "GetPixel", "long", $memory_dc[0], "long", $x, "long", $y + 1)
            $l = DllCall("gdi32.dll", "long", "GetPixel", "long", $memory_dc[0], "long", $x - 1, "long", $y)
            $r = DllCall("gdi32.dll", "long", "GetPixel", "long", $memory_dc[0], "long", $x + 1, "long", $y)

            $rv = Floor(BitShift(BitAND(0xFF0000, $cc[0]), 16) / 5 + BitShift(BitAND(0xFF0000, $l[0]), 16) / 5 + BitShift(BitAND(0xFF0000, $r[0]), 16) / 5 + BitShift(BitAND(0xFF0000, $t[0]), 16) / 5 + BitShift(BitAND(0xFF0000, $b[0]), 16) / 5)
            $gv = Floor((BitShift(BitAND(0x00ff00, $cc[0]), 8) / 5 + BitShift(BitAND(0x00ff00, $l[0]), 8) / 5 + BitShift(BitAND(0x00ff00, $r[0]), 8) / 5 + BitShift(BitAND(0x00ff00, $t[0]), 8) / 5 + BitShift(BitAND(0x00ff00, $b[0]), 8) / 5))
            $bv = Floor((BitAND(0xFF, $cc[0]) / 5 + BitAND(0xFF, $l[0]) / 5 + BitAND(0xFF, $r[0]) / 5 + BitAND(0xFF, $t[0]) / 5 + BitAND(0xFF, $b[0]) / 5))
            DllCall("gdi32.dll", "long", "SetPixel", "long", $dc[0], "long", $x, "long", $y, "long", "0x" & Hex($rv, 2) & Hex($gv, 2) & Hex($bv, 2))
        Next
    Next
EndFunc  ;==>blur

Share this post


Link to post
Share on other sites

Darn, if that worked I would have used it too! So this is why Windows Vista is so slow... it takes over a minute to fully "blur" my screen. Clever coding, though!

Share this post


Link to post
Share on other sites

For every pixel on your screen it collects 4 surrounding pixels. On my 24 inch monitor at 1920 x 1200 (2,304,000 pixels) it is running the GetPixel call 11,520,000 times.

Share this post


Link to post
Share on other sites

384 ms on my 1024x768 screen

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Would it be worth to get every other pixel, or every 3rd to speed it up? If you are bluring, then the pixel next to it isn't that important. Your goal is distortation, not sharp edges.

I tried this by adding Step 2 to the For loops, still slow and created more of a "lattice".

Edited by weaponx

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

I would think you could use the integrated GDI functions in 3.2.10.0. Capture the screenshot to an object and then run the blur algorithm on it, this way you aren't getting each pixel individually.

EDIT: I found a link to a C++ example of this but my eyes went crossed.

http://www.codeproject.com/KB/GDI-plus/csh...aspx?print=true

Edited by weaponx

Share this post


Link to post
Share on other sites

Darn, if that worked I would have used it too! So this is why Windows Vista is so slow... it takes over a minute to fully "blur" my screen. Clever coding, though!

That isn't how Vista works. Vista uses Pixel Shaders wich is dedicated hardware for providing the effects you are trying to do. :)

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

IMO no implementation of any gfx transform algo using only native AutoIt commands will be fast enough, especially if we are talking large resolutions. At least that's what my common sense tells me. Scripting languages are meant for other tasks.

So you're better off utilizing functions from some dlls.

Easy way is to use screen bitmap resizing with GDI+ which has various antialiasing settings.

You can play around with SetInterpolationMode, SetPixelOffsetMode etc...

For me HighQualityBilinear seems to provide the nicest blurs, especially when stretching alot.

#include <GUIConstants.au3>
#Include <ScreenCapture.au3>
#include <GDIPlus.au3>

$hGUI = GUICreate("Blurp", 200,120)
GUICtrlCreateLabel("InterpolationMode", 20, 20, 100, 20)
GUICtrlCreateLabel("Stretch ratio", 20, 50, 100, 20)
$cInputIM = GUICtrlCreateInput("6", 120, 15, 50, 20)
GUICtrlSetTip(-1, "Possible values" & @CRLF & "0 - 7")
$cInputSR = GUICtrlCreateInput("1.25", 120, 45, 50, 20)
GUICtrlSetTip(-1, "Possible values" & @CRLF & "1.0 - @DesktopHeight.0")
$cBtnBlur = GUICtrlCreateButton("Blur", 20, 80, 80, 20)
$cBtnClear = GUICtrlCreateButton("Clear", 100, 80, 80, 20)
GUISetState()

_GDIPlus_Startup()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            _GDIPlus_Shutdown()
            Exit
        Case $cBtnBlur
            _ScreenBlur(GUICtrlRead($cInputSR), GUICtrlRead($cInputIM))
        Case $cBtnClear
            _ScreenClear()
    EndSwitch
WEnd

Func _ScreenClear()
    _WinAPI_RedrawWindow(_WinAPI_GetDesktopWindow(), 0, 0, $RDW_INVALIDATE+$RDW_UPDATENOW+$RDW_ALLCHILDREN)
EndFunc
Func _ScreenBlur($nRatio, $iInterMode, $iSmoothMode=0, $iPixOffsetMode = 2)
    
    $hBMP = _ScreenCapture_Capture("", 0,0,-1,-1, False)
    $hImg = _GDIPlus_BitmapCreateFromHBITMAP($hBMP)

    $hScreenDC = _WinAPI_GetDC(0)
    $hScreenGraph = _GDIPlus_GraphicsCreateFromHDC($hScreenDC)
    
    $hImg2 = _GDIPlus_BitmapCloneArea($hImg, 0, 0, @DesktopWidth/$nRatio, @DesktopHeight/$nRatio)
    $hMemGraph = _GDIPlus_ImageGetGraphicsContext($hImg2)
;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
    $a = DllCall("gdiplus.dll", "int", "GdipSetInterpolationMode", "hwnd", $hMemGraph, "int", $iInterMode)
    $a = DllCall("gdiplus.dll", "int", "GdipSetInterpolationMode", "hwnd", $hScreenGraph, "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
    $a = DllCall("gdiplus.dll", "int", "GdipSetPixelOffsetMode", "hwnd", $hMemGraph, "int", $iPixOffsetMode)
    $a = DllCall("gdiplus.dll", "int", "GdipSetPixelOffsetMode", "hwnd", $hScreenGraph, "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
    $a = DllCall("gdiplus.dll", "int", "GdipSetSmoothingMode", "hwnd", $hMemGraph, "int", $iSmoothMode)
    $a = DllCall("gdiplus.dll", "int", "GdipSetSmoothingMode", "hwnd", $hScreenGraph, "int", $iSmoothMode)

    _GDIPlus_GraphicsDrawImageRectRect($hMemGraph, $hImg, 0, 0, @DesktopWidth, @DesktopHeight, 0, 0, @DesktopWidth/$nRatio, @DesktopHeight/$nRatio)
    _GDIPlus_GraphicsDrawImageRectRect($hScreenGraph, $hImg2, 0, 0, @DesktopWidth/$nRatio, @DesktopHeight/$nRatio, 0, 0, @DesktopWidth, @DesktopHeight)
    
    _WinAPI_DeleteObject($hBMP)
    _GDIPlus_ImageDispose($hImg)
    _GDIPlus_ImageDispose($hImg2)
    _GDIPlus_GraphicsDispose($hMemGraph)
    _GDIPlus_GraphicsDispose($hScreenGraph)
    _WinAPI_ReleaseDC(0, $hScreenDC)

EndFunc

Edit: updated example - some tinkering with and documentation of modes.

Edited by Siao

"be smart, drink your wine"

Share this post


Link to post
Share on other sites

IMO no implementation of any gfx transform algo using only native AutoIt commands will be fast enough, especially if we are talking large resolutions. At least that's what my common sense tells me. Scripting languages are meant for other tasks.

So you're better off utilizing functions from some dlls.

Easy way is to use screen bitmap resizing with GDI+ which has various antialiasing settings.

You can play around with SetInterpolationMode, SetPixelOffsetMode etc...

For me HighQualityBilinear seems to provide the nicest blurs, especially when stretching alot.

#include <GUIConstants.au3>
#Include <ScreenCapture.au3>
#include <GDIPlus.au3>

$hGUI = GUICreate("Blurp", 200,120)
GUICtrlCreateLabel("InterpolationMode", 20, 20, 100, 20)
GUICtrlCreateLabel("Stretch ratio", 20, 50, 100, 20)
$cInputIM = GUICtrlCreateInput("6", 120, 15, 50, 20)
GUICtrlSetTip(-1, "Possible values" & @CRLF & "0 - 7")
$cInputSR = GUICtrlCreateInput("1.25", 120, 45, 50, 20)
GUICtrlSetTip(-1, "Possible values" & @CRLF & "1.0 - @DesktopHeight.0")
$cBtnBlur = GUICtrlCreateButton("Blur", 20, 80, 80, 20)
$cBtnClear = GUICtrlCreateButton("Clear", 100, 80, 80, 20)
GUISetState()

_GDIPlus_Startup()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            _GDIPlus_Shutdown()
            Exit
        Case $cBtnBlur
            _ScreenBlur(GUICtrlRead($cInputSR), GUICtrlRead($cInputIM))
        Case $cBtnClear
            _ScreenClear()
    EndSwitch
WEnd

Func _ScreenClear()
    _WinAPI_RedrawWindow(_WinAPI_GetDesktopWindow(), 0, 0, $RDW_INVALIDATE+$RDW_UPDATENOW+$RDW_ALLCHILDREN)
EndFunc
Func _ScreenBlur($nRatio, $iInterMode, $iSmoothMode=0, $iPixOffsetMode = 2)
    
    $hBMP = _ScreenCapture_Capture("", 0,0,-1,-1, False)
    $hImg = _GDIPlus_BitmapCreateFromHBITMAP($hBMP)

    $hScreenDC = _WinAPI_GetDC(0)
    $hScreenGraph = _GDIPlus_GraphicsCreateFromHDC($hScreenDC)
    
    $hImg2 = _GDIPlus_BitmapCloneArea($hImg, 0, 0, @DesktopWidth/$nRatio, @DesktopHeight/$nRatio)
    $hMemGraph = _GDIPlus_ImageGetGraphicsContext($hImg2)
;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
    $a = DllCall("gdiplus.dll", "int", "GdipSetInterpolationMode", "hwnd", $hMemGraph, "int", $iInterMode)
    $a = DllCall("gdiplus.dll", "int", "GdipSetInterpolationMode", "hwnd", $hScreenGraph, "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
    $a = DllCall("gdiplus.dll", "int", "GdipSetPixelOffsetMode", "hwnd", $hMemGraph, "int", $iPixOffsetMode)
    $a = DllCall("gdiplus.dll", "int", "GdipSetPixelOffsetMode", "hwnd", $hScreenGraph, "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
    $a = DllCall("gdiplus.dll", "int", "GdipSetSmoothingMode", "hwnd", $hMemGraph, "int", $iSmoothMode)
    $a = DllCall("gdiplus.dll", "int", "GdipSetSmoothingMode", "hwnd", $hScreenGraph, "int", $iSmoothMode)

    _GDIPlus_GraphicsDrawImageRectRect($hMemGraph, $hImg, 0, 0, @DesktopWidth, @DesktopHeight, 0, 0, @DesktopWidth/$nRatio, @DesktopHeight/$nRatio)
    _GDIPlus_GraphicsDrawImageRectRect($hScreenGraph, $hImg2, 0, 0, @DesktopWidth/$nRatio, @DesktopHeight/$nRatio, 0, 0, @DesktopWidth, @DesktopHeight)
    
    _WinAPI_DeleteObject($hBMP)
    _GDIPlus_ImageDispose($hImg)
    _GDIPlus_ImageDispose($hImg2)
    _GDIPlus_GraphicsDispose($hMemGraph)
    _GDIPlus_GraphicsDispose($hScreenGraph)
    _WinAPI_ReleaseDC(0, $hScreenDC)

EndFunc

Edit: updated example - some tinkering with and documentation of modes.

wow thats actually pretty good! an fast!

thank you

Share this post


Link to post
Share on other sites

Hehe, that's a neat program.


- Dan [Website]

Share this post


Link to post
Share on other sites

I tried to run the example, but gdiplus.au3 gives errors.

A Messagebox appears with:

Fatal error: AVector: []: Out of bounds

After closing this message box I get the Blurp window, but when I click [blur] I get the same fatal error a few times

and the lower window in SCITE shows:

C:\Program Files\AutoIt3\Include\GDIPlus.au3 (415) : ==> Subscript used with non-Array variable.:

Return SetError($aResult[0], 0, $aResult[7])

Return SetError($aResult^ ERROR

I am using autoit v3.2.10.0 and WINNT4 (is this the reason?).

Share this post


Link to post
Share on other sites

I tried to run the example, but gdiplus.au3 gives errors.

A Messagebox appears with:

Fatal error: AVector: []: Out of bounds

After closing this message box I get the Blurp window, but when I click [blur] I get the same fatal error a few times

and the lower window in SCITE shows:

C:\Program Files\AutoIt3\Include\GDIPlus.au3 (415) : ==> Subscript used with non-Array variable.:

Return SetError($aResult[0], 0, $aResult[7])

Return SetError($aResult^ ERROR

I am using autoit v3.2.10.0 and WINNT4 (is this the reason?).

Windows NT does not come with GDI+ installed.

Share this post


Link to post
Share on other sites

Is it possible to dump the blurred image to a file, so that you never see the bluring until you open the file?


INI TreeViewA bus station is where a bus stops, a train station is where a train stops. Onmy desk I have a work station...

Share this post


Link to post
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
Sign in to follow this  
Followers 0