Good morning,

I'm coding a game which ovject is to capture the feed of a webcam, then apply some filters to detect movement, so far i've managed to get the webcam to work but when i apply the filters it says "Bitmap locked" i've managed to solve that error, right after that said something about PixelFormat overlay must be valid, or something like that, anyways i fixed that one also, but now i'm stuck on this error "System out of memory exception", i clearly have enough memory for my game.

The error appears on:

image = eventArgs.Frame.Clone(Rec, PixelFormat.Format8bppIndexed);

But when i used the breakpoint thing it says the eroor comes from:

 for (int i = 0; i < imgData.Length; i++)
                {
                    byteData[i] = (byteData[i] & 0x000000ff) << 16 | (byteData[i] & 0x0000FF00) | (byteData[i] & 0x00FF0000) >> 16 | (byteData[i] & 0xFF000000);
                }

Below are 2 of the methods:

private Texture2D GetTexture(GraphicsDevice dev, System.Drawing.Bitmap bmp)
        {
            int[] imgData = new int[bmp.Width * bmp.Height];
            Texture2D texture = new Texture2D(dev, bmp.Width, bmp.Height);
            unsafe
            {
                // lock bitmap 
                System.Drawing.Imaging.BitmapData origdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
                uint* byteData = (uint*)origdata.Scan0;
                // Switch bgra -> rgba
                for (int i = 0; i < imgData.Length; i++)
                {
                    byteData[i] = (byteData[i] & 0x000000ff) << 16 | (byteData[i] & 0x0000FF00) | (byteData[i] & 0x00FF0000) >> 16 | (byteData[i] & 0xFF000000);
                }
                // copy data 
                System.Runtime.InteropServices.Marshal.Copy(origdata.Scan0, imgData, 0, bmp.Width * bmp.Height);
                byteData = null;
                // unlock bitmap
                bmp.UnlockBits(origdata);
            }
            texture.SetData(imgData);
            return texture;
        } 




private void device_NewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs)
        {
            image = eventArgs.Frame.Clone(Rec, PixelFormat.Format8bppIndexed);

            MoveTowards moveTowardsFilter = new MoveTowards();
            Difference differenceFilter = new Difference();
            IFilter thresholdFilter = new Threshold(15);
            if (backgroundFrame == null)
            {
                backgroundFrame = processingFilter1.Apply(image);
                width = image.Width;
                height = image.Height;
                return;
            }
            processingFilter1.Add(new Difference(backgroundFrame));
            processingFilter1.Add(new Threshold(15));
            processingFilter1.Add(new Opening());
            processingFilter1.Add(new Edges());

            tmpImage = processingFilter1.Apply(image);

            if (++counter == 2)
            {
                counter = 0;
                moveTowardsFilter.OverlayImage = tmpImage;
                moveTowardsFilter.ApplyInPlace(backgroundFrame);
            }

            differenceFilter.OverlayImage = backgroundFrame;

            bitmapData = tmpImage.LockBits(new System.Drawing.Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);

            differenceFilter.ApplyInPlace(bitmapData);
            thresholdFilter.Apply(bitmapData);

            blobCounter.ProcessImage(bitmapData);
            System.Drawing.Rectangle[] rects = blobCounter.GetObjectsRectangles();
            Graphics g = Graphics.FromImage(image);
            using (Pen pen = new Pen(System.Drawing.Color.Red, 1))
            {
                foreach (System.Drawing.Rectangle rc in rects)
                {
                    g.DrawRectangle(pen, rc);

                    if ((rc.Width > 15) && (rc.Height > 15))
                    {
                        //Para os retângulos maiores
                    }
                }
            }
            g.Dispose();

        }

Recommended Answers

All 9 Replies

Hmm, before the line '8', try to add something like this:

Console.WriteLine("Bitmap format: " + bitmap.PixelFormat);

... and see what it tells you. Then, you should probably use the same pixel format on the error line.

Also, on the side note, I don't think it's necessary to swap the RGBA order if you can use correct pixel formats. I had some closely-related problems yesterday, and I just swapped the pixelformats I used and it solved the problem. :) Also, to find out if it's the colors swap loop or not that causes the problem, try to comment it out. It should work nonetheless, of course the color channels might be on wrong places, but at least you can get some hint. :)

It says it's "Format8bpp" but it changes to "Format32ARGB" for like half a second and changes back to "Format8bpp".
And now i get a new error "Attempt to write or read on protected memory. This is normally an indication that it exists another damaged memory".

byteData[i] = (byteData[i] & 0x000000ff) << 16 | (byteData[i] & 0x0000FF00) | (byteData[i] & 0x00FF0000) >> 16 | (byteData[i] & 0xFF000000);

Console.WriteLine("Bitmap format: " + bitmap.PixelFormat);

The error is most likely caused by the wrong pixel format. If it's 8pp format, then the argb conversion will fail since it expects the data to be 32bpp. What happens if you comment out the argb conversion?

commented: Solved one fo the errors. +0

The same error appears on the next line:

System.Runtime.InteropServices.Marshal.Copy(origdata.Scan0, imgData, 0, bmp.Width * bmp.Height);

And i have tried to apply the 32 pixel format but it says the source and overlay images need to be the same format but at least the first frame of the webcam feed appears then the error comes.

EDIT:
If i use breakpoints, it says the bitmap region is blocked on this line:

tmpImage = processingFilter1.Apply(tmpImage);

Hmm, just noticed, you don't use the "byteData" variable for anything. Should you make the marshal copy from that instead?

EDIT: Ah, you're using pointers, never mind. :D
This is quite an interesting case. Many possible things come to mind, but can't surely say anything definite. Maybe using unsigned bytes instead of uints would help..?

Can you explain a little better please? :)
Thanks. Marshal copy of what?
EDIT: How can i can i use Ubytes ? How's the variable called?

I think it's just 'byte', as it's from 0 to 255 and the size is the same as unsigned integer.

Note that this is all just from top of my head, but it could work like this:
byte origData = (byte)bd.Scan0;

byte origData = (byte)bd.Scan0;

By using that, do i have to remove some code lines, like the one that says System...Bitmap origData = ..."? or not quite?

Because if i switch this line

uint* byteData = (uint*)origdata.Scan0;

To:

byte* byteData = (byte*)origdata.Scan0;

Error "Cannot implicitly convert type 'long' to 'byte'. An explicit conversion exists (are you missing a cast?)
" appears on line:

byteData[i] = (byteData[i] & 0x000000ff) << 16 | (byteData[i] & 0x0000FF00) | (byteData[i] & 0x00FF0000) >> 16 | (byteData[i] & 0xFF000000);

Ok so i've ound a way to solve this problem, by commenting/removing the 2nd lockbits and unlockbits:

private Texture2D GetTexture(GraphicsDevice dev, System.Drawing.Bitmap bmp)
        {
            int[] imgData = new int[bmp.Width * bmp.Height];
            Texture2D texture = new Texture2D(dev, bmp.Width, bmp.Height);
            unsafe
            {
                // Bloqueia bitmap
                //try
                //{
                //    origdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
                //}
                //finally
                //{
                //    bmp.UnlockBits(origdata);
                //}

                uint* byteData = (uint*)bitmapData.Scan0;
                // troca bgra -> rgba
                for (int i = 0; i < imgData.Length; i++)
                {
                        byteData[i] = (byteData[i] & 0x000000ff) << 16 | (byteData[i] & 0x0000FF00) | (byteData[i] & 0x00FF0000) >> 16 | (byteData[i] & 0xFF000000);
                }
                // copia dados
                System.Runtime.InteropServices.Marshal.Copy(bitmapData.Scan0, imgData, 0, bmp.Width * bmp.Height);
                byteData = null;
                // desbloqueia bitmap
                //try
                //{
                //    bmp.UnlockBits(origdata);
                //}
                //catch
                //{
                //}
            }
            texture.SetData(imgData);
            return texture;
        } 

But now, how can i create a new reference out of uint* byteData(that's the current error now) since you cant create object references from uints.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.