I'm working with WriteableBitmap (PixelFormats.Bgr32). This is the format I need to save for the rest of the program to work.
Writable = new WriteableBitmap(inImage.XSize, inImage.YSize, dpi, dpi, PixelFormats.Bgr32, null);
The image from the device comes in grayscaled, (ushort[] Gray16). To use this image in my program I use the following code (inImage - received image, ImageData = ushort[]):
int[] pixels = Array.ConvertAll(inImage.ImageData, val => checked((int)val));
Writable.WritePixels(new Int32Rect(0, 0, width, height), pixels, width * 4, 0);
If I just use
Writable.WritePixels(new Int32Rect(0, 0, width, height), inImage.ImageData, width * 4, 0);
I get a message about insufficient buffer size. (System.ArgumentException: "Buffer size is not sufficient." )
Code
int[] pixels = Array.ConvertAll(inImage.ImageData, val => checked((int)val))
or
int[] pixels = new int[inImage.XSize * inImage.YSize];
for (int i = 0; i < inImage.ImageData.Length; i++)
{
pixels[i] = inImage.ImageData[i];
}
This seems to me to be a very long and slow and unoptimized process.
Is there any way to optimize the process and immediately write ushort[] array to WriteableBitmap (Bgr32) without converting it to int[] ?
EDIT***
I need this code to be able to work with images with a resolution of 4300x4300 with 45 FPS. Below is the full code how I load images (this code is called 45 times per second to load a new image)
public class ImageStruct
{
public ushort[] ImageData;
public int XSize;
public int YSize;
public int XDpi;
public int YDpi;
}
WriteableBitmap Writeable;
public void LoadFrame(ImageStruct inImage)
{
var width = inImage.XSize;
var height = inImage.YSize;
var destBpp = PixelFormats.Bgr32.BitsPerPixel / 8;
var uPixels = inImage.ImageData;
fluoroWritable = new WriteableBitmap(inImage.XSize, inImage.YSize, 96, 96, PixelFormats.Bgr32, null);
var iPixels = Array.ConvertAll(uPixels, val => checked((int)val));
fluoroWritable.WritePixels(new Int32Rect(0, 0, width, height), iPixels, width * 4, 0);
}
This code works well when FPS is ~10, If you increase the FPS, it starts to freeze. Profiling shows that it is the moment when I make from ushort[] => int[] takes the longest time.
I tried to use the code suggested in the answer below:
unsafe public void LoadFrameWithLock(ImageStruct inImage)
{
var width = inImage.XSize;
var height = inImage.YSize;
var destBpp = PixelFormats.Bgr32.BitsPerPixel / 8;
var uPixels = inImage.ImageData;
fluoroWritable = new WriteableBitmap(inImage.XSize, inImage.YSize, 96, 96, PixelFormats.Bgr32, null);
fluoroWritable.Lock();
int* outputIntValues = (int*)fluoroWritable.BackBuffer;
ushort[] inputShortValues = inImage.ImageData;
for (int i = 0; i < inputShortValues.Length; i++)
{
byte as8bpp = (byte)(inputShortValues[i] >> 8);
outputIntValues[i] = /*B*/ as8bpp | /*G*/ (as8bpp << 8) | /*R*/ (as8bpp << 16);
}
fluoroWritable.AddDirtyRect(new Int32Rect(0, 0, fluoroWritable.PixelWidth, fluoroWritable.PixelHeight));
fluoroWritable.Unlock();
}
But the FPS with this code is even lower and in addition the WPF application has a completely hanging interface. and images have no grayscale, but are completely black and white (white or black pixels).
I need the BGR32 format because this WritableBitmap (WPF Image object) is then overlaid with shader effects, and I can also get color images in another place.