Jump to content

GuiCtrlSetImage for .tga images


AutID
 Share

Recommended Posts

Hello,

I am trying to make a simple image viewr for .tga images.
The GuiCtrlSetImage doesn't work with .tga files. I know I can show tga images with SDL.dll but I am having difficulties.
This is what I have tried so far with no success.

#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
Global $hDLL = DllOpen("SDL_image.dll")
Global $sDLL = DllOpen("SDL.dll")

$hGUI = GUICreate("Image Viewer", 1500, 900)
$Group1 = GUICtrlCreateGroup("Image Viewer", 8, 8, 1450, 850)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$Button1 = GUICtrlCreateButton("Browser...", 1400, 870, 75, 25)
$Input1 = GUICtrlCreateInput("", 8, 870, 265, 21)
$Image = GUICtrlCreatePic('',9,9,1430,830)
GUISetState(@SW_SHOW)
While 1
 $nMsg = GUIGetMsg()
 Switch $nMsg
  Case $GUI_EVENT_CLOSE
   DllClose($hDLL)
   DllClose($sDLL)
   Exit
  Case $Button1
   $sRet = FileOpenDialog("Select .tga file to open", "", "TARGA files (*.tga)")
   $tImage = DllCall($hDLL, "ptr*:cdecl", "IMG_Load", "str", $sRet)
   GUICtrlSetData($Input1, $sRet)
   $setimg = DllCall($sDLL, "int:cdecl", "SDL_UpperBlit", "ptr", $tImage, "ptr", DllStructGetPtr(0), "ptr", $Image, "ptr", DllStructGetPtr(0))
   GUICtrlSetImage($Image, $tImage)
   DllClose($hDLL)
   DllClose($sDLL)
 EndSwitch
WEnd

Any ideas?

 

Edited by AutID
Link to comment
Share on other sites

Ok I made a progress. I found this script on the forum.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=n
#AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include "SDL.au3"
#include "SDL_image.au3"
;Select file
$sRet = FileOpenDialog("Select .tga file to open", "", "TARGA files (*.tga)")
If @error Then Exit 0* ConsoleWrite("blah blah" & @LF)
;Init stuff
_SDL_Init($_SDL_INIT_VIDEO, @ScriptDir & "\")
_SDL_Init_image(@ScriptDir & "\")
;Load picture
$pImage = _IMG_Load($sRet)
;Get size
$tImage = DllStructCreate($tagSDL_SURFACE, $pImage)
$iWidth = DllStructGetData($tImage, "w")
$iHeight = DllStructGetData($tImage, "h")
;Something to display on
$pScreen = _SDL_GuiCreate("Some title", $iWidth, $iHeight, 0, 0)
;Copy to screen
_SDL_BlitSurface($pImage, 0, $pScreen, 0)
;Show
_SDL_Flip($pScreen)
;Close window as normal
While 1
    Sleep(10)
WEnd

It is able to display a .tga image but as far as I am understanding, he is showing the image with SDL_UpperBlit in a SDL_SetVideoMode. Calling SDL_SetVideoMode will automaticly create a separated  gui with the stats of the photo and then display.
Is it possible to display it on my gui?
Anyone ever used this dll?

Edited by AutID
Link to comment
Share on other sites

To merge the double windows use:

EnvSet("SDL_WINDOWID", $pscreen)

right after the $pscreen= guicreate()

$pScreen = _SDL_GuiCreate("Some title", $iWidth, $iHeight, 0, 0)
EnvSet("SDL_WINDOWID", $pScreen)
 

It's my understanding that _IMG_Load() returns a SDL_Surface.

GuiCtrlSetImage() probably doesn't use SDL_Surfaces

I try to keep gui controls and SDL_Surfaces separate.

This >Link by AutoIt SDL_UDF creator AdmiralAlkex may show how to combine them.

Video of a SDL_UDF project >Surfer:

Edited by Xandy
Link to comment
Share on other sites

I once made a UDF :-)

Edit: added example

#include "TGA AutoIt.au3"

Global $tTGA = DllStructCreate($tagTGA)

Global $hBitmap_TGA = _loadTarga($tTGA, @ScriptDir & "\0.tga")
If @error Then
ConsoleWrite("UDF error: " & @error & @CRLF)
Exit
EndIf

Global $hGui = GUICreate("TGA example")

Global $nPic = GUICtrlCreatePic("", 10, 10, 100, 100, 0x1000)

_GDIPlus_Startup()

Global $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap_TGA)

Global $iX = _GDIPlus_ImageGetWidth($hImage)
Global $iY = _GDIPlus_ImageGetHeight($hImage)
Global $hClone = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iX, $iY, $GDIP_PXF24RGB)

Global $hImageNew = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hClone)
_WinAPI_DeleteObject(GUICtrlSendMsg($nPic, 370, 0, $hImageNew))
_WinAPI_DeleteObject($hImageNew)
_GDIPlus_ImageDispose($hClone)
_GDIPlus_ImageDispose($hImage)
_freeTarga($tTGA)

_GDIPlus_Shutdown()


GUISetState()

; Save targa image to bitmap file
;~ _GDIPlus_ImageSaveToFile($hClone, @ScriptDir & "\TGA_AutoIt.bmp")
; Save targa image to jpg file
;~ _GDIPlus_ImageSaveToFile($hClone, @ScriptDir & "\TGA_AutoIt.jpg")

Do
Until GUIGetMsg() = -3
Edited by funkey

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Link to comment
Share on other sites

To merge the double windows use:

EnvSet("SDL_WINDOWID", $pscreen)

right after the $pscreen= guicreate()

$pScreen = _SDL_GuiCreate("Some title", $iWidth, $iHeight, 0, 0)
EnvSet("SDL_WINDOWID", $pScreen)
 

It's my understanding that _IMG_Load() returns a SDL_Surface.

GuiCtrlSetImage() probably doesn't use SDL_Surfaces

 

I try to keep gui controls and SDL_Surfaces separate.

This 

Edit: added example

#include "TGA AutoIt.au3"

Global $tTGA = DllStructCreate($tagTGA)

Global $hBitmap_TGA = _loadTarga($tTGA, @ScriptDir & "\0.tga")
If @error Then
ConsoleWrite("UDF error: " & @error & @CRLF)
Exit
EndIf

Global $hGui = GUICreate("TGA example")

Global $nPic = GUICtrlCreatePic("", 10, 10, 100, 100, 0x1000)

_GDIPlus_Startup()

Global $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap_TGA)

Global $iX = _GDIPlus_ImageGetWidth($hImage)
Global $iY = _GDIPlus_ImageGetHeight($hImage)
Global $hClone = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iX, $iY, $GDIP_PXF24RGB)

Global $hImageNew = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hClone)
_WinAPI_DeleteObject(GUICtrlSendMsg($nPic, 370, 0, $hImageNew))
_WinAPI_DeleteObject($hImageNew)
_GDIPlus_ImageDispose($hClone)
_GDIPlus_ImageDispose($hImage)
_freeTarga($tTGA)

_GDIPlus_Shutdown()


GUISetState()

; Save targa image to bitmap file
;~ _GDIPlus_ImageSaveToFile($hClone, @ScriptDir & "\TGA_AutoIt.bmp")
; Save targa image to jpg file
;~ _GDIPlus_ImageSaveToFile($hClone, @ScriptDir & "\TGA_AutoIt.jpg")

Do
Until GUIGetMsg() = -3
 

I tried it. It returns me an UDF error: 1

I checked your udf and you just return the errors in case of an error. I don't know tga.dll to understand the error :/

 

 

 

Use search on the forum.

 

I already found that and I already posted a code from that post...

EDIT: I also tried of getting control of the picture and then changing it to png but still it wont show in the gui with the GuiCtrlSetImage...

Edited by AutID
Link to comment
Share on other sites

FreeImage doesn't seem to work neither

#AutoIt3Wrapper_UseX64=n
#include<WinAPI.au3>
#include<FreeImage.au3>
#include <GUIConstants.au3>

; modify these variables
Global Const $sFreeImageDLL = @ScriptDir & "\FreeImage.dll"
Global Const $sTIFF_File = @ScriptDir & "\test.tga"

_FreeImage_LoadDLL($sFreeImageDLL)

#region - GUI Create
GUICreate('Display', 400, 400)
$iPic = GUICtrlCreatePic("", 0, 0, 400, 400)
GUISetState()
#endregion


; Load image, create thumbnail, maximum 400x400px
$pDIBOrg = _FreeImage_Load($FIF_TIFF, $sTIFF_File);
$pDIB = _FreeImage_MakeThumbnail($pDIBOrg, 400)
_FreeImage_Unload($pDIBOrg)

; create windows HBITMAP for picture control
$hDC = _WinAPI_GetDC(GUICtrlGetHandle($iPic))
$hBitmap = DllCall('gdi32.dll', 'ptr', 'CreateDIBitmap', 'hwnd', $hDC, 'ptr', _FreeImage_GetInfoHeader($pDIB), 'dword', 0x04, 'ptr', _FreeImage_GetBits($pDIB), 'ptr', _FreeImage_GetInfo($pDIB), "uint", 0)
$hBitmap = $hBitmap[0]
_WinAPI_ReleaseDC(GUICtrlGetHandle($iPic), $hDC)

; Free FreeImage image
_FreeImage_Unload($pDIB);

; set HBITMAP to control
_GUICtrlStatic_SetImage($iPic, $hBitmap)


#region - GUI SelectLoop
While 1
$msg = GUIGetMsg()
Select
Case $msg = $GUI_EVENT_CLOSE
Exit
EndSelect
WEnd
#endregion

; #FUNCTION# ====================================================================================================================
; Name...........: _GUICtrlStatic_SetImage
; Description ...: Sets a HBITMAP to a static control like image or label
; Syntax.........: _GUICtrlStatic_SetImage($iCtrlId, $hBitmap)
; Parameters ....: $iCtrlId - CtrlId or handle of Control in the current process
; $hBitmap - Pointer top Windows HBITMAP
; Return values .: Success - 1
; Failure - 0 and set @error:
; |1 - invalid $pSource
; |1 - invalid $pSource
; Author ........: ProgAndy, Zedna
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......:
; ===============================================================================================================================
Func _GUICtrlStatic_SetImage($iCtrlId, $hBitmap)
Local Const $STM_SETIMAGE = 0x0172
Local Const $IMAGE_BITMAP = 0
Local Const $SS_BITMAP = 0xE
Local Const $GWL_STYLE = -16

If IsHWnd($iCtrlId) Then
If WinGetProcess($iCtrlId) <> @AutoItPID Then Return SetError(1,0,0)
Else
$iCtrlId = GUICtrlGetHandle($iCtrlId)
If Not $iCtrlId Then Return SetError(2,0,0)
EndIf
; set SS_BITMAP style to control
Local $oldStyle = DllCall("user32.dll", "long", "GetWindowLong", "hwnd", $iCtrlId, "int", $GWL_STYLE)
If @error Then Return SetError(3, 0, 0)
DllCall("user32.dll", "long", "SetWindowLong", "hwnd", $iCtrlId, "int", $GWL_STYLE, "long", BitOR($oldStyle[0], $SS_BITMAP))
If @error Then Return SetError(4, 0, 0)
Local $oldBmp = DllCall("user32.dll", "handle", "SendMessageW", "hwnd", $iCtrlId, "int", $STM_SETIMAGE, "wparam", $IMAGE_BITMAP, "handle", $hBitmap)
If @error Then Return SetError(5, 0, 0)
If $oldBmp[0] Then _WinAPI_DeleteObject($oldBmp[0])
Return 1
EndFunc
Link to comment
Share on other sites

#Include <FreeImage.au3>
#Include <WinAPI.au3>

$File = @ScriptDir & '\Test.tga'

_FreeImage_LoadDLL(@ScriptDir & '\FreeImage.dll')
$pDIB = _FreeImage_LoadU(_FreeImage_GetFIFFromFilenameU($File), $File)
If Not $pDIB Then
    Exit
EndIf
$Width = _FreeImage_GetWidth($pDIB)
$Height = _FreeImage_GetHeight($pDIB)
$hDC = _WinAPI_GetDC(0)
$Ret = DllCall('gdi32.dll', 'ptr', 'CreateDIBitmap', 'hwnd', $hDC, 'ptr', _FreeImage_GetInfoHeader($pDIB), 'dword', 0x04, 'ptr', _FreeImage_GetBits($pDIB), 'ptr', _FreeImage_GetInfo($pDIB), 'uint', 0)
If (Not @Error) And ($Ret[0]) Then
    $hDIB = $Ret[0]
Else
    $hDIB = 0
EndIf
_WinAPI_ReleaseDC(0, $hDC)
_FreeImage_Unload($pDIB)
;~_FreeImage_UnLoadDLL()
If Not $hDIB Then
    Exit
EndIf

GUICreate('MyGUI', $Width, $Height)
GUICtrlCreatePic('', 0, 0, $Width, $Height)
;~GUICtrlSendMsg(-1, $STM_SETIMAGE, $IMAGE_BITMAP, $hDIB)
GUICtrlSendMsg(-1, 0x0172, 0, $hDIB)
GUISetState()

Do
Until GUIGetMsg() = -3

>FreeImage UDF by Prog@ndy

Edited by Yashied
Link to comment
Share on other sites

#Include <FreeImage.au3>
#Include <WinAPI.au3>

$File = @ScriptDir & '\Test.tga'

_FreeImage_LoadDLL(@ScriptDir & '\FreeImage.dll')
$pDIB = _FreeImage_LoadU(_FreeImage_GetFIFFromFilenameU($File), $File)
If Not $pDIB Then
    Exit
EndIf
$Width = _FreeImage_GetWidth($pDIB)
$Height = _FreeImage_GetHeight($pDIB)
$hDC = _WinAPI_GetDC(0)
$Ret = DllCall('gdi32.dll', 'ptr', 'CreateDIBitmap', 'hwnd', $hDC, 'ptr', _FreeImage_GetInfoHeader($pDIB), 'dword', 0x04, 'ptr', _FreeImage_GetBits($pDIB), 'ptr', _FreeImage_GetInfo($pDIB), 'uint', 0)
If (Not @Error) And ($Ret[0]) Then
    $hDIB = $Ret[0]
Else
    $hDIB = 0
EndIf
_WinAPI_ReleaseDC(0, $hDC)
_FreeImage_Unload($pDIB)
;~_FreeImage_UnLoadDLL()
If Not $hDIB Then
    Exit
EndIf

GUICreate('MyGUI', $Width, $Height)
GUICtrlCreatePic('', 0, 0, $Width, $Height)
;~GUICtrlSendMsg(-1, $STM_SETIMAGE, $IMAGE_BITMAP, $hDIB)
GUICtrlSendMsg(-1, 0x0172, 0, $hDIB)
GUISetState()

Do
Until GUIGetMsg() = -3
>FreeImage UDF by Prog@ndy

Thanks, it works perfectly. When I try to attach it on a pic it works fine if I set the $iW and $iH of the GUI the same as the image's.

If the GUI is standar, for example if it is 400,400, the image doesn't resize and it shows only a part of the picture.

I tried GDI to resize the image and then display it but I am not sure if GDI will work on a .tga file because after the resize the image won't appear.

I won't lie, I am not good with GDI but is there someone who would help me resize the image before displaying it so it could fit in the GUI???

Anyway Yashied and everyone thank you all ;)

This is what I tried:

Func _Resize($oImage, $sPath, $iW, $iH)
$oldImage = _GDIPlus_ImageLoadFromFile($oImage)

$GC = _GDIPlus_ImageGetGraphicsContext($oldImage)
$newImage = _GDIPlus_BitmapCreateFromGraphics($iW,$iH,$GC)
$newGC = _GDIPlus_ImageGetGraphicsContext($newImage)

_GDIPlus_GraphicsDrawImageRect($newGC,$oldImage,0,0,$iW,$iH)
_GDIPlus_ImageSaveToFile($newImage,$sPath)

_GDIPlus_GraphicsDispose($GC)
_GDIPlus_GraphicsDispose($newGC)
_GDIPlus_BitmapDispose($newImage)
_GDIPlus_ImageDispose($oldImage)
EndFunc
and this is the error I get from the GDI include.

C:\Users\test\Desktop\test\program\GDIPlus.au3 (957) : ==> Subscript used with non-Array variable.:
For $iI = 1 To $aEncoders[0][0]
For $iI = 1 To $aEncoders^ ERROR
->01:20:28 AutoIt3.exe ended.rc:1
>Exit code: 1    Time: 3.156
Seems like the info returned from the _GDIPlus_Encoders() doesn't support tga files. I am not sure I am understanding it right. Edited by AutID
Link to comment
Share on other sites

You can use _WinAPI_AdjustBitmap() function from >WinAPIEx UDF for GDI HBITMAP ($hDib) but FreeImage is better.

 

#Include <FreeImage.au3>
#Include <WinAPI.au3>

$File = @ScriptDir & '\Test.tga'

_FreeImage_LoadDLL(@ScriptDir & '\FreeImage.dll')
$pSrc = _FreeImage_LoadU(_FreeImage_GetFIFFromFilenameU($File), $File)
If Not $pSrc Then
    Exit
EndIf
$pDst = _FreeImage_Rescale($pSrc, 400, 400, $FILTER_BICUBIC)
$hDC = _WinAPI_GetDC(0)
$Ret = DllCall('gdi32.dll', 'ptr', 'CreateDIBitmap', 'hwnd', $hDC, 'ptr', _FreeImage_GetInfoHeader($pDst), 'dword', 0x04, 'ptr', _FreeImage_GetBits($pDst), 'ptr', _FreeImage_GetInfo($pDst), 'uint', 0)
If (Not @Error) And ($Ret[0]) Then
    $hDib = $Ret[0]
Else
    $hDib = 0
EndIf
_WinAPI_ReleaseDC(0, $hDC)
_FreeImage_Unload($pSrc)
_FreeImage_Unload($pDst)
;~_FreeImage_UnLoadDLL()
If Not $hDib Then
    Exit
EndIf

GUICreate('MyGUI', 400, 400)
GUICtrlCreatePic('', 0, 0, 400, 400)
;~GUICtrlSendMsg(-1, $STM_SETIMAGE, $IMAGE_BITMAP, $hDIB)
GUICtrlSendMsg(-1, 0x0172, 0, $hDib)
GUISetState()

Do
Until GUIGetMsg() = -3
Edited by Yashied
Link to comment
Share on other sites

You can use _WinAPI_AdjustBitmap() function from >WinAPIEx UDF for GDI HBITMAP ($hDib) but FreeImage is better. 

#Include <FreeImage.au3>
#Include <WinAPI.au3>

$File = @ScriptDir & '\Test.tga'

_FreeImage_LoadDLL(@ScriptDir & '\FreeImage.dll')
$pSrc = _FreeImage_LoadU(_FreeImage_GetFIFFromFilenameU($File), $File)
If Not $pSrc Then
    Exit
EndIf
$pDst = _FreeImage_Rescale($pSrc, 400, 400, $FILTER_BICUBIC)
$hDC = _WinAPI_GetDC(0)
$Ret = DllCall('gdi32.dll', 'ptr', 'CreateDIBitmap', 'hwnd', $hDC, 'ptr', _FreeImage_GetInfoHeader($pDst), 'dword', 0x04, 'ptr', _FreeImage_GetBits($pDst), 'ptr', _FreeImage_GetInfo($pDst), 'uint', 0)
If (Not @Error) And ($Ret[0]) Then
    $hDib = $Ret[0]
Else
    $hDib = 0
EndIf
_WinAPI_ReleaseDC(0, $hDC)
_FreeImage_Unload($pSrc)
_FreeImage_Unload($pDst)
;~_FreeImage_UnLoadDLL()
If Not $hDib Then
    Exit
EndIf

GUICreate('MyGUI', 400, 400)
GUICtrlCreatePic('', 0, 0, 400, 400)
;~GUICtrlSendMsg(-1, $STM_SETIMAGE, $IMAGE_BITMAP, $hDIB)
GUICtrlSendMsg(-1, 0x0172, 0, $hDib)
GUISetState()

Do
Until GUIGetMsg() = -3

I dont really know freeimage udf thats why i wanted to avoid including it in my project. A lot of dll calls scary me and using them for hour slow down my computer a lot. On the other side it seems a powerfull udf. Thanks for helping me.

Cheers

Link to comment
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
 Share

  • Recently Browsing   0 members

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