simple rotation support for gdk-pixbuf
- From: Matthias Clasen <mclasen redhat com>
- To: gtk-devel-list gnome org
- Subject: simple rotation support for gdk-pixbuf
- Date: Sun, 20 Jun 2004 02:55:22 -0400
Since a full transformation api a la 
http://mail.gnome.org/archives/gtk-devel-list/2003-February/msg00157.html
will probably have to wait for Cairo, here is what I intend to add to
gdk-pixbuf in the 2.6 timeframe:
typedef enum {
	GDK_PIXBUF_ANGLE_0   =   0,
	GDK_PIXBUF_ANGLE_90  =  90,
	GDK_PIXBUF_ANGLE_180 = 180,
	GDK_PIXBUF_ANGLE_270 = 270
} GdkPixbufAngle;
GdkPixbuf *gdk_pixbuf_rotate_simple (const GdkPixbuf *src,
				     GdkPixbufAngle   angle);
GdkPixbuf *gdk_pixbuf_flip          (const GdkPixbuf *src,
				     gboolean         horizontal,
				     gboolean         vertical);
Does this look reasonable ? Full implementation attached below.
Matthias
#define OFFSET(pb, x, y) ((x) * (pb)->n_channels + (y) * (pb)->rowstride)
/**
 * gdk_pixbuf_rotate_simple:
 * @src: a #GdkPixbuf
 * @angle: the angle to rotate by
 *
 * Rotates a pixbuf by a multiple of 90 degrees, and returns the
 * result in a new pixbuf.
 *
 * Returns: a new pixbuf
 *
 * Since: 2.6
 */
GdkPixbuf *
gdk_pixbuf_rotate_simple (const GdkPixbuf *src,
			  GdkPixbufAngle   angle)
{
  GdkPixbuf *dest;
  guchar *p, *q;
  gint x, y;
  
  if (angle == 0)
    return gdk_pixbuf_copy (src);
  if (angle == 180)
    dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB, src->has_alpha, 
			   8, src->width, src->height);
  else
    dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB, src->has_alpha, 
			   8, src->height, src->width);
    
  if (!dest)
    return NULL;
  
  switch (angle % 360)
    {
    case 90:
      for (y = 0; y < src->height; y++) 
	{ 
	  for (x = 0; x < src->width; x++) 
	    { 
	      p = src->pixels + OFFSET (src, x, y); 
	      q = dest->pixels + OFFSET (dest, y, src->width - x - 1); 
	      memcpy (q, p, dest->n_channels);
	    }
	} 
      break;
    case 180:
      for (y = 0; y < src->height; y++) 
	{ 
	  for (x = 0; x < src->width; x++) 
	    { 
	      p = src->pixels + OFFSET (src, x, y); 
	      q = dest->pixels + OFFSET (dest, src->width - x - 1, src->height - y - 1); 
	      memcpy (q, p, dest->n_channels);
	    }
	} 
      break;
    case 270:
      for (y = 0; y < src->height; y++) 
	{ 
	  for (x = 0; x < src->width; x++) 
	    { 
	      p = src->pixels + OFFSET (src, x, y); 
	      q = dest->pixels + OFFSET (dest, src->height - y - 1, x); 
	      memcpy (q, p, dest->n_channels);
	    }
	} 
      break;
    default:
      g_assert_not_reached ();
  } 
  return dest;
}
/**
 * gdk_pixbuf_flip:
 * @src: a #GdkPixbuf
 * @horizontal: %TRUE to flip horizontally
 * @vertical: %TRUE to flip vertically
 *
 * Flips a pixbuf horizontally and/or vertically and returns the
 * result in a new pixbuf.
 *
 * Returns: a new pixbuf.
 *
 * Since: 2.6
 */
GdkPixbuf *
gdk_pixbuf_flip (const GdkPixbuf *src,
		 gboolean         horizontal,
		 gboolean         vertical)
{
  GdkPixbuf *dest;
  guchar *p, *q;
  gint x, y;
  if (!horizontal && !vertical)
    return gdk_pixbuf_copy (src);
  dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB, src->has_alpha, 
			 8, src->width, src->height);
  if (!dest)
    return NULL;
  if (!horizontal) /* flip vertical */
    {
      for (y = 0; y < dest->height; y++)
	{
	  p = src->pixels + OFFSET (src, 0, y);
	  q = dest->pixels + OFFSET (dest, 0, dest->height - y - 1);
	  memcpy (q, p, dest->rowstride);
	}
    }
  else if (!vertical) /* flip horizontal */
    {
      for (y = 0; y < dest->height; y++)
	{
	  for (x = 0; x < dest->width; x++)
	    {
	      p = src->pixels + OFFSET (src, x, y);
	      q = dest->pixels + OFFSET (dest, dest->width - x - 1, y);
	      memcpy (q, p, dest->n_channels);
	    }
	}
    }
  else /* flip both */
    {
      for (y = 0; y < dest->height; y++)
	{
	  for (x = 0; x < dest->width; x++)
	    {
	      p = src->pixels + OFFSET (src, x, y);
	      q = dest->pixels + OFFSET (dest, dest->width - x - 1, dest->height - y - 1);
	      memcpy (q, p, dest->n_channels);
	    }
	}
    }
  return dest;
}
				     
[
Date Prev][
Date Next]   [
Thread Prev][
Thread Next]   
[
Thread Index]
[
Date Index]
[
Author Index]