Image.Save异常“GDI +中发生了一般错误。”保存到MemoryStream时

时间:2012-05-14 02:47:05

标签: c# image gdi+

我有一个服务器 - 客户端应用程序,我想从服务器获取一个屏幕截图,但是在行上bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);我得到了这个例外:A generic error occurred in GDI+.

    private Socket ScreenSocket;
    private MemoryStream ms;
    public void ConnectScreenShot(IPEndPoint ep)
    {
        if (ScreenSocket != null)
        {
            ScreenSocket.Dispose();
            ScreenSocket = null;
        }
        if (ms != null)
        {
            ms.Dispose();
            ms = null;
        }
        ScreenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        ScreenSocket.Connect(ep);
        ms = new MemoryStream();
        Rectangle bounds = Screen.GetBounds(Point.Empty);
        using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height))
        {
            using (Graphics g = Graphics.FromImage(bitmap))
            {
                g.CopyFromScreen(Point.Empty, Point.Empty, bitmap.Size);
            }
            bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
        }
    }

为什么会发生这种情况以及如何解决?

更新:当我使用ImageFormat.Jpeg代替ImageFormat.Png时,它可以正常工作,但我仍然需要PNG格式。

5 个答案:

答案 0 :(得分:1)

你说:

  

我想从服务器获取屏幕截图

与GDI +相关的错误表明运行此代码的上下文可能是服务上下文(例如IIS),而不是桌面。那是对的吗?如果是这样,你期望在截图中返回什么?

对于记录,以下(最小)代码可以正常工作:

    var ms = new MemoryStream();
    Rectangle bounds = Screen.GetBounds(Point.Empty);
    using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height))
    {
        using (Graphics g = Graphics.FromImage(bitmap))
        {
            g.CopyFromScreen(Point.Empty, Point.Empty, bitmap.Size);
        }
        bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
    }

bitmapms都包含预期的数据。因此,我认为您需要提供有关此代码运行的位置和内容的信息。

答案 1 :(得分:0)

它以这种方式与我合作:

  • 当客户想要接收截图时,您需要在转移开始前知道图像大小。
    请致电GetScreenShotSize()以获取图片的大小。

  • 获得尺寸后,请致电GetScreenShot()以接收图片数据。

我使用using (MemoryStream ms = new MemoryStream())所以现在PNG格式正在运行。

    private Image img = null;
    public long GetScreenShotSize()
    {
        Rectangle bounds = Screen.GetBounds(Point.Empty);
        using (Bitmap bmp = new Bitmap(bounds.Width, bounds.Height))
        {
            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.CopyFromScreen(Point.Empty, Point.Empty, bounds.Size);
            }
            using (MemoryStream ms = new MemoryStream())
            {
                bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                img = Image.FromStream(ms);
                return ms.Length;
            }
        }
    }
    public void GetScreenShot(IPEndPoint ep)
    {
        using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
        {
            socket.Connect(ep);
            using (MemoryStream ms = new MemoryStream())
            {
                img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                socket.Send(ms.ToArray(), SocketFlags.None);
            }
            img.Dispose();
            img = null;
        }
    }

答案 2 :(得分:0)

对我来说,我使用的是Image.Save(Stream, ImageCodecInfo, EncoderParameters),显然这导致了臭名昭着的A generic error occurred in GDI+错误。

我试图使用EncoderParameter以100%的质量保存jpeg。这完全适用于“我的机器”(doh!),而不是生产。

当我使用Image.Save(Stream, ImageFormat)时,错误消失了!所以就像一个白痴我继续使用后者,虽然它将它们保存为默认质量,我认为这只是50%。

希望此信息可以帮助某人。

答案 3 :(得分:0)

我知道这是一篇旧帖子,但我也想添加这些信息,以防万一像我这样的人在将来遇到这个问题。

我无法保存.PNG图像,因为IIS应用程序池帐户无法访问此密钥。

HKEY_CLASSES_ROOT \ CLSID {FAE3D380-FEA4-4623-8C75-C6B61110B681}

使用png图形时需要使用。

答案 4 :(得分:-2)

abrirConexion();
cmd = new SqlCommand(" INSERT INTO [SICRE_BI].[Credito_CCSS].[bi_img](Descripcion,img) VALUES (@nom_img,@img)",cn);                                
cmd.Parameters.Add("@Descripcion", SqlDbType.NChar);
cmd.Parameters.Add("@img", SqlDbType.Image);

cmd.Parameters["@Descripcion"].Value = descripcion;

System.IO.MemoryStream ms = new System.IO.MemoryStream();

pbImagen.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);//Aqui se me cae.Aqui se me cae.Aqui .

cmd.Parameters["@img"].Value = ms.GetBuffer();    //ms.GetBuffer();

cmd.ExecuteNonQuery();
return true;