1

I have a video stream from a camera to an Image in a WPF. I am trying to access the WritableBitMap Image pixel by pixel before displaying it. As a test I am trying to set the whole image to white or black. In both cases however, I get the AccessViolationException error.

I checked other posts and it seems that this error is very wide and not specific to my case. I can't seem to know why I am not getting this working.

So what is the best way to play with the pixels in my case? or why this is not working? Any help is appreciated

     private async void UpdateMasterCameraPreview(IdsFrame frame)
    {
        if (masterImage != null)
            frame.Image.CopyTo(masterImage);
        else
            masterImage = frame.Image.ToWriteableBitmap();

        //BitmapImage temp = ConvertWriteableBitmapToBitmapImage(masterImage);
        WriteableBitmap temp = masterImage;

        // Here I get the exception, on every pixel access
        for (int y = 0; y < temp.PixelHeight; y++)
            for (int x = 0; x < temp.PixelWidth; x++)
                temp.SetPixel(x, y, 255);

        masterImage = temp;

        masterImage.Lock();
        masterImage.AddDirtyRect(new Int32Rect(0, 0, masterImage.PixelWidth, masterImage.PixelHeight));
        masterImage.Unlock();

        if (OnMasterFrameCaptured != null)
            OnMasterFrameCaptured(this, new CameraFrameCapturedArgs(CameraType.Master, masterImage));
    }
Radai
  • 230
  • 3
  • 8
Khalil Khalaf
  • 9,259
  • 11
  • 62
  • 104

2 Answers2

1

You have swapped X and Y, i represents height, j represents width, then you shouldcall SetPixel like:

temp.SetPixel(j, i, 255);

On cases like this is better to use meaningful names for variables, like X and Y.

Gusman
  • 14,905
  • 2
  • 34
  • 50
  • You are right, I just saw the function prototype too. I swapped them but however, I am still getting the same error, AcessViolationException – Khalil Khalaf Mar 01 '16 at 16:13
  • SetPixel is not part of WriteableBitmap, so you have an extension or component, post the function's code. – Gusman Mar 01 '16 at 16:17
  • But we both just used it. How come it's not part of WritableBitmap? – Khalil Khalaf Mar 01 '16 at 16:19
  • I have an extension like that, and WriteableBitmapEx also implemented it. Look at MSDN: https://msdn.microsoft.com/en-us/library/system.windows.media.imaging.writeablebitmap%28v=vs.110%29.aspx – Gusman Mar 01 '16 at 16:20
  • I see. Thanks. I just added the whole thing, maybe you can help? – Khalil Khalaf Mar 01 '16 at 16:31
  • Still missing where SetPixel comes from... and the problem should be there. – Gusman Mar 01 '16 at 16:34
  • It comes from the System.Windows.Media.Imaging.WriteableBitmapExtensions, and basically I just saw it in intellisense suggestions when typing '.' after the WritableBitMap instance.. couldn't find its body though – Khalil Khalaf Mar 01 '16 at 16:58
  • Maybe you added the WriteableBitmapEx component? I think it comes from there, then, if that's the case I would ask on the component support forum/contact form on your case. – Gusman Mar 01 '16 at 17:00
  • well I am working on someone else's code and yeah I just noticed. Thanks I will do that – Khalil Khalaf Mar 01 '16 at 17:35
0

I ended up using the answer of this post. I now can edit raw pixel data of any WriteableBitmap image before sending it to image control in WPF. Below is what I exactly used but here I just convert every frame to some transparency under a condition:

        public void ConvertImage(ref WriteableBitmap Wbmp)
    {
        int width = Wbmp.PixelWidth;
        int height = Wbmp.PixelHeight;
        int stride = Wbmp.BackBufferStride;
        int bytesPerPixel = (Wbmp.Format.BitsPerPixel + 7) / 8;

        unsafe
        {
            byte* pImgData = (byte*)Wbmp.BackBuffer;

            // set alpha to transparent for any pixel with red < 0x88 and invert others
            int cRowStart = 0;
            int cColStart = 0;
            for (int row = 0; row < height; row++)
            {
                cColStart = cRowStart;
                for (int col = 0; col < width; col++)
                {
                    byte* bPixel = pImgData + cColStart;
                    UInt32* iPixel = (UInt32*)bPixel;

                    if (bPixel[2 /* bgRa */] < 0x44)
                    {
                        // set to 50% transparent
                        bPixel[3 /* bgrA */] = 0x7f;
                    }
                    else
                    {
                        // invert but maintain alpha
                        *iPixel = *iPixel ^ 0x00ffffff;
                    }

                    cColStart += bytesPerPixel;
                }
                cRowStart += stride;
            }
        }
    }

And the routine of using it is like this:

        masterImage.Lock();
        ConvertImage(ref masterImage);
        masterImage.AddDirtyRect(new Int32Rect(0, 0, masterImage.PixelWidth, masterImage.PixelHeight));
        masterImage.Unlock();
Community
  • 1
  • 1
Khalil Khalaf
  • 9,259
  • 11
  • 62
  • 104