Hier ein kleines Skript zum Parsen von Targa (TGA) Bild Dateien (1-Bit, 8-Bit, 15-Bit, 16-Bit, 24-Bit und 32-Bit). Falls erfolgreich, wird ein GDI+ Bitmap erstellt.
Da der Code nativ in AutoIt geschrieben ist, dauert das Umwandelt für größere Bilder entsprechend.
Download nativ AutoIt Code: _GDIPlus_TGAImageLoadFromFile v0.85.au3
v0.80 mit Assembler Unterstützung, aber ohne RLE Support!:
AutoIt
;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
Alles anzeigen
Falls eine TGA Datei nicht umgewandelt werden kann, dann bitte hier melden.
Danke.