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;
}


How to deal with 48 or 64bit images in C#
I do not think you will have much success with System.Drawing.Bitmap. In my experience these just have poor support high bit depths. I would instead take a look at the corresponding System.Windows.Media classes. I know PngBitmapEncoder/decoder at least support 16 bit grayscale, but I suspect 48/64 bit works fine as well.
For display I would expect that you would want to do your own tone mapping, since I have never seen any builtin method do a particular good job.
If you want a format for interchange I would suggest creating your own. Any image is essentially represented using just a few properties:

Width
Height
Stride - The number of bytes on a row. This must be at least large enough to fit a row of pixels, but may be larger for alignment reasons.
PixelFormat
Pixel Data - This can essentially anything representing binary data. Byte[], a pointer, a stream, Memory<T> etc. The total size of the data should be Height * Stride.

Most image processing libraries should have methods accepting raw image data. You might need to jump thru some hoops to get it to work, like using unsafe code or doing a blockCopy. You also likely need some mapping code to convert between all the various PixelFormat enums.
Libraries typically provide Bitmap access for convenience, but convert this data to some internal format as soon as possible. You should be able to do the same.
