I've been using the Bitmap-class and it's png-ByteStream to deal with images in my WPF-application, mostly with reading/writing files, getting images from native cam libs and showing them in the UI.
Lately I've got some new requirements and tried to upgrade some of that to deal with 64 bit deep images (or 48 bits, I don't need an alpha channel). In pretty much every operation bitmap is converting my image back to 32bppArgb. I've figured out deepcopying and am currently looking into Image.FromStream()
, but needing to deal with this got me wondering:
Is there a way to properly deal with non 32bppArgb-images within a C#-application (including true greyscale)? Or does microsoft just neglect the need for it? I've found some related questions, but mostly with 10 year old hacks, so I'd expect there to be a proper way by now...
Edit: As requested, I'm gonna show some code. It's running on .netStandard2.0 to be used mostly inside .net6.0 apps; with System.Drawing.Common on Version 5.0.2 (I don't think it matters but would be willing to upgrade if that's the case). Imagine nativeImage
to be a struct from some cameraLib, so we want a deepcopy to get away from the shared memory:
using Bitmap bitmap = new(nativeImage.Width, nativeImage.Height, nativeImage.stride, PixelFormat.Format64bppArgb, nativeImage.DataPtr);
using Bitmap copy = bitmap.DeepCopy(); //custom function
using MemoryStream stream = new();
copy.Save(stream, ImageFormat.Png);
byte[] byteStream = stream.ToArray(); //Saving this to file shows it's really 64 bit
//These bits are stitched together for testing, normally this byte-Array might get passed around quite a bit
using MemoryStream ms = new(byteStream);
using Image image = Image.FromStream(ms, true); //this suddenly is 32bppArgb
with:
public static Bitmap DeepCopy(this Image original)
{
// this just copies the code of the Bitmap(Image)-constructor but uses the original pixelFromat instead of 32bppArgb
var result = new Bitmap(original.Width, original.Height, original.PixelFormat);
using (Graphics g = Graphics.FromImage(result))
{
g.Clear(Color.Transparent);
g.DrawImage(original, 0, 0, original.Width, original.Height);
}
return result;
}