Что нового

Заменить определенный цвет в картинке на прозрачный

asdf8

Скриптер
Сообщения
564
Репутация
152
Интересует, как заменить в картинке определенный цвет (например, цвет первого пикселя изображения) на прозрачный. И, особенно интересует, поддержка, при этом, полупрозрачности.
Как пример, в идеале, хотелось бы из test_prim.png получить test_result.png.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Если с прозрачностью, то никак вы этого не сделаете, только в Photoshop, обтравив изображение + размытие. Здесь либо пример неудачный, либо вопрос немного в другом. По сути, первое изображение, это испорченное второе.
 
Автор
A

asdf8

Скриптер
Сообщения
564
Репутация
152
Yashied [?]
По сути, первое изображение, это испорченное второе.

В общем - да. Причем, довольно часто - испорченное изображение есть (с убранной прозрачностью), а оригинала не найти.


Если с прозрачностью, то никак вы этого не сделаете
Возможно да, но, может можно пробежаться по всем пикселам изображения и выставить каждому пикселу прозрачность в зависимости отклонения его цвета от эталонного?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
asdf8 сказал(а):
...может можно пробежаться по всем пикселам изображения и выставить каждому пикселу прозрачность в зависимости отклонения его цвета от эталонного?

Вы не можете этого сделать, поскольку убрана не прозрачность, а добавлен черный цвет по всему изображению. Таким образом информация о первоначальном цвете полностью потеряна. Восстановить изображение можно только руками.
 
Автор
A

asdf8

Скриптер
Сообщения
564
Репутация
152
Получилось в первом приближении:
Код:
#Include <GUIConstantsEx.au3>
#Include <GDIPlus.au3>

$Form1 = GUICreate("", 196, 196, -1, -1)
$iPic = GUICtrlCreatePic("", 32, 32, 128, 128)
GUISetState(@SW_SHOW)

_GDIPlus_Startup()
$hIMG = _GDIPlus_ImageLoadFromFile(@ScriptDir & '\test_prim.png')
$iW = _GDIPlus_ImageGetWidth($hIMG)
$iH = _GDIPlus_ImageGetHeight($hIMG)

$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hIMG)
_SendMessage(GUICtrlGetHandle($iPic), 0x0172, 0, $hBitmap)
Sleep(500)

$_strct = _GDIPlus_BitmapLockBits($hIMG, 0, 0, $iW, $iH, $GDIP_ILMREAD + $GDIP_ILMWRITE, $GDIP_PXF32ARGB)
$_width = DllStructGetData($_strct, "width")
$_height = DllStructGetData($_strct, "height")
$_stride = DllStructGetData($_strct, "stride")
$_format = DllStructGetData($_strct, "format")
$_Scan0 = DllStructGetData($_strct, "Scan0")
Local $_buffer, $i_R, $i_G, $i_B, $iMaxDiff = 8

$iMaxDiff *= 3 * (255 ^ 2) / 100
For $x = 0 To $iW - 1
	For $y = 0 To $iH - 1
		$_buffer = DllStructCreate("dword", $_Scan0 + ($y * $_stride) + ($x * 4))
		$tmp = DllStructGetData($_buffer, 1)
		$iR = BitShift(BitAND($tmp, 0xFF0000), 16)
		$iG = BitShift(BitAND($tmp, 0x00FF00), 8)
		$iB = BitAND($tmp, 0xFF)
		If $x = 0 And $y = 0 Then
			DllStructSetData($_buffer, 1, 0x0)
			$i_R = $iR
			$i_G = $iG
			$i_B = $iB
		Else
			$iDist = ($i_R - $iR) ^ 2 + ($i_G - $iG) ^ 2 + ($i_B - $iB) ^ 2
			If $iDist < $iMaxDiff Then
				$iDist = Int(255 * $iDist / $iMaxDiff)
				DllStructSetData($_buffer, 1, '0x' & Hex($iDist, 2) & Hex($iR, 2) & Hex($iG, 2) & Hex($iB, 2))
			EndIf
		EndIf
	Next
Next

_GDIPlus_BitmapUnlockBits($hIMG, $_strct)

$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hIMG)
_SendMessage(GUICtrlGetHandle($iPic), 0x0172, 0, $hBitmap)
_WinAPI_RedrawWindow($Form1)

_GDIPlus_ImageDispose($hIMG)
_GDIPlus_Shutdown()

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

ЗЫ: фактически осталось определиться с наиболее адекватной функцией определения устанавливаемой прозрачности.
 
Верх