Results 1 to 6 of 6

Thread: [RESOLVED] LockBits has different effect?

  1. #1

    Thread Starter
    Stack Overflow mod​erator
    Join Date
    May 2008
    Location
    British Columbia, Canada
    Posts
    2,824

    Resolved [RESOLVED] LockBits has different effect?

    Hi, I've made an Aero-style form header (see signature) and I wanted to speed it up, so I used LockBits, and it had a different effect. These two methods should do the same thing, right? Well, it doesn't. Image 1 is before LockBits, Image 2 is after. Using LockBits gives a streaking effect that I don't like. What's happening?
    vb.net Code:
    1. Private Sub BlurImage(ByVal img As Bitmap, Optional ByVal radius As Integer = 3, Optional ByVal blur_bounds As Object = Nothing)
    2.         Dim bb As Rectangle
    3.         If blur_bounds IsNot Nothing Then
    4.             bb = CType(blur_bounds, Rectangle)
    5.         Else
    6.             bb = New Rectangle(0, 0, img.Width, img.Height)
    7.         End If
    8.         Dim i As Integer
    9.         For i = 0 To radius
    10.             Dim y, x As Integer
    11.             For y = bb.Y To bb.Bottom - 1
    12.                 For x = bb.X To bb.Right - 1
    13.                     Try
    14.                         Dim px_up As Color = img.GetPixel(x, y - 1)
    15.                         Dim px_down As Color = img.GetPixel(x, y + 1)
    16.                         Dim px_left As Color = img.GetPixel(x - 1, y)
    17.                         Dim px_right As Color = img.GetPixel(x + 1, y)
    18.                         Dim pxR As Integer = Average_Int(px_up.R, px_down.R, px_left.R, px_right.R)
    19.                         Dim pxG As Integer = Average_Int(px_up.G, px_down.G, px_left.G, px_right.G)
    20.                         Dim pxB As Integer = Average_Int(px_up.B, px_down.B, px_left.B, px_right.B)
    21.                         Dim n_px As Color = Color.FromArgb(255, pxR, pxG, pxB)
    22.                         img.SetPixel(x, y, n_px)
    23.                     Catch ex As Exception
    24.                     End Try
    25.                 Next
    26.             Next
    27.         Next
    28.     End Sub
    29.     Private Sub BlurImageLockBits(ByVal img As Bitmap, Optional ByVal radius As Integer = 3, Optional ByVal blur_bounds As Object = Nothing)
    30.         Dim bb As Rectangle
    31.         If blur_bounds IsNot Nothing Then
    32.             bb = CType(blur_bounds, Rectangle)
    33.         Else
    34.             bb = New Rectangle(0, 0, img.Width, img.Height)
    35.         End If
    36.         Dim bdata As Imaging.BitmapData = img.LockBits(bb, Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format32bppArgb)
    37.         Dim img_info(bdata.Width * bdata.Height) As Integer
    38.         System.Runtime.InteropServices.Marshal.Copy(bdata.Scan0, img_info, 0, img_info.Length)
    39.         Dim i As Integer
    40.         For i = 0 To radius
    41.             Dim y, x As Integer
    42.             For y = bb.Y To bb.Bottom - 1
    43.                 For x = bb.X To bb.Right - 1
    44.                     Try
    45.                         Dim px_up As Color = Color.FromArgb(img_info(((y - 1) * bdata.Width) + x))
    46.                         Dim px_down As Color = Color.FromArgb(img_info(((y + 1) * bdata.Width) + x))
    47.                         Dim px_left As Color = Color.FromArgb(img_info((y * bdata.Width) + x - 1))
    48.                         Dim px_right As Color = Color.FromArgb(img_info((y * bdata.Width) + x + 1))
    49.                         Dim pxR As Integer = Average_Int(px_up.R, px_down.R, px_left.R, px_right.R)
    50.                         Dim pxG As Integer = Average_Int(px_up.G, px_down.G, px_left.G, px_right.G)
    51.                         Dim pxB As Integer = Average_Int(px_up.B, px_down.B, px_left.B, px_right.B)
    52.                         Dim n_px As Color = Color.FromArgb(255, pxR, pxG, pxB)
    53.                         img_info((y * bdata.Width) + x) = n_px.ToArgb()
    54.                     Catch ex As Exception
    55.                     End Try
    56.                 Next
    57.             Next
    58.         Next
    59.         System.Runtime.InteropServices.Marshal.Copy(img_info, 0, bdata.Scan0, img_info.Length)
    60.         img.UnlockBits(bdata)
    61.     End Sub
    Attached Images Attached Images   

  2. #2
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: LockBits has different effect?

    hi minitech,
    You are not dealing with the edge pixels correctly. Since you are using a 1-D array, you are averaging the first pixel of each row with the last pixel of the previous row. Maybe that is causing the streaking. You will need to watch out for potential Index Out of Range errors, for example by skipping the edge pixels of the image. BB
    Last edited by boops boops; Jan 14th, 2010 at 01:15 AM.

  3. #3

    Thread Starter
    Stack Overflow mod​erator
    Join Date
    May 2008
    Location
    British Columbia, Canada
    Posts
    2,824

    Re: LockBits has different effect?

    But that's what I'm doing with the first code. They should be doing the same things, right? I'm averaging all four adjacent pixels in both code.

  4. #4
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: LockBits has different effect?

    Quote Originally Posted by minitech View Post
    But that's what I'm doing with the first code. They should be doing the same things, right? I'm averaging all four adjacent pixels in both code.
    It's not the same. GetPixel gets the pixel at position x,y. At the start of a line, at x=0, it tries to find the pixel at position x= - 1, which doesn't exist, and it throws an exception. But you do not see the exception because you are using Try-Catch with an empty Catch clause. You are getting away with it but it's like putting your head in the sand.

    In the LockBits method, the code is throwing similarly disguised "Index Out of Range" exceptions, but only on the first row (x=0, y=0) and the last row. Apart from that it interprets position x-1 as 1 place to the left in the array, which is the last pixel of the line above. And similarly for x+1 at the end of each line. The effect will hardly be noticeable on a single pass of the blur, but on many iterations the artefacts will propagate diagonally through the bitmap as you alternately process it rightwards and downwards. I think that is why you are getting the slanting streaks.

    It just occurred to me that there may be an easy way to deal with it. Suppose you trim your loops to skip the edge pixels like this:
    vb.net Code:
    1. For y = bb.Y + 1 To bb.Bottom - 2
    2.    For x = bb.X + 1 To bb.Right - 2
    I'm not promising you it will work but I have my fingers crossed.

    bye, BB
    Last edited by boops boops; Jan 14th, 2010 at 10:06 PM.

  5. #5

    Thread Starter
    Stack Overflow mod​erator
    Join Date
    May 2008
    Location
    British Columbia, Canada
    Posts
    2,824

    Re: LockBits has different effect?

    Ok, thanks, I'll try that. I have the Try-Catch in case someone puts in an invalid rectangle, but I don't want an exception to be thrown. Normally the blur boundaries are very small.

  6. #6

    Thread Starter
    Stack Overflow mod​erator
    Join Date
    May 2008
    Location
    British Columbia, Canada
    Posts
    2,824

    Re: LockBits has different effect?

    It works!! And it's much faster now. Thank you!


    P.S.
    (I would give you rep, but I haven't rated 6 other people yet, sorry. Hope you don't mind.)

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