Home All Groups Group Topic Archive Search About

Is there a quick way to see if a small pic in a picturebox is in a larger one?

Author
2 Feb 2006 3:28 PM
BR
Is there a quick way to see if a small pic in a picturebox is in a
larger one?

I think getpixel and going through about 4 FOR loops might work,, seems
like it would be too slow.  Is there a way to dump them in arrays and
do some kind of compare? or is there a copymem or some other way to do
it.

If you know how can you give me code or pseudocode?


TIA

Author
2 Feb 2006 5:00 PM
J French
On 2 Feb 2006 07:28:34 -0800, "BR" <aceci***@gmail.com> wrote:

>Is there a quick way to see if a small pic in a picturebox is in a
>larger one?
>
>I think getpixel and going through about 4 FOR loops might work,, seems
>like it would be too slow.  Is there a way to dump them in arrays and
>do some kind of compare? or is there a copymem or some other way to do
>it.
>
>If you know how can you give me code or pseudocode?

Here is a snippet that gets an image into a Byte Array
- it also copies it to a second Picturebox to prove the point

More below.

Option Explicit

' Tom Shelton - 24/9/02

' Distorts bitmap - annoying
' - if Pictures are different sizes
' - SavePicture creates a larger file

Private 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

Private Declare Function GetObject Lib "gdi32" Alias "GetObjectA" _
    (ByVal hObject As Long, _
     ByVal nCount As Long, _
     ByRef lpObject As BITMAP) As Long

Private Declare Function GetBitmapBits Lib "gdi32" _
    (ByVal hBitmap As Long, _
     ByVal dwCount As Long, _
     ByRef lpBits As Byte) As Long

Private Declare Function SetBitmapBits Lib "gdi32" _
    (ByVal hBitmap As Long, _
     ByVal dwCount As Long, _
     ByRef lpBits As Byte) As Long

Private Sub Command1_Click()
    Dim bm As BITMAP
    Dim bytes() As Byte
    Dim NumBytes&

    ' GET THE BITMAP SIZE AND ALLOCATE THE STORAGE
    Call GetObject(Picture1.Image, Len(bm), bm)
    ReDim bytes(0 To (bm.bmWidthBytes * bm.bmHeight) - 1)

    ' GET THE BITMAP BITS IN THE ARRAY
    Call GetBitmapBits(Picture1.Image, bm.bmWidthBytes * bm.bmHeight,
bytes(0))

    Me.Print bm.bmBitsPixel

    NumBytes = bm.bmWidthBytes * bm.bmHeight

    'Picture2.Picture = Nothing
    Set Picture2.Picture = New StdPicture
    Call SetBitmapBits(Picture2.Image.Handle, NumBytes, bytes(0))
    Picture2.Refresh

End Sub

You can get the Bits per pixel, and if that is 8 or a multiple of 8
you have the possibility of using something like InStr() or InStrB()
to find the first line of your smaller picture in the larger picture.

This should give you some ideas :-

Private Sub Command1_Click()
   Dim B(1 To 100) As Byte
   Dim S$

   B(51) = 1
   B(52) = 1

   S$ = B()

   Me.Print InStrB(1, S$, ChrB(1) + ChrB(1))
   Me.Print "Str Len"; Len(S$)

End Sub

If you find the first line you will then need to drop down (move
right) by the width of the large picture and check whether the next
line matches exactly.

Bear in mind that the small picture will have to be exactly the same
as the portion in the large picture

You should be able to speed things up by checking that the last byte
in the small picture matches the appropriate byte in the large one.

However, when compiled dealing with Byte Arrays is incredibly fast, so
you might not need to worry about optimization.

Incidentally multi dimensional arrays are stored in row order, so
B(1,1) is followed by B(2,1) so you could look at the bitmap as a two
dimensional Array eg: B( Y, X )  ... sort of on its side

I don't think I would do that as it is a bit painful and one would
lose the chance of using InStrB()