GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Thu Sep 18, 2014 7:45 pm

All times are UTC




Post new topic Reply to topic  [ 13 posts ] 
Author Message
 Post subject: How to initialize gtk for using pixbuf with cairo
PostPosted: Fri Jan 27, 2012 5:14 pm 
Offline
Familiar Face

Joined: Fri Jan 27, 2012 5:04 pm
Posts: 8
I need to use a pixbuf with cairo to render images from file. The resulting image is simply a memory buffer (RGB) which is not displayed on the system it is generated on. To use a pixbuf I need to initialize gtk with gtk_init(). This is not a CLI application so there are no arguments. Using gtk_init(NULL, NULL) works fine on my Windows system. On Linux it results in a segfault because it is looking for a DISPLAY setting. The Linux system does not provide a DISPLAY variable, there is no display. Is there some other way of initializing gtk so I can use the pixbuf? Using gtk_init_check(NULL, NULL) is a bit better. It does not cause a segfault but the images still do not render on to the cairo surface.

Thanks,
Bob


Top
 Profile  
 
 Post subject: Re: How to initialize gtk for using pixbuf with cairo
PostPosted: Fri Jan 27, 2012 6:46 pm 
Offline
Familiar Face

Joined: Fri Jan 27, 2012 5:04 pm
Posts: 8
Slight typo, replace gtk_init with gdk_init, etc.

I tried adding 'g_setenv("DISPLAY", "/dev/null", true);' but this has no effect. Windows still works fine but there are no images rendered when running on the Linux system.


Top
 Profile  
 
 Post subject: Re: How to initialize gtk for using pixbuf with cairo
PostPosted: Fri Jan 27, 2012 7:16 pm 
Offline
Familiar Face

Joined: Fri Jan 27, 2012 5:04 pm
Posts: 8
Seems this works after all. The problem is that the system can't handle jpg files, png files work. Thanks! :)


Top
 Profile  
 
 Post subject: Re: How to initialize gtk for using pixbuf with cairo
PostPosted: Fri Jan 27, 2012 9:11 pm 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hello and welcome to the GTK+ forums!

Why are you using GTK+ at all? You can use GDK-PixBuf library for loading images into RGB(A) buffers (GdkPixbufs) and if no modification is necessary, this is basically all you need. If you need to add something to that image, use cairo (again, with no GTK+) (create new image surface, copy contents of the pixbuf onto it, create cairo context on this surface and draw missing parts).

Or did I miss any requirements of your application?

Cheers,
Tadej


Top
 Profile  
 
 Post subject: Re: How to initialize gtk for using pixbuf with cairo
PostPosted: Fri Jan 27, 2012 9:21 pm 
Offline
Familiar Face

Joined: Fri Jan 27, 2012 5:04 pm
Posts: 8
Thanks Tadej, that is exactly what I am doing. I miss-typed gtk vs. gdk in my initial posting. I am a bit new to this. I have the issue resolved using gdk_init_check setting DISPLAY to /dev/null.

Thanks again,
Bob


Top
 Profile  
 
 Post subject: Re: How to initialize gtk for using pixbuf with cairo
PostPosted: Fri Jan 27, 2012 9:28 pm 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hi.

GDK and GDK-PixBuf are two separate libraries and no initialization is needed for GDK-PixBuf. To make things a bit clearer, here are links to GDK API documentation and GDK-PixBuf API documentation.

What I was trying to say is: you don't need GTK+/GDK for your application, just GDK-PixBuf and possibly cairo.

Cheers,
Tadej


Top
 Profile  
 
 Post subject: Re: How to initialize gtk for using pixbuf with cairo
PostPosted: Fri Jan 27, 2012 9:50 pm 
Offline
Familiar Face

Joined: Fri Jan 27, 2012 5:04 pm
Posts: 8
Ah, now I understand what you meant. However, if I comment out the call to gdk_init_check() I get an exception. If I comment out '#include <gdk.h>' I can't build because I am using gdk_cairo_set_source_pixbuf(). Is there some other function I should be using? I do not see any cairo in the gdk_pixbuf stuff.

Thanks!
Bob


Top
 Profile  
 
 Post subject: Re: How to initialize gtk for using pixbuf with cairo
PostPosted: Fri Jan 27, 2012 10:08 pm 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Yeah, that function is what I meant by "copy data from pixbuf to cairo image source". I agree that it's quite handy to use something that is readily available already, but you're pulling in a hefty piece of library for single function.

It's not that hard to write function from scratch to do this (I did it quite a few times already when I was trying to avoid limitations of GDK being only thread-aware, not thread safe), but even simpler solution is to copy it directly from GDK. The function implementation is here: gdk_cairo_set_source_pixbuf() and as you can see, it doesn't rely on any other part of GDK. All it uses are glib, GDK-PixBuf and cairo calls.

Again, I usually support code reuse, but with this function, I think it's safe to simply copy it and be done with heavy-weight libs.

Cheers,
Tadej


Top
 Profile  
 
 Post subject: Re: How to initialize gtk for using pixbuf with cairo
PostPosted: Fri Jan 27, 2012 10:40 pm 
Offline
Familiar Face

Joined: Fri Jan 27, 2012 5:04 pm
Posts: 8
Great, will take a look. Thanks again!


Top
 Profile  
 
 Post subject: Re: How to initialize gtk for using pixbuf with cairo
PostPosted: Fri Jan 27, 2012 11:11 pm 
Offline
Familiar Face

Joined: Fri Jan 27, 2012 5:04 pm
Posts: 8
Well, I copied the code over to my app and tried again. Seems it was not crashing from this function but from 'gdk_pixbuf_get_file_info()'. :/ I call this to get the dimensions of the image being loaded. Perhaps there is another way to get this.


Top
 Profile  
 
 Post subject: Re: How to initialize gtk for using pixbuf with cairo
PostPosted: Fri Jan 27, 2012 11:21 pm 
Offline
Familiar Face

Joined: Fri Jan 27, 2012 5:04 pm
Posts: 8
Nope, even 'gdk_pixbuf_new_from_file()' causes an exception if I do not call 'gdk_init_check()'. :(


Top
 Profile  
 
 Post subject: Re: How to initialize gtk for using pixbuf with cairo
PostPosted: Sat Jan 28, 2012 8:18 pm 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hi.

Are you sure you're properly initializing glib before you start (that is: calling g_type_init() before any other glib/GDK_PixBuf call)? Symptoms suggest that you're missing that call (and yes, this function is called for you by various inits like gtk_init() and gdk_init() higher up in the library stack).

Cheers,
Tadej


Top
 Profile  
 
 Post subject: Re: How to initialize gtk for using pixbuf with cairo
PostPosted: Sun Jan 29, 2012 12:01 pm 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hi.

I had some spare time to kill today, so I quickly wrote simple application that showcases the functionality you need. As you can see, I haven't used GTK+ at all (application is linked only against glib, gdk-pixbuf and cairo).

Hope this sample code helps you a bit with your endeavor.

Cheers,
Tadej

Code:
#include <glib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <cairo.h>

/* RGBA image */
/*#define INPUT  "Exhausted.gif" */

/* RGB image */
#define INPUT  "Exhausted.jpg"

#define OUTPUT "out.png"


static cairo_surface_t *
convert_pixbuf_to_cairo_surface (GdkPixbuf *pixbuf)
{
  /* Pixbuf properties */
  int w = gdk_pixbuf_get_width (pixbuf),
      h = gdk_pixbuf_get_height (pixbuf),
      p_stride = gdk_pixbuf_get_rowstride (pixbuf),
      ch = gdk_pixbuf_get_n_channels (pixbuf);
  unsigned char *p_pixels = gdk_pixbuf_get_pixels (pixbuf);

  /* Equavalent cairo props */
  cairo_surface_t *surface;
  int c_stride;
  unsigned char *c_pixels;
  cairo_format_t format;

  /* Initialize properties */
  if (ch == 3)
    format = CAIRO_FORMAT_RGB24;
  else
    format = CAIRO_FORMAT_ARGB32;

  surface = cairo_image_surface_create (format, w, h);
  c_stride = cairo_image_surface_get_stride (surface);
  c_pixels = cairo_image_surface_get_data (surface);

  /* Loop that copies the pixels */
  if (ch == 3) /* RGB image */
    {
      int i;
      for (i = 0; i < h; i++)
        {
          unsigned char *pp = p_pixels + i * p_stride,
                        *pc = c_pixels + i * c_stride;
          int j;
          for (j = 0; j < w; j++)
            {
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
              /* RGB -> BGR(A) */
              pc[0] = pp[2];
              pc[1] = pp[1];
              pc[2] = pp[0];
#else
              /* RGB -> (A)RGB */
              pc[1] = pp[0];
              pc[2] = pp[1];
              pc[3] = pp[2];
#endif
              pc += 4;
              pp += 3;
            }
        }
    }
  else /* RGBA image - rounding is not 100% right */
    {
      int i;
      for (i = 0; i < h; i++)
        {
          unsigned char *pp = p_pixels + i * p_stride,
                        *pc = c_pixels + i * c_stride;
          int j;
          for (j = 0; j < w; j++)
            {
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
              /* RGBA -> BGRA */
              pc[0] = (pp[2] * pp[3] + 0x7f) / 0xff;
              pc[1] = (pp[1] * pp[3] + 0x7f) / 0xff;
              pc[2] = (pp[0] * pp[3] + 0x7f) / 0xff;
              pc[3] = pp[3];
#else
              /* RGBA -> ARGB */
              pc[0] = pp[3];
              pc[1] = (pp[0] * pp[3] + 0x7f) / 0xff;
              pc[2] = (pp[1] * pp[3] + 0x7f) / 0xff;
              pc[3] = (pp[2] * pp[3] + 0x7f) / 0xff;
#endif
              pc += 4;
              pp += 4;
            }
        }
    }

  return surface;
}


int
main (int    argc,
      char **argv)
{
  GdkPixbuf *pixbuf;
  cairo_surface_t *surf;

  g_type_init ();

  pixbuf = gdk_pixbuf_new_from_file (INPUT, NULL);
  g_print ("Channels: %d\n", gdk_pixbuf_get_n_channels (pixbuf));
  surf = convert_pixbuf_to_cairo_surface (pixbuf);

  /* You can now do just about anything you want using cairo */

  cairo_surface_write_to_png (surf, OUTPUT);

  return 0;
}


Makefile (for convenience)
Code:
PKGS=glib-2.0 gdk-pixbuf-2.0 cairo
CFLAGS=-ggdb -Wall `pkg-config --cflags ${PKGS}`
LDFLAGS=-ggdb -Wall `pkg-config --libs ${PKGS}`


all: stamp

clean:
   rm -f stamp *.o


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

All times are UTC


Who is online

Users browsing this forum: Google Adsense [Bot] and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group