Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# ImageProcessing
    public unsafe Bitmap  MedianFilter(Bitmap Img)
    {
        int Size =2;
        List<byte> R = new List<byte>();
        List<byte> G = new List<byte>();
        List<byte> B = new List<byte>();
        int ApetureMin = -(Size / 2);
        int ApetureMax = (Size / 2);
        BitmapData imageData = Img.LockBits(new Rectangle(0, 0, Img.Width, Img.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
        byte* start = (byte*)imageData.Scan0.ToPointer ();
        for (int x = 0; x < imageData.Width; x++)
        {
            for (int y = 0; y < imageData.Height; y++)
            {
                for (int x1 = ApetureMin; x1 < ApetureMax; x1++)
                {
                    int valx = x + x1;
                    if (valx >= 0 && valx < imageData.Width)
                    {
                        for (int y1 = ApetureMin; y1 < ApetureMax; y1++)
                        {
                            int valy = y + y1;
                            if (valy >= 0 && valy < imageData.Height)
                            {
                                // error come from here
                                Color tempColor = Img.GetPixel(valx, valy);
 
                                R.Add(tempColor.R);
                                G.Add(tempColor.G);
                                B.Add(tempColor.B);
                            }
                        }
                    }
                }
            }
        }
        R.Sort();
        G.Sort();
        B.Sort();
        Img.UnlockBits(imageData);
        return Img;
    }
I tried to do this. but i got an error call "Bitmap region is already locked" can anyone help how to solve this. (error position is highlighted)
Posted 11-May-11 2:42am
Edited 11-May-11 3:02am
v3
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

If you're going to use the unsafe approach, don't use GetPixel. The whole point of the unsafe approach is to bypass the slow managed API. You should be using *scan++ (if you are reading whole rows from the rectangle you selected, which you seem to be).
 
As for the error, I guess Get/SetPixel lock the image internally (possibly a part of why they're so slow), and since you are (correctly) locking it yourself, that fails. But your problem is that you have a horrible mashing together of the safe, slow way and the unsafe, fast way.
  Permalink  
Comments
Olivier Levrey at 11-May-11 8:05am
   
You are completely right. Have my 5.
Isuru Ranasinghe at 11-May-11 8:43am
   
can you show me how to make this done.I'm new to image processing and this is median filtering. i got an code which provided by the codeproject but it is not unsafe method. :(
BobJanova at 11-May-11 10:33am
   
There are actually other serious problems with your code: you return Img without ever modifying it or doing anything with the R/G/B lists. I think you need to understand the algorithm you're trying to do better. I don't know what a median filter is myself so I can't help with that.
 
The link Oliver posted in his solution shows you how to do this the 'safe' way. You want something like
 

byte* start = (byte*)imageData.Scan0.ToPointer ();
for (int x = 0; x < imageData.Width; x++)
{
for (int y = 0; y < imageData.Height; y++)
{
for (int x1 = ApetureMin; x1 < ApetureMax; x1++)
{
int valx = x + x1;
if (valx >= 0 && valx < imageData.Width)
{
for (int y1 = ApetureMin; y1 < ApetureMax; y1++)
int valy = y + y1;
if (valy >= 0 && valy < imageData.Height)
{
byte a = *(start + valy * stride + valx);
byte r = *(1 + start + valy * stride + valx);
byte g = *(2 + start + valy * stride + valx);
byte b = *(3 + start + valy * stride + valx);

// OR: uint col = *(uint*)(start + valy * stride + valx)
// if you want to work with all 32 bits

R.add(r); G.add(g); B.add(b);
}
}

Color output = SomeCleverFunction(R, G, B);
byte* rp = *(1 + start + y * stride + x);
(*rp) = output.R;
// etc
}
}
}
 
disclaimer: not tested, I've not done this stuff for real. Always double check pointer related code off the internet before trying to use it!
SAKryukov at 11-May-11 13:56pm
   
Absolutely right, my 5.
 
Also, GetPixel/SetPixel is a real performance killer. Please see my answer.
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

BobJanova is right.
 
GetPixel and SetPixel call LockBits and UnlockBits internally. This is why these functions are so slow and shouldn't be used for image processing.
 
Follow this link to learn how to use LockBits and access internal data:
http://msdn.microsoft.com/en-us/library/5ey6h79d.aspx[^]
  Permalink  
v2
Comments
SAKryukov at 11-May-11 13:55pm
   
This is correct answer, my 5.
 
Also, GetPixel/SetPixel presents performance problem. Please see my answer.
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

Never use GetPixel/SetPixel unless you need just one or two (which is pretty rare) or ready to kill your performance. When you use LockBits, its more than enough to access individual pixels.
 
—SA
  Permalink  

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 515
1 Maciej Los 340
2 Richard MacCutchan 265
3 BillWoodruff 225
4 Mathew Soji 155
0 OriginalGriff 8,804
1 Sergey Alexandrovich Kryukov 7,457
2 DamithSL 5,689
3 Maciej Los 5,279
4 Manas Bhardwaj 4,986


Advertise | Privacy | Mobile
Web04 | 2.8.1411028.1 | Last Updated 11 May 2011
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100