Debarshi's den

Archive for the ‘GIMP’ Category

Libre Graphics Meeting 2018

with 2 comments

I spent the last seven days attending Libre Graphics Meeting in sunny and beautiful Seville. This was my second LGM, the first being six years ago in Vienna, so it was refreshing to be back. I stayed in one of the GIMP apartments near the Alameda de Hércules garden square. Being right in the middle of the city meant that everything of interest was either within walking distance or a short bus ride away.

IMG_20180425_140117284

Unlike other conferences that I have been to, LGM 2018 started at six o’clock in the evening. That was good because one didn’t have to worry about waking up in time not to miss the opening keynote; and you haven’t attended LGM if you haven’t been to the State of Libre Graphics. Other than that I went to Øyvind’s presentation on colour; saw Nara describe her last ten years with Estúdio Gunga; and listened to Dave Crossland and Nathan Willis talk about fonts. There was a lot of live coding based music and algorave going on this year. My favourite was Neil C. Smith’s performance using Praxis LIVE.

IMG_20180425_155837676.jpg

All said and done, the highlight of this LGM had to be the GIMP 2.10.0 release at the beginning of the conference. GEGL 0.4.0 was also rolled out to celebrate the occasion. Much happiness and rejoicing ensued.

I spent my time at LGM alternating between delicious tapas, strolling down the narrow and colourful alleys of Seville, sight-seeing, and hacking on GEGL. I started sketching out a proper codec API for GeglBuffer modelled on GdkPixbuf, and continued to performance tune babl, but those are topics for later blog posts.

IMG_20180430_140438859~2

Written by Debarshi Ray

30 April, 2018 at 22:33

Image wrangling with GEGL: an introduction

with 6 comments

One of the core dependencies of GNOME Photos, other than GTK+ and Tracker, is a library called GEGL. It is a GObject-based image processing library primarily developed for GIMP. GEGL is used by Photos to load pixels from files, create thumbnails, edit, share and export images.

Unfortunately, even though GEGL is a powerful and generic image processing framework, it can be hard to find documentation and code samples to refer to, and the pool of people who understand it well enough is relatively small. I am going to do a series of blog posts to address this by feeding the search engines. Hopefully this will be useful for new contributors to GIMP and GNOME Photos, and some of it can be folded back into the reference GEGL documentation; or maybe it will encourage adoption in new and interesting places.

Nodes and operations

Processing images with GEGL requires the creation of a graph, represented by a GeglNode. A GeglNode can either have a number of child nodes connected to each other forming a directed acyclic graph, or it can have a GeglOperation. An operation is where the actual image processing takes place. Multiple operations are chained together in a graph to obtain the desired outcome.

This is enough to get started with some basic effects and enhancements. Here is a snippet that takes a path to an input image, enhances the blacks and saves it as a PNG.

  #include <gegl.h>
  …
  g_autoptr (GeglNode) graph = NULL;
  GeglNode *exposure;
  GeglNode *load;
  GeglNode *sink;

  graph = gegl_node_new ();
  load = gegl_node_new_child (graph,
                              "operation", "gegl:load",
                              "path", /* input path as C string */,
                              NULL);
  exposure = gegl_node_new_child (graph,
                                  "operation", "gegl:exposure",
                                  "black-level", 0.03,
                                  NULL);
  sink = gegl_node_new_child (graph,
                              "operation", "gegl:png-save",
                              "bitdepth", 8,
                              "path", /* output path as C string */,
                              NULL);

  gegl_node_link_many (load, exposure, sink, NULL);
  gegl_node_process (sink);

Notice the many similarities with GStreamer.

There is a whole list of such filters to choose from. Such as gegl:cartoon to simulate a cartoon drawn with a black felt pen, gegl:mosaic to transform an image into a mosaic, gegl:saturation to change the colourfulness of the image, or gegl:posterize, which is used by the similarly named tool in GIMP.

example-00

Buffers

Image pixels are held in a GeglBuffer. Most applications would directly interact with a GeglBuffer at one point or the other. For example, to decode an image file and carry the pixels around instead of repeatedly decoding them off the storage. In the above code sample, the buffers were implicitly created by GEGL unbeknownst to us, but we can use a similar graph to load pixels off a file into a GeglBuffer.

  #include <gegl.h>
  …
  g_autoptr (GeglBuffer) buffer = NULL;
  g_autoptr (GeglNode) graph = NULL;
  GeglNode *load;
  GeglNode *sink;

  graph = gegl_node_new ();
  load = gegl_node_new_child (graph,
                              "operation", "gegl:load",
                              "path", /* input path as C string */,
                              NULL);
  sink = gegl_node_new_child (graph,
                              "operation", "gegl:buffer-sink",
                              "buffer", &buffer,
                              NULL);

  gegl_node_link_many (load, sink, NULL);
  gegl_node_process (sink);

A loaded buffer can be then fed into a graph using a gegl:buffer-source.

As the custodian of pixels, GeglBuffer is similar to the role played by GdkPixbuf, but it has some extra features that are handy for image processing.

Most notably, a GeglBuffer is designed to handle massive images that are larger than the amount of physical RAM available on the system. Instead of holding all the pixels in a linear sequence of bytes, it splits them up into small tiles that can be paged out into a file when not in use. However, if necessary, it is possible to optionally dumb down a GeglBuffer by setting it up to use a single array of bytes, or forcing all tiles to be held in RAM.

A GeglBuffer is not restricted to a single pixel format such as RGB with 8 bits per channel. It can transparently handle a horde of formats — monochrome, Lab, HSL, etc. with different degrees of precision per channel. Finally, it is mipmap-capable.

All these features make GeglBuffer a very sophisticated data structure for storing image pixels. However, they aren’t that important for an introduction to GEGL, so we will save them for a future article.

Happy hacking

This is enough to start playing with GEGL. Here is the code used to create the above image, and is proof that knowing just this much is enough to do practically useful things.

Written by Debarshi Ray

20 November, 2017 at 13:30

Posted in C, GEGL, GIMP, GNOME, Photography, Photos

WilberWeek 2017

leave a comment »

For the past three days, I am in El Bruc, a little village on the side of Montserrat near Barcelona, for WilberWeek — the annual retreat for members of the GIMP and GEGL communities. We have rented out half of the Can Serrat art residency for 10 days of good food, idyllic surroundings, sedated discussions and a bit of moody hacking.

img_20170204_120425

So far, I have spent my time eating paella; understanding the nuances of non-destructive image editing from Øyvind Kolås; walking in the countryside; and poring over Darktable and Shotwell to learn the workings of various “exposure and blacks” tools and get RAW decoding right. I have vague expectations that this will greatly improve the image editing experience in GNOME Photos.

c3sajyuuyaiqace

c3qmzkowcaaup0r

I am grateful to the GIMP project for inviting me and sponsoring my stay, and especially to Jehan Pagès and Aryeom for coming all the way to Barcelona to pick me up.

Photographs featuring Wilber are from Michael Natterer’s Twitter feed.

Written by Debarshi Ray

4 February, 2017 at 13:56

Posted in Blogroll, GEGL, GIMP, Photos