By
UEZ
Here a little script to load a TGA image file and create a GDI+ bitmap. Currently supported TGA formats are 1/8/15/16/24 and 32-bit.
As v0.85 is written completely in AutoIt, it might take some time to convert larger 8/15/16/24/32-bit images. ☕
_GDIPlus_TGAImageLoadFromFile.au3 UDF
v0.85 without assembler acceleration code but with RLE support:
;Coded by UEZ
#AutoIt3Wrapper_UseX64=n
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WinAPIFiles.au3>
; #FUNCTION# ====================================================================================================================
; Name ..........: _GDIPlus_TGAImageLoadFromFile
; Description ...: Loads a TGA compressed (RLE) / uncompressed image file (1/8/15/16/24/32-bit) and converts it to a GDI+ bitmap format.
; Syntax ........: _GDIPlus_TGAImageLoadFromFile($sFile[, $bPrintInfo = False.])
; Parameters ....: $sFile - TGA file name to load from disk.
; $bPrintInfo - [optional] Prints some information about the TGA image to console. Default is False.
; Return values .: Success: GDI+ bitmap handle
; Failure: error 1 - file cannot be opened
; error 2 - TGA image is not in one of these formats: 1/8/15/16/24/32-bit
; error 3 - unsupported TGA image type
; error 4 - unable to read file to struct
; error 5 - unknown TGA pixel depth
; error 6 - return bitmap cannot be created
; Version .......: v0.85 build 2019-11-08 beta
; Author ........: UEZ
; Remarks .......: 8/15/16/24/32-bit images might be slow on converting ^^
; Related .......: _GDIPlus_BitmapCreateFromScan0, _GDIPlus_ImageRotateFlip, DllStructCreate, _WinAPI_CreateFile, _WinAPI_SetFilePointer
; Link ..........: https://www.loc.gov/preservation/digital/formats/fdd/fdd000180.shtml, http://www.fileformat.info/format/tga/egff.htm
; Example .......: Yes
; ===============================================================================================================================
Func _GDIPlus_TGAImageLoadFromFile($sFile, $bPrintInfo = False)
Local Const $hFile = _WinAPI_CreateFile($sFile, 2, 2)
If Not $hFile Then Return SetError(1, 0, 0)
Local Const $tagTGAHeader = "align 1;byte idLength;byte colormapType;byte imageType;word firstEntryIndex;word colormapLength;byte colormapEntrySize;word xOrigin;word yOrigin;word width;word height;byte pixelDepth;byte imageDescriptor"
Local Const $tagTGAFooter = "dword extAreaOffset;dword devDirOffset;byte imageID[18]"
Local Const $tagTGAExtention = "align 1;word extSize;byte authorName[41];byte authorComments[324];word timeM;word timeD;word timeY;word timeHr;word timeMin;word timeSec;byte jobName[41];word jobTimeHr;word jobTimeMin;word jobTimeSec;byte swID[41];word swVersionNr;byte swVersionLetter;long keyColor;word pxAspectRatioNum;word pxAspectRatioDom;word gammaNum;word gammaDom;dword colCorrOffset;dword postStampOffset;dword scanLineOffset;byte attribType"
Local Const $tTGAHeader = DllStructCreate($tagTGAHeader)
Local $tTGAFooter = DllStructCreate($tagTGAFooter)
Local Const $tTGAExtention = DllStructCreate($tagTGAExtention)
Local $dwBytesRead, $tTGAImageID, $tagTGAImageID, $iColorValuesStartPos = 0
_WinAPI_ReadFile($hFile, $tTGAHeader, DllStructGetSize($tTGAHeader), $dwBytesRead)
$iColorValuesStartPos += $dwBytesRead
If $tTGAHeader.idLength > 0 Then
$tagTGAImageID = "byte imageID[" & $tTGAHeader.idLength & "]"
$tTGAImageID = DllStructCreate($tagTGAImageID)
_WinAPI_ReadFile($hFile, $tTGAImageID, $tTGAHeader.idLength, $dwBytesRead)
$iColorValuesStartPos += $dwBytesRead
EndIf
Local Const $iPxDepth = $tTGAHeader.pixelDepth
If Not BitOR($iPxDepth = 32, $iPxDepth = 24, $iPxDepth = 16, $iPxDepth = 15, $iPxDepth = 8, $iPxDepth = 1) Then
_WinAPI_CloseHandle($hFile)
Return SetError(2, 0, 0)
EndIf
#cs
ImageType Image Data Type Colormap Encoding
0 No image data included in file No No
1 Colormapped image data Yes No
2 Truecolor image data No No
3 Monochrome image data No No
9 Colormapped image data Yes Yes
10 Truecolor image data No Yes
11 Monochrome image data No Yes
#ce
If Not BitOR($tTGAHeader.imageType = 0x01, $tTGAHeader.imageType = 0x02, $tTGAHeader.imageType = 0x03, $tTGAHeader.imageType = 0x09, $tTGAHeader.imageType = 0x0A, $tTGAHeader.imageType = 0x0B) Then
_WinAPI_CloseHandle($hFile)
Return SetError(3, 0, 0)
EndIf
Local $iW = $tTGAHeader.width, $iH = $tTGAHeader.height, $colorwidth = $tTGAHeader.colormapEntrySize / 8, _
$colorTblSize = $tTGAHeader.colormapLength * $colorwidth
Local $dwBufferSize = FileGetSize($sFile)
Local $tSrcBmp = DllStructCreate("ubyte color[" & $dwBufferSize & "]")
_WinAPI_ReadFile($hFile, $tSrcBmp, $dwBufferSize, $dwBytesRead)
_WinAPI_SetFilePointer($hFile, -26, $FILE_END)
_WinAPI_ReadFile($hFile, $tTGAFooter, 26, $dwBytesRead)
Local $sFooter = StringTrimRight(BinaryToString($tTGAFooter.imageID), 1), $iOffset = 0, $iOffset2, $iOffset3
If Not StringCompare($sFooter, "TRUEVISION-XFILE.") Then ;read extension information to struct if available
$iOffset = $tTGAFooter.extAreaOffset
_WinAPI_SetFilePointer($hFile, $iOffset, $FILE_BEGIN)
_WinAPI_ReadFile($hFile, $tTGAExtention, 0x01EF, $dwBytesRead)
Else
$tTGAFooter.extAreaOffset = 0
EndIf
_WinAPI_CloseHandle($hFile)
If $dwBytesRead = 0 Then Return SetError(4, _WinAPI_GetLastError(), 0)
Local $bRLE = BitOR($tTGAHeader.imageType = 0x09, $tTGAHeader.imageType = 0x0A, $tTGAHeader.imageType = 0x0B)
If $bPrintInfo Then
ConsoleWrite("idLength: " & $tTGAHeader.idLength & @CRLF)
ConsoleWrite("colormapType: " & $tTGAHeader.colormapType & @CRLF)
ConsoleWrite("imageType: " & $tTGAHeader.imageType & @CRLF)
ConsoleWrite("firstEntryIndex: " & $tTGAHeader.firstEntryIndex & @CRLF)
ConsoleWrite("colormapLength: " & $tTGAHeader.colormapLength & @CRLF)
ConsoleWrite("colormapEntrySize: " & $tTGAHeader.colormapEntrySize & @CRLF)
ConsoleWrite("xOrigin: " & $tTGAHeader.xOrigin & @CRLF)
ConsoleWrite("yOrigin: " & $tTGAHeader.yOrigin & @CRLF)
ConsoleWrite("width: " & $tTGAHeader.width & @CRLF)
ConsoleWrite("height: " & $tTGAHeader.height & @CRLF)
ConsoleWrite("pixelDepth: " & $iPxDepth & @CRLF)
ConsoleWrite("imageDescriptor: " & $tTGAHeader.imageDescriptor & @CRLF)
If $tTGAHeader.idLength > 0 Then ConsoleWrite("ImageID: " & RemoveNullChars($tTGAImageID.imageID) & @CRLF)
If $iOffset Then
ConsoleWrite("authorName: " & RemoveNullChars($tTGAExtention.authorName) & @CRLF)
ConsoleWrite("authorComments: " & RemoveNullChars($tTGAExtention.authorComments) & @CRLF)
ConsoleWrite("jobName: " & RemoveNullChars($tTGAExtention.jobName) & @CRLF)
ConsoleWrite("swID: " & RemoveNullChars($tTGAExtention.swID) & @CRLF)
EndIf
ConsoleWrite("RLE packed: " & $bRLE & @CRLF)
EndIf
Local Static $tDestBmp ;must be static otherwise bitmap data might get corrupted or in worst case script will crash
Local $stride, $iPixelFormat
Switch $iPxDepth
Case 1 ;1-bit
$iPixelFormat = $GDIP_PXF01INDEXED
$stride = BitAND(($iW * 1) + 1, BitNOT(1))
$tDestBmp = DllStructCreate("uint color[" & $stride * $iH & "];")
Case 8, 24
$iPixelFormat = $GDIP_PXF24RGB
$stride = BitAND(($iW * 3) + 3, BitNOT(3))
$tDestBmp = DllStructCreate("ubyte color[" & $stride * $iH & "];")
Case 15, 16
$iPixelFormat = $GDIP_PXF16RGB555
$stride = BitAND(($iW * 2) + 2, BitNOT(2))
$tDestBmp = DllStructCreate("ubyte color[" & $stride * $iH & "];")
Case 32
$iPixelFormat = $GDIP_PXF32ARGB
$stride = $iW * 4
$tDestBmp = DllStructCreate("ubyte color[" & $stride * $iH & "];")
Case Else
Return SetError(5, 0, 0)
EndSwitch
If Mod($stride, 4) <> 0 Then $stride += 4 - Mod($stride, 4)
Local Const $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH, $iPixelFormat, $stride, $tDestBmp)
If @error Or Not $hBitmap Then Return SetError(6, @error, 0)
Local $c, $q, $x, $y, $t1, $t2, $t3, $t4, $col, $red, $green, $blue, $alpha, $iLen, $iStart, $iEnd, $iLength, $iWW
Local Const $hDLL = DllOpen("msvcrt.dll")
Switch $iPxDepth
Case 1 ;1-bit
For $y = 0 To $iH - 1
$t1 = $y * $stride
DllCall($hDLL, "ptr:cdecl", "memcpy", "ptr", DllStructGetPtr($tDestBmp) + $t1, "ptr", DllStructGetPtr($tSrcBmp) + BitShift($t1, 3), "uint", $stride)
Next
Case 8 ;8-bit
;if a color table is available, just use it
If $tTGAHeader.colormapType = 1 Then
Local $tMapColorTbl = DllStructCreate("ubyte bgr[" & $colorTblSize & "]", DllStructGetPtr($tSrcBmp, "color") + $tTGAHeader.firstEntryIndex)
Switch $bRLE
Case 0
For $y = 0 To ($iH - 1)
$iOffset = $y * $iW + $colorTblSize
$iOffset2 = $y * $stride
For $x = 0 To ($iW - 1)
$t1 = $iOffset2 + $x * 3
$t2 = $tSrcBmp.color($iOffset + $x + 1) * $colorwidth
Switch $colorwidth
Case 3, 4
$tDestBmp.color($t1 + 1) = $tMapColorTbl.bgr($t2 + 1)
$tDestBmp.color($t1 + 2) = $tMapColorTbl.bgr($t2 + 2)
$tDestBmp.color($t1 + 3) = $tMapColorTbl.bgr($t2 + 3)
Case 2 ;convert from RGB555 to RGB
$col = BitOR(BitShift($tMapColorTbl.bgr($t2 + 2), -8), $tMapColorTbl.bgr($t2 + 1))
;RGB555
$tDestBmp.color($t1 + 1) = BitShift(BitAND($col, 0x001F), -3) ;B
$tDestBmp.color($t1 + 2) = BitShift(BitShift(BitAND($col, 0x03E0), 5), -3) ;G
$tDestBmp.color($t1 + 3) = BitShift(BitShift(BitAND($col, 0x7C00), 10), -3) ;R
EndSwitch
Next
Next
Case Else ;RLE encoded TGA images
$c = 0
$x = 0
$y = 0
$iOffset = $colorTblSize + 1
$iStart = Int($iColorValuesStartPos + $colorTblSize)
$iEnd = $tTGAFooter.extAreaOffset > 0 ? $tTGAFooter.extAreaOffset : $dwBufferSize
$iLength = $iEnd - $iStart - 1
$iWW = $iW - 1
$t3 = $colorwidth = 2 ? 2 : 3
While $c <= $iLength
$iOffset2 = Int($tSrcBmp.color($iOffset + $c))
$iLen = BitAND($iOffset2, 0x7F) + 1
If BitAND($iOffset2, 0x80) Then ; check for packet format
;run length packet format
$c += 1
$iOffset3 = Int($tSrcBmp.color($iOffset + $c)) * $t3
$t2 = $y * $stride
For $q = 1 To $iLen
$t1 = $t2 + $x * 3
Switch $colorwidth
Case 3, 4
$tDestBmp.color($t1 + 1) = $tMapColorTbl.bgr($iOffset3 + 1)
$tDestBmp.color($t1 + 2) = $tMapColorTbl.bgr($iOffset3 + 2)
$tDestBmp.color($t1 + 3) = $tMapColorTbl.bgr($iOffset3 + 3)
Case 2 ;convert from RGB555 to RGB
$col = BitOR(BitShift($tMapColorTbl.bgr($iOffset3 + 2), -8), $tMapColorTbl.bgr($iOffset3 + 1))
;RGB555
$tDestBmp.color($t1 + 1) = BitShift(BitAND($col, 0x001F), -3) ;B
$tDestBmp.color($t1 + 2) = BitShift(BitShift(BitAND($col, 0x03E0), 5), -3) ;G
$tDestBmp.color($t1 + 3) = BitShift(BitShift(BitAND($col, 0x7C00), 10), -3) ;R
EndSwitch
$x += 1
If $x > $iWW Then
$x = 0
$y += 1
$t2 = $y * $stride
EndIf
Next
$c += 1
Else
;raw packet format
$c += 1
$t2 = $y * $stride
For $q = 1 To $iLen
$iOffset3 = Int($tSrcBmp.color($iOffset + $c)) * $t3
$t1 = $t2 + $x * 3
Switch $colorwidth
Case 3, 4
$tDestBmp.color($t1 + 1) = $tMapColorTbl.bgr($iOffset3 + 1)
$tDestBmp.color($t1 + 2) = $tMapColorTbl.bgr($iOffset3 + 2)
$tDestBmp.color($t1 + 3) = $tMapColorTbl.bgr($iOffset3 + 3)
Case 2 ;convert from RGB555 to RGB
$col = BitOR(BitShift($tMapColorTbl.bgr($iOffset3 + 2), -8), $tMapColorTbl.bgr($iOffset3 + 1))
;RGB555
$tDestBmp.color($t1 + 1) = BitShift(BitAND($col, 0x001F), -3) ;B
$tDestBmp.color($t1 + 2) = BitShift(BitShift(BitAND($col, 0x03E0), 5), -3) ;G
$tDestBmp.color($t1 + 3) = BitShift(BitShift(BitAND($col, 0x7C00), 10), -3) ;R
EndSwitch
$x += 1
If $x > $iWW Then
$x = 0
$y += 1
$t2 = $y * $stride
EndIf
$c += 1
Next
EndIf
WEnd
EndSwitch
Else ;convert it to grayscale
Switch $bRLE
Case 0
For $y = 0 To $iH - 1
$iOffset = $y * $iW + $colorTblSize
$iOffset2 = $y * $stride
For $x = 0 To $iW - 1
$t1 = $iOffset + $x - 2
$t2 = $iOffset2 + $x * 3
$blue = $tSrcBmp.color($t1 + 1)
$green = $tSrcBmp.color($t1 + 2)
$red = $tSrcBmp.color($t1 + 3)
$col = $red
$col = $col < 0 ? 0 : $col > 255 ? 255 : $col
$tDestBmp.color($t2 + 1) = $col
$tDestBmp.color($t2 + 2) = $col
$tDestBmp.color($t2 + 3) = $col
Next
Next
Case Else
$c = 0
$x = 0
$y = 0
$iOffset = $colorTblSize + 1
$iStart = Int($iColorValuesStartPos + $colorTblSize)
$iEnd = $tTGAFooter.extAreaOffset > 0 ? $tTGAFooter.extAreaOffset : $dwBufferSize
$iLength = $iEnd - $iStart - 1
$iWW = $iW - 1
While $c <= $iLength
$iOffset2 = Int($tSrcBmp.color($iOffset + $c))
$iLen = BitAND($iOffset2, 0x7F) + 1
If BitAND($iOffset2, 0x80) Then ; check for packet format
;run length packet format
$c += 1
$iOffset3 = Int($tSrcBmp.color($iOffset + $c)) * 3
$blue = $iOffset3
$green = $iOffset3 + 1
$red = $iOffset3 + 2
$col = ($red + $green + $blue) / 9
$col = $col < 0 ? 0 : $col > 255 ? 255 : $col
$t2 = $y * $stride
For $q = 1 To $iLen
$t1 = $t2 + $x * 3
$tDestBmp.color($t1 + 1) = $col
$tDestBmp.color($t1 + 2) = $col
$tDestBmp.color($t1 + 3) = $col
$x += 1
If $x > $iWW Then
$x = 0
$y += 1
$t2 = $y * $stride
EndIf
Next
$c += 1
Else
;raw packet format
$c += 1
$t2 = $y * $stride
For $q = 1 To $iLen
$iOffset3 = Int($tSrcBmp.color($iOffset + $c)) * 3
$blue = $iOffset3
$green = $iOffset3 + 1
$red = $iOffset3 + 2
$col = ($red + $green + $blue) / 9
$col = $col < 0 ? 0 : $col > 255 ? 255 : $col
$t1 = $t2 + $x * 3
$tDestBmp.color($t1 + 1) = $col
$tDestBmp.color($t1 + 2) = $col
$tDestBmp.color($t1 + 3) = $col
$x += 1
If $x > $iWW Then
$x = 0
$y += 1
$t2 = $y * $stride
EndIf
$c += 1
Next
EndIf
WEnd
EndSwitch
EndIf
Case 15, 16, 24, 32 ;15/16/24/32-bit, as the bitmap format is the same we can use memcpy to copy the pixel data directly to the memory.
;Exeptions are 15/16/24-bit images whose width is not a divider of 4!
If BitOR($iPxDepth = 15, $iPxDepth = 16, $iPxDepth = 24) Then
If BitOR(Mod($iW, 4), $bRLE) Then
Switch $iPxDepth
Case 15, 16
Switch $bRLE
Case 0
$t4 = $iW * 2
For $y = 0 To ($iH - 1)
$iOffset = $y * $t4
$iOffset2 = $y * $stride
For $x = 0 To ($iW - 1)
$t3 = $x * 2
$t1 = $iOffset + $t3
$t2 = $iOffset2 + $t3
;RGB555
$tDestBmp.color($t2 + 1) = $tSrcBmp.color($t1 + $colorTblSize + 1)
$tDestBmp.color($t2 + 2) = $tSrcBmp.color($t1 + $colorTblSize + 2)
Next
Next
Case Else
$c = 0
$x = 0
$y = 0
$iStart = Int($iColorValuesStartPos + $colorTblSize)
$iEnd = $tTGAFooter.extAreaOffset > 0 ? $tTGAFooter.extAreaOffset : $dwBufferSize
$iLength = $iEnd - $iStart - 1
$iWW = $iW - 1
While $c <= $iLength
$iOffset2 = Int($tSrcBmp.color($colorTblSize + $c + 1))
$iLen = BitAND($iOffset2, 0x7F) + 1
If BitAND($iOffset2, 0x80) Then ; check for packet format
;run length packet format
$c += 1
$t3 = $y * $stride
For $q = 1 To $iLen
$t1 = $t3 + $x * 2
$t2 = $colorTblSize + $c
$tDestBmp.color($t1 + 1) = $tSrcBmp.color($t2 + 1)
$tDestBmp.color($t1 + 2) = $tSrcBmp.color($t2 + 2)
$x += 1
If $x > $iWW Then
$x = 0
$y += 1
$t3 = $y * $stride
EndIf
Next
$c += 2
Else
;raw packet format
$c += 1
$t3 = $y * $stride
For $q = 1 To $iLen
$t1 = $t3 + $x * 2
$t2 = $colorTblSize + $c
$tDestBmp.color($t1 + 1) = $tSrcBmp.color($t2 + 1)
$tDestBmp.color($t1 + 2) = $tSrcBmp.color($t2 + 2)
$x += 1
If $x > $iWW Then
$x = 0
$y += 1
$t3 = $y * $stride
EndIf
$c += 2
Next
EndIf
WEnd
EndSwitch
Case 24
Switch $bRLE
Case 0
$t4 = $iW * 3
For $y = 0 To $iH - 1
$iOffset = $y * $t4
$iOffset2 = $y * $stride
For $x = 0 To ($iW - 1)
$t3 = $x * 3
$t1 = $iOffset + $t3
$blue = $tSrcBmp.color($t1 + 1)
$green = $tSrcBmp.color($t1 + 2)
$red = $tSrcBmp.color($t1 + 3)
$t2 = $iOffset2 + $t3
$tDestBmp.color($t2 + 1) = $blue
$tDestBmp.color($t2 + 2) = $green
$tDestBmp.color($t2 + 3) = $red
Next
Next
Case Else
$c = 0
$x = 0
$y = 0
$iStart = Int($iColorValuesStartPos + $colorTblSize)
$iEnd = $tTGAFooter.extAreaOffset > 0 ? $tTGAFooter.extAreaOffset : $dwBufferSize
$iLength = $iEnd - $iStart - 1
$iWW = $iW - 1
While $c <= $iLength
$iOffset2 = Int($tSrcBmp.color($c + 1))
$iLen = BitAND($iOffset2, 0x7F) + 1
If BitAND($iOffset2, 0x80) Then ; check for packet format
;run length packet format
$c += 1
$blue = $tSrcBmp.color($c + 1)
$green = $tSrcBmp.color($c + 2)
$red = $tSrcBmp.color($c + 3)
$t2 = $y * $stride
For $q = 1 To $iLen
$t1 = $t2 + $x * 3
$tDestBmp.color($t1 + 1) = $blue
$tDestBmp.color($t1 + 2) = $green
$tDestBmp.color($t1 + 3) = $red
$x += 1
If $x > $iWW Then
$x = 0
$y += 1
$t2 = $y * $stride
EndIf
Next
$c += 3
Else
;raw packet format
$c += 1
$t2 = $y * $stride
For $q = 1 To $iLen
$blue = $tSrcBmp.color($c + 1)
$green = $tSrcBmp.color($c + 2)
$red = $tSrcBmp.color($c + 3)
$t1 = $t2 + $x * 3
$tDestBmp.color($t1 + 1) = $blue
$tDestBmp.color($t1 + 2) = $green
$tDestBmp.color($t1 + 3) = $red
$x += 1
If $x > $iWW Then
$x = 0
$y += 1
$t2 = $y * $stride
EndIf
$c += 3
Next
EndIf
WEnd
EndSwitch
EndSwitch
Else
For $y = 0 To $iH - 1
$t1 = $y * $stride
DllCall($hDLL, "ptr:cdecl", "memcpy", "ptr", DllStructGetPtr($tDestBmp) + $t1, "ptr", DllStructGetPtr($tSrcBmp) + $t1, "uint", $stride)
Next
EndIf
Else
Switch $bRLE
Case 0
For $y = 0 To $iH - 1
$t1 = $y * $stride
DllCall($hDLL, "ptr:cdecl", "memcpy", "ptr", DllStructGetPtr($tDestBmp) + $t1, "ptr", DllStructGetPtr($tSrcBmp) + $t1, "uint", $stride)
Next
Case Else
$c = 0
$x = 0
$y = 0
$iStart = Int($iColorValuesStartPos + $colorTblSize)
$iEnd = $tTGAFooter.extAreaOffset > 0 ? $tTGAFooter.extAreaOffset : $dwBufferSize
$iLength = $iEnd - $iStart - 1
$iWW = $iW - 1
While $c <= $iLength
$iOffset2 = Int($tSrcBmp.color($c + 1))
$iLen = BitAND($iOffset2, 0x7F) + 1
If BitAND($iOffset2, 0x80) Then ; check for packet format
;run length packet format
$c += 1
$blue = $tSrcBmp.color($c + 1)
$green = $tSrcBmp.color($c + 2)
$red = $tSrcBmp.color($c + 3)
$alpha = $tSrcBmp.color($c + 4)
$t2 = $y * $stride
For $q = 1 To $iLen
$t1 = $t2 + $x * 4
$tDestBmp.color($t1 + 1) = $blue
$tDestBmp.color($t1 + 2) = $green
$tDestBmp.color($t1 + 3) = $red
$tDestBmp.color($t1 + 4) = $alpha
$x += 1
If $x > $iWW Then
$x = 0
$y += 1
$t2 = $y * $stride
EndIf
Next
$c += 4
Else
;raw packet format
$c += 1
$t2 = $y * $stride
For $q = 1 To $iLen
$blue = $tSrcBmp.color($c + 1)
$green = $tSrcBmp.color($c + 2)
$red = $tSrcBmp.color($c + 3)
$alpha = $tSrcBmp.color($c + 4)
$t1 = $t2 + $x * 4
$tDestBmp.color($t1 + 1) = $blue
$tDestBmp.color($t1 + 2) = $green
$tDestBmp.color($t1 + 3) = $red
$tDestBmp.color($t1 + 4) = $alpha
$x += 1
If $x > $iWW Then
$x = 0
$y += 1
$t2 = $y * $stride
EndIf
$c += 4
Next
EndIf
WEnd
EndSwitch
EndIf
EndSwitch
DllClose($hDLL)
;TGA image is stored bottom up in file. Need to flip it.
If BitAND($tTGAHeader.imageDescriptor, 0x30) <> 0x20 Then _GDIPlus_ImageRotateFlip($hBitmap, $GDIP_Rotate180FlipX)
$tSrcBmp = 0
Return $hBitmap
EndFunc ;==>_GDIPlus_TGAImageLoadFromFile
; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name ..........: RemoveNullChars
; Description ...: Converts a null terminated binary string to a string
; Author ........: UEZ
; ===============================================================================================================================
Func RemoveNullChars($bin)
Local $a = StringRegExp($bin, "[[:xdigit:]+]{2}", 3), $s, $i
If @error Then Return $s
For $i = 0 To UBound($a) - 1
If $a[$i] = "00" Then ExitLoop
$s &= Chr(Dec($a[$i]))
Next
Return $s
EndFunc ;==>RemoveNullChars
;------------- Example -------------
Global $sFile = FileOpenDialog("Select a TGA file", "", "TGA image(*.tga)")
If @error Then Exit
_GDIPlus_Startup()
Global $endtime, $timer = TimerInit()
Global $hImage = _GDIPlus_TGAImageLoadFromFile($sFile, True)
If @error Then
ConsoleWrite(@error & " / " & @extended & @CRLF)
_GDIPlus_Shutdown()
Exit
EndIf
$endtime = TimerDiff($timer)
;~ _GDIPlus_ImageSaveToFile($hImage, @ScriptDir & "\Converted.png")
;~ ShellExecute(@ScriptDir & "\Converted.png")
Global $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage)
Global $hGui = GUICreate("TGA Image Loader by UEZ", $iW, $iH)
GUISetState()
Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
_GDIPlus_GraphicsDrawImageRect($hGraphics, $hImage, 0, 0, $iW, $iH)
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
_GDIPlus_BitmapDispose($hImage)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_Shutdown()
Exit
Case $GUI_EVENT_RESTORE
_GDIPlus_GraphicsDrawImageRect($hGraphics, $hImage, 0, 0, $iW, $iH)
EndSwitch
WEnd
v0.80 with assembler acceleration (thanks to AndyG for Assembleit2) but without RLE support yet:
;Coded by UEZ
#AutoIt3Wrapper_Compile_Both=y
#AutoIt3Wrapper_UseX64=n
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <Memory.au3>
#include <WinAPIFiles.au3>
; #FUNCTION# ====================================================================================================================
; Name ..........: _GDIPlus_TGAImageLoadFromFile
; Description ...: Loads an uncompressed TGA image file (1/8/15/16/24/32-bit) and converts it to a GDI+ bitmap format.
; Syntax ........: _GDIPlus_TGAImageLoadFromFile($sFile[, $bPrintInfo = False.])
; Parameters ....: $sFile - TGA file name to load from disk.
; $bPrintInfo - [optional] Prints some information about the TGA image to console. Default is False.
; Return values .: Success: GDI+ bitmap handle
; Failure: error 1 - file cannot be opened
; error 2 - TGA image is not in one of these formats: 1/8/15/16/24/32-bit
; error 3 - unsupported TGA image type
; error 4 - unable to read file to struct
; error 5 - unknown TGA pixel depth
; error 6 - return bitmap cannot be created
; Version .......: v0.80 build 2019-10-23 beta
; Author ........: UEZ - thanks to AndyG for Assembleit2
; Remarks .......: No RLE compressed TGA image support yet!
; Related .......: _GDIPlus_BitmapCreateFromScan0, _GDIPlus_ImageRotateFlip, DllStructCreate, _WinAPI_CreateFile, _WinAPI_SetFilePointer
; Link ..........: https://www.loc.gov/preservation/digital/formats/fdd/fdd000180.shtml, http://www.fileformat.info/format/tga/egff.htm
; Example .......: Yes
; ===============================================================================================================================
Func _GDIPlus_TGAImageLoadFromFile($sFile, $bPrintInfo = False)
Local Const $hFile = _WinAPI_CreateFile($sFile, 2, 2)
If Not $hFile Then Return SetError(1, 0, 0)
Local Const $tagTGAHeader = "align 1;byte idLength;byte colormapType;byte imageType;word firstEntryIndex;word colormapLength;byte colormapEntrySize;word xOrigin;word yOrigin;word width;word height;byte pixelDepth;byte imageDescriptor"
Local Const $tagTGAFooter = "dword extAreaOffset;dword devDirOffset;byte imageID[18]"
Local Const $tagTGAExtention = "align 1;word extSize;byte authorName[41];byte authorComments[324];word timeM;word timeD;word timeY;word timeHr;word timeMin;word timeSec;byte jobName[41];word jobTimeHr;word jobTimeMin;word jobTimeSec;byte swID[41];word swVersionNr;byte swVersionLetter;long keyColor;word pxAspectRatioNum;word pxAspectRatioDom;word gammaNum;word gammaDom;dword colCorrOffset;dword postStampOffset;dword scanLineOffset;byte attribType"
Local Const $tTGAHeader = DllStructCreate($tagTGAHeader)
Local Const $tTGAFooter = DllStructCreate($tagTGAFooter)
Local Const $tTGAExtention = DllStructCreate($tagTGAExtention)
Local $dwBytesRead, $tTGAImageID, $tagTGAImageID
_WinAPI_ReadFile($hFile, $tTGAHeader, DllStructGetSize($tTGAHeader), $dwBytesRead)
If $tTGAHeader.idLength > 0 Then
$tagTGAImageID = "byte imageID[" & $tTGAHeader.idLength & "]"
$tTGAImageID = DllStructCreate($tagTGAImageID)
_WinAPI_ReadFile($hFile, $tTGAImageID, $tTGAHeader.idLength, $dwBytesRead)
EndIf
Local Const $iPxDepth = $tTGAHeader.pixelDepth
If Not BitOR($iPxDepth = 32, $iPxDepth = 24, $iPxDepth = 16, $iPxDepth = 15, $iPxDepth = 8, $iPxDepth = 1) Then
_WinAPI_CloseHandle($hFile)
Return SetError(2, 0, 0)
EndIf
#cs
ImageType Image Data Type Colormap Encoding
0 No image data included in file No No
1 Colormapped image data Yes No
2 Truecolor image data No No
3 Monochrome image data No No
9 Colormapped image data Yes Yes
10 Truecolor image data No Yes
11 Monochrome image data No Yes
#ce
If Not BitOR($tTGAHeader.imageType = 0x01, $tTGAHeader.imageType = 0x02, $tTGAHeader.imageType = 0x03) Then
_WinAPI_CloseHandle($hFile)
Return SetError(3, 0, 0)
EndIf
Local $iW = $tTGAHeader.width, $iH = $tTGAHeader.height, $bytesPerPixel = $iPxDepth / 8, $colorwidth = $tTGAHeader.colormapEntrySize / 8, _
$colorTblSize = $tTGAHeader.colormapLength * $colorwidth
If $tTGAHeader.colormapEntrySize < 24 Then $bytesPerPixel = 4
Local Const $dwBufferSize = FileGetSize($sFile)
Local $tSrcBmp = DllStructCreate("ubyte color[" & $dwBufferSize + $colorTblSize & "]")
_WinAPI_ReadFile($hFile, $tSrcBmp, $dwBufferSize + $colorTblSize, $dwBytesRead)
_WinAPI_SetFilePointer($hFile, -26, $FILE_END)
_WinAPI_ReadFile($hFile, $tTGAFooter, 26, $dwBytesRead)
Local $sFooter = StringTrimRight(BinaryToString($tTGAFooter.imageID), 1), $iOffset = 0, $iOffset2
If Not StringCompare($sFooter, "TRUEVISION-XFILE.") Then ;read extension information to struct if available
$iOffset = $tTGAFooter.extAreaOffset
_WinAPI_SetFilePointer($hFile, $iOffset, $FILE_BEGIN)
_WinAPI_ReadFile($hFile, $tTGAExtention, 0x01EF, $dwBytesRead)
EndIf
_WinAPI_CloseHandle($hFile)
If $dwBytesRead = 0 Then Return SetError(4, _WinAPI_GetLastError(), 0)
If $bPrintInfo Then
ConsoleWrite("idLength: " & $tTGAHeader.idLength & @CRLF)
ConsoleWrite("colormapType: " & $tTGAHeader.colormapType & @CRLF)
ConsoleWrite("imageType: " & $tTGAHeader.imageType & @CRLF)
ConsoleWrite("firstEntryIndex: " & $tTGAHeader.firstEntryIndex & @CRLF)
ConsoleWrite("colormapLength: " & $tTGAHeader.colormapLength & @CRLF)
ConsoleWrite("colormapEntrySize: " & $tTGAHeader.colormapEntrySize & @CRLF)
ConsoleWrite("xOrigin: " & $tTGAHeader.xOrigin & @CRLF)
ConsoleWrite("yOrigin: " & $tTGAHeader.yOrigin & @CRLF)
ConsoleWrite("width: " & $tTGAHeader.width & @CRLF)
ConsoleWrite("height: " & $tTGAHeader.height & @CRLF)
ConsoleWrite("pixelDepth: " & $iPxDepth & @CRLF)
ConsoleWrite("imageDescriptor: " & $tTGAHeader.imageDescriptor & @CRLF)
If $tTGAHeader.idLength > 0 Then ConsoleWrite("ImageID: " & RemoveNullChars($tTGAImageID.imageID) & @CRLF)
If $iOffset Then
ConsoleWrite("authorName: " & RemoveNullChars($tTGAExtention.authorName) & @CRLF)
ConsoleWrite("authorComments: " & RemoveNullChars($tTGAExtention.authorComments) & @CRLF)
ConsoleWrite("jobName: " & RemoveNullChars($tTGAExtention.jobName) & @CRLF)
ConsoleWrite("swID: " & RemoveNullChars($tTGAExtention.swID) & @CRLF)
EndIf
EndIf
Local Static $tDestBmp ;must be static otherwise bitmap data might get corrupted or in worst case script will crash
Local $stride, $iPixelFormat
Switch $iPxDepth
Case 1 ;1-bit
$iPixelFormat = $GDIP_PXF01INDEXED
$stride = BitAND(($iW * 1) + 1, BitNOT(1))
$tDestBmp = DllStructCreate("uint color[" & $stride * $iH + 1 & "];")
Case 8, 24
$iPixelFormat = $GDIP_PXF24RGB
$stride = BitAND(($iW * 3) + 3, BitNOT(3))
$tDestBmp = DllStructCreate("uint color[" & $stride * $iH + 1 & "];")
Case 15, 16
$iPixelFormat = $GDIP_PXF16RGB555
$stride = BitAND(($iW * 2) + 2, BitNOT(2))
$tDestBmp = DllStructCreate("uint color[" & $stride * $iH + 1 & "];")
Case 32
$iPixelFormat = $GDIP_PXF32ARGB
$stride = $iW * 4
$tDestBmp = DllStructCreate("uint color[" & $stride * $iH + 1 & "];")
Case Else
Return SetError(5, 0, 0)
EndSwitch
If Mod($stride, 4) <> 0 Then $stride += 4 - Mod($stride, 4)
Local Const $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH, $iPixelFormat, $stride, $tDestBmp)
If @error Or Not $hBitmap Then Return SetError(6, @error, 0)
Local $fTimer = TimerInit()
Local $x, $x1, $y, $t1
Local Const $hDLL = DllOpen("msvcrt.dll")
Local Const $tagParam = "ptr tSrcBmp;ptr tDestBmp;dword strideSrc;dword strideDest;dword w;dword h;dword colorTblSize;dword t1;dword t2"
Local $tParam
If @AutoItX64 Then
$tParam = _DLLStructCreate64($tagParam)
Else
$tParam = DLLStructCreate($tagParam)
EndIf
$tParam.tSrcBmp = DllStructGetPtr($tSrcBmp)
$tParam.tDestBmp = DllStructGetPtr($tDestBmp)
$tParam.strideDest = $stride
$tParam.w = ($iW - 1)
$tParam.h = ($iH - 1)
$tParam.colorTblSize = $colorTblSize
Switch $iPxDepth
Case 1 ;1-bit
For $y = 0 To $iH - 1
$t1 = $y * $stride
DllCall($hDLL, "ptr:cdecl", "memcpy", "ptr", DllStructGetPtr($tDestBmp) + $t1, "ptr", DllStructGetPtr($tSrcBmp) + BitShift($t1, 3), "uint", $stride)
Next
Case 8 ;8-bit
ConsoleWrite("Using Assembler code to speed-up..." & @CRLF)
;if a color table is available, just use it
If $tTGAHeader.colormapType = 1 Then
Local $tMapColorTbl = DllStructCreate("ubyte bgr[" & $colorTblSize & "]", DllStructGetPtr($tSrcBmp, "color") + $tTGAHeader.firstEntryIndex)
Local $tParam2, $tagParam2 = "align 1;ptr tSrcBmp;ptr tDestBmp;ptr colormap;dword strideSrc;dword strideDest;dword w;dword h;dword colorTblSize;dword colorwidth;dword t1;dword t2;byte r5;byte g5;byte b5;"
If @AutoItX64 Then
$tParam2 = _DLLStructCreate64($tagParam2)
Else
$tParam2 = DllStructCreate($tagParam2)
EndIf
$tParam2.tSrcBmp = DllStructGetPtr($tSrcBmp)
$tParam2.tDestBmp = DllStructGetPtr($tDestBmp)
$tParam2.colormap = DllStructGetPtr($tMapColorTbl)
$tParam2.strideSrc = $iW
$tParam2.strideDest = $stride
$tParam2.colorwidth = $colorwidth
$tParam2.w = ($iW - 1)
$tParam2.h = ($iH - 1)
$tParam2.colorTblSize = $colorTblSize
Switch @AutoItX64
Case False
Local Const $bBinASM8cm_x86 = Binary("0x608B7C242431C990909090909090909089C8F7670C03471C89472489C8F7671089472831DB8B472401D8030789C231C08A02F767208B570801C28B32B803000000F7E303472803470489C5837F200275476689F26683E21F66C1E20388572E6689F26681E2E00366C1EA0566C1E20388572D6689F26681E2007C66C1EA0A66C1E20388572C31C00A472CC1E0080A472DC1E0080A472E89C6897500433B5F147684413B4F180F8665FFFFFF61C20400")
Local $tBinASM8cm_x86 = DllStructCreate("ubyte asm[" & BinaryLen($bBinASM8cm_x86) & "]")
$tBinASM8cm_x86.asm = $bBinASM8cm_x86
DllCallAddress("none", DllStructGetPtr($tBinASM8cm_x86), "ptr", DllStructGetPtr($tParam2))
Case Else
Local Const $bBinASM8cm_x64 = Binary("0x575653554989CF41BE000000009090904489F041F7671841034728418947304489F041F7671C418947344531ED418B47304401E84903074889C24831C08A0241F7672C498B57104801C2448B0A4831C048C7C00300000041F7E541034734490347084989C041837F2C02755A4831D2664489CA6683E21F66C1E2034188573A4831D2664489CA6681E2E00366C1EA0566C1E203418857394831D2664489CA6681E2007C66C1EA0A66C1E2034188573831C0410A4738C1E008410A4739C1E008410A473A4189C145890841FFC5453B6F200F8657FFFFFF41FFC6453B77240F862DFFFFFF5D5B5E5FC20800")
Local $tBinASM8cm_x64 = _DLLStructCreate64("ubyte asm[" & BinaryLen($bBinASM8cm_x64) & "]")
$tBinASM8cm_x64.asm = $bBinASM8cm_x64
DllCallAddress("none", DllStructGetPtr($tBinASM8cm_x64), "ptr", DllStructGetPtr($tParam2))
EndSwitch
Else ;convert it 1:1 directly
Switch @AutoItX64
Case False
$tParam.strideSrc = $iW
$tParam.colorTblSize -= 2
Local Const $bBinASM8_x86 = Binary("0x8B7C2404BB00000000B900000000909089C8F7670889471C89C8F7670C8947208B471C01D8034718030789C252B803000000F7E30347200347045A8B328930433B5F1076DB31DB413B4F1476C3C20400")
Local $tBinASM8_x86 = DllStructCreate("ubyte asm[" & BinaryLen($bBinASM8_x86) & "]")
$tBinASM8_x86.asm = $bBinASM8_x86
DllCallAddress("none", DllStructGetPtr($tBinASM8_x86), "ptr", DllStructGetPtr($tParam))
Case Else
$tParam.strideSrc = $iW
Local Const $bBinASM8_x64 = Binary("0x575653554989CF49836F2002BB00000000B9000000009090909090909090909089C841F767104989C289C841F767144989C34D89D04901D84D0347204D030748C7C00300000048F7E34C01D8490347084D8B08448908FFC3413B5F1876D44831DBFFC1413B4F1C76B75D5B5E5FC20800")
Local $tBinASM8_x64 = _DLLStructCreate64("ubyte asm[" & BinaryLen($bBinASM8_x64) & "]")
$tBinASM8_x64.asm = $bBinASM8_x64
DllCallAddress("none", DllStructGetPtr($tBinASM8_x64), "ptr", DllStructGetPtr($tParam))
EndSwitch
EndIf
Case 15, 16, 24, 32 ;15/16/24/32-bit, as the bitmap format is the same we can use memcpy to copy the pixel data directly to the memory.
;Exeptions are 15/16/24-bit images whose width is not a divider of 4!
If BitOR($iPxDepth = 15, $iPxDepth = 16, $iPxDepth = 24) And Mod($iW, 4) Then
ConsoleWrite("Using Assembler code to speed-up..." & @CRLF)
Switch $iPxDepth
Case 15, 16
$tParam.strideSrc = $iW * 2
Switch @AutoItX64
Case False
Local Const $bBinASM1516_x86 = Binary("0x8B7C2404BB00000000B900000000909089C8F7670889471C89C8F7670C894720B802000000F7E35003471C034718030789C2580347200347048B32668930433B5F1076DC31DB413B4F1476C4C20400")
Local $tBinASM1516_x86 = DllStructCreate("ubyte asm[" & BinaryLen($bBinASM1516_x86) & "]")
$tBinASM1516_x86.asm = $bBinASM1516_x86
DllCallAddress("none", DllStructGetPtr($tBinASM1516_x86), "ptr", DllStructGetPtr($tParam))
Case Else
Local Const $bBinASM1516_x64 = Binary("0x575653554989CFBB00000000B90000000090909090909090909090909090909089C841F767104989C189C841F767144989C25389D8D1E04C89D24801C2490357084D89C84901C04D0347204D0307498B00488902FFC3FFC3413B5F1876D55BFFC1413B4F1C76B95D5B5E5FC20800")
Local $tBinASM1516_x64 = _DLLStructCreate64("ubyte asm[" & BinaryLen($bBinASM1516_x64) & "]")
$tBinASM1516_x64.asm = $bBinASM1516_x64
DllCallAddress("none", DllStructGetPtr($tBinASM1516_x64), "ptr", DllStructGetPtr($tParam))
EndSwitch
Case 24
$tParam.strideSrc = $iW * 3
Switch @AutoItX64
Case False
Local Const $bBinASM24_x86 = Binary("0x8B7C2404BB00000000B900000000909089C8F7670889471C89C8F7670C894720B803000000F7E35003471C034718030789C2580347200347048B328930433B5F1076DD31DB413B4F1476C5C20400")
Local $tBinASM24_x86 = DllStructCreate("ubyte asm[" & BinaryLen($bBinASM24_x86) & "]")
$tBinASM24_x86.asm = $bBinASM24_x86
DllCallAddress("none", DllStructGetPtr($tBinASM24_x86), "ptr", DllStructGetPtr($tParam))
Case Else
Local Const $bBinASM24_x64 = Binary("0x575653554989CF4831C990909090909089C841F767104989C189C841F767144989C24831DB48C7C00300000048F7E34C89D24801C2490357084D89C84901C04D0347204D0307498B00488902FFC3FFC3413B5F1876CFFFC1413B4F1C76B25D5B5E5FC20800")
Local $tBinASM24_x64 = _DLLStructCreate64("ubyte asm[" & BinaryLen($bBinASM24_x64) & "]")
$tBinASM24_x64.asm = $bBinASM24_x64
DllCallAddress("none", DllStructGetPtr($tBinASM24_x64), "ptr", DllStructGetPtr($tParam))
EndSwitch
EndSwitch
Else
For $y = 0 To $iH - 1
$t1 = $y * $stride
DllCall($hDLL, "ptr:cdecl", "memcpy", "ptr", DllStructGetPtr($tDestBmp) + $t1, "ptr", DllStructGetPtr($tSrcBmp) + $t1, "uint", $stride)
Next
EndIf
EndSwitch
ConsoleWrite(TimerDiff($fTimer) & " ms" & @CRLF)
DllClose($hDLL)
;TGA image is stored bottom up in file. Need to flip it.
If BitAND($tTGAHeader.imageDescriptor, 0x30) <> 0x20 Then _GDIPlus_ImageRotateFlip($hBitmap, $GDIP_Rotate180FlipX)
$tSrcBmp = 0
Return $hBitmap
EndFunc ;==>_GDIPlus_TGAImageLoadFromFile
; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name ..........: RemoveNullChars
; Description ...: Converts a null terminated binary string to a string
; Author ........: UEZ
; ===============================================================================================================================
Func RemoveNullChars($bin)
Local $a = StringRegExp($bin, "[[:xdigit:]+]{2}", 3), $s, $i
If @error Then Return $s
For $i = 0 To UBound($a) - 1
If $a[$i] = "00" Then ExitLoop
$s &= Chr(Dec($a[$i]))
Next
Return $s
EndFunc ;==>RemoveNullChars
; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name ..........: _DLLStructCreate64
; Description ...: Creates a struct for x64 assembler code execution
; Author ........: AndyG
; ===============================================================================================================================
Func _DLLStructCreate64($struct) ;align auf 16-byte Adresse
Local $temp = DllStructCreate($struct)
Local $tempsize = DllStructGetSize($temp) + 64
Local $ptr = DllStructGetPtr($struct)
Local $a1 = Mod(Number($ptr), 64)
Local $temp = 0
Local $mem = _MemVirtualAlloc($ptr + $a1, $tempsize, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE)
Local $mem_dllstructcreate64_internal = $mem
Local $a2 = Mod(Number($mem), 64) ;rest div 16 adresse = offset
Local $sstruct = DllStructCreate($struct, (Number($mem) - $a2 + 64))
Return $sstruct ;auf 16 alingned pointer
EndFunc ;==>_DLLStructCreate64
Global $sFile = FileOpenDialog("Select a TGA file", "", "TGA image(*.tga)")
If @error Then Exit
_GDIPlus_Startup()
Global $hImage = _GDIPlus_TGAImageLoadFromFile($sFile, True)
If @error Then
ConsoleWrite(@error & " / " & @extended & @CRLF)
_GDIPlus_Shutdown()
Exit
EndIf
;save result
;~ _GDIPlus_ImageSaveToFile($hImage, @ScriptDir & "\Converted.png")
;~ ShellExecute(@ScriptDir & "\Converted.png")
Global $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage)
Global $hGui = GUICreate("TGA Image Loader by UEZ", $iW, $iH)
GUISetState()
Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
_GDIPlus_GraphicsDrawImageRect($hGraphics, $hImage, 0, 0, $iW, $iH)
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
_GDIPlus_BitmapDispose($hImage)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_Shutdown()
Exit
Case $GUI_EVENT_RESTORE
_GDIPlus_GraphicsDrawImageRect($hGraphics, $hImage, 0, 0, $iW, $iH)
EndSwitch
WEnd
Here my rookie assembler code ^^:
#cs _ASM8cm_x86
use32
define tSrcBmp dword[edi]
define tDestBmp dword[edi + 04]
define colortable dword[edi + 08]
define strideSrc dword[edi + 12]
define strideDest dword[edi + 16]
define w dword[edi + 20]
define h dword[edi + 24]
define colorTblSize dword[edi + 28]
define colorwidth dword[edi + 32]
define iOffset dword[edi + 36]
define iOffset2 dword[edi + 40]
define r5 byte[edi + 44]
define g5 byte[edi + 45]
define b5 byte[edi + 46]
pushad
;~ _ASMDBG_()
mov edi, dword[esp + 36] ;pointer to the struct
xor ecx, ecx; y = 0
align 16
_y:
mov eax, ecx
mul strideSrc
add eax, colorTblSize
mov iOffset, eax ;iOffset = y * $strideSrc + $colorTblSize
mov eax, ecx
mul strideDest
mov iOffset2, eax ;iOffset2 = y * $strideDest
xor ebx, ebx ;x = 0
_x:
mov eax, iOffset
add eax, ebx ;iOffset + x
add eax, tSrcBmp
mov edx, eax ;edx = iOffset + x + tSrcBmp
xor eax, eax
mov al, byte[edx] ;get index from color table
mul colorwidth ;multiply it with colorwidth -> eax = index of the color table
mov edx, colortable
add edx, eax
mov esi, dword[edx] ;get the color from the color table
mov eax, 3
mul ebx ;
add eax, iOffset2 ;
add eax, tDestBmp ;$x * 3 + iOffset2 + tDestBmp = t1
mov ebp, eax
cmp colorwidth, 2
jne _col_rgb
mov dx, si ;BitShift(BitAND($col, 0x001F), -3) ;B
and dx, 0x001F
shl dx, 3
mov b5, dl
mov dx, si ;BitShift(BitShift(BitAND($col, 0x03E0), 5), -3) ;G
and dx, 0x03E0
shr dx, 5
shl dx, 3
mov g5, dl
mov dx, si ;BitShift(BitShift(BitAND($col, 0x7C00), 10), -3) ;R
and dx, 0x7C00
shr dx, 10
shl dx, 3
mov r5, dl
xor eax, eax ;eax = 0
or al, r5 ;generate rgb value from rgb555
shl eax, 8
or al, g5
shl eax, 8
or al, b5
mov esi, eax
_col_rgb:
mov dword[ebp], esi ;write to destination
inc ebx
cmp ebx, w
jbe _x
inc ecx
cmp ecx, h
jbe _y
;~ _ASMDBG_()
popad
ret ;4
#ce _ASM8cm_x86
#cs _ASM8cm_x64
use64
define tSrcBmp qword[r15]
define tDestBmp qword[r15 + 08]
define colortable qword[r15 + 16]
define strideSrc dword[r15 + 24]
define strideDest dword[r15 + 28]
define w dword[r15 + 32]
define h dword[r15 + 36]
define colorTblSize dword[r15 + 40]
define colorwidth dword[r15 + 44]
define iOffset dword[r15 + 48]
define iOffset2 dword[r15 + 52]
define r5 byte[r15 + 56]
define g5 byte[r15 + 57]
define b5 byte[r15 + 58]
define x r13d
define y r14d
push rdi
push rsi
push rbx
push rbp
mov qword r15, rcx
mov y, 0
align 16
_y:
mov eax, y
mul strideSrc
add eax, colorTblSize
mov iOffset, eax ;iOffset = y * $strideSrc + $colorTblSize
mov eax, y
mul strideDest
mov iOffset2, eax ;iOffset2 = y * $strideDest
xor x, x ;x = 0
_x:
mov eax, iOffset
add eax, x ;iOffset + x
add rax, tSrcBmp
mov rdx, rax ;edx = iOffset + x + tSrcBmp
xor rax, rax
mov al, byte[rdx] ;get index from color table
mul colorwidth ;multiply it with colorwidth -> eax = index of the color table
mov rdx, colortable
add rdx, rax
mov r9d, dword[rdx] ;get the color from the color table
xor rax, rax
mov rax, 3
mul x ;
add eax, iOffset2 ;
add rax, tDestBmp ;$x * 3 + iOffset2 + tDestBmp = t1
mov r8, rax
cmp colorwidth, 2
jne _col_rgb
xor rdx, rdx
mov dx, r9w ;BitShift(BitAND($col, 0x001F), -3) ;B
and dx, 0x001F
shl dx, 3
mov b5, dl
xor rdx, rdx
mov dx, r9w ;BitShift(BitShift(BitAND($col, 0x03E0), 5), -3) ;G
and dx, 0x03E0
shr dx, 5
shl dx, 3
mov g5, dl
xor rdx, rdx
mov dx, r9w ;BitShift(BitShift(BitAND($col, 0x7C00), 10), -3) ;R
and dx, 0x7C00
shr dx, 10
shl dx, 3
mov r5, dl
xor eax, eax ;eax = 0
or al, r5 ;generate rgb value from rgb555
shl eax, 8
or al, g5
shl eax, 8
or al, b5
mov r9d, eax
_col_rgb:
mov dword[r8], r9d ;write to destination
inc x
cmp x, w
jbe _x
inc y
cmp y, h
jbe _y
pop rbp
pop rbx
pop rsi
pop rdi
ret 8
#ce
#cs _ASM8_x86
use32
pushad
mov edi, dword[esp + 36] ;pointer to the struct
define tSrcBmp dword[edi]
define tDestBmp dword[edi + 04]
define strideSrc dword[edi + 08]
define strideDest dword[edi + 12]
define w dword[edi + 16]
define h dword[edi + 20]
define colorTblSize dword[edi + 24]
define iOffset dword[edi + 28]
define iOffset2 dword[edi + 32]
mov ecx, 0 ; y
align 16
_y:
mov eax, ecx
mul strideSrc
add eax, colorTblSize
mov iOffset, eax ;iOffset = y * $strideSrc + $colorTblSize
mov eax, ecx
mul strideDest
mov iOffset2, eax ;iOffset2 = y * $strideDest
xor ebx, ebx ;x = 0
_x:
mov ebp, iOffset
sub ebp, 2
add ebp, ebx
add ebp, tSrcBmp ;ebp = t1
mov eax, 3
mul ebx
add eax, iOffset2
add eax, tDestBmp ;eax = t2
mov esi, dword[ebp] ;get the color from source bitmap
mov dword[eax], esi ;write to destination
inc ebx
cmp ebx, w
jbe _x
inc ecx
cmp ecx, h
jbe _y
popad
ret ;4
#ce _ASM8_x86
#cs _ASM8_x64
use64
push rdi
push rsi
push rbx
push rbp
define tSrcBmp qword[r15]
define tDestBmp qword[r15 + 08]
define strideSrc [r15 + 16]
define strideDest [r15 + 20]
define w [r15 + 24]
define h [r15 + 28]
define colorTblSize [r15 + 32]
define iOffset [r15 + 36]
define iOffset2 [r15 + 40]
mov qword r15, rcx
sub qword colorTblSize, 2
mov ebx, 0 ;w - 1
mov ecx, 0 ;h - 1
align 16
_y:
mov eax, ecx
mul dword strideSrc
mov r10, rax ;r10 = y * $strideSrc
mov eax, ecx
mul dword strideDest
mov r11, rax ;r11 = y * $strideDest
_x:
mov r8, r10
add r8, rbx
add r8, colorTblSize
add r8, tSrcBmp ;r8 = t1
mov rax, 3
mul rbx
add rax, r11
add rax, tDestBmp ;eax = t2
mov r9, [r8] ;get the color from source bitmap
mov dword[rax], r9d ;write to destination
inc ebx
cmp ebx, w
jbe _x
xor rbx, rbx
inc ecx
cmp ecx, h
jbe _y
pop rbp
pop rbx
pop rsi
pop rdi
ret 8
#ce _ASM8_x64
#cs _ASM1516_x86
use32
mov edi, dword[esp + 4] ;pointer to the struct
define tSrcBmp ptr[edi]
define tDestBmp ptr[edi + 04]
define strideSrc dword[edi + 08]
define strideDest dword[edi + 12]
define w dword[edi + 16]
define h dword[edi + 20]
define colorTblSize dword[edi + 24]
define iOffset dword[edi + 28]
define iOffset2 dword[edi + 32]
mov ebx, 0 ; x
mov ecx, 0 ; y
align 16
_y:
mov eax, ecx
mul strideSrc
mov iOffset, eax ;iOffset = y * $strideSrc
mov eax, ecx
mul strideDest
mov iOffset2, eax ;iOffset2 = y * $strideDest
_x:
mov eax, 2
mul ebx ;x * 2
push eax
add eax, iOffset
add eax, colorTblSize
add eax, tSrcBmp
mov edx, eax ;edx = t1
pop eax ;restore x * 2
add eax, iOffset2
add eax, tDestBmp ;eax = t2
mov esi, dword[edx] ;get the color from source bitmap
mov word[eax], si ;write to destination
inc ebx
cmp ebx, w
jbe _x
xor ebx, ebx
inc ecx
cmp ecx, h
jbe _y
ret ;4
#ce _ASM1516_x86
#cs _ASM1516_x64
use64
;~ define tSrcBmp dword[r15 + 0]
;~ define tDestBmp dword[r15 + 8]
;~ define strideS dword[r15 + 16]
;~ define strideD dword[r15 + 20]
;~ define width dword[r15 + 24]
;~ define height dword[r15 + 28]
;~ define colorTblSize dword[r15 + 32]
;~ define t1 dword[r15 + 36] ;not needed
;~ define t2 dword[r15 + 40] ;not needed
push rdi
push rsi
push rbx
push rbp
mov qword r15, rcx
mov ebx, 0 ;dword[r15 + 24] ;ebx = w - 1
mov ecx, 0 ;dword[r15 + 28] ;ecx = h - 1
align 16
_y:
mov eax, ecx
mul dword[r15 + 16]
mov r9, rax
mov eax, ecx
mul dword[r15 + 20]
mov r10, rax
push rbx
_x:
mov eax, ebx
shl eax, 1
mov rdx, r10
add rdx, rax
add rdx, [r15 + 8]
mov r8, r9
add r8, rax
add r8, [r15 + 32]
add r8, [r15]
mov rax, [r8]
mov [rdx], rax
inc ebx
inc ebx
cmp ebx, dword[r15 + 24]
jbe _x
pop rbx
inc ecx
cmp ecx, dword[r15 + 28]
jbe _y
pop rbp
pop rbx
pop rsi
pop rdi
ret 8
#ce _ASM1516_x64
#cs _ASM24_x86
use32
mov edi, dword[esp + 4] ;pointer to the struct
define tSrcBmp dword[edi]
define tDestBmp dword[edi + 04]
define strideSrc dword[edi + 08]
define strideDest dword[edi + 12]
define w dword[edi + 16]
define h dword[edi + 20]
define colorTblSize dword[edi + 24]
define iOffset dword[edi + 28]
define iOffset2 dword[edi + 32]
mov ebx, 0 ; x
mov ecx, 0 ; y
align 16
_y:
mov eax, ecx
mul strideSrc
mov iOffset, eax ;iOffset = y * $strideSrc
mov eax, ecx
mul strideDest
mov iOffset2, eax ;iOffset2 = y * $strideDest
_x:
mov eax, 3
mul ebx ;x * 3
push eax
add eax, iOffset
add eax, colorTblSize
add eax, tSrcBmp
mov edx, eax ;edx = t1
pop eax ;restore x * 3
add eax, iOffset2
add eax, tDestBmp ;eax = t2
mov esi, dword[edx] ;get the color from source bitmap
mov dword[eax], esi ;write to destination
inc ebx
cmp ebx, w
jbe _x
xor ebx, ebx
inc ecx
cmp ecx, h
jbe _y
ret ;4
#ce _ASM24_x86
#cs _ASM24_x64
use64
;~ define tSrcBmp dword[r15 + 0]
;~ define tDestBmp dword[r15 + 8]
;~ define strideS dword[r15 + 16]
;~ define strideD dword[r15 + 20]
;~ define width dword[r15 + 24]
;~ define height dword[r15 + 28]
;~ define colorTblSize dword[r15 + 32]
;~ define t1 dword[r15 + 36] ;not needed
;~ define t2 dword[r15 + 40] ;not needed
push rdi
push rsi
push rbx
push rbp
mov qword r15, rcx
xor rcx, rcx
align 16
_y:
mov eax, ecx
mul dword[r15 + 16]
mov r9, rax
mov eax, ecx
mul dword[r15 + 20]
mov r10, rax
xor rbx, rbx
_x:
mov rax, 3
mul rbx
mov rdx, r10
add rdx, rax
add rdx, [r15 + 8]
mov r8, r9
add r8, rax
add r8, [r15 + 32]
add r8, [r15]
mov rax, [r8]
mov [rdx], rax ;copy 64 bits
inc ebx
inc ebx
cmp ebx, dword[r15 + 24]
jbe _x
inc ecx
cmp ecx, dword[r15 + 28]
jbe _y
pop rbp
pop rbx
pop rsi
pop rdi
ret 8
#ce _ASM24_x64
If you find a TGA image which is in scope of this script but doesn't convert it properly, please report it here.
Thanks.