Что нового

Приравнить высоту и ширину Bitmap'a

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Что - то я совсем затупил, ни как не врублюсь как расчитать:

Предположим W = 900 а H = 970
W я сразу приравниваю к 800, а как теперь уравнять H?
Тоже самое нужно и с H = 970 а W = 900
H сразу 800 - нужно прировнять W

Вообщем вот готовый скрипт:

Передатчик
Код:
#include <APIConstants.au3>
#include <GDIPlus.au3>
#include <Memory.au3>
#include <Misc.au3>
#include <WinAPIEx.au3>
#include <GDIP.au3>

Opt("GUICloseOnESC", 0)

TCPStartup()
$Socket = TCPConnect(@IPAddress1, 8080)

_GDIPlus_Startup()
Global $tEncoder, $pEncoder, $tParams, $pParams, $tQuality
$tEncoder = _WinAPI_GUIDFromString(_GDIPlus_EncodersGetCLSID("jpg"))
$pEncoder = DllStructGetPtr($tEncoder)
$tParams = _GDIPlus_ParamInit(1)
$pParams = DllStructGetPtr($tParams)
$tQuality = DllStructCreate("int")
DllStructSetData($tQuality, 1, 30)
_GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, DllStructGetPtr($tQuality))

While 1
	$hWnd = _WinAPI_GetForegroundWindow()
    If $hWnd Then
        Local $iSize = _WinAPI_GetPosFromRect(_WinAPI_GetClientRect($hWnd))
	    TCPSend($Socket, GetScreenshot($hWnd, 0, 0, $iSize[2], $iSize[3]))
	    If @error Then
		    $Socket = TCPConnect(@IPAddress1, 8080)
	    EndIf
	EndIf
WEnd

_GDIPlus_Shutdown()
TCPCloseSocket($Socket)
TCPShutdown()

Func GetScreenshot($hWnd, $iX, $iY, $iWidth, $iHeight)
	Local $hSrcDC, $hDstDC, $hDstSv, $hBitmap, $hDesktop, $hScreen, $hMemory, $pMemory, $pStream, $tOut, $pOut, $iSize

	$hSrcDC = _WinAPI_GetDC($hWnd)
	$hScreen = _WinAPI_CreateCompatibleBitmap($hSrcDC, $iWidth, $iHeight)
	$hDstDC = _WinAPI_CreateCompatibleDC($hSrcDC)
	$hDstSv = _WinAPI_SelectObject($hDstDC, $hScreen)
	_WinAPI_BitBlt($hDstDC, $iX, $iY, $iWidth, $iHeight, $hSrcDC, $iX, $iY, $MERGECOPY)

	$iX = _WinAPI_GetMousePosX(True, $hWnd)
	$iY = _WinAPI_GetMousePosY(True, $hWnd)

	If _IsPressed(1) Then
		_WinAPI_DrawSight($hDstDC, $iX, $iY, 1, 8, 0xFF)
	Else
        _WinAPI_DrawSight($hDstDC, $iX, $iY)
    EndIf

	$tRECT = _WinAPI_CreateRect($iX + 25, $iY - 50, $iX + 500, $iY + 50)
	_WinAPI_DrawWindowText($hDstDC, $hWnd, $tRECT, 0xFFFFFF, 0x000000, 'Cambria', 15, 500, True) ;~ Пишем заголовок окна

	_WinAPI_SelectObject($hDstDC, $hDstSv)
	_WinAPI_DeleteDC($hDstDC)
	$hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hScreen)
	If $iWidth > 800 Then
        $hBitmap = _GDIPlus_GetImageThumbnail($hBitmap, 800, $iHeight - ($iWidth - 800)) ; Тут нужно расчитать
    EndIf
	_WinAPI_DeleteObject($hScreen)
	$pStream = _WinAPI_CreateStreamOnHGlobal(0)
	_GDIPlus_ImageSaveToStream($hBitmap, $pStream, $pEncoder, $pParams)
	_GDIPlus_BitmapDispose($hBitmap)
	$hMemory = _WinAPI_GetHGlobalFromStream($pStream)
	$pMemory = _MemGlobalLock($hMemory)
	$iSize = _MemGlobalSize($hMemory)
	$tOut = DllStructCreate("dword;dword;byte[" & ($iSize - Mod($iSize, 4) + 4) & "]")
	$pOut = DllStructGetPtr($tOut)
	DllStructSetData($tOut, 1, DllStructGetSize($tOut))
	DllStructSetData($tOut, 2, $iSize)
	_MemMoveMemory($pMemory, $pOut + 8, $iSize)
	_MemGlobalFree($hMemory)
	_WinAPI_StrFormatByteSize($iSize)
	Return DllStructGetData(DllStructCreate("byte[" & DllStructGetSize($tOut) & "]", DllStructGetPtr($tOut)), 1)
EndFunc

Func _WinAPI_DrawSight($hDC, $iX, $iY, $iSize = 8, $Width = 1, $iColor = 0x000000)
	$hPen = _WinAPI_CreatePen($Width, $Width, $iColor)
	$PenObj = _WinAPI_SelectObject($hDC, $hPen)
	_WinAPI_DrawLine($hDC, $iX, $iY + $iSize, $iX, $iY)
	_WinAPI_DrawLine($hDC, $iX + $iSize, $iY, $iX, $iY)
	_WinAPI_DrawLine($hDC, $iX, $iY - $iSize, $iX, $iY)
	_WinAPI_DrawLine($hDC, $iX - $iSize, $iY, $iX, $iY)
	_WinAPI_SelectObject($hDC, $PenObj)
	_WinAPI_DeleteObject($hPen)
EndFunc

Func _WinAPI_DrawWindowText($hDC, $hWnd, $tRECT, $TextColor = 0xFFFFFF, $BkColor = 0x000000, $Font = 'Arial', $iSizeFont = 10, $iWidth = 600, $Italic = False, $Underline = False, $Strikeout = False)
	$hFont = _WinAPI_CreateFont($iSizeFont, 0, 0, 0, $iWidth, $Italic, $Underline, $Strikeout, 1, 0, 0, 0, 0, $Font)
    $hObjFont = _WinAPI_SelectObject($hDC, $hFont)
	_WinAPI_SetTextColor($hDC, $TextColor)
	_WinAPI_SetBkColor($hDC, $BkColor)
    _WinAPI_DrawText($hDC, _WinAPI_GetWindowText($hWnd), $tRECT, BitOR(0x00000000, 0x00000020, 0x00000004))
	_WinAPI_SelectObject($hDC, $hObjFont)
	_WinAPI_DeleteObject($hFont)
EndFunc

Func _GDIPlus_GetImageThumbnail($hImage, $iWidth, $iHeight)
    Local $Ret = DllCall($ghGDIPDll, 'int', 'GdipGetImageThumbnail', 'ptr', $hImage, 'int', $iWidth, 'int', $iHeight, 'ptr*', 0, 'ptr', 0, 'ptr', 0)
    If (@error) Or ($Ret[0]) Then
        Return SetError(1, 0, 0)
    EndIf
    Return $Ret[4]
EndFunc

Приёмник
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>
#include <GDIPlus.au3>
#include <Memory.au3>
#include <WinAPIEx.au3>

TCPStartup()
$Main = TCPListen(@IPAddress1, 8080)
If @error Then
	Exit
EndIf

$hForm = GUICreate("", -1, -1, 0, 0, $WS_POPUP, $WS_EX_LAYERED)
GUISetState()

Do
	$Socket = TCPAccept($Main)
	Switch GUIGetMsg()
		Case - 3
			Exit
	EndSwitch
Until $Socket <> -1

Global $tHeader = DllStructCreate('byte[4]')
Global $pHeader = DllStructGetPtr($tHeader)
Global $bData = 0, $Count = 0

_GDIPlus_Startup()

While 1
	If Not IsBinary($bData) Then
		$bData = TCPRecv($Socket, 8384, 1)
		If @error Then
			Do
				$Socket = TCPAccept($Main)
				Switch GUIGetMsg()
					Case - 3
						Exit
				EndSwitch
			Until $Socket <> -1
		EndIf
	EndIf
	If IsBinary($bData) Then
		If Not $Count Then
			DllStructSetData($tHeader, 1, $bData)
			$tData = DllStructCreate('dword', $pHeader)
			$Size = DllStructGetData($tData, 1)
			$tData = DllStructCreate('byte[' & $Size & ']')
			$pData = DllStructGetPtr($tData)
		EndIf
		$Lenght = BinaryLen($bData)
		$Sum = $Count + $Lenght
		If $Sum > $Size Then
			$dL = $Size - $Count
			$tPart = DllStructCreate('byte[' & $dL & ']', $pData + $Count)
			DllStructSetData($tPart, 1, $bData)
			$tByte = DllStructCreate('byte[' & $Lenght & ']')
			$tRecv = DllStructCreate('byte[' & ($Lenght - $dL) & ']', DllStructGetPtr($tByte) + $dL)
			DllStructSetData($tByte, 1, $bData)
			$bData = DllStructGetData($tRecv, 1)
			$Sum = $Size
		Else
			$tPart = DllStructCreate('byte[' & $Lenght & ']', $pData + $Count)
			DllStructSetData($tPart, 1, $bData)
			$Count = $Sum
			$bData = 0
		EndIf
		If $Sum = $Size Then
			SetScreenshot($hForm, $tData)
			$Count = 0
		EndIf
	EndIf
	Switch GUIGetMsg()
		Case - 3
			Exit
	EndSwitch
WEnd

_GDIPlus_Shutdown()
TCPCloseSocket($Socket)
TCPShutdown()

Func SetScreenshot($hWin, ByRef $tData)

	Local $hBitmap, $hPrev, $hScreen, $hMemory, $pMemory, $pStream, $pData, $iSize

	$pData = DllStructGetPtr($tData)
	$iSize = DllStructGetData(DllStructCreate('dword', $pData + 4), 1)
	$hMemory = _MemGlobalAlloc($iSize, $GMEM_MOVEABLE)
	$pMemory = _MemGlobalLock($hMemory)
	_MemMoveMemory($pData + 8, $pMemory, $iSize)
	_MemGlobalUnlock($hMemory)
	$pStream = _WinAPI_CreateStreamOnHGlobal($hMemory)
	$hBitmap = _GDIPlus_BitmapCreateFromStream($pStream)
	$hScreen = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
	_GDIPlus_BitmapDispose($hBitmap)
	_MemGlobalFree($hMemory)
	_WinAPI_UpdateLayeredWindowEx($hWin, 0, 0, $hScreen, 255, 1)
EndFunc

Func _GDIPlus_BitmapCreateFromStream($pStream)
	Local $Ret = DllCall($ghGDIPDll, 'uint', 'GdipCreateBitmapFromStream', 'ptr', $pStream, 'ptr*', 0)
	If (@error) Or ($Ret[0]) Then
		Return SetError(@error, @extended, 0)
	EndIf
	Return $Ret[2]
EndFunc

В приёмнике ни чего делать не нужно, кинул для теста.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Вспоминаем математику.

Отношение ширины W1 к высоте H1 равно отношению ширины W2 к высоте H2, т.е.

$W_Old / $H_Old = $W_New / $H_New

Отсюда

$W_New = $W_Old * $H_New / $H_Old

или

$H_New = $H_Old * $W_New / $W_Old
 
Автор
V

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Re: Приравнить высоту и ширину Bitmap\\\'a

Спасибо Yashied за формулу, попробую сейчас воспроизвести её в коде :smile:


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

Получилось, я думал щас заплачу пока додумаюсь ;D, чуть позже выложу сюда готовый вариант.


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

Приёмник
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>
#include <GDIPlus.au3>
#include <Memory.au3>
#include <WinAPIEx.au3>

TCPStartup()
$Main = TCPListen(@IPAddress1, 8080)
If @error Then
	Exit
EndIf

$hForm = GUICreate("", -1, -1, 0, 0, $WS_POPUP, $WS_EX_LAYERED)
GUISetState()

Do
	$Socket = TCPAccept($Main)
	Switch GUIGetMsg()
		Case - 3
			Exit
	EndSwitch
Until $Socket <> -1

Global $tHeader = DllStructCreate('byte[4]')
Global $pHeader = DllStructGetPtr($tHeader)
Global $bData = 0, $Count = 0

_GDIPlus_Startup()

While 1
	If Not IsBinary($bData) Then
		$bData = TCPRecv($Socket, 8384, 1)
		If @error Then
			Do
				$Socket = TCPAccept($Main)
				Switch GUIGetMsg()
					Case - 3
						Exit
				EndSwitch
			Until $Socket <> -1
		EndIf
	EndIf
	If IsBinary($bData) Then
		If Not $Count Then
			DllStructSetData($tHeader, 1, $bData)
			$tData = DllStructCreate('dword', $pHeader)
			$Size = DllStructGetData($tData, 1)
			$tData = DllStructCreate('byte[' & $Size & ']')
			$pData = DllStructGetPtr($tData)
		EndIf
		$Lenght = BinaryLen($bData)
		$Sum = $Count + $Lenght
		If $Sum > $Size Then
			$dL = $Size - $Count
			$tPart = DllStructCreate('byte[' & $dL & ']', $pData + $Count)
			DllStructSetData($tPart, 1, $bData)
			$tByte = DllStructCreate('byte[' & $Lenght & ']')
			$tRecv = DllStructCreate('byte[' & ($Lenght - $dL) & ']', DllStructGetPtr($tByte) + $dL)
			DllStructSetData($tByte, 1, $bData)
			$bData = DllStructGetData($tRecv, 1)
			$Sum = $Size
		Else
			$tPart = DllStructCreate('byte[' & $Lenght & ']', $pData + $Count)
			DllStructSetData($tPart, 1, $bData)
			$Count = $Sum
			$bData = 0
		EndIf
		If $Sum = $Size Then
			SetScreenshot($hForm, $tData)
			$Count = 0
		EndIf
	EndIf
	Switch GUIGetMsg()
		Case - 3
			Exit
	EndSwitch
WEnd

_GDIPlus_Shutdown()
TCPCloseSocket($Socket)
TCPShutdown()

Func SetScreenshot($hWin, ByRef $tData)

	Local $hBitmap, $hPrev, $hScreen, $hMemory, $pMemory, $pStream, $pData, $iSize

	$pData = DllStructGetPtr($tData)
	$iSize = DllStructGetData(DllStructCreate('dword', $pData + 4), 1)
	$hMemory = _MemGlobalAlloc($iSize, $GMEM_MOVEABLE)
	$pMemory = _MemGlobalLock($hMemory)
	_MemMoveMemory($pData + 8, $pMemory, $iSize)
	_MemGlobalUnlock($hMemory)
	$pStream = _WinAPI_CreateStreamOnHGlobal($hMemory)
	$hBitmap = _GDIPlus_BitmapCreateFromStream($pStream)
	$hScreen = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
	_GDIPlus_BitmapDispose($hBitmap)
	_MemGlobalFree($hMemory)
	_WinAPI_UpdateLayeredWindowEx($hWin, 0, 0, $hScreen, 255, 1)
EndFunc

Func _GDIPlus_BitmapCreateFromStream($pStream)
	Local $Ret = DllCall($ghGDIPDll, 'uint', 'GdipCreateBitmapFromStream', 'ptr', $pStream, 'ptr*', 0)
	If (@error) Or ($Ret[0]) Then
		Return SetError(@error, @extended, 0)
	EndIf
	Return $Ret[2]
EndFunc

Передатчик
Код:
#include <APIConstants.au3>
#include <GDIPlus.au3>
#include <Memory.au3>
#include <Misc.au3>
#include <WinAPIEx.au3>
#include <GDIP.au3>

Opt("GUICloseOnESC", 0)

TCPStartup()
$Socket = TCPConnect(@IPAddress1, 8080)

_GDIPlus_Startup()
Global $tEncoder, $pEncoder, $tParams, $pParams, $tQuality
$tEncoder = _WinAPI_GUIDFromString(_GDIPlus_EncodersGetCLSID("jpg"))
$pEncoder = DllStructGetPtr($tEncoder)
$tParams = _GDIPlus_ParamInit(1)
$pParams = DllStructGetPtr($tParams)
$tQuality = DllStructCreate("int")
DllStructSetData($tQuality, 1, 30)
_GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, DllStructGetPtr($tQuality))

While 1
	$hWnd = _WinAPI_GetForegroundWindow()
    If $hWnd Then
        Local $iSize = _WinAPI_GetPosFromRect(_WinAPI_GetClientRect($hWnd))
	    TCPSend($Socket, GetScreenshot($hWnd, 0, 0, $iSize[2], $iSize[3]))
	    If @error Then
		    $Socket = TCPConnect(@IPAddress1, 8080)
	    EndIf
	EndIf
WEnd

_GDIPlus_Shutdown()
TCPCloseSocket($Socket)
TCPShutdown()

Func GetScreenshot($hWnd, $iX, $iY, $iWidth, $iHeight)
	Local $hSrcDC, $hDstDC, $hDstSv, $hBitmap, $hDesktop, $hScreen, $hMemory, $pMemory, $pStream, $tOut, $pOut, $iSize

	$hSrcDC = _WinAPI_GetDC($hWnd)
	$hScreen = _WinAPI_CreateCompatibleBitmap($hSrcDC, $iWidth, $iHeight)
	$hDstDC = _WinAPI_CreateCompatibleDC($hSrcDC)
	$hDstSv = _WinAPI_SelectObject($hDstDC, $hScreen)
	_WinAPI_BitBlt($hDstDC, $iX, $iY, $iWidth, $iHeight, $hSrcDC, $iX, $iY, $MERGECOPY)

	$iX = _WinAPI_GetMousePosX(True, $hWnd)
	$iY = _WinAPI_GetMousePosY(True, $hWnd)

	If _IsPressed(1) Then
		_WinAPI_DrawSight($hDstDC, $iX, $iY, 1, 8, 0xFF)
	Else
        _WinAPI_DrawSight($hDstDC, $iX, $iY)
    EndIf

	$tRECT = _WinAPI_CreateRect($iX + 25, $iY - 50, $iX + 500, $iY + 50)
	_WinAPI_DrawWindowText($hDstDC, $hWnd, $tRECT, 0xFFFFFF, 0x000000, 'Cambria', 15, 500, True) ;~ Пишем заголовок окна

	_WinAPI_SelectObject($hDstDC, $hDstSv)
	_WinAPI_DeleteDC($hDstDC)
	$hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hScreen)
	If $iWidth > 800 Then
        $hBitmap = _GDIPlus_GetImageThumbnail($hBitmap, 800, (($iHeight * 800) / $iWidth)) ; Тут нужно расчитать
    ElseIf $iHeight > 800 Then
		$hBitmap = _GDIPlus_GetImageThumbnail($hBitmap, (($iWidth * 800) / $iHeight), 800)
	EndIf
	_WinAPI_DeleteObject($hScreen)
	$pStream = _WinAPI_CreateStreamOnHGlobal(0)
	_GDIPlus_ImageSaveToStream($hBitmap, $pStream, $pEncoder, $pParams)
	_GDIPlus_BitmapDispose($hBitmap)
	$hMemory = _WinAPI_GetHGlobalFromStream($pStream)
	$pMemory = _MemGlobalLock($hMemory)
	$iSize = _MemGlobalSize($hMemory)
	$tOut = DllStructCreate("dword;dword;byte[" & ($iSize - Mod($iSize, 4) + 4) & "]")
	$pOut = DllStructGetPtr($tOut)
	DllStructSetData($tOut, 1, DllStructGetSize($tOut))
	DllStructSetData($tOut, 2, $iSize)
	_MemMoveMemory($pMemory, $pOut + 8, $iSize)
	_MemGlobalFree($hMemory)
	_WinAPI_StrFormatByteSize($iSize)
	Return DllStructGetData(DllStructCreate("byte[" & DllStructGetSize($tOut) & "]", DllStructGetPtr($tOut)), 1)
EndFunc

Func _WinAPI_DrawSight($hDC, $iX, $iY, $iSize = 8, $Width = 1, $iColor = 0x000000)
	$hPen = _WinAPI_CreatePen($Width, $Width, $iColor)
	$PenObj = _WinAPI_SelectObject($hDC, $hPen)
	_WinAPI_DrawLine($hDC, $iX, $iY + $iSize, $iX, $iY)
	_WinAPI_DrawLine($hDC, $iX + $iSize, $iY, $iX, $iY)
	_WinAPI_DrawLine($hDC, $iX, $iY - $iSize, $iX, $iY)
	_WinAPI_DrawLine($hDC, $iX - $iSize, $iY, $iX, $iY)
	_WinAPI_SelectObject($hDC, $PenObj)
	_WinAPI_DeleteObject($hPen)
EndFunc

Func _WinAPI_DrawWindowText($hDC, $hWnd, $tRECT, $TextColor = 0xFFFFFF, $BkColor = 0x000000, $Font = 'Arial', $iSizeFont = 10, $iWidth = 600, $Italic = False, $Underline = False, $Strikeout = False)
	$hFont = _WinAPI_CreateFont($iSizeFont, 0, 0, 0, $iWidth, $Italic, $Underline, $Strikeout, 1, 0, 0, 0, 0, $Font)
    $hObjFont = _WinAPI_SelectObject($hDC, $hFont)
	_WinAPI_SetTextColor($hDC, $TextColor)
	_WinAPI_SetBkColor($hDC, $BkColor)
    _WinAPI_DrawText($hDC, _WinAPI_GetWindowText($hWnd), $tRECT, BitOR(0x00000000, 0x00000020, 0x00000004))
	_WinAPI_SelectObject($hDC, $hObjFont)
	_WinAPI_DeleteObject($hFont)
EndFunc

Func _GDIPlus_GetImageThumbnail($hImage, $iWidth, $iHeight)
    Local $Ret = DllCall($ghGDIPDll, 'int', 'GdipGetImageThumbnail', 'ptr', $hImage, 'int', $iWidth, 'int', $iHeight, 'ptr*', 0, 'ptr', 0, 'ptr', 0)
    If (@error) Or ($Ret[0]) Then
        Return SetError(1, 0, 0)
    EndIf
    Return $Ret[4]
EndFunc
 

SlavaS

Знающий
Сообщения
35
Репутация
5
В данном примере, в частности в передатчике очень сильная утечка памяти. Растет с невероятной скоростью.
 
Верх