Converting Bitmap to GDK# PixBuff

3.2k views Asked by At

How can I convert a System.Drawing.Bitmap to GDK# Image so that I can set to the image widget.

I have tried this...

System.Drawing.Bitmap b = new Bitmap (1, 1);
Gdk.Image bmp = new Gdk.Image (b);

UPDATE:

Bitmap bmp=new Bitmap(50,50);
        Graphics g=Graphics.FromImage(bmp);
        System.Drawing.Font ff= new System.Drawing.Font (System.Drawing.FontFamily.GenericMonospace, 12.0F, FontStyle.Italic, GraphicsUnit.Pixel);
        g.DrawString("hello world",ff,Brushes.Red,new PointF(0,0));
        MemoryStream ms = new MemoryStream ();
        bmp.Save (ms, ImageFormat.Png);
        Gdk.Pixbuf pb= new Gdk.Pixbuf (ms); 
        image1.Pixbuf=pb;

Exception:

    System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> GLib.GException: Unrecognized image file format
   at Gdk.PixbufLoader.Close()
   at Gdk.PixbufLoader.InitFromStream(Stream stream)
   at Gdk.PixbufLoader..ctor(Stream stream)
   at Gdk.Pixbuf..ctor(Stream stream)
3

There are 3 answers

16
O. R. Mapper On BEST ANSWER

One ugly, but working, way is to store the bitmap as a PNG in a MemoryStream.

To save the Bitmap, you can use the Save method:

b.Save(myMemoryStream, ImageFormat.Png);

That was easy enough. Loading the PNG data into the Gdk# Pixbuf is also rather easy; you can use the appropriate constructor:

Pixbuf pb = new Gdk.Pixbuf(myMemoryStream);

You may need to reset the memory stream so the reading position is at the start of the stream before creating the Pixbuf.

A word of caution: I do not consider this the best, or even a "good" solution. Transferring data between two object-oriented data structures by serializing and deserializing the data has a certain code smell to it. I genuinely hope someone else can come up with a better solution.

EDIT: As for the used libraries: This answer uses only plain GDI+ (System.Drawing.Bitmap) and Gdk# (Gdk.Pixbuf). Note that a Gtk.Image is a widget that displays a Gdk.Pixbuf. As such, Gtk.Image is the equivalent of Windows Forms' PictureBox, whereas Gdk.Pixbuf is roughly equivalent to Windows Forms' System.Drawing.Bitmap.

EDIT2: After testing your code, I have found that there are three additional preconditions to ensure before you can run your minimum example:

  • As suspected above, you must reset the stream position to the beginning of the after saving your Bitmap and before loading your Pixbuf: ms.Position = 0;
  • You must compile the application for x86 CPUs.
  • You must invoke Gtk.Application.Init(); before you do anything with Pixbuf.
3
Deffiss On

You may draw in Gtk# like in Winforms. For this you must obtain System.Drawing.Graphics object and then you may draw lines, images and text on it. You may do it like this: 1. Create new Widget. 2. Subscribe on ExposeEvent. 3. On event handler write some code:

protected void OnExposeEvent(object o, ExposeEventArgs e)
{
    Gdk.Window window = e.Event.Window;      
    using (System.Drawing.Graphics graphics =
        Gtk.DotNet.Graphics.FromDrawable(window))
    {
        // draw your stuff here...
        graphics.DrawLine(new System.Drawing.Pen(System.Drawing.Brushes.Black), 0, 0, 30, 40);
    }
}

Also you need to add reference on gtk-dotnet.dll.

0
Nirav Patel On

try this ....

Gdk.Pixbuf pixbufImage = mew Gdk.Pixbuf(@"images/test.png");
Gtk.Image gtkImage = new Gtk.Image(pixbufImage);
Gdk.Image gdkImage = gtkImage.ImageProp;