0

I am trying to save jpeg image from buffer array of RGBA.
I tried this code

byte[] buffer = new byte[m_FrameProps.ImgSize];
Marshal.Copy(m_BM.BackBuffer, buffer, 0, m_FrameProps.ImgSize); //m_BM is WriteableBitmap
using (MemoryStream imgStream = new MemoryStream(buffer))
{
    using (System.Drawing.Image image = System.Drawing.Image.FromStream(imgStream))
    {
        image.Save(m_WorkingDir + "1", ImageFormat.Jpeg); 
    }
} 

But I am getting run-time error: "An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll

Additional information: Parameter is not valid."

I tried also to create bitmap and then to use JpegBitmapEncoder

Bitmap bitmap;
using (var ms = new MemoryStream(buffer))
{
    bitmap = new Bitmap(ms);
} 

But I am getting the same error.
I guess it is because the alpha.
How should I do it? Do I need to loop the values and copy without alpha?

Ditza
  • 129
  • 1
  • 10
  • What's the actual image format of the array? Are they just 32-bit pixel data (8 bit per channel), or something else? – CodeCaster Sep 03 '18 at 08:19
  • 1
    https://stackoverflow.com/questions/38989837/convert-rgb-array-to-image-in-c-sharp, https://stackoverflow.com/questions/21555394/how-to-create-bitmap-from-byte-array, https://stackoverflow.com/questions/21428272/show-rgba-image-from-memory, and so on. – CodeCaster Sep 03 '18 at 08:20
  • Do you have a more complete code sample you could post? – AdaRaider Sep 03 '18 at 08:26
  • It's part of long process, And I just took the relevant rows. The image format is 32 bit pixel data – Ditza Sep 03 '18 at 08:29
  • Ok sure, but as you said the essence of what you're trying to do is just to take a byte array and use it to create a jpeg, that code is fairly straight forward to isolate. The problem with your code sample is that it's a bit limited, I can't see your inputs which makes it difficult – AdaRaider Sep 03 '18 at 08:32
  • Ok so a flat array of uint 32 is basically what you are using as your input – AdaRaider Sep 03 '18 at 08:33

1 Answers1

1

It is not possible to construct an image from an array of pixel data alone. At minimum pixel format information and image dimensions would also be required. This means any attempt to create a Bitmap directly from an ARGB array using streams will fail, the Image.FromStream() and Bitmap() methods both require that the stream contain some kind of header information to construct an image.

That said, given that you appear to know the dimensions and pixel format of the image you wish to save you can use the following method:

public void SaveAsJpeg(int width, int height, byte[] argbData, int sourceStride, string path)
{
    using (Bitmap img = new Bitmap(width, height, PixelFormat.Format32bppPArgb))
    {
        BitmapData data = img.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, img.PixelFormat);
        for (int y = 0; y < height; y++)
        {
            Marshal.Copy(argbData, sourceStride * y, data.Scan0 + data.Stride * y, width * 4);
        }
        img.UnlockBits(data);
        img.Save(path, ImageFormat.Jpeg);
    }
}
Khan Maxfield
  • 379
  • 1
  • 10