Debarshi's den

Archive for the ‘Photography’ Category

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.

Advertisements

Written by Debarshi Ray

20 November, 2017 at 13:30

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

Robbed. Camera gone.

with 3 comments

We got robbed in Barcelona the day before yesterday. It happened a little after 23:00 hr on the Passeig de Colom. We could have lost more, but in the end it was just my Canon EOS 60D with the EF-S 18-135mm f/3.5-5.6 IS lens attached to it.

We filed a report at the police station on Carrer Nou de la Rambla with the serial numbers of the devices. We believe we have identified one of the two robbers — the one who had confronted us from the front. I must say that the police were friendly and helpful, and they had people who spoke good English.

But that is not the point of this blog post.

Thanks to my friend, Arjun, we figured out that the EXIF data has the serial number of the camera and the lens embedded in it; and if, like me, you upload your photos to Flickr, you can easily see all the metadata even if you do not have any fancy photography software at hand. This makes me wonder if it is possible for websites like Flickr or Facebook or Imgur to flag uploads originating from a tainted device. Client-side programs could do this too. I guess, this needs some kind of stolen cameras and lenses database, which could be tricky. Does something like this exist?

Anyway, I will leave the details of my stolen camera and lens here to leave a trail in the sands of the Internet.

  • Serial number: 1881125429
  • Internal serial number: WB0778966
  • Lens serial number: 0000124725

Written by Debarshi Ray

15 December, 2013 at 13:37

Short-listed for Schmap Helsinki Guide

leave a comment »


aleksanterinkatu-4

Originally uploaded by debarshi2001in

Came to know yesterday that this photo has been short-listed for the tenth edition of the Schmap Helsinki Guide. The photo was taken on Aleksanterinkatu.

Written by Debarshi Ray

4 February, 2010 at 17:49

Posted in Helsinki, Photography