【发布时间】:2017-07-20 05:42:43
【问题描述】:
图像实际上是从我的本机 DLL 抽取的字节数组(作为字节 *)。
我正在将其转换成如下图片。
Img = new Bitmap(g_Width, g_Height, g_Width * 3, PixelFormat.Format24bppRgb, ptr);
注意:“图像”在全局范围内。 “ptr”是一个 IntPtr(本地范围)。
我正在尝试从 BackgroundWorker 方法中保存此图像。当我这样做时,我得到“GDI+ 中发生一般错误”异常。
我错过了什么?
编辑:
我正在尝试保存图像
Img.Save("test.bmp", ImageFormat.Bmp);
此外,我已尝试在创建图像后立即保存图像。文件保存成功。我也可以显示。但我无法从工人那里存钱。
编辑 2: 全局:
BackgroundWorker Worker;
Image img = null;
回调如下,
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);
}
}
修改后的代码:
全局:
BackgroundWorker Worker;
Image img = null;
Byte[] g_Buffer;
Intptr ptr;
回调如下,
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);
}
}
编辑 4:工作代码
请找出修改后的代码,
在回调中,
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();
还有工人,
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);
}
}
【问题讨论】:
-
我们缺少保存命令,包括路径。另外:图像是否“有效”,即您可以将其显示在例如 PictureBox 中吗?
-
@sam 请提供完整的代码,包括工人和图像检索。
-
@sam
GrabFrame是来自非托管环境的回调吗?如果是这样,很明显您的异步工作者无法保存数据,因为它们可能已经发布。您需要将GrabFrame中的数据复制到例如托管byte[],然后保存在worker中。 -
@vasek 我已根据您的评论修改了代码。尽管如此,问题仍然存在。请在问题中找到修改后的代码。
-
@sam 不要让你的
g_Buffer全局化,在GrabFrame本地创建它,然后将它作为参数传递给你的worker。ptr和img也不必是全局的。
标签: c# winforms callback marshalling