;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