Cairo FAQ Images in Cairo

Материал из Wiki.crossplatform.ru

(Различия между версиями)
Перейти к: навигация, поиск
(Новая: In this part of the Cairo graphics tutorial, we will talk about the images. We will show how to display an image on the GTK window. We will also create some effects with images. == Disp...)
(Удалено по требованию автора...)
 
(1 промежуточная версия не показана)
Строка 1: Строка 1:
-
In this part of the Cairo graphics tutorial, we will talk about the images. We will show how to display an image on the GTK window. We will also create some effects with images.
 
-
== Displaying an image ==
 
-
 
-
In the first example, we will display an image.
 
-
 
-
<source lang="cpp">
 
-
#include <cairo.h>
 
-
#include <gtk/gtk.h>
 
-
 
-
cairo_surface_t *image;
 
-
 
-
static gboolean
 
-
on_expose_event(GtkWidget *widget,
 
-
    GdkEventExpose *event,
 
-
    gpointer data)
 
-
{
 
-
  cairo_t *cr;
 
-
 
-
  cr = gdk_cairo_create (widget->window);
 
-
 
-
  cairo_set_source_surface(cr, image, 10, 10);
 
-
  cairo_paint(cr);
 
-
 
-
  cairo_destroy(cr);
 
-
 
-
  return FALSE;
 
-
}
 
-
 
-
 
-
int main(int argc, char *argv[])
 
-
{
 
-
  GtkWidget *window;
 
-
 
-
  image = cairo_image_surface_create_from_png("plaveckycastle.png");
 
-
 
-
  gtk_init(&argc, &argv);
 
-
 
-
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
-
 
-
  g_signal_connect(window, "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), 320, 250);
 
-
  gtk_widget_set_app_paintable(window, TRUE);
 
-
 
-
  gtk_widget_show_all(window);
 
-
 
-
  gtk_main();
 
-
 
-
  cairo_surface_destroy(image);
 
-
 
-
  return 0;
 
-
}
 
-
 
-
</source>
 
-
 
-
The example displays an image. The image size is 300x225. These are ruins of a medieval castle in Plavecke Podhradie in western part of the Slovakia.
 
-
 
-
<source lang="cpp">
 
-
image = cairo_image_surface_create_from_png("plaveckycastle.png");
 
-
</source>
 
-
 
-
We create an image surface from a png image. For efficiency reasons, the function is called in the main function.
 
-
 
-
<source lang="cpp">
 
-
cairo_set_source_surface(cr, image, 10, 10);
 
-
</source>
 
-
 
-
We create a source for painting from the previously created image surface.
 
-
 
-
<source lang="cpp">
 
-
cairo_paint(cr);
 
-
</source>
 
-
 
-
We paint the source on the window.
 
-
 
-
[[image: cairo_faq_castleimage.png | center]]
 
-
 
-
== Blind down effect ==
 
-
 
-
In this code example, we will blind down our image. This is similar to what we do with a roller-blind.
 
-
 
-
<source lang="cpp">
 
-
#include <cairo.h>
 
-
 
-
#include <gtk/gtk.h>
 
-
 
-
 
-
gboolean timer = TRUE;
 
-
cairo_surface_t *image;
 
-
 
-
 
-
static gboolean
 
-
on_expose_event(GtkWidget *widget,
 
-
    GdkEventExpose *event,
 
-
    gpointer data)
 
-
{
 
-
  cairo_t *cr;
 
-
  cairo_t *ic;
 
-
 
-
  cairo_surface_t *surface;
 
-
 
-
  static gdouble angle = 0;
 
-
  static gint image_width = 0;
 
-
  static gint image_height = 0;
 
-
 
-
  static gint w = 0;
 
-
  static gint h = 0;
 
-
 
-
  cr = gdk_cairo_create(widget->window);
 
-
 
-
  gint width, height;
 
-
  gtk_window_get_size(GTK_WINDOW(widget), &width, &height);
 
-
 
-
  image_width = cairo_image_surface_get_width(image);
 
-
  image_height = cairo_image_surface_get_height(image);
 
-
  w = image_width;
 
-
 
-
  surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, image_width, image_height);
 
-
  ic = cairo_create(surface);
 
-
 
-
  cairo_rectangle(ic, 0, 0, w, h);
 
-
  cairo_fill(ic);
 
-
 
-
  h += 1;
 
-
  if ( h == image_height) timer = FALSE;
 
-
 
-
  cairo_set_source_surface(cr, image, 10, 10);
 
-
  cairo_mask_surface(cr, surface, 10, 10);
 
-
 
-
  cairo_surface_destroy(surface);
 
-
 
-
  cairo_destroy(cr);
 
-
  cairo_destroy(ic);
 
-
  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;
 
-
 
-
  image = cairo_image_surface_create_from_png("plaveckycastle.png");
 
-
 
-
  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), 325, 250);
 
-
  gtk_window_set_title(GTK_WINDOW(window), "blind down");
 
-
 
-
  gtk_widget_set_app_paintable(window, TRUE);
 
-
  g_timeout_add(15, (GSourceFunc) time_handler, (gpointer) window);
 
-
 
-
  gtk_widget_show_all(window);
 
-
 
-
  gtk_main();
 
-
 
-
  cairo_surface_destroy(image);
 
-
 
-
  return 0;
 
-
}
 
-
</source>
 
-
 
-
The idea behind the blind down effect is quite simple. The image is h pixels high. We draw 0, 1, 2 ... lines of 1px height, each cycle the portion of the image is 1px higher, until the whole image is visible.
 
-
 
-
<source lang="cpp">
 
-
 
-
cairo_t *cr;
 
-
cairo_t *ic;
 
-
</source>
 
-
 
-
We declare two cairo contexts. One will be tied to a GtkWindow and the other one to an image.
 
-
 
-
<source lang="cpp">
 
-
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, image_width, image_height);
 
-
ic = cairo_create(surface);
 
-
</source>
 
-
 
-
Here we create an image surface. An from this surface, we create a cairo context.
 
-
 
-
<source lang="cpp">
 
-
cairo_rectangle(ic, 0, 0, w, h);
 
-
cairo_fill(ic);
 
-
</source>
 
-
 
-
We will draw into the initially empty image a rectagle. The rectangle will be 1px higher each cycle. The image created this way will serve as a mask later.
 
-
 
-
<source lang="cpp">
 
-
  h += 1;
 
-
  if ( h == image_height) timer = FALSE;
 
-
</source>
 
-
 
-
We stop the timer function, when we draw the whole image on the GTK window.
 
-
 
-
<source lang="cpp">
 
-
cairo_set_source_surface(cr, image, 10, 10);
 
-
cairo_mask_surface(cr, surface, 10, 10);
 
-
</source>
 
-
 
-
The image of a castle is set as a source for painting. The <b>cairo_mask_surface()</b> paints the current source using the alpha channel of surface as a mask.
 
-
 
-
== The spectrum effect ==
 
-
 
-
I call this a spectrum effect, because I do not have a better name for it. Maybe some of you remember the old times with ZX Spectrum computer. When you were loading an image into this computer, it was gradually appearing on the screen.
 
-
The next example is loosly based on this experience.
 
-
 
-
<source lang="cpp">
 
-
#include <cairo.h>
 
-
#include <gtk/gtk.h>
 
-
 
-
 
-
gboolean timer = TRUE;
 
-
cairo_surface_t *image;
 
-
 
-
static gboolean
 
-
on_expose_event(GtkWidget *widget,
 
-
    GdkEventExpose *event,
 
-
    gpointer data)
 
-
{
 
-
  cairo_t *cr;
 
-
  cairo_t *ic;
 
-
 
-
  cairo_surface_t *surface;
 
-
 
-
  static gdouble angle = 0;
 
-
  static gint w = 0;
 
-
  static gint h = 0;
 
-
 
-
  static gint image_width = 0;
 
-
  static gint image_height = 0;
 
-
 
-
  static gint count = 0;
 
-
 
-
  cr = gdk_cairo_create(widget->window);
 
-
 
-
  gint width, height;
 
-
  gtk_window_get_size(GTK_WINDOW(widget), &width, &height);
 
-
 
-
  surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, image_width, image_height); 
 
-
 
-
  image_width = cairo_image_surface_get_width(image);
 
-
  image_height = cairo_image_surface_get_height(image);
 
-
  w = image_width; 
 
-
 
-
  ic = cairo_create(surface);
 
-
 
-
  gint i, j;
 
-
  for (i = 0; i <= image_height; i+=7) {
 
-
      for (j=0 ; j < count; j++) {
 
-
          cairo_move_to(ic, 0, i+j);
 
-
          cairo_line_to(ic, w, i+j);
 
-
      }
 
-
  }
 
-
 
-
  count++;
 
-
  if ( count == 8) timer = FALSE;
 
-
 
-
  cairo_stroke(ic);
 
-
 
-
  cairo_set_source_surface(cr, image, 10, 10);
 
-
  cairo_mask_surface(cr, surface, 10, 10);
 
-
 
-
  cairo_surface_destroy(surface);
 
-
 
-
  cairo_destroy(cr);
 
-
  cairo_destroy(ic);
 
-
  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;
 
-
 
-
  image = cairo_image_surface_create_from_png("plaveckycastle.png");
 
-
 
-
  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), 325, 250);
 
-
 
-
  gtk_widget_set_app_paintable(window, TRUE);
 
-
  g_timeout_add(400, (GSourceFunc) time_handler, (gpointer) window);
 
-
 
-
  gtk_widget_show_all(window);
 
-
 
-
  gtk_main();
 
-
 
-
  cairo_surface_destroy(image);
 
-
 
-
  return 0;
 
-
}
 
-
 
-
</source>
 
-
 
-
In most details, the example is similar to the previous one. This time, we divide the image into n parts consisting of 8 lines.
 
-
Each cycle each part of the image will get bigger by one pixel. The created image will serve again as a mask for displaying the image of the castle.
 
-
 
-
<source lang="cpp">
 
-
gint i, j;
 
-
for (i = 0; i <= image_height; i+=7) {
 
-
    for (j=0 ; j < count; j++) {
 
-
        cairo_move_to(ic, 0, i+j);
 
-
        cairo_line_to(ic, w, i+j);
 
-
    }
 
-
}
 
-
</source>
 
-
 
-
Here is the main logic behind the example. We gradully draw lines into each of the n parts.
 
-
 
-
[[image: cairo_faq_spectrum.png | center]]
 
-
 
-
[[Категория:GTK+]]
 
-
[[Категория:Cairo]]
 

Текущая версия на 11:31, 7 апреля 2009