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.



PyGobject(九十三)Cairo系列——简介&简单示例

Cairo 安装 Cairo在PyGobject中的使用 简单示例 Cairo Cario是一个2D图形库,支持多种输出设备。 目前支持的输出目标包括X Window,Quartz,Win3...
  • a87b01c14
  • a87b01c14
  • 2016年08月03日 08:58
  • 1495

cairo学习简单总结

Cairo将成为Linux 2D 绘图的未来 内容: 1,什么是Cairo 2.理解cairo 3.常用函数 4.常用代码片断举例 注意:目...
  • hetangbian
  • hetangbian
  • 2016年08月25日 10:37
  • 759

linux下不能画图的问题解决

Warning in grDevices:::png("/tmp/RtmpWTwF68/a0ee957a346f405dbc06815f37fd0971.png", : 本R版本不支持png 0...
  • wa2003
  • wa2003
  • 2015年06月01日 14:55
  • 4204

Cairo 图形指南 (4) —— 基本绘图

这一部分讲述如何绘制一些简单的图元,包括直线、填充与笔画操作、虚线、线端(Cap)与线的交合等图形的绘制方法。 直线段 直线段是非常基础的矢量图形对象。画一条直线段,需要调用两个函数:ca...
  • jiangnanyidiao
  • jiangnanyidiao
  • 2014年10月21日 18:07
  • 711

使用cairo绘制图形的部分函数总结

一 绘制文本 [cpp] view plain copy //设置源的颜色   cairo_set_source_rgb(cr,0.627,0,0...
  • xingzouagain
  • xingzouagain
  • 2016年09月11日 11:55
  • 1026

Cairo开发环境安装与在VC++2012中简单实现

     最近有一个任务就是利用vc++将设计好的地图生成pdf文件,于是开始零基础接触Cairo库,边学边整理吧。这是自己一开始Cairo环境安装与一个简单的实现例子,算是我这种菜鸟级别的...
  • Shixi_vivian
  • Shixi_vivian
  • 2016年10月16日 17:50
  • 415

14、交叉编译cairo

14、交叉编译cairo 目标平台:LOONGSON-1B开发板 内核:Linux 3.0 编译平台:ubuntu10.04 交叉工具链:gcc-3.4.6-2f   一、简介   ...
  • water_cow
  • water_cow
  • 2013年03月27日 20:15
  • 4350

PyGobject(九十五)Cairo系列——渐变

渐变分为线性渐变和径向渐变需要用到cairo.Pattern类cairo.PatternPatterns are the paint with which cairo draws. The prima...
  • a87b01c14
  • a87b01c14
  • 2016年08月03日 10:36
  • 1297

PyGobject(一百)Cairo系列——cairo.Surface实现图片倒影

cairoSurface class cairoSurface copy_page create_similarcontent width height finish flush get_conten...
  • a87b01c14
  • a87b01c14
  • 2016年08月03日 11:17
  • 1589

Cairo 图形指南 (6) —— 透明

这一篇讲述有关透明的一些基本知识,并提供两个有趣的透明效果。 透明是透过某种材质的可见度。理解透明最简单的方式就是想像一下玻璃或者水。从技术上讲,光线可以穿过玻璃,因此我们可以看到玻璃之后的物体...
  • jiangnanyidiao
  • jiangnanyidiao
  • 2014年10月21日 18:12
  • 883
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:The Cairo graphics tutorial -------Transparency
举报原因:
原因补充:

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