The image is actually a byte array pumped from my native DLL (as Byte *).
I am converting it into an image as follows.
Img = new Bitmap(g_Width, g_Height, g_Width * 3, PixelFormat.Format24bppRgb, ptr);
Note: The "Image" is in the global scope. "ptr" is an IntPtr(local scope).
I am trying to save this image from the BackgroundWorker method. When I do so, I get "A generic error occurred in GDI+" exception.
What is the I am missing?
Edit:
I am trying to save the image like
Img.Save("test.bmp", ImageFormat.Bmp);
Also, I have tried to save the image as soon as I create the image. The file is saved successfully. I am able to display as well. But I am not able to save in from the worker.
Edit 2: Globals:
BackgroundWorker Worker;
Image img = null;
The callback is as follows,
private unsafe void GrabFrame(Byte* InputBuff, ref Int32 lBufferLen)
{
Img = new Bitmap(g_Width, g_Height, g_Width * 3,
PixelFormat.Format24bppRgb, (IntPtr)InputBuff);
//Img.Save("test.bmp", ImageFormat.Bmp); // This works fine.
Worker = new BackgroundWorker();
Worker.DoWork += new DoWorkEventHandler(Worker_DoWork);
Worker.RunWorkerAsync();
}
void Worker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
Img.Save("test.bmp", ImageFormat.Bmp); //This is were i get the exception
}
catch (Exception ex)
{
Trace.WriteLine("Exception at Worker_DoWork: " + ex.Message);
}
}
Modified code:
Globals:
BackgroundWorker Worker;
Image img = null;
Byte[] g_Buffer;
Intptr ptr;
The callback is as follows,
private unsafe void GrabFrame(Byte* InputBuff, ref Int32 lBufferLen)
{
Img = new Bitmap(g_Width, g_Height, g_Width * 3,
PixelFormat.Format24bppRgb, (IntPtr)InputBuff);
g_Buffer = new byte[lBufferLen];
Marshal.Copy((IntPtr)InputBuff, g_Buffer, 0, lBufferLen);
//Img.Save("test.bmp", ImageFormat.Bmp); // This works fine.
Worker = new BackgroundWorker();
Worker.DoWork += new DoWorkEventHandler(Worker_DoWork);
Worker.RunWorkerAsync();
}
void Worker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
ptr = Marshal.AllocHGlobal(g_Buffer.Length);
Marshal.Copy(g_Buffer, 0, ptr, g_Buffer.Length);
Img = new Bitmap(g_Width, g_Height, g_Width * 3, PixelFormat.Format24bppRgb, ptr);
Img.Save("test.bmp", ImageFormat.Bmp); //still issue persists
// Call unmanaged code
Marshal.FreeHGlobal(ptr);
}
catch (Exception ex)
{
Trace.WriteLine("Exception at Worker_DoWork: " + ex.Message);
}
}
Edit 4: Working Code
Please find the modified code.,
In call back,
Byte[] Buffer = new Byte[lBufferLen];
Marshal.Copy((IntPtr)InputBuff, Buffer, 0, lBufferLen);
Worker = new BackgroundWorker();
Worker.DoWork += (obj, e) => Worker_DoWork(obj, e, Buffer);
Worker.RunWorkerAsync();
And the worker,
void Worker_DoWork(object sender, DoWorkEventArgs e, Byte[] Buffer)
{
try
{
Image Img = null;
IntPtr ptr = Marshal.AllocHGlobal(Buffer.Length);
Marshal.Copy(Buffer, 0, ptr, Buffer.Length);
if (ptr != IntPtr.Zero)
{
Img = new Bitmap(g_Width, g_Height, g_Width * 3, PixelFormat.Format24bppRgb, ptr);
}
Img.Save("test.bmp", ImageFormat.Bmp);
Marshal.FreeHGlobal(ptr);
}
catch (Exception ex)
{
Trace.WriteLine("Exception at Worker_DoWork: " + ex.Message);
}
}
Thank you @Vasek. As suggested in the comment, I had to create a local buffer and pass it to the worker.
Please find the working code in the edited question.