找回密码
 加入
搜索
楼主: jorlon

[图形处理] 如何对图片局部选择区域高亮和打上马赛克?

 火.. [复制链接]
发表于 2012-4-6 14:37:46 | 显示全部楼层
回复 15# afan

这个办法好哈。。
发表于 2012-4-6 23:30:58 | 显示全部楼层
回复 15# afan

    A版写个出来,让我等学习一下嘛。

前几天回这个帖时,想到一个可能效率高点的办法:就是对打马的区域,    把光点的RGB互换下,并且求一下XOR。当然也可以别的,象上下/左右反转

但这种包括前面搞的,都容易被人反马掉。

现在回头想想,得搞个好点的想法/算法,让效果好,速度快,并且让反马效果很差
发表于 2012-4-7 01:04:06 | 显示全部楼层
本帖最后由 happytc 于 2012-4-7 01:22 编辑

回复 15# afan

我试了下我在五楼提的把位图先锁进内存再操作
效率比5楼的马上提高了4倍左右。看来对图片,直接操作指针/内存,效果的确好很多
下面是两个方法的比较,大家可以分注释其中一个测试下:

#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
        Local $iTestDotNum = 200, $iInit
        
        $sLink = "myarticle.enet.com.cn"
        $sPic = "/images/2007/0917/1189986155220/1.jpg"
        
        If FileExists(@ScriptDir & "\Beauty.jpg") Then
                $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Beauty.jpg")
        Else
                ToolTip("Wait for downloading image...", @DesktopWidth / 2, @DesktopHeight /2, "Mosaic for image")
                $hImage = _ImageFromNet($sLink, $sPic)
                ToolTip("")
                _GDIPlus_ImageSaveToFile($hImage, @ScriptDir & "\Beauty.jpg")
        EndIf
        
        $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)
        
#cs-----------------------------------------Method 1 -------------------------------------------
        $iInit = TimerInit()
        For $iX = $iXnum - $iTestDotNum To $iXnum + $iTestDotNum Step 10
                For $iY = $iYnum - $iTestDotNum To $iYnum + $iTestDotNum 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

#ce-----------------------------------------Method 1 -------------------------------------------
        
        
;#cs=========================================Method 2 =====================================================
        Local $tBitmapData, $iStride, $iScan0, $tColor, $tPixel
        
        $iInit = TimerInit()
        $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iWidth, $iHeight, $GDIP_ILMWRITE, $GDIP_PXF32ARGB)
        $iStride = DllStructGetData($tBitmapData, "Stride")
        $iScan0 = DllStructGetData($tBitmapData, "Scan0")
        
        For $iX = $iXnum - $iTestDotNum To $iXnum + $iTestDotNum Step 10
                For $iY = $iYnum - $iTestDotNum To $iYnum + $iTestDotNum Step 10
                        $tColor = DllStructCreate("int", $iScan0 + (($iY + 1) * $iStride) + (($iX + 1) * 4))
                        $iColor = DllStructGetData($tColor, 1)

                        For $i = 0 To 10
                                For $j = 0 To 10
                                        $tPixel = DllStructCreate("int", $iScan0 + (($iY + $j) * $iStride) + (($iX + $i) * 4))
                                        DllStructSetData($tPixel, 1, $iColor)
                                Next
                        Next
                Next
        Next
        _GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)
        
;#ce=========================================Method 2 =====================================================
        
        _GDIPlus_GraphicsDrawImage($hGraphics, $hImage, $iWidth, 0)
        
        ConsoleWrite(TimerDiff($iInit) & " ms" & @CRLF)
        
        Do
        Until GUIGetMsg() = $GUI_EVENT_CLOSE

        _GDIPlus_ImageDispose($hImage)
        _WinAPI_DeleteObject($hBmp)
        _GDIPlus_GraphicsDispose($hGraphics)
EndFunc   ;==>ImageMosaic



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   ;==>_ImageFromNet



发表于 2012-4-7 01:30:21 | 显示全部楼层
回复 18# happytc


    可以试试我说的思路啊~ 先缩小指定区域(可以用_GDIPlus_GraphicsDrawImageRectRect),再 _WinAPI_StretchBlt() 放大至指定区域。

BTW,手上的事挺杂的,我就不班门弄斧写什么破代码了,说说至少不会显得太白金星~
发表于 2012-4-7 06:12:15 | 显示全部楼层
本帖最后由 happytc 于 2012-4-7 06:13 编辑
回复  happytc


    可以试试我说的思路啊~ 先缩小指定区域(可以用_GDIPlus_GraphicsDrawImageRectRec ...
afan 发表于 2012-4-7 01:30


(可能就是昨晚想写个18楼的这个东西了,居然才睡几个小时就醒了,再也睡不着了)
算法的重要性在这里体现得太明显了(后来想了想,用StretchBlt函数肯定效率会下降些,所以没用)
下面的代码仅仅调用了很简单‘k-最近邻内插’算法来处理像素,速度马上就上去了。
等有空了,我再试一下高斯内插算法,看看效果是不是更好!

#include <GDIP.au3>
#include <GUIConstantsEx.au3>
#include <Memory.au3>
#include <String.au3>

Global $SocketID
;Opt('MustDeclareVars', 1)
_GDIPlus_Startup()
ImageMosaic()
_GDIPlus_Shutdown()

Func ImageMosaic()
        Local $hGUI, $hImage, $hClone, $hGraphics, $hContext
        Local $iColor, $iX, $iY, $iWidth, $iHeight, $sLink, $sPic
        Local $iTestDotNum = 200, $fstretch = 10, $iInterMode = 5, $iSmoothMode = 7, $iOffsetMode = 4
        
        $sLink = "myarticle.enet.com.cn"
        $sPic = "/images/2007/0917/1189986155220/1.jpg"
        
        If FileExists(@ScriptDir & "\Beauty.jpg") Then
                $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Beauty.jpg")
        Else
                ToolTip("Wait for downloading image...", @DesktopWidth / 2, @DesktopHeight /2, "Mosaic for image")
                $hImage = _ImageFromNet($sLink, $sPic)
                ToolTip("")
                _GDIPlus_ImageSaveToFile($hImage, @ScriptDir & "\Beauty.jpg")
        EndIf
        
        $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)        
        
        $hClone = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iTestDotNum/$fstretch, $iTestDotNum/$fstretch)
        $hContext = _GDIPlus_ImageGetGraphicsContext($hClone)

        _GDIPlus_GraphicsSetInterpolationMode($hContext, $iInterMode)
        _GDIPlus_GraphicsSetInterpolationMode($hGraphics, $iInterMode)
        _GDIPlus_GraphicsSetPixelOffsetMode($hContext, $iOffsetMode)
        _GDIPlus_GraphicsSetPixelOffsetMode($hGraphics, $iOffsetMode)
        _GDIPlus_GraphicsSetSmoothingMode($hContext, $iSmoothMode)
        _GDIPlus_GraphicsSetSmoothingMode($hGraphics, $iSmoothMode)
        
        _GDIPlus_GraphicsDrawImage($hGraphics, $hImage, $iWidth, 0)
        _GDIPlus_GraphicsDrawImageRectRect($hContext, $hImage, 0, 0, $iWidth, $iHeight, 0, 0, $iWidth/$fstretch, $iHeight/$fstretch)
        _GDIPlus_GraphicsDrawImageRectRect($hGraphics, $hClone, 0, 0, $iWidth/$fstretch, $iHeight/$fstretch, $iWidth, 0, $iWidth, $iHeight)
        
        Do
        Until GUIGetMsg() = $GUI_EVENT_CLOSE

        _GDIPlus_ImageDispose($hImage)
        _WinAPI_DeleteObject($hClone)
        _GDIPlus_GraphicsDispose($hGraphics)
EndFunc   ;==>ImageMosaic




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   ;==>_ImageFromNet


发表于 2012-4-7 12:27:18 | 显示全部楼层
高手,谢谢共享
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-11-14 13:00 , Processed in 0.125416 second(s), 14 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表