Что нового

Изменить цвет картинки с помощью GDIPlus

Viktor1703

AutoIT Гуру
Сообщения
1 535
Репутация
410
Имеется чёрная картинка с альфа каналом, как с помощью GDIPlus изменить её цвет например на синий?

Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPIEx.au3>
#include <GDIPlus.au3>

Global $Width = 500
Global $Height = 300
Global $SizeShadow = 15
Global $TransShadow = 130

$hShadow = GUICreate("", ($Width + ($SizeShadow * 2)), ($Height + ($SizeShadow * 2)) - 5, -1, -1, $WS_POPUP, $WS_EX_LAYERED)
SetWindowShadow($hShadow, @ScriptDir & "\Shadow.png", $TransShadow)
GUISetState()

$hForm = GUICreate("", $Width, $Height, -1, -1, BitOR($WS_CHILD, $WS_POPUP), -1, $hShadow)
GUICtrlCreateLabel("", 0, 0, $Width, $Height, -1, $GUI_WS_EX_PARENTDRAG)
$hPos = WinGetPos($hShadow)
WinMove($hForm, "", $hPos[0] + $SizeShadow, $hPos[1] + ($SizeShadow - 2))
GUIRegisterMsg($WM_MOVE, "WM_MOVE")
GUISetState()

While 1    
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func SetWindowShadow($hWnd, $hImage, $Transparant)
	$iSize = WinGetPos($hWnd)
	_GDIPlus_Startup()
	$iImage = __LoadImage($hImage)
	$hThumb = DllCall($ghGDIPDll, "int", "GdipGetImageThumbnail", "ptr", $iImage, "int", $iSize[2], "int", $iSize[3], "ptr*", 0, "ptr", 0, "ptr", 0)
	$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hThumb[4])
	_WinAPI_UpdateLayeredWindowEx($hWnd, -1, -1, $hBitmap, $Transparant)
	_GDIPlus_ImageDispose($hThumb[4])
    _GDIPlus_ImageDispose($iImage)
    _GDIPlus_Shutdown()	
EndFunc

Func __LoadImage($hImage)
	
	Local $sData, $hSize, $hStruct, $hData, $pData, $pStream, $pBitmap

	If StringLen($hImage) < 100 Then	
		Return _GDIPlus_ImageLoadFromFile($hImage)
	Else	
	    $sData = Binary($hImage)
	    $hSize = BinaryLen($sData)
	    $hStruct = DllStructCreate("byte[" & $hSize & "]")
	    DllStructSetData($hStruct, 1, $sData)
	    $hData = DllCall("kernel32.dll", "handle", "GlobalAlloc", "uint", 2, "ulong_ptr", $hSize)
	    $pData = DllCall("kernel32.dll", "ptr", "GlobalLock", "handle", $hData[0])
		DllCall("kernel32.dll", "none", "RtlMoveMemory", "ptr", $pData[0], "ptr", DllStructGetPtr($hStruct), "ulong_ptr", $hSize)
		DllCall("kernel32.dll", "bool", "GlobalUnlock", "handle", $hData[0])
	    $pStream = DllCall("ole32.dll", "int", "CreateStreamOnHGlobal", "int", $hData[0], "long", 1, "Int*", 0)
	    $pBitmap = DllCall($ghGDIPDll, "int", "GdipCreateBitmapFromStream", "ptr", $pStream[3], "int*", 0)
		If Not @error Then Return $pBitmap[2]
	    _GDIPlus_BitmapDispose($pBitmap[2])
        _WinAPI_DeleteObject($pStream[3])
        DllCall("kernel32.dll", "ptr", "GlobalFree", "handle", $hData[0])
	EndIf	
	
EndFunc

Func WM_MOVE()
    Local $aParent = WinGetPos($hForm)
    WinMove($hShadow, "", $aParent[0] - $SizeShadow, $aParent[1] - ($SizeShadow - 2))
EndFunc
 

Ganibal95

GreenBytes
Сообщения
876
Репутация
239
UP

Возникла такая-же потребность, у меня имеется картинка:

как можно изменить цвет, например на красный/синий/голубой?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 712
В GDIP.au3 есть такая функция _GDIPlus_ImageAttributesSetRemapTable(). Возможно, если покопаться поглубже, то можно найти и более простой вариант (никогда этого не использовал). Можно еще написать функцию для быстрой обработки данных на PB.

Код:
#Include <GDIP.au3>

_GDIPlus_Startup()

$hSrc = _GDIPlus_ImageLoadFromFile(@ScriptDir & '\Black.png')
$aSize = _GDIPlus_ImageGetDimension($hSrc)
$hDst = _GDIPlus_BitmapCreateFromScan0($aSize[0], $aSize[1])
$hGraphics = _GDIPlus_ImageGetGraphicsContext($hDst)
$hIA = _GDIPlus_ImageAttributesCreate()
Dim $aTable[257][2] = [[256]]
For $i = 0 To 255
	$aTable[$i + 1][0] = BitOR(BitShift($i, -24), 0x00000000)
	$aTable[$i + 1][1] = BitOR(BitShift($i, -24), 0x00FF0000)
Next
_GDIPlus_ImageAttributesSetRemapTable($hIA, 1, 1, $aTable)
_GDIPlus_GraphicsDrawImageRectRectIA($hGraphics, $hSrc, 0, 0, $aSize[0], $aSize[1], 0, 0, $aSize[0], $aSize[1], $hIA)
_GDIPlus_ImageSaveToFile($hDst, @ScriptDir & '\Red.png')
_GDIPlus_ImageAttributesDispose($hIA)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_ImageDispose($hDst)
_GDIPlus_ImageDispose($hSrc)

_GDIPlus_Shutdown()
 

Ganibal95

GreenBytes
Сообщения
876
Репутация
239
Теперь появилась потребность изменить все цвета картинки, кроме прозрачности.
Я пробовал загонять в массив все цвета, работает очень долго! Более 30 мин, я так и не дождался.
Вот пример картинки:

На выходе должен получится такой:

Заранее спасибо.
 

WSWR

AutoIT Гуру
Сообщения
941
Репутация
361
Ganibal95

Можно так попробовать:
Код:
#include <GDIP.au3>
#include <Array.au3>

$sImage = @ScriptDir & '\api.png'

_GDIPlus_Startup()
$hImage = _GDIPlus_ImageLoadFromFile($sImage)
$iWidth = _GDIPlus_ImageGetWidth($hImage)
$iHeight = _GDIPlus_ImageGetHeight($hImage)
$iBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
$hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($iBitmap)

$hDst = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight)

For $H = 0 To $iHeight - 1
	For $W = 0 To $iWidth - 1
		$iMatrix = '0x' & Hex(_GDIPlus_BitmapGetPixel($hBitmap, $W, $H), 6)
		If $iMatrix <> 0x000000 Then _GDIPlus_BitmapSetPixel($hDst, $W, $H, 0xFF000000)
	Next
Next
_GDIPlus_ImageSaveToFile($hDst, @ScriptDir & '\GDIPlus_Image.png')
_GDIPlus_ImageDispose($hImage)
_GDIPlus_ImageDispose($hDst)
_GDIPlus_Shutdown()
 

Ganibal95

GreenBytes
Сообщения
876
Репутация
239
WSWR
Пример быстрый, но это не то... Хочется прозрачность...


Добавлено:
Сообщение автоматически объединено:

умудрился сделать, но скорость бы хотелось улучшить...

Код:
#include <GDIP.au3>
;#include <E:\Колекция\Ganibal95\Autoit\Проекты Ganibal95\GAPI\GAPI.au3>

$sImage = @ScriptDir & '\api.png'
_GDIPlus_Startup()
$hImage = _GDIPlus_ImageLoadFromFile($sImage)
$iWidth = _GDIPlus_ImageGetWidth($hImage)
$iHeight = _GDIPlus_ImageGetHeight($hImage)
$hDst = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight)
For $H = 0 To $iHeight - 1
    For $W = 0 To $iWidth - 1
        $iMatrix = _GDIPlus_BitmapGetPixel($hImage, $W, $H)
		if $iMatrix <> 0 Then
			_GDIPlus_BitmapSetPixel($hDst, $W, $H, Dec(_GAPI_ARGBGetA($iMatrix)&'000000'))
		EndIf
    Next
Next
_GDIPlus_ImageSaveToFile($hDst, @ScriptDir & '\GDIPlus_Image.png')
_GDIPlus_ImageDispose($hImage)
_GDIPlus_ImageDispose($hDst)
_GDIPlus_Shutdown()
ShellExecute(@ScriptDir & '\GDIPlus_Image.png')

Func _GAPI_ARGBGetA($Color)
	Return StringLeft(String(Hex($Color,8)),2)
EndFunc


Если кто знает способ по быстрее, напишите...
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 712
Ganibal95 сказал(а):
Если кто знает способ по быстрее, напишите...
Код:
#Include <GDIP.au3>
#Include <GDIPlusConstants.au3>
#Include <WinAPIEx.au3>

_GDIPlus_Startup()

$hBitmap = _GDIPlus_ImageLoadFromFile(@ScriptDir & '\Api.png')
$aSize = _GDIPlus_ImageGetDimension($hBitmap)
$tData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $aSize[0], $aSize[1], BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE), $GDIP_PXF32ARGB)
$Ret = DllCall('user32.dll', 'int', 'CallWindowProc', 'ptr', __PBProc(), 'ptr', 0, 'uint', 0, 'ptr', DllStructGetData($tData, 'Scan0'), 'uint_ptr', $aSize[0] * $aSize[1] * 4)
If (@Error) Or (Not $Ret[0]) Then
	; Error
EndIf
_GDIPlus_BitmapUnlockBits($hBitmap, $tData)
$hPng = _GDIPlus_BitmapCreateFromScan0($aSize[0], $aSize[1])
$hGraphics = _GDIPlus_ImageGetGraphicsContext($hPng)
_GDIPlus_GraphicsDrawImageRect($hGraphics, $hBitmap, 0, 0, $aSize[0], $aSize[1])
_GDIPlus_ImageSaveToFile($hPng, @ScriptDir & '\Black.png')
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_ImageDispose($hBitmap)
_GDIPlus_ImageDispose($hPng)

_GDIPlus_Shutdown()

Func __PBProc()

	Static $pProc = Ptr(0)

	If Not $pProc Then
		If @AutoItX64 Then
			$pProc = __Init(Binary( _
					  '0x48894C240848895424104C894424184C894C24205541574831C050504883EC28' & _
						'48837C24600074054831C0EB0748C7C0010000004821C0751A837C2468007405' & _
						'4831C0EB0748C7C0010000004821C07502EB0948C7C001000000EB034831C048' & _
						'21C074084831C04863C0EB6248C7442428000000004C637C24684983C7FC4C3B' & _
						'7C24287C3A4C8B7C24604C037C24284C897C2430488B6C24304C637D0048B800' & _
						'0000FF000000004921C74C89F850488B6C24385889450048834424280471B648' & _
						'C7C0010000004863C0EB034831C04883C438415F5DC3'))
		Else
			$pProc = __Init(Binary( _
					  '0x555331C05050837C241C00740431C0EB05B80100000021C07516837C24200074' & _
						'0431C0EB05B80100000021C07502EB07B801000000EB0231C021C0740431C0EB' & _
						'43C70424000000008B5C242083C3FC3B1C247C278B5C241C031C24895C24048B' & _
						'6C24048B5D0081E3000000FF538B6C2408588945008304240471CDB801000000' & _
						'EB0231C083C4085B5DC21000'))
		EndIf
	EndIf
	Return $pProc
EndFunc   ;==>__PBProc
 
Верх