Что нового

Конвертировать цвет изображения в чёрно - белый

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Есть 2 скрипта (примеры Yashied'a), 1й передаёт скриншот экрана, а 2й принимает и показывает на форме, так вот, изображение передаётся цветное, а если его зделать чёрно - белым то картинка будет меньше весить, следовательно в ней будет меньше данных которые требуется передать, нашёл пример как сделать картинку чёрно - белой, но не могу сообразить как этот пример применить в передающую часть?

Передающая часть:
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#include <Memory.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
	TCPSend($Socket, GetScreenshot(_WinAPI_GetDesktopWindow(), 0, 0, @DesktopWidth - 5, @DesktopHeight - 5))
	If @error Then
		$Socket = TCPConnect(@IPAddress1, 8080)
		Sleep(100)
	EndIf
	Switch GUIGetMsg()
		Case - 3
			Exit
	EndSwitch
WEnd

_GDIPlus_Shutdown()
TCPCloseSocket($Socket)
TCPShutdown()

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

	$hSrcDC = _WinAPI_GetDC($hWnd)
	$hScreen = _WinAPI_CreateCompatibleBitmapEx($hSrcDC, $iWidth, $iHeight, 0xFF000000)
	$hDstDC = _WinAPI_CreateCompatibleDC($hSrcDC)
	$hDstSv = _WinAPI_SelectObject($hDstDC, $hScreen)
	_WinAPI_BitBlt($hDstDC, $iX, $iY, $iWidth, $iHeight, $hSrcDC, $iX, $iY, $SRCCOPY)
	_WinAPI_SelectObject($hDstDC, $hDstSv)
	_WinAPI_DeleteDC($hDstDC)
	$hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hScreen, 1)
	_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

Принимающая часть:
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>
#include <GDIPlus.au3>
#include <Memory.au3>
#include <WinAPIEx.au3>

Global Const $STM_SETIMAGE = 0x0172
Global Const $STM_GETIMAGE = 0x0173

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

$hForm = GUICreate("Remote Web Server v2.106.3.1", 320, 240, 0, 0, BitOR($WS_MINIMIZEBOX, $WS_SIZEBOX, $WS_MAXIMIZEBOX))
$Pic = GUICtrlCreatePic('', 0, 0, 320, 240)
GUICtrlSetState($Pic, $GUI_DISABLE)
_WinAPI_SetWindowLong($hForm, -16, BitOR(_WinAPI_GetWindowLong($hForm, -16), $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS))
GUIRegisterMsg(0x0401, 'WM_USER')
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
				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($Pic, $tData)
			$Count = 0
		EndIf
	EndIf
	Switch GUIGetMsg()
		Case - 3
			Exit
	EndSwitch
WEnd

_GDIPlus_Shutdown()
TCPCloseSocket($Socket)
TCPShutdown()

Func WM_USER($hWnd, $iMsg, $wParam, $lParam)
    Switch $hWnd
        Case $hForm
            Local $iPos = WinGetPos($hWnd)
			GUICtrlSetPos($Pic, 0, 0, $iPos[2], $iPos[3])
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func SetScreenshot($CtrlID, ByRef $tData)

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

	$hWnd = GUICtrlGetHandle($CtrlID)
	If Not $hWnd Then
		Return 0
	EndIf
    $hSize = WinGetPos($hWnd)

	$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)
	$hBitmap = _GDIPlus_GetImageThumbnail($hBitmap, $hSize[2], $hSize[3])
	$hScreen = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
	_GDIPlus_BitmapDispose($hBitmap)
	_MemGlobalFree($hMemory)
	_WinAPI_DeleteObject(_SendMessage($hWnd, $STM_SETIMAGE, $IMAGE_BITMAP, $hScreen))
	_SendMessage($hForm, 0x0401)
	_WinAPI_UpdateWindow($hWnd)
EndFunc

Func _GDIPlus_GetImageThumbnail($hImage, $iWidth, $iHeight)
    Local $Ret = DllCall($ghGDIPDll, 'uint', 'GdipGetImageThumbnail', 'ptr', $hImage, 'uint', $iWidth, 'uint', $iHeight, 'ptr*', 0, 'ptr', 0, 'ptr', 0)
    If (@error) Or ($Ret[0]) Then
        Return SetError(@error, @extended, 0)
    EndIf
    Return $Ret[4]
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 <GDIP.au3>
#include <GUIConstantsEx.au3>
#include <ScreenCapture.au3>

_GDIPlus_Startup()
$hGUI = GUICreate("", @DesktopWidth, @DesktopHeight)


$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
$hBmp = _ScreenCapture_Capture("", 0, 0, -1, -1, True)
$hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBmp)
$hGrayIA = _GDIPlus_ImageAttributesCreate()

$tColorMatrix = _GDIPlus_ColorMatrixCreateGrayScale()
$pColorMatrix = DllStructGetPtr($tColorMatrix)
_GDIPlus_ImageAttributesSetColorMatrix($hGrayIA, 0, True, $pColorMatrix)
GUISetState()

_GDIPlus_GraphicsSetInterpolationMode($hGraphics, 7)
_GDIPlus_GraphicsDrawImageRectRectIA($hGraphics, $hBitmap, 0, 0, @DesktopWidth, @DesktopHeight, 0, 0,@DesktopWidth, @DesktopHeight, $hGrayIA)

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

_GDIPlus_ImageAttributesDispose($hGrayIA)
_WinAPI_DeleteObject($hBmp)
_GDIPlus_ImageDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_Shutdown()
 

Arei

Скриптер
Сообщения
938
Репутация
115
Какая интересная тема, быстрей бы узнать ответ. На этот животрепещущий вопрос.
 

Medic84

Омега
Команда форума
Администратор
Сообщения
1,590
Репутация
341
Arei
Предупреждение Будешь АПать не свои темы, да еще и не во время - схлопотаешь отстранение от форума.
 

Arei

Скриптер
Сообщения
938
Репутация
115
За что,если я не знаю ответа на вопрос, но мне тема интересна и хочется узнать быстрее, то мне кажется что это нормально.И нету запретов на Up чужых тем.А насчёт 24 часов, это правило для создателя темы. :IL_AutoIt_1:
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Arei [?]
если я не знаю ответа на вопрос, но мне тема интересна и хочется узнать быстрее, то мне кажется что это нормально
Это нормально если ты это делаешь не сразу (не в тот же день) после создания темы.

[?]
насчёт 24 часов, это правило для создателя темы
Такого правила вовсе нет, это рекомендация, и как разумный человек, ты должен понимать что оно относится не только к создателю темы.
 

Arei

Скриптер
Сообщения
938
Репутация
115
OffTopic:
Конечно, буду себя сдерживать, просто некоторые вопросы хочется узнать сразу.
 
Верх