Results 1 to 27 of 27

Thread: Fast picture masking

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Jan 2002
    Location
    Palermo, Italy
    Posts
    325

    Fast picture masking

    What is the fastest way to create the mask of picture?

    Here's the code I wrote:

    Code:
    Public Function Mask(Color As Long) As Boolean
        Dim i As Long
        Dim j As Long
        
        Mask=false
    
        If bValidSprite Then
            For i = 0 To lSpriteWidth - 1
                For j = 0 To lSpriteHeight - 1
                    If GetPixel(DCSprite, i, j) = Color Then
                        Call SetPixel(DCMask, i, j, vbWhite)
                    Else
                        Call SetPixel(DCMask, i, j, vbBlack)
                    End If
                Next j
            Next i
            bValidMask = True
            Mask=true
    
        End If
    
    End Function

    Thanks Xmas.

  2. #2
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    change the i and j longs to integers.
    change 'next i' and 'next j' to only 'next'
    and use setpixelv instead of setpixel...
    if you are using a picturebox, use ScaleMode 3
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

  3. #3
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    if you're using a picturebox with scalemode = 3, use scalewidth and scaleheight instead of width and height...
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

  4. #4
    Good Ol' Platypus Sastraxi's Avatar
    Join Date
    Jan 2000
    Location
    Ontario, Canada
    Posts
    5,134
    Originally posted by cyborg
    change the i and j longs to integers. slower
    change 'next i' and 'next j' to only 'next' bad coding practice
    and use setpixelv instead of setpixel... good
    if you are using a picturebox, use ScaleMode 3 irrelevant
    For best performance, use Get/SetDIBits.
    All contents of the above post that aren't somebody elses are mine, not the property of some media corporation.
    (Just a heads-up)

  5. #5
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    hmm.... i've heard that integer is the fastest variable type...

    if scalemode are set to 1 - twips, there are about 15 times more pixels to check...or did i get it wrong?
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

  6. #6

    Thread Starter
    Hyperactive Member
    Join Date
    Jan 2002
    Location
    Palermo, Italy
    Posts
    325
    Ok for setpixelv... I'm using DCs into memory. How better performance with Get/SetDIBits ?

  7. #7
    Retired G&G Mod NoteMe's Avatar
    Join Date
    Oct 2002
    Location
    @ Opera Software
    Posts
    10,190
    Integers don't have to be the fastest variable type. We had this discussion a couple a weeks ago.

    http://www.vbforums.com/showthread.p...hreadid=211533

  8. #8
    Good Ol' Platypus Sastraxi's Avatar
    Join Date
    Jan 2000
    Location
    Ontario, Canada
    Posts
    5,134
    Here it is, it's very complex code, so I'll walk through it with you:
    VB Code:
    1. Public Function Morph2D(X As Long, Y As Long, NumRow As Long) As Long
    2.     Morph2D = (Y - 1) * NumRow + X
    3. End Function
    4. Public Function Mask(Color As Long) As Boolean
    5. Dim Co As mLong
    6.  
    7. Dim sBitmap As Long
    8. Dim sBMP As BITMAP
    9. Dim sPic() As mRGB
    10. Dim sMem As BITMAPINFO
    11. Dim mBitmap As Long
    12. Dim mBMP As BITMAP
    13. Dim mPic() As mRGB
    14. Dim mMem As BITMAPINFO
    15.  
    16. Dim i As Long
    17. Dim j As Long
    18.  
    19.     sBitmap = GetCurrentObject(DCSprite, OBJ_BITMAP)
    20.     GetObjectAPI sBitmap, Len(sBMP), sBMP
    21.     With sMem.bmiHeader
    22.         .biBitCount = 32
    23.         .biCompression = BI_RGB
    24.         .biPlanes = 1
    25.         .biSize = Len(sMem.bmiHeader)
    26.         .biWidth = sBMP.bmWidth
    27.         .biHeight = sBMP.bmHeight
    28.         ReDim Preserve sPic(0 To (.biWidth * .biHeight) - 1) As mRGB
    29.     End With
    30.     GetDIBits DCSprite, sBitmap, 0, sBMP.bmHeight, sPic(0), sMem, DIB_RGB_COLORS
    31.  
    32.     mBitmap = GetCurrentObject(DCMask, OBJ_BITMAP)
    33.     GetObjectAPI mBitmap, Len(mBMP), mBMP
    34.     With mMem.bmiHeader
    35.         .biBitCount = 32
    36.         .biCompression = BI_RGB
    37.         .biPlanes = 1
    38.         .biSize = Len(mMem.bmiHeader)
    39.         .biWidth = mBMP.bmWidth
    40.         .biHeight = mBMP.bmHeight
    41.         ReDim Preserve mPic(0 To (.biWidth * .biHeight) - 1) As mRGB
    42.     End With
    43.     GetDIBits DCMask, mBitmap, 0, mBMP.bmHeight, mPic(0), mMem, DIB_RGB_COLORS
    44.    
    45.     Mask=false
    46.  
    47.     If bValidSprite Then
    48.         For j = 0 To lSpriteHeight - 1
    49.             For i = 0 To lSpriteWidth - 1
    50.                 LSet Co = sPic(Morph2D(i, lSpriteHeight - j, lSpriteWidth))
    51.                 If Co.L = Color Then
    52.                     Co.L = 0
    53.                 Else
    54.                     Co.L = RGB(255, 255, 255)
    55.                 End If
    56.                 LSet mPic(Morph2D(i, lSpriteHeight - j, lSpriteWidth)) = Co
    57.             Next i
    58.         Next j
    59.         bValidMask = True
    60.         Mask=true
    61.        
    62.     SetDIBits DCMask, mBitmap, 0, mBMP.bmHeight, mPic(0), mMem, DIB_RGB_COLORS
    63.  
    64.     End If
    65.  
    66. End Function
    I'm still not sure how to do the cleanup in this code, but I'm sure it would be deleting the bitmaps and BMPs, etc. Here are the declarations:
    VB Code:
    1. Public Const BI_RGB = 0&
    2. Public Const DIB_RGB_COLORS = 0
    3. Public Type mLong
    4.     L As Long
    5. End Type
    6. Public Type mRGB
    7.     R As Byte
    8.     G As Byte
    9.     B As Byte
    10.     A As Byte
    11. End Type
    12. Public Type BITMAP
    13.     bmType As Long
    14.     bmWidth As Long
    15.     bmHeight As Long
    16.     bmWidthBytes As Long
    17.     bmPlanes As Integer
    18.     bmBitsPixel As Integer
    19.     bmBits As Long
    20. End Type
    21. Private Type BITMAPINFOHEADER '40 bytes
    22.     biSize As Long
    23.     biWidth As Long
    24.     biHeight As Long
    25.     biPlanes As Integer
    26.     biBitCount As Integer
    27.     biCompression As Long
    28.     biSizeImage As Long
    29.     biXPelsPerMeter As Long
    30.     biYPelsPerMeter As Long
    31.     biClrUsed As Long
    32.     biClrImportant As Long
    33. End Type
    34. Public Type BITMAPINFO
    35.     bmiHeader As BITMAPINFOHEADER
    36.     bmiColors As mRGB
    37. End Type
    38. Public Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
    39. Public Declare Function SetDIBits Lib "gdi32" (ByVal hdc As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
    40. Public Declare Function GetCurrentObject Lib "gdi32" (ByVal hdc As Long, ByVal uObjectType As Long) As Long
    41. Public Declare Function GetObjectAPI Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
    Last edited by Sastraxi; Nov 16th, 2002 at 01:19 PM.
    All contents of the above post that aren't somebody elses are mine, not the property of some media corporation.
    (Just a heads-up)

  9. #9
    Good Ol' Platypus Sastraxi's Avatar
    Join Date
    Jan 2000
    Location
    Ontario, Canada
    Posts
    5,134
    This is what the code does, step by step. First, it get's the hDC's bitmap pointer. Then, it takes this and, from it, gets the actual bitmap's info. After this, it fills in the values for a normal bitmap in the header, since from a DC this is one of the two things we don't get back (if you sent it a picture, you'd be able to get it all back, but we'd have to modify the code heavily). The other thing it doesn't get back is the actual bitmap data (sBMP/mBMP.bmBits), so we get this with GetDIBits. Now we have a one-dimensional array holding all of our bytes.

    Now, you see all these Morph2D calls in there. They get the one-dimensional index from a two-dimensional one (one-dimensional arrays are faster so that's why they are used). And, GetDIBits returns the bitmap upside-down, so we always use Height - J to get the real Y value.

    The LSet value puts any value into any other value (like putting a type with two bytes in it into an integer). In this case, we're assigning two long values to a 4-byte type, and since long is 4 bytes, it fills up the type nicely with the R, G, B data we want.

    After this, we use SetDIBits to put the bits back to the DC from whence they came. I think that's it, but I haven't tested the code yet, so if there are any errors (and probably stupid ones), let me know.
    All contents of the above post that aren't somebody elses are mine, not the property of some media corporation.
    (Just a heads-up)

  10. #10
    Stuck in the 80s The Hobo's Avatar
    Join Date
    Jul 2001
    Location
    Michigan
    Posts
    7,256
    Originally posted by cyborg
    if you're using a picturebox with scalemode = 3, use scalewidth and scaleheight instead of width and height...
    ScaleWidth and ScaleHeight should be used regardless of the ScaleMode. No matter what mode you're in, if the border's still there, Width and Height are going to give you inproper values.
    My evil laugh has a squeak in it.

    kristopherwilson.com

  11. #11
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    yep
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

  12. #12
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    NoteMe, i tried your variable test program...
    it showed me that integer was the fastest!

    Long = 0,9574 ms
    Integer = 0,9092 ms
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

  13. #13
    Retired G&G Mod NoteMe's Avatar
    Join Date
    Oct 2002
    Location
    @ Opera Software
    Posts
    10,190
    How many times did you try it? Did you try to switch the order of the two tests? Those who have most often got the result of the integer test using nearly twice the time of long.

    But Sastraxi posted a better way to time the test. I used his code (I hope he doesn't mind me using it) to developed a test for both variable types. Try this.

  14. #14
    Retired G&G Mod NoteMe's Avatar
    Join Date
    Oct 2002
    Location
    @ Opera Software
    Posts
    10,190
    Ops...forgot the attachment...
    Attached Files Attached Files

  15. #15
    Good Ol' Platypus Sastraxi's Avatar
    Join Date
    Jan 2000
    Location
    Ontario, Canada
    Posts
    5,134
    Thanks, NoteMe, I don't mind at all, I love it when others use my code

    So, long came up 7.3 s and integer was 9 s (with Winamp running). A second test, using integer first, came up with 7.7 for integer and 7.3 for long. So, in both tests, longs were faster And I'm about to make changes to some code, as it's wrong...
    All contents of the above post that aren't somebody elses are mine, not the property of some media corporation.
    (Just a heads-up)

  16. #16
    Stuck in the 80s The Hobo's Avatar
    Join Date
    Jul 2001
    Location
    Michigan
    Posts
    7,256
    Originally posted by NoteMe
    How many times did you try it? Did you try to switch the order of the two tests? Those who have most often got the result of the integer test using nearly twice the time of long.

    But Sastraxi posted a better way to time the test. I used his code (I hope he doesn't mind me using it) to developed a test for both variable types. Try this.
    All the times I've tested it, the differences were always in milliseconds, not nearly twice as long.
    My evil laugh has a squeak in it.

    kristopherwilson.com

  17. #17
    Retired G&G Mod NoteMe's Avatar
    Join Date
    Oct 2002
    Location
    @ Opera Software
    Posts
    10,190
    The Hobo: Did you try the new test. I think you would get a more precise test result using

  18. #18
    Stuck in the 80s The Hobo's Avatar
    Join Date
    Jul 2001
    Location
    Michigan
    Posts
    7,256
    Originally posted by NoteMe
    The Hobo: Did you try the new test. I think you would get a more precise test result using
    "The New Test?" I didn't know time comparisons came with updates...
    My evil laugh has a squeak in it.

    kristopherwilson.com

  19. #19
    Retired G&G Mod NoteMe's Avatar
    Join Date
    Oct 2002
    Location
    @ Opera Software
    Posts
    10,190
    I didn't know you where a comedian HOBO. But don't try to make any money on it. You wouldn't get rich. But seriously you should try the OTHER TEST.....

  20. #20
    Stuck in the 80s The Hobo's Avatar
    Join Date
    Jul 2001
    Location
    Michigan
    Posts
    7,256
    Originally posted by NoteMe
    I didn't know you where a comedian HOBO. But don't try to make any money on it. You wouldn't get rich. But seriously you should try the OTHER TEST.....
    Dude. Seriously. I don't know what you're talkinga bout? What's 'the other test?' In that matter, what do you refer to as the 'old test?'
    My evil laugh has a squeak in it.

    kristopherwilson.com

  21. #21
    Good Ol' Platypus Sastraxi's Avatar
    Join Date
    Jan 2000
    Location
    Ontario, Canada
    Posts
    5,134
    He posted a link to a thread, and then a few posts later made a post with an EXE. These were the two tests if I'm not mistaken... a simple miscommunication guys; NoteMe thought that you (Hobo) were talking about his first test in your post "all the times i've tested it....", and it all went downhill from there.
    All contents of the above post that aren't somebody elses are mine, not the property of some media corporation.
    (Just a heads-up)

  22. #22
    Stuck in the 80s The Hobo's Avatar
    Join Date
    Jul 2001
    Location
    Michigan
    Posts
    7,256
    Oh. I didn't even see his post or his attachment.

    NoteMe: I wasn't trying to be an ass our anything. In the first post, yes I was joking around, but I didn't mean for it to be offensive or anything. I was interested in seeing what you meant.
    My evil laugh has a squeak in it.

    kristopherwilson.com

  23. #23
    Lively Member
    Join Date
    Mar 2002
    Posts
    110
    long should be the faster datatype, according to MS, long is the 32 bit native datatype, so the compiler has less work to do, but if those tests say otherwise, i can't exactly argue.

  24. #24
    Good Ol' Platypus Sastraxi's Avatar
    Join Date
    Jan 2000
    Location
    Ontario, Canada
    Posts
    5,134
    It is true, and is even more noticable in the IDE (usually). On mine (my celeron has the worst fricken' FPU), they are very close. But it may have nothing to do with the FPU... it probably doesn't.... why am I posting th--

    I just went cross-eyed...
    All contents of the above post that aren't somebody elses are mine, not the property of some media corporation.
    (Just a heads-up)

  25. #25

    Thread Starter
    Hyperactive Member
    Join Date
    Jan 2002
    Location
    Palermo, Italy
    Posts
    325
    Ok guys... Just stop discussing on longs and integers... The best method of improving performance is to improve algorithms, and not changing longs to bytes or boolean or whatever... Sure data alignment is important for fast data transfer. But if I have to do an array of colors, if I use bytes or longs is the same thing. I can read up to 4 bytes at time and put them on a long (I don't think vb can do this, but C sure can). If I really want to speed up things without optimizing algorithms I MUST program in assemby... Or at least in C... But windows programming in C isn't easy, a LOT of costants and a LOT of API calls... You just enter into Windows specifics... And it is so hard to make a simple "hello world" application from scratch (and without the template ), think about making a game!!! VB is the most productive programming language, you can do everything (almost) in a short time...

    Sastraxi:

    Thanks for code... At first look I can understand nothing... Maybe I'll get more in feel with it looking, and looking, and overlooking at it

    Cyborg:
    Thanks for SetPixelV, but I want accurate colors

    Thx Xmas

  26. #26
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    xmas79:
    accurate colors?
    dont they get accurate with setpixelv?
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

  27. #27

    Thread Starter
    Hyperactive Member
    Join Date
    Jan 2002
    Location
    Palermo, Italy
    Posts
    325
    from MSDN:
    The SetPixelV function sets the pixel at the specified coordinates to the closest approximation of the specified color. SetPixelV is faster than SetPixel because it does not need to return the color value of the point actually painted.
    Maybe the approximation is not noticeable, I think it depends from the type of device you write to... About the speed, the difference with SetPixel is an assignment at the end of the "job"... In assembly means:
    Code:
    ' Assuming that the eax register is modified,
    'Maybe I can pop the color from the stack:
    ...
    Pop eax
    Ret
    
    'Or if the eax register is not modified at all, simply:
    ...
    Ret
    These are a one cycle clock instructions (from Pentium I to ....), so I don't think the speed gain is noticeable... Maybe anyone has tested it ???
    Tomorrow I'll do the test and post code (if anybody else do)...

    Good night,
    Xmas.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width