Ecore_Evas buffer example

Between the Evas examples, there is one in which one creates a canvas bound to the Evas buffer engine and uses its pixel contents to create an PPM image on disk.

There, one does that by creating the canvas "by hand", with `evas_new()`, `evas_engine_info_set()`, etc.

On this example, we accomplish the very same task, but by using the `Ecore_Evas` helper wrapper functions on a buffer engine canvas. If you compare both codes, you'll see how much code one is saved from by using the `Ecore_Evas` wrapper functions.

The code is simple as it can be. After instantianting our canvas window, with ecore_evas_buffer_new(), we grab its canvas pointer and create the desired objects scene on it, which in this case is formed by 3 rectangles over the top left corner of a white background:

main(void)
{
Evas *canvas;
Evas_Object *bg, *r1, *r2, *r3;
ecore_evas_init();
ee = ecore_evas_buffer_new(WIDTH, HEIGHT);
if (!ee) goto error;
canvas = ecore_evas_get(ee);
bg = evas_object_rectangle_add(canvas);
evas_object_color_set(bg, 255, 255, 255, 255); /* white bg */
evas_object_move(bg, 0, 0); /* at origin */
evas_object_resize(bg, WIDTH, HEIGHT); /* covers full canvas */
evas_object_show(bg);
r1 = evas_object_rectangle_add(canvas);
evas_object_color_set(r1, 255, 0, 0, 255); /* 100% opaque red */
evas_object_move(r1, 10, 10);
evas_object_resize(r1, 100, 100);
evas_object_show(r1);
r2 = evas_object_rectangle_add(canvas);
evas_object_color_set(r2, 0, 128, 0, 128); /* 50% opaque green */
evas_object_move(r2, 10, 10);
evas_object_resize(r2, 50, 50);
evas_object_show(r2);
r3 = evas_object_rectangle_add(canvas);
evas_object_color_set(r3, 0, 128, 0, 255); /* 100% opaque dark green */
evas_object_move(r3, 60, 60);
evas_object_resize(r3, 50, 50);
evas_object_show(r3);
ecore_evas_init
EAPI int ecore_evas_init(void)
Inits the Ecore_Evas system.
Definition ecore_evas.c:608
ecore_evas_get
EAPI Evas * ecore_evas_get(const Ecore_Evas *ee)
Gets an Ecore_Evas's Evas.
Definition ecore_evas.c:1314
ecore_evas_buffer_new
EAPI Ecore_Evas * ecore_evas_buffer_new(int w, int h)
Creates a new Ecore_Evas canvas bound to the Evas buffer engine.
Definition ecore_evas_buffer.c:895
Evas
Eo Evas
An opaque handle to an Evas canvas.
Definition Evas_Common.h:163
evas_object_show
EVAS_API void evas_object_show(Evas_Object *eo_obj)
Makes the given Evas object visible.
Definition evas_object_main.c:1814
evas_object_color_set
EVAS_API void evas_object_color_set(Evas_Object *obj, int r, int g, int b, int a)
Sets the general/main color of the given Evas object to the given one.
Definition evas_object_main.c:2024
evas_object_move
EVAS_API void evas_object_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
Move the given Evas object to the given location inside its canvas' viewport.
Definition evas_object_main.c:1171
Evas_Object
Efl_Canvas_Object Evas_Object
An Evas Object handle.
Definition Evas_Common.h:185
evas_object_resize
EVAS_API void evas_object_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
Changes the size of the given Evas object.
Definition evas_object_main.c:1236
evas_object_rectangle_add
EVAS_API Evas_Object * evas_object_rectangle_add(Evas *e)
Adds a rectangle to the given evas.
Definition evas_object_rectangle.c:78

Since it's a buffer canvas and we're using it to only save its contents on a file, we even needn't ecore_evas_show() it. We make it render itself, forcefully, without the aid of Ecore's main loop, with ecore_evas_manual_render():

ecore_evas_manual_render(ee);
ecore_evas_manual_render
EAPI void ecore_evas_manual_render(Ecore_Evas *ee)
Forces immediate rendering on a given Ecore_Evas window.
Definition ecore_evas.c:2659

And we're ready to save the window's shiny rendered contents as a simple PPM image. We do so by grabbing the pixels of the `Ecore_Evas'` internal canvas, with ecore_evas_buffer_pixels_get():

_scene_save(Evas *canvas,
const char *dest)
{
const unsigned int *pixels, *pixels_end;
int width, height;
FILE *f;
evas_output_size_get(canvas, &width, &height);
f = fopen(dest, "wb+");
if (!f)
{
fprintf(stderr, "ERROR: could not open for writing '%s': %s\n",
dest, strerror(errno));
return;
}
evas_output_size_get
EVAS_API void evas_output_size_get(const Evas *eo_e, int *w, int *h)
Retrieve the output size of the render engine of the given evas.
Definition evas_main.c:1402
/* support function to save scene as PPM image */
static void
_scene_save(Evas *canvas,
const char *dest)
{
const unsigned int *pixels, *pixels_end;
int width, height;
FILE *f;
evas_output_size_get(canvas, &width, &height);
f = fopen(dest, "wb+");
if (!f)
{
fprintf(stderr, "ERROR: could not open for writing '%s': %s\n",
dest, strerror(errno));
return;
}
pixels = ecore_evas_buffer_pixels_get(ee);
pixels_end = pixels + (width * height);
/* PPM P6 format is dead simple to write: */
fprintf(f, "P6\n%d %d\n255\n", width, height);
for (; pixels < pixels_end; pixels++)
{
int r, g, b;
r = ((*pixels) & 0xff0000) >> 16;
g = ((*pixels) & 0x00ff00) >> 8;
b = (*pixels) & 0x0000ff;
fprintf(f, "%c%c%c", r, g, b);
}
ecore_evas_buffer_pixels_get
EAPI const void * ecore_evas_buffer_pixels_get(Ecore_Evas *ee)
Grabs a pointer to the actual pixels array of a given Ecore_Evas buffer canvas/window.
Definition ecore_evas_buffer.c:917
fclose(f);
printf("Saved scene as '%s'\n", dest);
}

Check that destination file for the result. The full example follows.

#ifdef HAVE_CONFIG_H
#include "config.h"
#else
#define EINA_UNUSED
#endif
#include <Ecore_Evas.h>
#include <stdio.h>
#define WIDTH (320)
#define HEIGHT (240)
static Ecore_Evas *ee;
/* support function to save scene as PPM image */
static void
_scene_save(Evas *canvas,
const char *dest)
{
const unsigned int *pixels, *pixels_end;
int width, height;
FILE *f;
evas_output_size_get(canvas, &width, &height);
f = fopen(dest, "wb+");
if (!f)
{
fprintf(stderr, "ERROR: could not open for writing '%s': %s\n",
dest, strerror(errno));
return;
}
pixels = ecore_evas_buffer_pixels_get(ee);
pixels_end = pixels + (width * height);
/* PPM P6 format is dead simple to write: */
fprintf(f, "P6\n%d %d\n255\n", width, height);
for (; pixels < pixels_end; pixels++)
{
int r, g, b;
r = ((*pixels) & 0xff0000) >> 16;
g = ((*pixels) & 0x00ff00) >> 8;
b = (*pixels) & 0x0000ff;
fprintf(f, "%c%c%c", r, g, b);
}
fclose(f);
printf("Saved scene as '%s'\n", dest);
}
int
main(void)
{
Evas *canvas;
Evas_Object *bg, *r1, *r2, *r3;
ecore_evas_init();
ee = ecore_evas_buffer_new(WIDTH, HEIGHT);
if (!ee) goto error;
canvas = ecore_evas_get(ee);
bg = evas_object_rectangle_add(canvas);
evas_object_color_set(bg, 255, 255, 255, 255); /* white bg */
evas_object_move(bg, 0, 0); /* at origin */
evas_object_resize(bg, WIDTH, HEIGHT); /* covers full canvas */
evas_object_show(bg);
r1 = evas_object_rectangle_add(canvas);
evas_object_color_set(r1, 255, 0, 0, 255); /* 100% opaque red */
evas_object_move(r1, 10, 10);
evas_object_resize(r1, 100, 100);
evas_object_show(r1);
r2 = evas_object_rectangle_add(canvas);
evas_object_color_set(r2, 0, 128, 0, 128); /* 50% opaque green */
evas_object_move(r2, 10, 10);
evas_object_resize(r2, 50, 50);
evas_object_show(r2);
r3 = evas_object_rectangle_add(canvas);
evas_object_color_set(r3, 0, 128, 0, 255); /* 100% opaque dark green */
evas_object_move(r3, 60, 60);
evas_object_resize(r3, 50, 50);
evas_object_show(r3);
ecore_evas_manual_render(ee);
_scene_save(canvas, "/tmp/evas-buffer-simple-render.ppm");
ecore_evas_free(ee);
ecore_evas_shutdown();
return 0;
error:
fprintf(stderr, "error: Requires at least one Evas engine built"
" and linked to ecore-evas for this example to run"
" properly.\n");
ecore_evas_shutdown();
return -1;
}
Ecore_Evas.h
Evas wrapper functions.
ecore_evas_shutdown
EAPI int ecore_evas_shutdown(void)
Shuts down the Ecore_Evas system.
Definition ecore_evas.c:672
ecore_evas_free
EAPI void ecore_evas_free(Ecore_Evas *ee)
Frees an Ecore_Evas.
Definition ecore_evas.c:1097