Jump to content

Recommended Posts

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
Posted

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
Posted

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.

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
Posted

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. :)

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"

Posted

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

  • 4 weeks later...
Posted

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?).

Posted

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.
  • 11 months later...
Posted

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...

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
  • Recently Browsing   0 members

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