The Cairo graphics tutorial -------Transparency

转载 2012年03月30日 08:19:55

In this part of the Cairo C API tutorial, we will talk about transparency. We will provide some basic definitions andtwo interesting transparency effects.


Transparency is the quality of being able to see through a material. The easiest way to understand transparency is to imagine a piece of glass or water. Technically, the rays of light can go through the glass and this way we can see objects behind the glass.

In computer graphics, we can achieve transparency effects using alpha compositing.Alpha compositing is the process of combining an image with a background to create the appearance of partial transparency. The composition process uses an alpha channel.Alpha channel is an 8-bit layer in a graphics file format that is used for expressing translucency (transparency). The extra eight bits per pixel serves as a mask and represents 256 levels of translucency.
(answers.com, wikipedia.org)

Transparent rectangles

The first example will draw ten rectangles with different levels of transparency.

#include <cairo.h>
#include <gtk/gtk.h>

static gboolean
on_expose_event(GtkWidget *widget,
    GdkEventExpose *event,
    gpointer data)
{
  cairo_t *cr;

  cr = gdk_cairo_create(widget->window);

  gint i;
  for ( i = 1; i <= 10; i++) {
      cairo_set_source_rgba(cr, 0, 0, 1, i*0.1);
      cairo_rectangle(cr, 50*i, 20, 40, 40);
      cairo_fill(cr);  
  }


  cairo_destroy(cr);

  return FALSE;
}


int
main (int argc, char *argv[])
{

  GtkWidget *window;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  g_signal_connect(G_OBJECT(window), "expose-event",
      G_CALLBACK(on_expose_event), NULL);
  g_signal_connect(G_OBJECT(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), 590, 90); 
  gtk_window_set_title(GTK_WINDOW(window), "transparency");

  gtk_widget_set_app_paintable(window, TRUE);
  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}

The cairo_set_source_rgba() has an optional alpha parameter to provide transparency.

 gint i;
 for ( i = 1; i <= 10; i++) {
     cairo_set_source_rgba(cr, 0, 0, 1, i*0.1);
     cairo_rectangle(cr, 50*i, 20, 40, 40);
     cairo_fill(cr);  
 }

This code creates ten rectangles with alpha values from 0.1 ... 1.


Transparency
Figure: Transparency

Fade out effect

In the next example, we will fade out an image. The image will gradually get more transparent until it is completelyinvisible.

#include <cairo.h>
#include <gtk/gtk.h>


cairo_surface_t *image;
gboolean timer = TRUE;

static gboolean
on_expose_event(GtkWidget *widget,
    GdkEventExpose *event,
    gpointer data)
{
  cairo_t *cr;

  cr = gdk_cairo_create(widget->window);

  static double alpha = 1;
  double const delta = 0.01;

  cairo_set_source_surface(cr, image, 10, 10);
  cairo_paint_with_alpha(cr, alpha);

  alpha -= delta; 

  if (alpha <= 0) timer = FALSE;

  cairo_destroy(cr);

  return FALSE;
}

static gboolean
time_handler (GtkWidget *widget)
{
  if (widget->window == NULL) return FALSE;

  if (!timer) return FALSE;

  gtk_widget_queue_draw(widget);
  return TRUE;
}

int
main (int argc, char *argv[])
{

  GtkWidget *window;
  GtkWidget *darea;

  gint width, height;

  image = cairo_image_surface_create_from_png("turnacastle.png");
  width = cairo_image_surface_get_width(image);
  height = cairo_image_surface_get_height(image);

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

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

  g_signal_connect(darea, "expose-event",
      G_CALLBACK(on_expose_event), 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), width+20, height+20);

  gtk_window_set_title(GTK_WINDOW(window), "fade out");
  g_timeout_add(50, (GSourceFunc) time_handler, (gpointer) window);
  gtk_widget_show_all(window);

  gtk_main();

  cairo_surface_destroy(image);

  return 0;
}

In our example we display an image that will gradually fade out. We use a photo of ruins of a Turna Castle, locatedin east part of Slovakia. You can download the picture here.

 image = cairo_image_surface_create_from_png("turnacastle.png");

For efficiency reasons, the creation of the image surface is placed inside the main function.

 cairo_set_source_surface(cr, image, 10, 10);

Here we set the source for painting.

 cairo_paint_with_alpha(cr, alpha);

The fade out effect is created using the cairo_paint_with_alpha() function call. This functionuses transparency value as a mask.

 alpha -= delta;

We decrease the alpha value each time, the on_expose_event() function is executed.

 if (alpha <= 0) timer = FALSE;

If the alpha value is less or equal to zero, we finished our fade out effect. We set the timer value to FALSE. Wedo not need our timer function anymore.

 g_timeout_add(50, (GSourceFunc) time_handler, (gpointer) window);

We create a timer function. This function will call time_handler every 50 ms.

 static gboolean
 time_handler (GtkWidget *widget)
 {
   if (widget->window == NULL) return FALSE;

   if (!timer) return FALSE;

   gtk_widget_queue_draw(widget);
   return TRUE;
 }

The main function of the time_handler call is to redraw the window regularly. When the function returns FALSE, the timeout function will cease to work.

 if (widget->window == NULL) return FALSE;

You might wonder, what this code line is there for. It is a simple check. If the timeout value is too small, like 5 ms, it happens that while closing the application, the window is already destroyed but still we get the timeout function executed.This code line prevents from manipulating with a window in such cases.


Fade out
Figure: Fade out

Waiting demo

In this examle, we use transparency effect to create a waiting demo. We will draw 8 lines that will gradually fade out creating an illusion, that a line is moving. Such effects are often used to inform users, that a lengthy task is going on behind the scenes. An example is streaming video over the internet.

#include <cairo.h>
#include <gtk/gtk.h>
#include <math.h>

static gushort count = 0;

static gboolean
on_expose_event(GtkWidget *widget,
    GdkEventExpose *event,
    gpointer data)
{
  cairo_t *cr;

  cr = gdk_cairo_create(widget->window);

  static gdouble const trs[8][8] = {
      { 0.0, 0.15, 0.30, 0.5, 0.65, 0.80, 0.9, 1.0 },
      { 1.0, 0.0,  0.15, 0.30, 0.5, 0.65, 0.8, 0.9 },
      { 0.9, 1.0,  0.0,  0.15, 0.3, 0.5, 0.65, 0.8 },
      { 0.8, 0.9,  1.0,  0.0,  0.15, 0.3, 0.5, 0.65},
      { 0.65, 0.8, 0.9,  1.0,  0.0,  0.15, 0.3, 0.5 },
      { 0.5, 0.65, 0.8, 0.9, 1.0,  0.0,  0.15, 0.3 },
      { 0.3, 0.5, 0.65, 0.8, 0.9, 1.0,  0.0,  0.15 },
      { 0.15, 0.3, 0.5, 0.65, 0.8, 0.9, 1.0,  0.0, }
  };


  gint width, height;
  gtk_window_get_size(GTK_WINDOW(widget), &width, &height);

  cairo_translate(cr, width / 2, height /2);

  gint i = 0;
  for (i = 0; i < 8; i++) {
      cairo_set_line_width(cr, 3);
      cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
      cairo_set_source_rgba(cr, 0, 0, 0, trs[count%8][i]);

      cairo_move_to(cr, 0.0, -10.0);
      cairo_line_to(cr, 0.0, -40.0);
      cairo_rotate(cr, M_PI/4);

      cairo_stroke(cr);
  }

  cairo_destroy(cr);

  return FALSE;
}

static gboolean
time_handler (GtkWidget *widget)
{
  count += 1;
  gtk_widget_queue_draw(widget);
  return TRUE;
}

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

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  g_signal_connect(G_OBJECT(window), "expose-event",
      G_CALLBACK(on_expose_event), NULL);
  g_signal_connect(G_OBJECT(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), 250, 150); 

  gtk_window_set_title(GTK_WINDOW(window), "waiting demo");

  gtk_widget_set_app_paintable(window, TRUE);
  gtk_widget_show_all(window);
  g_timeout_add(100, (GSourceFunc) time_handler, (gpointer) window);

  gtk_main();

  return 0;
}

We draw eight lines with eight different alpha values.

 static gdouble const trs[8][8] = {
     { 0.0, 0.15, 0.30, 0.5, 0.65, 0.80, 0.9, 1.0 },
     { 1.0, 0.0,  0.15, 0.30, 0.5, 0.65, 0.8, 0.9 },
     { 0.9, 1.0,  0.0,  0.15, 0.3, 0.5, 0.65, 0.8 },
     { 0.8, 0.9,  1.0,  0.0,  0.15, 0.3, 0.5, 0.65},
     { 0.65, 0.8, 0.9,  1.0,  0.0,  0.15, 0.3, 0.5 },
     { 0.5, 0.65, 0.8, 0.9, 1.0,  0.0,  0.15, 0.3 },
     { 0.3, 0.5, 0.65, 0.8, 0.9, 1.0,  0.0,  0.15 },
     { 0.15, 0.3, 0.5, 0.65, 0.8, 0.9, 1.0,  0.0, }
 };

This is a two dimensional array of transparency values used in this demo. There are 8 rows, each for one state. Each of the 8 lines will continuosly use these values.

 cairo_set_line_width(cr, 3);
 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);

We make the lines a bit thicker, so that they are better visible. We draw the lines with rouded caps.

 cairo_set_source_rgba(cr, 0, 0, 0, trs[count%8][i]);

Here we define the transparency value for a line.

 cairo_move_to(cr, 0.0, -10.0);
 cairo_line_to(cr, 0.0, -40.0);
 cairo_rotate(cr, M_PI/4);

These code will draw each of the eight lines.

 g_timeout_add(100, (GSourceFunc) time_handler, (gpointer) window);

We use a timer function to create animation.


Waiting demo
Figure: Waiting demo

In this part of the Cairo tutorial, we have covered transparency.



相关文章推荐

The Cairo graphics tutorial -------Transformations

In this part of the Cairo graphics programming tutorial, we will talk about transformations. ...

The Cairo graphics tutorial -------Custom GTK widget

In this part of the Cairo graphics tutorial, we will create a custom GTK widget, where we will use t...

The Cairo graphics tutorial -------Clipping and masking

In this part of the Cairo tutorial, we will talk about clipping and masking. Clipping ...

The Cairo graphics tutorial -------Text in Cairo

In this part of the Cairo graphics tutorial, we will work with text. Soulmate In the first...

The Cairo graphics tutorial -------Cairo definitions

Cairo definitions In this part of the Cairo graphics tutorial, we will provide some useful definiti...

The Cairo graphics tutorial -------Basic drawing in Cairo

In this part of the Cairo graphics tutorial, we will draw some basic primitives. We will draw simple...

The Cairo graphics tutorial -------Shapes and fills in Cairo

In this part of the Cairo tutorial, we will create some basic and more advanced shapes. We will fill...

The Cairo graphics tutorial -------Cairo backends

The Cairo library supports various backends. In this section of the Cairo graphics tutorial, we will...

Core Graphics Tutorial Part 3: Patterns and Playgrounds

原文链接:Core Graphics Tutorial Part 3: Patterns and Playgrounds 原文作者: Caroline Begbie 译文出自:开发者前线 www.d...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)