Thoughts about a new GdkPixbuf transform interface



This is pretty much idle/far future thinking, but I had
some ideas about how to rework gdk_pixbuf_scale()
gdk_pixbuf_composite() to be more sane.

What we all know and love:

void gdk_pixbuf_scale           (const GdkPixbuf *src,
                                 GdkPixbuf       *dest,
                                 int              dest_x,
                                 int              dest_y,
                                 int              dest_width,
                                 int              dest_height,
                                 double           offset_x,
                                 double           offset_y,
                                 double           scale_x,
                                 double           scale_y,
                                 GdkInterpType    interp_type);
void gdk_pixbuf_composite       (const GdkPixbuf *src,
                                 GdkPixbuf       *dest,
                                 int              dest_x,
                                 int              dest_y,
                                 int              dest_width,
                                 int              dest_height,
                                 double           offset_x,
                                 double           offset_y,
                                 double           scale_x,
                                 double           scale_y,
                                 GdkInterpType    interp_type,
                                 int              overall_alpha);
void gdk_pixbuf_composite_color (const GdkPixbuf *src,
                                 GdkPixbuf       *dest,
                                 int              dest_x,
                                 int              dest_y,
                                 int              dest_width,
                                 int              dest_height,
                                 double           offset_x,
                                 double           offset_y,
                                 double           scale_x,
                                 double           scale_y,
                                 GdkInterpType    interp_type,
                                 int              overall_alpha,
                                 int              check_x,
                                 int              check_y,
                                 int              check_size,
                                 guint32          color1,
                                 guint32          color2);
GdkPixbuf *gdk_pixbuf_scale_simple           (const GdkPixbuf *src,
                                              int              dest_width,
                                              int              dest_height,
                                              GdkInterpType    interp_type);

GdkPixbuf *gdk_pixbuf_composite_color_simple (const GdkPixbuf *src,
                                              int              dest_width,
                                              int              dest_height,
                                              GdkInterpType    interp_type,
                                              int              overall_alpha,
                                              int              check_size,
                                              guint32          color1,
                                              guint32          color2);


Yikes. Problems:

 - The 17 arguments to gdk_pixbuf_composite_color()
 - Nobody understands it
 - Not extensible ... I'd like to add the choice of what to 
   do for source pixels off the edge of the source from
   RENDER.
 - No support for rotation (or other arbitrary transforms)

What I was thinking of:

GdkPixbufTransform *gdk_pixbuf_transform_new (GdkPixbuf *source);

void       gdk_pixbuf_transform_rotate          (GdkPixbufTransform *transform,
						 gdouble             angle);
void       gdk_pixbuf_transform_scale           (GdkPixbufTransform *transform,
						 gdouble             scale_x,
						 gdouble             scale_y);
void       gdk_pixbuf_transform_offset          (GdkPixbufTransform *transform,
						 gdouble             offset_x,
						 gdouble             offset_y);
void       gdk_pixbuf_transform_set_affine      (GdkPixbufTransform *transform,
						 double              a00,
						 double              a01,
						 double              a02,
						 double              a10,
						 double              a11,
						 double              a12);
void       gdk_pixbuf_transform_set_interp_type (GdkPixbufTransform *transform,
						 GdkInterpType       interp_type);
void       gdk_pixbuf_set_overall_alpha         (GdkPixbufTransform *transform,
						 int                 overall_alpha);
/* Composite onto a pixbuf */
void       gdk_pixbuf_transform_composite       (GdkPixbufTransform *transform,
						 GdkPixbuf          *dest,
						 int                 render_x,
						 int                 render_y,
						 int                 render_width,
						 int                 render_height);
/* Composite onto a constant color and render to a pixbuf */
void       gdk_pixbuf_transform_composite_color (GdkPixbufTransform *transform,
						 GdkPixbuf          *dest,
						 guint32             bg_color,
						 int                 render_x,
						 int                 render_y,
						 int                 render_width,
						 int                 render_height);
/* Convenience function to create a pixbuf from the bounding box of the
 * transformed source and composite_color() on it.
 */
GdkPixbuf *gdk_pixbuf_transform_output          (GdkPixbufTransform *transform,
						 guint32             bg_color);

typedef enum GdkPixbufEdgeMode {
  GDK_PIXBUF_EDGE_NEAREST,
  GDK_PIXBUF_EDGE_TRANSPARENT,
  GDK_PIXBUF_EDGE_TILE
};

/* Specify what to do for source pixels off the edge */
void gdk_pixbuf_transform_set_edge_mode (GdkPixbufTransform *transform,
					 GdkPixbufEdgeMode   mode);
				     
/* To make up for the missing checks feature from composite color */
void gdk_pixbuf_fill_checks (GdkPixbuf *pixbuf,
			     int        check_x_offset,
			     int        check_y_offset,
			     int        check_size,
			     guint32    color1,
			     guint32    color2);

  /* Some examples */
  
  /* Double the size of a pixbuf and rotate by 90 degrees
   */
  GdkPixbufTransform *transform = gdk_pixbuf_transform_new ();
  gdk_pixbuf_transform_scale (transform, 2., 2.);
  gdk_pixbuf_transform_rotate (transform, 90.);
  GdkPixbufTransform *result = gdk_pixbuf_transform_output (transform);
  g_object_unref (transform);

  /* Render a pixbuf at half size in 'dest', offset by 100 pixels
   */
  GdkPixbufTransform *transform = gdk_pixbuf_transform_new ();
  gdk_pixbuf_transform_scale (transform, 0.5, 0.5);
  gdk_pixbuf_transform_offset (transform, 100., 100.);
  gdk_pixbuf_transform_composite (transform, dest,
				  100, 100, width/2, height/2);
  g_object_unref (transform);

  /* Render a pixbuf rotated 45 degrees in 'dest', centered
   * at 100,100.
   */
  GdkPixbufTransform *transform = gdk_pixbuf_transform_new ();
  gdk_pixbuf_transform_offset (transform, -width/2, -height/2);
  gdk_pixbuf_transform_rotate (transform, 45.);
  gdk_pixbuf_transform_offset (transform, 100., 100.);
  gdk_pixbuf_set_edge_mode (transform, GDK_PIXBUF_EDGE_TRANSPARENT);
  gdk_pixbuf_transform_composite (transform, dest,
				  0, 0, -1, -1);
  g_object_unref (transform);

Notable differences from the old API:

 - Have an explicit object
 - Add edge mode
 - Add arbitrary transformation
 - Making the "transform then render a portion   of the transformed object" 
   model explicit hopefully makes it easier.
 - Checks feature of composite_color() removed. Was a silly demo-app thing,
   and won't be significantly faster than just filling a destination
   pixmap.

Main problem I see with the proposal is the name ... not crazy
about GdkPixbufTransform; GdkPixbufCompositor was another idea,
but even long.

Other possible questions:

 - Remove composite_color() entirely and just force the use
   to fill the dest pixmap?
 - Maybe should switch to RENDER's (SOURCE IN MASK) OVER DEST
   model? But makes the implementation that much worse.

Anyways.. that's my ideas on a possible future API direction.

Regards,
                                                Owen





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]