3

I have a server-client application, i want to get a Screen Shot from server,but on the line
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
i get this exception : 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);
        }
    }

Why is that happening and how would i fix it?

Update: It works when i use ImageFormat.Jpeg Instead of ImageFormat.Png, but i still need a PNG format.

Murhaf Sousli
  • 12,622
  • 20
  • 119
  • 185
  • Not sure if this is helpful. But could you not just pass the Graphics object back after your `CopyFromScreen`? Or does your method have to be void? Or actually maybe just your Bitmap object. – Steven Combs May 14 '12 at 02:56
  • @meanbunny Im not sure if i got your point, but CopyFromScreen is not my method, its Graphics.CopyFromScreen method! – Murhaf Sousli May 14 '12 at 03:15
  • Right I guess my point was how do you plan to get your bitmap back to your client if that was your intention. Regardless here is a post that might help you. http://forums.asp.net/t/1766006.aspx/1 – Steven Combs May 14 '12 at 03:38
  • Or this one http://stackoverflow.com/questions/1053052/a-generic-error-occurred-in-gdi-jpeg-image-to-memorystream – Steven Combs May 14 '12 at 03:43
  • This question isn't documented well enough to risk an answer. It certainly won't work well if this is Windows 2008 Server Core. – Hans Passant May 14 '12 at 14:03
  • I'd try "using (Bitmap bitmap = new Bitmap(bounds.Width/8, bounds.Height/8))" just to make sure it's not a memory allocation thing when the MemoryStream's buffer is expanding. – Dan Byström May 15 '12 at 10:51
  • That is, lower the bitmap size. 8 is arbitraty. – Dan Byström May 15 '12 at 11:37

5 Answers5

1

You say:

i want to get a Screen Shot from server

And the error being GDI+ related suggests that the context under which this code is being run is perhaps a service context (such as IIS), and not a desktop. Is that correct? If so, what do you expect to return in a screenshot?

For the record, the following (minimal) code works fine:

    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);
    }

Both bitmap and ms contain the data expected. As such, I think you need to provide information on where and in what this code is running.

yamen
  • 15,390
  • 3
  • 42
  • 52
  • It's a WCF service, i can get a ScreenShot and send it successfully if i changed that line to `bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);` but when the ImageFormat is Png i get that error. – Murhaf Sousli May 14 '12 at 12:24
  • Try moving everything out of `using` blocks. There seem to be issues with streams closing too early. Ultimately, it depends on what you want to do with `ms`. This kind of isolated code is always difficult. – yamen May 14 '12 at 12:39
1

I know this is an old post, but I wanted to add this information as well, in case someone like me runs across this issue in the future..

I wasn't able to save .PNG images and it because the IIS App Pool Account didn't have access to this, key.

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

Which is required when you use png graphics.

Henry
  • 2,953
  • 2
  • 21
  • 34
0

it worked with me this way :

  • When a client wants to a receive a screenshot, you need to know image size before transferring starts.
    Call GetScreenShotSize() to get the size of the image.

  • Once you get the size, call GetScreenShot() to receive image data.

i used using (MemoryStream ms = new MemoryStream()) so now PNG format is working.

    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;
        }
    }
Murhaf Sousli
  • 12,622
  • 20
  • 119
  • 185
0

For me I was using the Image.Save(Stream, ImageCodecInfo, EncoderParameters) and apparently this was causing the infamous A generic error occurred in GDI+ error.

I was trying to use EncoderParameter to save the jpegs in 100% quality. This was working perfectly on "my machine" (doh!) and not on production.

When I used the Image.Save(Stream, ImageFormat) instead, the error disappeared! So like an idiot I continued to use the latter although it saves them in default quality which I assume is just 50%.

Hope this info helps someone.

Ε Г И І И О
  • 11,199
  • 1
  • 48
  • 63
-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;
Paweł Tomkiel
  • 1,974
  • 2
  • 21
  • 39
Leo
  • 1
  • 1
    Can you translate your comments and function names? – Paweł Tomkiel Mar 17 '15 at 21:32
  • 1
    While this answer is probably correct and useful, it is preferred if you include some explanation along with it to explain how it helps to solve the problem. This becomes especially useful in the future, if there is a change (possibly unrelated) that causes it to stop working and users need to understand how it once worked. – Kevin Brown-Silva Mar 17 '15 at 22:09
  • @PaulTomkiel `//Aqui se me cae.Aqui se me cae.Aqui` means `//Here it fails.Here it fails.Here` – Diego Jancic Feb 16 '16 at 18:11