3
votes

I have opened an image in my app and getting the pixels data of image using the following piece of code.

  using (IRandomAccessStream fileStreams = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
            {
                BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStreams);
                BitmapTransform transform = new BitmapTransform()
                {
                    ScaledWidth = Convert.ToUInt32(bitmapImage.PixelWidth),
                    ScaledHeight = Convert.ToUInt32(bitmapImage.PixelHeight)
                };
                PixelDataProvider pixelData = await decoder.GetPixelDataAsync(
                    BitmapPixelFormat.Bgra8,
                    BitmapAlphaMode.Straight,
                    transform,
                    ExifOrientationMode.IgnoreExifOrientation,
                    ColorManagementMode.DoNotColorManage
               );

                byte[] sourcePixels = pixelData.DetachPixelData();                
            }

Here I have got an array of all the pixels of the image. The total number of pixels in this array are (width * height * 4). After analyzing this array I came to know that index numbers 0, 1, 2 and 3 contains the red, green blue and alpha values of the first pixel, index numbers 4, 5, 6 and 7 contains the red, green, blue and alpha values of second pixel of the image and so on.

Now I want to apply my 3x3 filter to this image, how can I do it with this 1-D array? I know how to do it if I have 2-D array of the image.

Right now, I have one idea in my mind.

  1. Store red pixels in one 2D array, green in other and so on
  2. Apply filter on each 2d array.
  3. Combine all of these to make a 1-D array again and return the result.

Is it a good solution? Help me if there is a better solution to do it.

1

1 Answers

3
votes

If you want to mask the Bitmapimage in the UWP you need to use a software bitmap for raw pixel data of the image. First, you need to separate image and mask data and convert it to a byte array with the format of BGRA. Then after that, you need to access the location using the unsafe code to achieve this.

Create an interface.

[ComImport] [Guid("5B0D3235-4DBA-4D44-865E-8F1D0E4FD04D")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] unsafe interface IMemoryBufferByteAccess { void GetBuffer(out byte* buffer, out uint capacity); }

Change /Edit software bitmap pixels using the following snippet.

create software bitmap .

softwareBitmap = new SoftwareBitmap(BitmapPixelFormat.Bgra8, 100, 100, BitmapAlphaMode.Premultiplied);

using (BitmapBuffer buffer = softwareBitmap.LockBuffer(BitmapBufferAccessMode.Write))
{
    using (var reference = buffer.CreateReference())
    {
        byte* dataInBytes;
        uint capacity;
        ((IMemoryBufferByteAccess)reference).GetBuffer(out dataInBytes, out capacity);

        // Fill-in the BGRA plane
        BitmapPlaneDescription bufferLayout = buffer.GetPlaneDescription(0);
        for (int i = 0; i < bufferLayout.Height; i++)
        {
            for (int j = 0; j < bufferLayout.Width; j++)
            {

                byte value = (byte)((float)j / bufferLayout.Width * 255);
                dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 0] = value;
                dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 1] = value;
                dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 2] = value;
                dataInBytes[bufferLayout.StartIndex + bufferLayout.Stride * i + 4 * j + 3] = (byte)255;
            }
        }
    }
}