|
-
Jan 13th, 2010, 10:55 PM
#1
Thread Starter
Stack Overflow moderator
[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:
Private Sub BlurImage(ByVal img As Bitmap, Optional ByVal radius As Integer = 3, Optional ByVal blur_bounds As Object = Nothing)
Dim bb As Rectangle
If blur_bounds IsNot Nothing Then
bb = CType(blur_bounds, Rectangle)
Else
bb = New Rectangle(0, 0, img.Width, img.Height)
End If
Dim i As Integer
For i = 0 To radius
Dim y, x As Integer
For y = bb.Y To bb.Bottom - 1
For x = bb.X To bb.Right - 1
Try
Dim px_up As Color = img.GetPixel(x, y - 1)
Dim px_down As Color = img.GetPixel(x, y + 1)
Dim px_left As Color = img.GetPixel(x - 1, y)
Dim px_right As Color = img.GetPixel(x + 1, y)
Dim pxR As Integer = Average_Int(px_up.R, px_down.R, px_left.R, px_right.R)
Dim pxG As Integer = Average_Int(px_up.G, px_down.G, px_left.G, px_right.G)
Dim pxB As Integer = Average_Int(px_up.B, px_down.B, px_left.B, px_right.B)
Dim n_px As Color = Color.FromArgb(255, pxR, pxG, pxB)
img.SetPixel(x, y, n_px)
Catch ex As Exception
End Try
Next
Next
Next
End Sub
Private Sub BlurImageLockBits(ByVal img As Bitmap, Optional ByVal radius As Integer = 3, Optional ByVal blur_bounds As Object = Nothing)
Dim bb As Rectangle
If blur_bounds IsNot Nothing Then
bb = CType(blur_bounds, Rectangle)
Else
bb = New Rectangle(0, 0, img.Width, img.Height)
End If
Dim bdata As Imaging.BitmapData = img.LockBits(bb, Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format32bppArgb)
Dim img_info(bdata.Width * bdata.Height) As Integer
System.Runtime.InteropServices.Marshal.Copy(bdata.Scan0, img_info, 0, img_info.Length)
Dim i As Integer
For i = 0 To radius
Dim y, x As Integer
For y = bb.Y To bb.Bottom - 1
For x = bb.X To bb.Right - 1
Try
Dim px_up As Color = Color.FromArgb(img_info(((y - 1) * bdata.Width) + x))
Dim px_down As Color = Color.FromArgb(img_info(((y + 1) * bdata.Width) + x))
Dim px_left As Color = Color.FromArgb(img_info((y * bdata.Width) + x - 1))
Dim px_right As Color = Color.FromArgb(img_info((y * bdata.Width) + x + 1))
Dim pxR As Integer = Average_Int(px_up.R, px_down.R, px_left.R, px_right.R)
Dim pxG As Integer = Average_Int(px_up.G, px_down.G, px_left.G, px_right.G)
Dim pxB As Integer = Average_Int(px_up.B, px_down.B, px_left.B, px_right.B)
Dim n_px As Color = Color.FromArgb(255, pxR, pxG, pxB)
img_info((y * bdata.Width) + x) = n_px.ToArgb()
Catch ex As Exception
End Try
Next
Next
Next
System.Runtime.InteropServices.Marshal.Copy(img_info, 0, bdata.Scan0, img_info.Length)
img.UnlockBits(bdata)
End Sub
-
Jan 14th, 2010, 12:59 AM
#2
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.
-
Jan 14th, 2010, 06:10 PM
#3
Thread Starter
Stack Overflow moderator
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.
-
Jan 14th, 2010, 09:11 PM
#4
Re: LockBits has different effect?
 Originally Posted by minitech
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:
For y = bb.Y + 1 To bb.Bottom - 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.
-
Jan 15th, 2010, 06:30 PM
#5
Thread Starter
Stack Overflow moderator
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.
-
Jan 15th, 2010, 06:48 PM
#6
Thread Starter
Stack Overflow moderator
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|