Что нового

[GDIPlus] Применение прозрачности к изображению

firex

AutoIT Гуру
Сообщения
943
Репутация
208
Исследовал этот и официальный форум, но так примеров и не нашел.
Необходимо средствами GDIPlus сделать загруженное изображение прозрачным на указанное значение ( 0 - 255 ).

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

lastangel

Новичок
Сообщения
39
Репутация
0
Почитай, вроде твой случай
http://autoit-script.ru/index.php/topic,10683.msg70544.html#msg70544
 

sims

Осваивающий
Сообщения
184
Репутация
24
Думаю что ТС хочет этого.
Код:
#include <GDIPlus.au3>
#include <SendMessage.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Const $STM_SETIMAGE = 370
Const $IMAGE_BITMAP = 0
Const $SS_BITMAP = 14

$hForm = GUICreate("Пример", 300, 200)
$iSlider = GUICtrlCreateSlider(0, 2, 300, 30)
GUICtrlSetLimit($iSlider, 255, 2)
GUICtrlSetData($iSlider, 100)
$ID = GUICtrlCreateLabel("",0, 40, 300, 170, $SS_BITMAP)
GUISetState()

global $dll = DllOpen("ImageTransparent.dll")
$result = DllCall($dll, "int", "NewImage", "str", "Test.png", "byte", 100)
_SendMessage(GUICtrlGetHandle($ID), $STM_SETIMAGE, $IMAGE_BITMAP, $result[0])

GUIRegisterMsg($WM_HSCROLL, "WM_HSCROLL")

While 1
    Switch GUIGetMsg()
        Case -3
            Exit
    EndSwitch
WEnd
 
Func WM_HSCROLL($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam, $ilParam
    $result = DllCall($dll, "int", "Transparent", "byte", GUICtrlRead($iSlider))
   _SendMessage(GUICtrlGetHandle($ID), $STM_SETIMAGE, $IMAGE_BITMAP, $result[0])
EndFunc   ;==>WM_HSCROLL
Не GDI+, но работает.
 
Автор
firex

firex

AutoIT Гуру
Сообщения
943
Репутация
208
lastangel, sims
Нет, все немного не так. Хорошо, что не удалил пример, где тестировал прозрачность главного битмапа. Но дело в том, что картинка, которую нужно сделать прозрачной, рисуется на на нем отдельно с определенной прозрачностью.

Код:
#include <GUIConstants.au3>

_GDIPlus_Startup()

$_hGUI_Dlg = GUICreate( '', 250, 250, -1, -1, $WS_POPUP, BitOR( $WS_EX_TRANSPARENT, $WS_EX_TOPMOST, $WS_EX_TOOLWINDOW, $WS_EX_LAYERED ))
GUISetBkColor($GUI_BKCOLOR_TRANSPARENT, $_hGUI_Dlg)
GUISetState(@SW_SHOW, $_hGUI_Dlg)

$_hGraphic = _GDIPlus_GraphicsCreateFromHWND( $_hGUI_Dlg )
$_hBitmap = _GDIPlus_BitmapCreateFromGraphics( 250, 250, $_hGraphic )
$_hBuffer = _GDIPlus_ImageGetGraphicsContext($_hBitmap)
_GDIPlus_GraphicsSetSmoothingMode( $_hBuffer, 2 )
DllCall($ghGDIPDll, "uint", "GdipSetInterpolationMode", "handle", $_hBuffer, "int", 7)
DllCall($ghGDIPDll, "uint", "GdipSetTextRenderingHint", "handle", $_hBuffer, "int", 4)
; ---
$_hDC = _WinAPI_GetDC($_hGUI_Dlg)
$_hCompatibleDC = _WinAPI_CreateCompatibleDC($_hDC)

$_hPen = _GDIPlus_PenCreate(0x70E0E000, 20) ;And after try 22E0E000 :C
While 1
	If GUIGetMsg() = -3 Then _
		_Quit()

	_GDIPlus_GraphicsClear($_hBuffer, 0x00000000)
	_GDIPlus_GraphicsDrawLine( $_hBuffer, 125, 0, 125, 250, $_hPen )

	;К примеру
	;_GDIPlus_GraphicsDrawImageRect($_hBuffer, $hImage, 0, 0, 100, 100)


	$gdibitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($_hBitmap)
	_UpdateLayered( $_hGUI_Dlg, $gdibitmap )
	_WinAPI_DeleteObject($gdibitmap)

	Sleep( 20 )
WEnd

Func _UpdateLayered( $hWnd, $hBitmap )
	$hDestSv = _WinAPI_SelectObject($_hCompatibleDC, $hBitmap)

	$tPOINT = DllStructCreate($tagPOINT)
	DllStructSetData($tPOINT, 1, 0)
	DllStructSetData($tPOINT, 2, 0)

	$tBLENDFUNCTION = DllStructCreate($tagBLENDFUNCTION)
	DllStructSetData($tBLENDFUNCTION, 3, 255)
	DllStructSetData($tBLENDFUNCTION, 4, 1)

	$tSize = DllStructCreate($tagSIZE)
	DllStructSetData($tSize, "X", 250)
	DllStructSetData($tSize, "Y", 250)

	DllCall('user32.dll', 'int', 'UpdateLayeredWindow', 'hwnd', $hWnd, 'hwnd', $_hDC, 'ptr', 0, 'ptr', DllStructGetPtr($tSIZE), 'hwnd', $_hCompatibleDC, 'ptr', DllStructGetPtr($tPOINT), 'dword', 0, 'ptr', DllStructGetPtr($tBLENDFUNCTION), 'dword', 0x02)
	DllCall('gdi32.dll', 'ptr', 'SelectObject', 'hwnd', $_hCompatibleDC, 'ptr', $hDestSv)

	Return 1
EndFunc   ;==>_WinAPI_UpdateLayeredWindowEx

Func _Quit()
	_WinAPI_ReleaseDC($_hGUI_Dlg, $_hDC)
	_WinAPI_ReleaseDC($_hGUI_Dlg, $_hCompatibleDC)
	_WinAPI_DeleteDC($_hDC)
	_WinAPI_DeleteDC($_hCompatibleDC)
	; ---
	_GDIPlus_GraphicsDispose($_hBuffer)
	_GDIPlus_BitmapDispose($_hBitmap)
	_GDIPlus_GraphicsDispose($_hGraphic)
	; ---
	_GDIPlus_Shutdown()
	GuiDelete($_hGUI_Dlg)

	Exit
EndFunc
 

sims

Осваивающий
Сообщения
184
Репутация
24
Нужно наложить одну картинку на другую заданной прозрачностью?
Это не сложно сделать используя dll из вложения.
В ней функция
Код:
NewImage(ImageBack, Image, x, y, Transparent)
Первый аргумент - путь к фоновому рисунку; второй - путь к рисунку, который нужно наложить с прозрачностью; x и y - координаты наложения и пятый аргумент - прозрачность наложения (0...255).
Функция вернет хендл рисунка или 0, если возникли проблемы с его загрузкой. Поддерживаются bmp и png форматы.
 
Автор
firex

firex

AutoIT Гуру
Сообщения
943
Репутация
208
sims [?]
Первый аргумент - путь к фоновому рисунку; второй - путь к рисунку, который нужно наложить с прозрачностью;
Путь или хендл? Обновление картинки на экране происходит к примеру 60 раз в секунду. Сама картинка составляется в памяти и нет возможности ее каждый раз сохранять на жесткий диск, так как это будет лишняя колоссальная нагрузка.

В любом случае прибегать к таким методам не лучший вариант, моя цель - как можно больше упростить работу скрипта, так как он и так слишком сильно нагружен. Надеюсь реализация этой библиотеки возможна в AutoIt.


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

Нашел рабочий вариант, остановлюсь пока на нем.

Код:
#include <GDIPlus.au3>
#include <misc.au3>
Opt("GUIOnEventMode", 1)
$hwnd = GUICreate("GDI+ Sample!", 500, 500)
GUISetOnEvent(-3, "close")
GUISetState()
$sFile = @ScriptDir & "\123.png"
_GDIPlus_Startup()
$hImage = _GDIPlus_ImageLoadFromFile($sFile)
$graphics = _GDIPlus_GraphicsCreateFromHWND($hwnd)
$bitmap = _GDIPlus_BitmapCreateFromGraphics(500, 500, $graphics);  This is actually the buffer
$backbuffer = _GDIPlus_ImageGetGraphicsContext($bitmap); This is to access the buffer
$TextureBrush = _GDIPlus_CreateTextureTrans($hImage, 0.6)
$white = _GDIPlus_BrushCreateSolid(0xFFFFFFFF)

$x = 175
$y = 175
$d = 50
draw($x, $y)
Do
    If _IsPressed("25") Then; Left arrow
        $x -= 5
        draw($x, $y)
    EndIf
    If _IsPressed("26") Then; up arrow
        $y -= 5
        draw($x, $y)
    EndIf
    If _IsPressed("27") Then; right arrow
        $x += 5
        draw($x, $y)
    EndIf
    If _IsPressed("28") Then; down arrow
        $y += 5
        draw($x, $y)
    EndIf
    If _IsPressed("44") Then; D KEY Decrease diameter of circle
        $d -= 1
        draw($x, $y)
    EndIf
    If _IsPressed("55") Then; U KEY increase diameter of circle
        $d += 1
        draw($x, $y)
    EndIf
    Sleep(50)
Until False

Func draw($x, $y)
    _GDIPlus_GraphicsClear($backbuffer, 0xFFFF0000); Always start with a clean buffer!


    _GDIPlus_GraphicsFillRect($backbuffer, $x, $y, 480, 480, $TextureBrush)
    _GDIPlus_GraphicsDrawImageRect($graphics, $bitmap, 0, 0, 500, 500); Present buffer to screen!
EndFunc   ;==>draw

Func close()
    ;_GDIPlus_ImageSaveToFile($bitmap, @DesktopDir & "\TestWrite1.png")
    ;ShellExecute(@DesktopDir & "\TestWrite1.png")
    _GDIPlus_BrushDispose($white)
    _GDIPlus_BrushDispose($TextureBrush)
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_GraphicsDispose($backbuffer)
    _GDIPlus_BitmapDispose($bitmap)
    _GDIPlus_ImageDispose ($hImage)
    _GDIPlus_Shutdown()
    Exit
EndFunc   ;==>close

;
; #FUNCTION# ============================================================================================
; Name...........: _GDIPlus_CreateTextureTrans
; Description ...: Creates a TextureBrush object based on an image, and sets image transparency property.
; Parameter
;           $hImage  - Pointer to the Image object.
;           $nTrans  - Value range from 0 (Zero for invisible) to 1.0 (fully opaque)
;           $iX      -  Leftmost coordinate of the image portion to be used by this brush.
;           $iY      - Uppermost coordinate of the image portion to be used by this brush.
;           $iWidth  - Width of the brush and width of the image portion to be used by the brush.
;           $iHeight - Height of the brush and height of the image portion to be used by the brush.
; Return   - Handle (pointer) to the new created TextureBrush object.
Func _GDIPlus_CreateTextureTrans($hImage, $nTrans = 0.5, $iX = 0, $iY = 0, $iWidth = "", $iHeight = "")
    Local $tColorMatrix, $x, $hImgAttrib, $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage)
    If $iWidth = 0 Or $iWidth = "" Then $iWidth = $iW
    If $iHeight = 0 Or $iHeight = "" Then $iHeight = $iH
    ;;create color matrix data
    $tColorMatrix = DllStructCreate("float[5];float[5];float[5];float[5];float[5]")
    ;blending values:
    $x = DllStructSetData($tColorMatrix, 1, 1, 1) * DllStructSetData($tColorMatrix, 2, 1, 2) * DllStructSetData($tColorMatrix, 3, 1, 3) * _
            DllStructSetData($tColorMatrix, 4, $nTrans, 4) * DllStructSetData($tColorMatrix, 5, 1, 5)
    ;;create an image attributes object and update its color matrix
    $hImgAttrib = DllCall($ghGDIPDll, "int", "GdipCreateImageAttributes", "ptr*", 0)
    $hImgAttrib = $hImgAttrib[1]
    DllCall($ghGDIPDll, "int", "GdipSetImageAttributesColorMatrix", "ptr", $hImgAttrib, "int", 1, _
            "int", 1, "ptr", DllStructGetPtr($tColorMatrix), "ptr", 0, "int", 0)
    ;;draw image into graphic object with alpha blend
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipCreateTextureIAI", "hwnd", $hImage, "ptr", $hImgAttrib, "int", $iX, "int", _
            $iY, "int", $iWidth, "int", $iHeight, "ptr*", 0)
    ;clean up
    DllCall($ghGDIPDll, "int", "GdipDisposeImageAttributes", "ptr", $hImgAttrib)
    Return $aResult[7]
EndFunc   ;==>_GDIPlus_CreateTextureTrans
 

sims

Осваивающий
Сообщения
184
Репутация
24
firex [?]
Путь или хендл? Обновление картинки на экране происходит к примеру 60 раз в секунду.
Путь.
Чтобы получить правильный ответ, нужно нормально задать вопрос. Где вы упоминаете что нужно так часто обновлять картинку?

Вам нужно не GDI+, а DirectX и OpenGL, чтобы использовать аппаратное ускорение видеокарты. Без этого может сильно тормозить и грузить процессор.
 
Автор
firex

firex

AutoIT Гуру
Сообщения
943
Репутация
208
sims [?]
Чтобы получить правильный ответ, нужно нормально задать вопрос. Где вы упоминаете что нужно так часто обновлять картинку?

Код:
While 1
    If GUIGetMsg() = -3 Then _
        _Quit()

    _GDIPlus_GraphicsClear($_hBuffer, 0x00000000)
    _GDIPlus_GraphicsDrawLine( $_hBuffer, 125, 0, 125, 250, $_hPen )

    ;К примеру
    ;_GDIPlus_GraphicsDrawImageRect($_hBuffer, $hImage, 0, 0, 100, 100)


    $gdibitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($_hBitmap)
    _UpdateLayered( $_hGUI_Dlg, $gdibitmap )
    _WinAPI_DeleteObject($gdibitmap)

    Sleep( 20 )
WEnd

В примере выше это вроде как было понятно.



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

sims [?]
Вам нужно не GDI+, а DirectX и OpenGL, чтобы использовать аппаратное ускорение видеокарты. Без этого может сильно тормозить и грузить процессор.
Этот аспект я уже изучил, при достаточном упрощении нагрузка приемлема.
 
Верх