【问题标题】:Generic error occured in GDI+ calling Image.SaveGDI+ 调用 Image.Save 时发生一般错误
【发布时间】: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。 ptrimg 也不必是全局的。

标签: c# winforms callback marshalling


【解决方案1】:

谢谢@Vasek。正如评论中所建议的,我必须创建一个本地缓冲区并将其传递给工作人员。

请在编辑后的问题中找到工作代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-02
    • 1970-01-01
    • 1970-01-01
    • 2010-12-12
    • 1970-01-01
    相关资源
    最近更新 更多