﻿#include <Array.au3>
#include <GDIPlus.au3>
#include <GDIPlusConstants.au3>
#include <WinAPIProc.au3>

Global $sImagefile = @ScriptDir & '\test1.jpg'
_GDIPlus_Startup()
Global $hImage = _GDIPlus_BitmapCreateFromFile($sImagefile)

ConsoleWrite('Platz 1: _GetUniqueColors1 (Array)' & @CR)
$iTimer = TimerInit()
$iCount = _GetUniqueColors1($hImage)
ConsoleWrite('Zeit: ' & Int(TimerDiff($iTimer)) & ' ms' & @CR)
ConsoleWrite('Anzahl der Farben: ' & $iCount & @CR & @CR)

ConsoleWrite('Platz 2: _GetUniqueColors2 (IsDeclared + Assign)' & @CR)
$iTimer = TimerInit()
$iCount = _GetUniqueColors2($hImage)
ConsoleWrite('Zeit: ' & Int(TimerDiff($iTimer)) & ' ms' & @CR)
ConsoleWrite('Anzahl der Farben: ' & $iCount & @CR & @CR)

ConsoleWrite('Platz 3: _GetUniqueColors3 (Dictionary)' & @CR)
$iTimer = TimerInit()
$iCount = _GetUniqueColors3($hImage)
ConsoleWrite('Zeit: ' & Int(TimerDiff($iTimer)) & ' ms' & @CR)
ConsoleWrite('Anzahl der Farben: ' & $iCount & @CR & @CR)

_GDIPlus_BitmapDispose($hImage)
_GDIPlus_Shutdown()
Exit

Func _GetUniqueColors1(ByRef $hImage) ; inspiriert von der Array-Variante von alpines
	Local $iColorCounter = 0, $aColor[0xFFFFFF + 1]
	Local $iW, $iH, $tBitmapData, $pScan0, $tPixel, $iOffset, $iColor
	$iW = _GDIPlus_ImageGetWidth($hImage)
	$iH = _GDIPlus_ImageGetHeight($hImage)
	$tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
	$pScan0 = $tBitmapData.Scan0
	$tPixel = DllStructCreate('uint[' & $iW * $iH & '];', $pScan0)
	ConsoleWrite(StringFormat('%d x %d = %d px\n', $iW, $iH, $iW * $iH))
	For $iIndex = 1 To $iW * $iH
		$iColor = DllStructGetData($tPixel, 1, $iIndex) - 0xFF000000
		$aColor[$iColor] += 1
		If $aColor[$iColor] = 1 Then $iColorCounter += 1
	Next
	Local $aData = _WinAPI_GetProcessMemoryInfo()
	ConsoleWrite('MemoryInfo: ' & $aData[2] & ' bytes' & @CRLF)
	_GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)
	$tPixel = 0
	Return $iColorCounter
EndFunc   ;==>_GetUniqueColors1

Func _GetUniqueColors2($hImage) ; inspiriert von der IsDeclared/Assign-Variante von UEZ
	Local $iW, $iH, $tBitmapData, $pScan0, $tPixel, $iOffset, $iColor, $iColorCounter = 0
	$iW = _GDIPlus_ImageGetWidth($hImage)
	$iH = _GDIPlus_ImageGetHeight($hImage)
	$tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
	$pScan0 = $tBitmapData.Scan0
	$tPixel = DllStructCreate('uint[' & $iW * $iH & '];', $pScan0)
	ConsoleWrite(StringFormat('%d x %d = %d px\n', $iW, $iH, $iW * $iH))
	For $iIndex = 1 To $iW * $iH
		$s = Hex(DllStructGetData($tPixel, 1, $iIndex), 6)
		If Not IsDeclared($s) Then
			Assign($s, 0, 1)
			$iColorCounter += 1
		EndIf
	Next
	Local $aData = _WinAPI_GetProcessMemoryInfo()
	ConsoleWrite('MemoryInfo: ' & $aData[2] & ' bytes' & @CRLF)
	_GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)
	$tPixel = 0
	Return $iColorCounter
EndFunc   ;==>_GetUniqueColors2

Func _GetUniqueColors3(ByRef $hImage) ; eine Abwandlung meiner urspruenglichen Version
	Local $oUnique = ObjCreate('Scripting.Dictionary')
	Local $iW, $iH, $tBitmapData, $pScan0, $tPixel, $iOffset, $iColor
	$iW = _GDIPlus_ImageGetWidth($hImage)
	$iH = _GDIPlus_ImageGetHeight($hImage)
	$tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
	$pScan0 = $tBitmapData.Scan0
	$tPixel = DllStructCreate('uint[' & $iW * $iH & '];', $pScan0)
	ConsoleWrite(StringFormat('%d x %d = %d px\n', $iW, $iH, $iW * $iH))
	For $iIndex = 1 To $iW * $iH
		$iColor = Hex(DllStructGetData($tPixel, 1, $iIndex), 6)
		$oUnique.Item($iColor) = 0
	Next
	Local $aData = _WinAPI_GetProcessMemoryInfo()
	ConsoleWrite('MemoryInfo: ' & $aData[2] & ' bytes' & @CRLF)
	_GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)
	$tPixel = 0
	Return $oUnique.Count
EndFunc   ;==>_GetUniqueColors3
