本帖最后由 happytc 于 2012-4-2 03:11 编辑
回复 1# jorlon
打马赛克原理很简单,就是定义个像素区块,如3X3的,然后把这个区块内的所有像素色彩都用这个区块的某一个像素色彩代替,如区块里第一个像素/中间像素/随机一个/或平均值都可以。难的是如何优化算法。若没有好的算法,一个大图,要花费很长时间来做这个东西。
若想增加速度,可以用_GDIPlus_BitmapLockBits()函数把位图锁进内存再操作,但又有指针有时操作错误(不安全)的可能。若直接用_GDIPlus_BitmapGetPixel()函数和_GDIPlus_BitmapSetetPixel()来做,效率明显不高。
下面给个后一种方法的打马赛克的。(看看美女的嘴打到了)
#Include <GDIP.au3>
#Include <GUIConstantsEx.au3>
#Include <ScreenCapture.au3>
#include <Memory.au3>
#include <String.au3>
Global $SocketID
Opt('MustDeclareVars', 1)
_GDIPlus_Startup()
ImageMosaic()
_GDIPlus_Shutdown()
Func ImageMosaic()
Local $hGUI, $hImage, $hBmp, $hGraphics
Local $iColor, $iX, $iY, $iWidth, $iHeight, $sLink, $sPic, $iXnum, $iYnum
$sLink = "myarticle.enet.com.cn"
$sPic = "/images/2007/0917/1189986155220/1.jpg"
$hImage = _ImageFromNet($sLink, $sPic)
$iWidth = _GDIPlus_ImageGetWidth($hImage)
$iHeight = _GDIPlus_ImageGetHeight($hImage)
$hGUI = GUICreate("Mosaic", $iWidth * 2, $iHeight)
GUISetState()
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
_GDIPlus_GraphicsDrawImage($hGraphics, $hImage, 0, 0)
$iXnum = Int($iWidth / 2)
$iYnum = Int($iHeight / 2)
For $iX = $iXnum - 50 To $iXnum + 50 Step 10
For $iY = $iYnum - 50 To $iYnum + 50 Step 10
$iColor = _GDIPlus_BitmapGetPixel($hImage, $iX + 1, $iY + 1)
For $i = 0 To 10
For $j = 0 To 10
_GDIPlus_BitmapSetPixel($hImage, $iX + $i, $iY + $j, $iColor)
Next
Next
Next
Next
_GDIPlus_GraphicsDrawImage($hGraphics, $hImage, $iWidth, 0)
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
_GDIPlus_ImageDispose($hImage)
_WinAPI_DeleteObject($hBmp)
_GDIPlus_GraphicsDispose($hGraphics)
EndFunc
Func _ImageFromNet($sHost, $sSource)
Local $sIp, $sData, $sSocket, $sRecvHeader = "", $sRecvBin = "0x", $aRet
Local $iBytes, $mBitmap, $iLength, $hData, $pData, $tMem, $aResult
TCPStartup()
$sIp = TCPNameToIP($sHost)
$sData = "GET " & $sSource & " HTTP/1.1" & @Crlf & "Host: " & $sHost & @Crlf & @CRLF
$sSocket = TCPConnect ($sIp, 80)
TCPSend ($sSocket, $sData)
If @error Then Return Seterror(1, 1, 1)
Do
$sRecvHeader = TCPRecv($sSocket, 1)
Until $sRecvHeader <> ""
Do
$sRecvHeader &= TCPRecv($sSocket, 1)
Until StringInStr($sRecvHeader, @Crlf & @Crlf)
$aRet = _StringBetween($sRecvHeader, 'Content-Length: ', @Crlf )
If IsArray($aRet) Then
$iBytes = $aRet[0]
Do
$sRecvBin &= StringTrimLeft(TCPRecv($sSocket, 1024, 1 ), 2)
Until BinaryLen(Binary($sRecvBin)) >= $iBytes
TCPCloseSocket($sSocket)
TCPShutdown()
$mBitmap = Binary($sRecvBin)
$iLength = BinaryLen($mBitmap)
$hData = _MemGlobalAlloc ($iLength, $GMEM_MOVEABLE)
$pData = _MemGlobalLock ($hData)
$tMem = DllStructCreate ( "byte[" & $iLength & "]", $pData )
DllStructSetData ($tMem, 1, $mBitmap)
_MemGlobalUnlock ($hData)
$aResult = DllCall("ole32.dll", "int", "CreateStreamOnHGlobal", "hwnd", $pData, "int", True, "ptr*", 0)
If @error Then Return SetError(@error, @extended, 0)
$aResult = DllCall ($ghGDIPDll, "uint", "GdipCreateBitmapFromStream", "ptr", $aResult[3], "int*", 0)
If @error Then Return SetError (@error, @extended, 0)
Return $aResult[2]
Else
TCPCloseSocket($SocketID)
TCPShutdown( )
Return Seterror(1, 1, 1)
EndIf
EndFunc
|