[cairo] How to output images from data originating from files?

Ken Resander kresander at yahoo.com
Fri Apr 5 13:40:01 PDT 2013


Hi Simon,

Thanks for the very useful advice...

I can make the GdkPixbufLoader work if the program does not prepare eventhandlers for area-prepared and area-updated. However, if I connect these they will not trigger and call the handlers. 

The test program is small so I can add it inline.

Hope someone can see what is wrong...

Ken
P.S. The test program:
static cairo_surface_t * imgpng ;

static unsigned char bigbuf [ 200000 ] ;
static GdkPixbuf * pixbuf;
static GdkPixbufLoader * loader ;


static GdkPixbuf * makepixbuf ( bool byfilename , const char * filename )
   {
   GError * err = NULL ;
   if ( byfilename )
      {
      return gdk_pixbuf_new_from_file(filename,&err);
      }
   // read file content into buffer
   FILE * f = fopen ( filename, "r");
   int length = fread (bigbuf, 1, sizeof(bigbuf), f);
   fclose (f);
   loader = gdk_pixbuf_loader_new ();
   gdk_pixbuf_loader_write (loader, bigbuf, length, NULL);
   gdk_pixbuf_loader_close (loader , &err ) ;
   //printf ( "pixbuf may not yet be ready...\n" ) ;
   //return NULL ;
  // actually it is ready here!!!!!
  return pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
   }

static void do_drawing(cairo_t *cr)
   {
   cairo_set_source_surface(cr, imgpng , 0,40);
   cairo_paint(cr);

   if ( pixbuf != NULL )
      {
      gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 150);
      cairo_paint (cr);
      }
   }

static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr,
                              gpointer user_data)
   {
   cr = gdk_cairo_create(gtk_widget_get_window(widget));
   do_drawing(cr);
   cairo_destroy(cr);
   return FALSE;
   }

static void on_area_prep( GdkPixbufLoader *loader, gpointer user_data)
   {
   // this is not called
   printf ( "area-prepared: pixbuf ready\n" ) ;
   pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
   }


static void on_area_update( GdkPixbufLoader *loader, gint x , gint y , gint width ,
                          gint height , gpointer user_data)
   {
   // same here - not called
   printf ( "area-updated: pixbuf ready\n" ) ;
   pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
   }

int main(int argc, char *argv[])
   {
   GtkWidget *window;
   GtkWidget *darea;

   gtk_init(&argc, &argv);

   imgpng = cairo_image_surface_create_from_png("sample_7.png");
   pixbuf = makepixbuf ( false , "parrots.jpg" );

   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

   darea = gtk_drawing_area_new();
   gtk_container_add(GTK_CONTAINER(window), darea);

   g_signal_connect(G_OBJECT(darea), "draw",
                    G_CALLBACK(on_draw_event), NULL);
   g_signal_connect(G_OBJECT(loader), "area-prepared",
                    G_CALLBACK(on_area_prep), NULL);
   g_signal_connect(G_OBJECT(loader), "area-updated",
                    G_CALLBACK(on_area_update), NULL);
   g_signal_connect(window, "destroy",
                    G_CALLBACK(gtk_main_quit), NULL);

   gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
   gtk_window_set_default_size(GTK_WINDOW(window), 400, 90);
   gtk_window_set_title(GTK_WINDOW(window), "GTK window");

   gtk_widget_show_all(window);

   gtk_main();

   cairo_surface_destroy(imgpng);

   return 0;
   }




 


________________________________
 From: Simon Sapin <simon.sapin at exyr.org>
To: cairo at cairographics.org 
Sent: Friday, 5 April 2013, 15:13
Subject: Re: [cairo] How to output images from data originating from files?
 
Le 05/04/2013 16:03, Ken Resander a écrit :
> I am new to Cairo and have fairly limited knowlege of graphics (Windows
> GDI,GDI+ years ago).
> I am now on Ubuntu 12.04 and need to render images in png and jpg from
> GTK in C/C++.
>
> I know how to do this when specifying .png and .jpg file names:
>
> cairo_surface_t * imgpng =
> cairo_image_surface_create_from_png("sample_7.png");
> cairo_set_source_surface(cr, imgpng, 0,40);
> cairo_paint(cr);
>
> GError * err = NULL;
> GdkPixbuf * imgpxb = gdk_pixbuf_new_from_file("parrots.jpg",&err);
> gdk_cairo_set_source_pixbuf(cr, imgpxb, 0, 150);
> cairo_paint (cr);
>
> My program will receive image data from another computer via standard
> protocols. There might be hundreds of small to small-medium images
> coming, so it would more efficient to batch the file content of these
> into a huge buffer and pass that across (from the other computer) along
> with the image format, buffer offset and length of each chunk.
>
> Of course I could copy a chunk into a tmp file and use the png surface
> and gdkpixbuf filename api calls above, but it seems such a shame having
> to put the data back into a file for cairo/gdk to read and convert it to
> the format needed.
>
> Is there a better way?

Hi,

If you have images (not all PNG) in memory, the easiest way to load them 
without going through temporary files is to use GdkPixbufLoader:

https://developer.gnome.org/gdk-pixbuf/stable/GdkPixbufLoader.html

This will give you GdkPixbuf objects that you can convert to cairo 
patterns with gdk_cairo_set_source_pixbuf, as you do above.

Cheers,
-- 
Simon Sapin
-- 
cairo mailing list
cairo at cairographics.org
http://lists.cairographics.org/mailman/listinfo/cairo
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cairographics.org/archives/cairo/attachments/20130405/8f1fde08/attachment.html>


More information about the cairo mailing list