Sign in to follow this  
Followers 0
CHronologist

Inverting RGB, the second

12 posts in this topic

#1 ·  Posted (edited)

As I already said in a post with the same name I don't have the problem to invert the RGB-information, but I need a faster way to do it. I have this program

$dll = DllOpen("Gdi32.dll")
$hwnd = DllCall("user32.dll", "hwnd", "GetActiveWindow")
$dc = DllCall("user32.dll", "hwnd", "GetDC", "hwnd", $hwnd[0])
For $i = 0 to @DesktopWidth 
    For $j = 0 to @DesktopHeight
        $rgb = DllCall($dll, "int", "GetPixel", "hwnd", $dc[0], "int", $i, "int", $j)
        $rgb[0] = BitNot("0x" & Hex($rgb[0]))
        DllCall($dll, "int", "SetPixel", "hwnd", $dc[0], "int", $i, "int", $j, "int", "0x00" & StringTrimLeft(Hex($rgb[0]), 2))
    Next
Next    
DllClose($dll)

It does basicially nothing else than getting every single pixel color and invert it, but as you might imagine, changing 1280x1024 pixel for example, takes quite long.

"weaponx" has already led my attention to a post from "Siao", thanks for this, but if I understood Siaos script right it can hardly help me. And because I don't wanted to spam the other RGB-invert topic furtheron I created my own, hoping anyone with more experience in GDI and GDIplus has any ideas.

Edited by CHronologist

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

What I would suggest is to create a memory bitmap and then use LockBits and change the bytes of the bitmap yourself. Then just draw the bitmap to the screen.

Edited by Richard Robertson

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

I also thought of doing something with LockBits but will it be faster? because I still have to make a loop like

For $i = 0 to @DesktopWidth

For $j = 0 to @DesktopHeight

[...]

Next

Next

Edited by CHronologist

Share this post


Link to post
Share on other sites

If you use GetDibSection + BitBlt (with the invert option) + LockBits, it would be much faster. No time to write a demonstration script, but should be interesting to see what you come up with.


[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

ok thanks for the inspiration, I'm currently working on the improvement and will try your suggestion

Share this post


Link to post
Share on other sites

Well, heres my solution for the slowness, I created 4 scripts that would run at the same time, the first one does every other vertical collumn, the second one does the ones it missed, then the other two do the same except starting at the right of the screen, all four of them stop at the middle of the screen

but even so its still not fast enough to refresh XD

$dll = DllOpen("Gdi32.dll")
$hwnd = DllCall("user32.dll", "hwnd", "GetActiveWindow")
$dc = DllCall("user32.dll", "hwnd", "GetDC", "hwnd", $hwnd[0])
For $i = 0 to @DesktopWidth / 2 Step +2
    For $j = 0 to @DesktopHeight
        $rgb = DllCall($dll, "int", "GetPixel", "hwnd", $dc[0], "int", $i, "int", $j)
        $rgb[0] = BitNOT("0x" & Hex($RGB[0]))
        DllCall($dll, "int", "SetPixel", "hwnd", $dc[0], "int", $i, "int", $j, "int", "0x00" & StringTrimLeft(Hex($rgb[0]), 2))
    Next
Next    
DllClose($dll)

$dll = DllOpen("Gdi32.dll")
$hwnd = DllCall("user32.dll", "hwnd", "GetActiveWindow")
$dc = DllCall("user32.dll", "hwnd", "GetDC", "hwnd", $hwnd[0])
For $i = 1 to @DesktopWidth / 2 Step +2
    For $j = 0 to @DesktopHeight
        $rgb = DllCall($dll, "int", "GetPixel", "hwnd", $dc[0], "int", $i, "int", $j)
        $rgb[0] = BitNOT("0x" & Hex($RGB[0]))
        DllCall($dll, "int", "SetPixel", "hwnd", $dc[0], "int", $i, "int", $j, "int", "0x00" & StringTrimLeft(Hex($rgb[0]), 2))
    Next
Next    
DllClose($dll)

$dll = DllOpen("Gdi32.dll")
$hwnd = DllCall("user32.dll", "hwnd", "GetActiveWindow")
$dc = DllCall("user32.dll", "hwnd", "GetDC", "hwnd", $hwnd[0])
For $i = @DesktopWidth to @DesktopWidth / 2 + 1 Step - 2
    For $j = 0 to @DesktopHeight
        $rgb = DllCall($dll, "int", "GetPixel", "hwnd", $dc[0], "int", $i, "int", $j)
        $rgb[0] = BitNOT("0x" & Hex($RGB[0]))
        DllCall($dll, "int", "SetPixel", "hwnd", $dc[0], "int", $i, "int", $j, "int", "0x00" & StringTrimLeft(Hex($rgb[0]), 2))
    Next
Next    
DllClose($dll)

$dll = DllOpen("Gdi32.dll")
$hwnd = DllCall("user32.dll", "hwnd", "GetActiveWindow")
$dc = DllCall("user32.dll", "hwnd", "GetDC", "hwnd", $hwnd[0])
For $i = @DesktopWidth - 1 to @DesktopWidth / 2 +1 Step - 2
    For $j = 0 to @DesktopHeight
        $rgb = DllCall($dll, "int", "GetPixel", "hwnd", $dc[0], "int", $i, "int", $j)
        $rgb[0] = BitNOT("0x" & Hex($RGB[0]))
        DllCall($dll, "int", "SetPixel", "hwnd", $dc[0], "int", $i, "int", $j, "int", "0x00" & StringTrimLeft(Hex($rgb[0]), 2))
    Next
Next    
DllClose($dll)

[center]"When you look at old, classic games like Snake, you often put it off because it's such a simple game, but it's only when you actually try and create your own unique game from scratch, do you finally appreciate those games."[/center][center]Don't ask for answers if you haven't TRIED yet![/center][center]Most answers can be answered in the help file! Use it![/center]

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

very creative solution, but I will try working on smoke_n 's idea, but it's quite hard to understand, because I just started working with GDI so if anyone has experience with those function let me know :P

Edited by CHronologist

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

So this is now the next step. It can invert the screen colors within 300ms. Two problems left:

1) it's still to slow, but the way it works now will surely hold methods to speed up more

2) when looped, the color turns normal every second time or if windows are moved only parts turn nomal again, so the program has top redraw the screen everytim, what makes it slower again

have a look at it

HotKeySet("{Esc}", "_Exit")

While 1
    $hdc = _WinAPI_GetDC(0)
    $hcdc = _WinAPI_CreateCompatibleDC($hdc)
    $hcbmp =  _WinAPI_CreateCompatibleBitmap($hdc, @DesktopWidth, @DesktopHeight)
    _WinAPI_SelectObject($hcdc, $hcbmp)
    _WinAPI_BitBlt($hcdc, 0, 0, @DesktopWidth, @DesktopHeight, $hdc, 0, 0, $NOTSRCERASE) 
    _GDIPlus_Startup()
    $gc = _GDIPlus_GraphicsCreateFromHDC($hdc)
    $bmp = _GDIPlus_BitmapCreateFromHBITMAP($hcbmp)
    _GDIPlus_GraphicsDrawImageRectRect($gc, $bmp, 0, 0, @DesktopWidth, @DesktopHeight, 0, 0, @DesktopWidth, @DesktopHeight)
    _WinAPI_RedrawWindow(0, 0, 0, $RDW_INVALIDATE+$RDW_UPDATENOW+$RDW_ALLCHILDREN)
    _GDIPlus_GraphicsDispose($gc)
    _GDIPlus_ImageDispose($bmp)
    _GDIPlus_Shutdown()
    _WinAPI_ReleaseDC(0, $hdc)
    _WinAPI_DeleteDC($hcdc)
    _WinAPI_DeleteObject($hcbmp)
WEnd

Func _Exit()
    Exit
EndFunc

I mean, it's a really annoying effect now, but not what I intended :P

Edited by CHronologist

Share this post


Link to post
Share on other sites

hmmm, interesting. I wonder if it can be done in autoit... would be very cool :P

Share this post


Link to post
Share on other sites

Pretty cool effect. Very annoying though :P

Just increase anyone wanted to know the Includes to make this work....

#include <WinAPI.au3>
#include <GuiConstantsEx.au3>
#Include <GDIPlus.au3>
#include <WindowsConstants.au3>

Share this post


Link to post
Share on other sites

CHronologist

Nice! Little modify :P

#include <WinAPI.au3>
#Include <GDIPlus.au3>
#include <WindowsConstants.au3>

HotKeySet("{Esc}", "_Exit")

$hdc = _WinAPI_GetDC(0)
$hcdc = _WinAPI_CreateCompatibleDC($hdc)
    
While 1
    $hcbmp =  _WinAPI_CreateCompatibleBitmap($hdc, @DesktopWidth, @DesktopHeight)
    $hOldBMP = _WinAPI_SelectObject($hcdc, $hcbmp)
   
   _WinAPI_BitBlt($hcdc, 0, 0, @DesktopWidth, @DesktopHeight, $hdc, 0, 0, $NOTSRCERASE)
    
    _GDIPlus_Startup()
    $gc = _GDIPlus_GraphicsCreateFromHDC($hdc)
    $bmp = _GDIPlus_BitmapCreateFromHBITMAP($hcbmp)
    _GDIPlus_GraphicsDrawImageRectRect($gc, $bmp, 0, 0, @DesktopWidth, @DesktopHeight, 0, 0, @DesktopWidth, @DesktopHeight)
    
    ;_WinAPI_RedrawWindow(0, 0, 0, BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_ALLCHILDREN))
    
    _GDIPlus_GraphicsDispose($gc)
    _GDIPlus_ImageDispose($bmp)
    _GDIPlus_Shutdown()
    
    _WinAPI_SelectObject($hOldBMP, $hcbmp)
    _WinAPI_DeleteObject($hcbmp)
    
    Sleep(100)
WEnd

Func _Exit()
    _WinAPI_ReleaseDC(0, $hdc)
    _WinAPI_DeleteDC($hcdc)
    _WinAPI_RedrawWindow(0, 0, 0, BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_ALLCHILDREN))
    Exit
EndFunc

Share this post


Link to post
Share on other sites

@rasim thanks for the little optimizing wanted to do this but forgot^^

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