Jump to content
patshi

How to Mix GDIPlus with WinAPI properly (mirror an image)

Recommended Posts

Hi,

I have following problem. I want to mirror an image (bitmap) and display it via  _WinAPI_BitBlt because the image needs to be shown really fast.
The first script works fine, showing the mirroring graphic just fine via GDI+, but the second script does not work the way I pulled it together.

My primary question is: how to mirror an image (like with _GDIPlus_ImageRotateFlip) but with Win_API commands properly?

This is the working version via GDI+ :

#include <GDIPlus.au3>
#include <winapi.au3>
#include <windowsconstants.au3>
Opt("GuiOnEventMode", 1)

If Not FileExists(@ScriptDir&"\smiley.png") Then InetGet("http://msp5.photobucket.com/albums/y196/dannydude182/smiley-300x300.png", @ScriptDir&"\smiley.png")

_GDIPlus_Startup()
$image = _GDIPlus_ImageLoadFromFile(@ScriptDir&"\smiley.png")
$w = _GDIPlus_ImageGetWidth($image)
$h = _GDIPlus_ImageGetHeight($image)

$hwnd = GUICreate("Test", $w, $h)
Guisetbkcolor(0)

GUISetState()
GUISetOnEvent(-3, "close")

$graphics = _GDIPlus_GraphicsCreateFromHWND($hwnd)
$bitmap = _GDIPlus_BitmapCreateFromGraphics($w, $h, $graphics)
$backbuffer = _GDIPlus_ImageGetGraphicsContext($bitmap)

_GDIPlus_ImageRotateFlip($image, 6) ; <<<<<==== needed function

; ### Draw via GDIPlus
 _GDIPlus_GraphicsDrawImageRect($backbuffer, $image, 0, 0, $w, $h)
 _GDIPlus_GraphicsDrawImageRect($graphics, $bitmap , 0, 0, $w, $h)


While 1
    Sleep(20)
WEnd

Func close()
    _GDIPlus_ImageDispose($image)
    _GDIPlus_GraphicsDispose($backbuffer)
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_Shutdown()
    Exit
EndFunc  ;==>close

 

This is the non-working WinAPI-GDI+-Mix version:
 

#include <GDIPlus.au3>
#include <winapi.au3>
#include <windowsconstants.au3>
Opt("GuiOnEventMode", 1)

If Not FileExists(@ScriptDir&"\smiley.png") Then InetGet("http://msp5.photobucket.com/albums/y196/dannydude182/smiley-300x300.png", @ScriptDir&"\smiley.png")

_GDIPlus_Startup()
$image = _GDIPlus_ImageLoadFromFile(@ScriptDir&"\smiley.png")
$w = _GDIPlus_ImageGetWidth($image)
$h = _GDIPlus_ImageGetHeight($image)

$hwnd = GUICreate("Test", $w, $h)
Guisetbkcolor(0)

;_WinAPI_SetLayeredWindowAttributes($hwnd,0,255)
GUISetState()
GUISetOnEvent(-3, "close")

$graphics = _GDIPlus_GraphicsCreateFromHWND($hwnd)
$bitmap = _GDIPlus_BitmapCreateFromGraphics($w, $h, $graphics)
$backbuffer = _GDIPlus_ImageGetGraphicsContext($bitmap)

_GDIPlus_ImageRotateFlip($image, 6) ; <<<<==== needed function
              
; ### Draw via WinAPI
$hGUI_DC = _WinAPI_GetDC($hwnd)
$hGfxDC = _WinAPI_CreateCompatibleDC($hGUI_DC)
_WinAPI_SetStretchBltMode($hGUI_DC, $STRETCH_HALFTONE)

Local $hDCbufferPtr, $hDCbufferHBmp
$hDCbuffer = CreateBmp32($w, $h, $hDCbufferPtr, $hDCbufferHBmp)
    
_WinAPI_BitBlt($hDCbuffer, 0, 0, $w, $h, $image, 0, 0, $SRCCOPY)    ; draw image
_WinAPI_BitBlt($hGUI_DC, 0, 0, $w, $h, $hDCbuffer, 0, 0, $SRCCOPY) ; show buffer on Canvas

While 1
    Sleep(20)
WEnd

Func close()
    _GDIPlus_ImageDispose($image)
    _GDIPlus_GraphicsDispose($backbuffer)
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_Shutdown()
    Exit
EndFunc  ;==>close

Func CreateBmp32($iWidth, $iHeight, ByRef $ptr, ByRef $hbmp)
    $hcdc = _WinAPI_CreateCompatibleDC(0)
    _WinAPI_SetStretchBltMode($hcdc, $STRETCH_HALFTONE)
    $tBMI = DllStructCreate($tagBITMAPINFO)
    DllStructSetData($tBMI, 1, DllStructGetSize($tBMI) - 4)
    DllStructSetData($tBMI, 2, $iWidth)
    DllStructSetData($tBMI, 3, -$iHeight)
    DllStructSetData($tBMI, 4, 1)
    DllStructSetData($tBMI, 5, 32)
    $adib = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBMI), 'uint', $DIB_RGB_COLORS, 'ptr*', 0, 'ptr', 0, 'uint', 0)
    $hbmp = $adib[0]
    $ptr = $adib[4]
    _WinAPI_SelectObject($hcdc, $hbmp)
    Return $hcdc
EndFunc

 

Any help appreciated!

Thanks,

Patrick.

 

Share this post


Link to post
Share on other sites
Posted (edited)

This is the GDI version to flip an image using _WinAPI_PlgBlt()

#include <GDIPlus.au3>
#include <winapi.au3>
#include <windowsconstants.au3>
Opt("GuiOnEventMode", 1)

If Not FileExists(@ScriptDir&"\smiley.png") Then InetGet("http://msp5.photobucket.com/albums/y196/dannydude182/smiley-300x300.png", @ScriptDir&"\smiley.png")

_GDIPlus_Startup()
$image = _GDIPlus_ImageLoadFromFile(@ScriptDir&"\smiley.png")
$w = _GDIPlus_ImageGetWidth($image)
$h = _GDIPlus_ImageGetHeight($image)

$hwnd = GUICreate("Test", $w, $h)
Guisetbkcolor(0)
GUISetState()
GUISetOnEvent(-3, "close")

$t = TimerInit()
$hDC = _WinAPI_GetDC($hWnd)
$hDC_backbuffer = _WinAPI_CreateCompatibleDC($hDC)
$hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($image)
$DC_obj = _WinAPI_SelectObject($hDC_backbuffer, $hHBitmap)

;p1----p2
;p3----|
;flip on horizotal axis
Local $aPoint[3][2]

; 2 - A 180-degree rotation without flipping (No rotation, a horizontal flip followed by a vertical flip)
;~ $aPoint[0][0] = $w    ;p1x
;~ $aPoint[0][1] = $h  ;p1y
;~ $aPoint[1][0] = 0    ;p2x
;~ $aPoint[1][1] = $h  ;p2y
;~ $aPoint[2][0] = $w ;p3x
;~ $aPoint[2][1] = 0   ;p3y

;6 - A 180-degree rotation followed by a horizontal flip (No rotation and a vertical flip)
$aPoint[0][0] = 0
$aPoint[0][1] = $h
$aPoint[1][0] = $w
$aPoint[1][1] = $h
$aPoint[2][0] = 0
$aPoint[2][1] = 0

_WinAPI_PlgBlt($hDC, $aPoint, $hDC_backbuffer, 0, 0, $w, $H)
ConsoleWrite(TimerDiff($t) & @CRLF)


While 1
    Sleep(20)
WEnd

Func close()
    _WinAPI_SelectObject($hDC_backbuffer, $DC_obj)
    _WinAPI_DeleteDC($hDC_backbuffer)
    _WinAPI_DeleteObject($hHBitmap)
    _WinAPI_ReleaseDC($hwnd, $hDC)
    _GDIPlus_ImageDispose($image)
    _GDIPlus_Shutdown()
    Exit
EndFunc  ;==>close

It should be faster than the GDIPlus version.

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

Here another way that is closer to your initial attempt :

#include <GDIPlus.au3>
#include <winapi.au3>
#include <windowsconstants.au3>

Opt("GuiOnEventMode", 1)

If Not FileExists(@ScriptDir & "\smiley.png") Then InetGet("http://msp5.photobucket.com/albums/y196/dannydude182/smiley-300x300.png", @ScriptDir & "\smiley.png")

_GDIPlus_Startup()
$image = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\smiley.png")
$w = _GDIPlus_ImageGetWidth($image)
$h = _GDIPlus_ImageGetHeight($image)

$hwnd = GUICreate("Test", $w, $h)
GUISetBkColor(0)

GUISetState()
GUISetOnEvent(-3, "close")

_GDIPlus_ImageRotateFlip($image, 6) ; <<<<==== needed function

$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($image)
_GDIPlus_ImageDispose($image)
_GDIPlus_Shutdown()

Local $hCompDC = _WinAPI_CreateCompatibleDC(0)
_WinAPI_SelectObject($hCompDC, $hBitmap)

$hGUI_DC = _WinAPI_GetDC($hwnd)
$hGfxDC = _WinAPI_CreateCompatibleDC($hGUI_DC)

Local $hDCbufferPtr, $hDCbufferHBmp
$hDCbuffer = CreateBmp32($w, $h, $hDCbufferPtr, $hDCbufferHBmp)

_WinAPI_BitBlt($hDCbuffer, 0, 0, $w, $h, $hCompDC, 0, 0, $SRCCOPY)    ; draw image
_WinAPI_BitBlt($hGUI_DC, 0, 0, $w, $h, $hDCbuffer, 0, 0, $SRCCOPY) ; show buffer on Canvas

While 1
  Sleep(20)
WEnd

Func close()
  _WinAPI_DeleteObject($hBitmap)
  _WinAPI_DeleteObject($hDCbufferHBmp)
  _WinAPI_DeleteDC($hCompDC)
  _WinAPI_ReleaseDC($hWND, $hGUI_DC)
  _WinAPI_DeleteDC($hGfxDC)
  _WinAPI_DeleteDC($hDCbuffer)
  Exit
EndFunc   ;==>close

Func CreateBmp32($iWidth, $iHeight, ByRef $ptr, ByRef $hbmp)
  Local $tBIV5HDR = DllStructCreate($tagBITMAPV5HEADER)
  DllStructSetData($tBIV5HDR, 'bV5Size', DllStructGetSize($tBIV5HDR))
  DllStructSetData($tBIV5HDR, 'bV5Width', $iWidth)
  DllStructSetData($tBIV5HDR, 'bV5Height', -$iHeight)
  DllStructSetData($tBIV5HDR, 'bV5Planes', 1)
  DllStructSetData($tBIV5HDR, 'bV5BitCount', 32)
  DllStructSetData($tBIV5HDR, 'biCompression', $BI_BITFIELDS)
  DllStructSetData($tBIV5HDR, 'bV5RedMask', 0x00FF0000)
  DllStructSetData($tBIV5HDR, 'bV5GreenMask', 0x0000FF00)
  DllStructSetData($tBIV5HDR, 'bV5BlueMask', 0x000000FF)
  DllStructSetData($tBIV5HDR, 'bV5AlphaMask', 0xFF000000)

  $hbmp = _WinAPI_CreateDIBSection(0, $tBIV5HDR, $DIB_RGB_COLORS, $ptr)
  Local $hCompDC = _WinAPI_CreateCompatibleDC(0)
  _WinAPI_SelectObject($hCompDC, $hbmp)
  Return $hCompDC
EndFunc   ;==>CreateBmp32

 

Share this post


Link to post
Share on other sites
Posted (edited)

I can't imagine this Forum without UEZ as soon as any image question is asked.
Edit: Nine's answer took me by surprise !


 

Edited by pixelsearch

Share this post


Link to post
Share on other sites
36 minutes ago, pixelsearch said:

I can't imagine this Forum without UEZ as soon as any image question is asked.

I was bored. 😉

Here the shorter version using GDI/GDI+

#include <GDIPlus.au3>
#include <winapi.au3>
#include <windowsconstants.au3>
Opt("GuiOnEventMode", 1)

If Not FileExists(@ScriptDir&"\smiley.png") Then InetGet("http://msp5.photobucket.com/albums/y196/dannydude182/smiley-300x300.png", @ScriptDir&"\smiley.png")

_GDIPlus_Startup()
$image = _GDIPlus_ImageLoadFromFile(@ScriptDir&"\smiley.png")
$w = _GDIPlus_ImageGetWidth($image)
$h = _GDIPlus_ImageGetHeight($image)

$hwnd = GUICreate("Test", $w, $h)
Guisetbkcolor(0)
GUISetState()
GUISetOnEvent(-3, "close")

$t = TimerInit()
$hDC = _WinAPI_GetDC($hWnd)
$hDC_backbuffer = _WinAPI_CreateCompatibleDC($hDC)
$hHBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $w, $h)
$DC_obj = _WinAPI_SelectObject($hDC_backbuffer, $hHBitmap)
$hCanvas = _GDIPlus_GraphicsCreateFromHDC($hDC_backbuffer)
_GDIPlus_ImageRotateFlip($image, 6) ; <<<<<==== needed function
_GDIPlus_GraphicsDrawImageRect($hCanvas, $image , 0, 0, $w, $h)
_WinAPI_BitBlt($hDC, 0, 0, $w, $h, $hDC_backbuffer, 0, 0, $SRCCOPY)
ConsoleWrite(TimerDiff($t) & @CRLF)


While 1
    Sleep(20)
WEnd

Func close()
    _WinAPI_SelectObject($hDC_backbuffer, $DC_obj)
    _WinAPI_DeleteDC($hDC_backbuffer)
    _WinAPI_DeleteObject($hHBitmap)
    _WinAPI_ReleaseDC($hwnd, $hDC)
    _GDIPlus_ImageDispose($image)
    _GDIPlus_GraphicsDispose($hCanvas)
    _GDIPlus_Shutdown()
    Exit
EndFunc  ;==>close

 


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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

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

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...