【问题标题】:Check if picturebox contains an image检查图片框是否包含图像
【发布时间】:2014-02-08 12:45:04
【问题描述】:

PictureBox 组件是否有任何内置方法来检查其内容的某个部分是否与另一个PictureBox 的内容匹配?例如:

我知道我可以通过将每个像素的颜色与PictureBox's Point(X,Y) 方法进行比较来做到这一点,但这对我来说似乎有点矫枉过正。更不用说它可能太慢了。

【问题讨论】:

    标签: visual-studio vb6 comparison picturebox


    【解决方案1】:

    您可以通过访问图片的内存来更快地比较每个像素。
    非常简单快捷,当我还是一个新的VB6程序员时,我就用这种方式编写了一个2D游戏引擎。 My 2D Game Engine (yLib)

    您要做的就是获取第一个像素的地址。
    以下函数为您完成这项工作:

    模块1:

    
        Public Declare Function VarPtrArray Lib "msvbvm60" Alias "VarPtr" (Ptr() As Any) As Long
        Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
        Public Declare Sub ZeroMemory Lib "kernel32" Alias "RtlZeroMemory" (destination As Any, ByVal Length As Long)
    
        Public Type SAFEARRAYBOUND
            cElements As Long
            lLbound As Long
        End Type
        Public Type SAFEARRAY2D
            cDims As Integer
            fFeatures As Integer
            cbElements As Long
            cLocks As Long
            pvData As Long
            Bounds(0 To 1) As SAFEARRAYBOUND
        End Type
        Public Type BITMAP
            bmType As Long
            bmWidth As Long
            bmHeight As Long
            bmWidthBytes As Long
            bmPlanes As Integer
            bmBitsPixel As Integer
            bmBits As Long
        End Type
        Public Type Picture
            pic As STDPicture
            c() As Byte
            bmp As BITMAP
            SA As SAFEARRAY2D
        End Type
    
        Public Type lyPicture
            pic As STDPicture
            c() As Byte
            bmp As BITMAP
            SA As SAFEARRAY2D
        End Type
    

    主窗体或模块:

    
        Private Sub LoadPicArray2D(val As lyPicture)
            ' get bitmap info from image box
            Call GetObjectAPI(val.pic, Len(val.bmp), val.bmp)  'dest
            ' exit if not 24-bit bitmap
            ' make the local matrix point to bitmap pixels
            If val.bmp.bmPlanes  1 Or val.bmp.bmBitsPixel  24 Or val.bmp.bmWidthBytes / val.bmp.bmWidth  3 Then
                Call Err.Raise(500, "Only 24-bit bitmaps.", "Only 24-bit bitmaps.")
            End If
            With val.SA
              .cbElements = 1
              .cDims = 2
              .Bounds(0).lLbound = 0
              .Bounds(0).cElements = val.bmp.bmHeight
              .Bounds(1).lLbound = 0
              .Bounds(1).cElements = val.bmp.bmWidthBytes
              .pvData = val.bmp.bmBits
            End With
            Call CopyMemory(ByVal VarPtrArray(val.c()), VarPtr(val.SA), 4)
        End Sub
    
        Public Sub Main()
            Dim pic As lyPicture
            Set pic.pic = Form1.TargetPictureBox.Picture
            Call LoadPicArray2D(pic)
    
            'Just remember that the picture's memory stored top-down this mean the 
            ' upper pixel lays in lower array bound.
            ' but the array is correct in horizontal arrangement.
            ' And the array is formated BGR pic.c(0,0) = B , pic.c(1,0) = G, pic.c(2,0) = R
    
            pic.c(0,0) = 0                      ' the pixel at the left bottom (0, MAX_PICTURE_HEIGHT-1) of the picture.
            pic.c(0,MAX_PICTURE_HEIGHT-1) = 0     ' the pixel at (0, 0)
    
            ' This is very IMPORTANT to release the array at the end of the code.
            Call ZeroMemory(ByVal VarPtrArray(val.c()), 4)
            ' I dont tested this code just copied from my game engine. :D
        End Sub
    

    【讨论】:

    • 最好创建一个具有长(32 位)值的 SAFEARRAY,并将该 SAFEARRAY 结构中的 pvData 指向 lyPictures,使用此新数组的 SAFEARRAY.pvData 将提供数据对齐以混合 CPU 优化访问对齐的指针,然后您可以屏蔽 B(Color And &HFF)、G(Color And &HFF00 / &H100)、B(Color And &HFF0000 / &H10000) 注意,这仅适用于您的图片为 32 位(答案中的图片必须是24位否则会引发错误)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多