#AutoIt3Wrapper_UseX64=n ; 32Bit-Modus!
#Region ;************ Includes ************
#include-once
#include <GDIPlus.au3>
#include <Memory.au3>
#EndRegion ;************ Includes ************
#Region ASM-Code
#cs _CountUniqueColors ;
Use32 ; 32Bit Modus!
mov esi,dword[esp+4] ; Pixelstruct-Pointer holen
mov ecx,dword[esp+8] ; Anzahl der Pixel holen (Pixelcounter)
mov edi,dword[esp+12] ; Colorstruct-Pointer holen
xor eax,eax ; eax als Farbzaehler (auf null setzen)
@pixel_count: ; Anfang der Schleife fuer alle Pixel
mov ebx,[esi] ; Farbwert aus Pixelstruct holen
and ebx,0xffffff ; Alphachannel eliminieren
cmp byte[edi+ebx],0 ; Wert aus der Colorstruct = 0?
jnz @next ; wenn nicht 0, dann wurde die Farbe bereits gezaehlt, weiter -> @next
inc eax ; den Farbzaehler um eins erhoehen
mov byte[edi+ebx],1 ; den Wert in der Colorstruct auf 1 setzen
@next:
add esi,4 ; den Pixelstruct-Pointer um 4 erhoehen (naechstes DWORD)
dec ecx ; Pixelcounter um eins verringern
jnz @pixel_count ; wenn Pixelcount nocht nicht 0, dann Schleife wiederholen
ret ; eax (Farbzaehler) wird zurueckgegeben
#ce
#EndRegion ASM-Code
; $__IGUC_g_bCode entspricht dem obigen ASM-Code im Binaerformat
Global Const $__IGUC_g_bCode = '0x8B7424048B4C24088B7C240C31C08B1E81E3FFFFFF00803C1F00750540C6041F0183C6044975E7C3'
; Die Speichergroesse fuer den ASM-Code berechnen
Global Const $__IGUC_g_iMemSize = StringLen($__IGUC_g_bCode) / 2 - 1
; Achtung! Hier unbedingt virtuellen Speicher mit "_MemVirtualAlloc" anfordern, weil sonst
; (bei eingeschalteter Datenausfuehrungsverhinderung = DEP) AutoIt mit einer Fehlermeldung beendet wird.
Global Const $__IGUC_g_pMem = _MemVirtualAlloc(0, $__IGUC_g_iMemSize, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE)
If $__IGUC_g_pMem = 0 Then Exit MsgBox(16, 'Error!', "Can't allocate virtual memory!")
; Struktur fuer den ASM-Code im virtuellen Speicher erstellen
Global $__IGUC_g_tCodeBuffer = DllStructCreate('byte[' & $__IGUC_g_iMemSize & ']', $__IGUC_g_pMem)
; den ASM-Code in den Speicher schreiben (wird unten bei DllCallAddress aufgerufen)
DllStructSetData($__IGUC_g_tCodeBuffer, 1, $__IGUC_g_bCode)
OnAutoItExitRegister('__IGUC_Exit')
_GDIPlus_Startup()
Func __IGUC_Exit()
_MemVirtualFree($__IGUC_g_pMem, $__IGUC_g_iMemSize, $MEM_DECOMMIT)
$__IGUC_g_tCodeBuffer = 0
_GDIPlus_Shutdown()
EndFunc ;==>__IGUC_Exit
Func _GDIPlus_ImageGetUniqueColors(ByRef $hImage)
Local $aDim, $tBitmapData, $tPixel, $pPixel, $tColors, $pColors, $aRet, $iError = 0
$aDim = _GDIPlus_ImageGetDimension($hImage)
$tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $aDim[0], $aDim[1], $GDIP_ILMREAD, $GDIP_PXF32PARGB)
If @error Then Return SetError(@error, 0, -1)
$tPixel = DllStructCreate('dword[' & $tBitmapData.Width * $tBitmapData.Height & '];', $tBitmapData.Scan0) ; Pixelstruct (dword = 32 Bit pro Pixel)
If @error Then Return SetError(10 + @error, 0, -1)
$pPixel = DllStructGetPtr($tPixel)
$tColors = DllStructCreate('byte[' & 0xffffff + 1 & '];') ; Colorstruct (1 Byte pro Farbwert)
If @error Then Return SetError(20 + @error, 0, -1)
$pColors = DllStructGetPtr($tColors)
$aRet = DllCallAddress('uint:cdecl', DllStructGetPtr($__IGUC_g_tCodeBuffer), 'ptr', $pPixel, 'dword', $tBitmapData.Width * $tBitmapData.Height, 'ptr', $pColors)
$iError = 30 + @error
_GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)
$tColors = 0
$tPixel = 0
$tBitmapData = 0
Return SetError($iError, 0, (IsArray($aRet) ? $aRet[0] : -1))
EndFunc ;==>_GDIPlus_ImageGetUniqueColors