Jump to content

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.

 

Link to post
Share on other sites

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

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

 

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

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