Aug 2007

etu: Hitting a Crossroad in a Simple Program

Or another way of saying if the route to take seems obvious then it is probably the correct route [1]. When dealing with a software system the obvious route may not always seem so simple. In fact, one might need to go back to the beginning of their particular project to see what route might be either the best or at least most correct. In this text, a program called etu is examined. This tiny program (at least by itself) came upon a crossroad of sorts and the simplest answers turned out to be the best route to take.

Background

A while ago the first pass at creating a jpeg thumb-nailer that leveraged the enlightenment epeg API was written as a demonstration program. The little (and fast) thumb utility that could turned out to be pretty handy. So, etu received a few small upgrades such as:

  • Better file handling.
  • The capability to do single directories.
  • Long and short options support.

... and etu was happy, until one day, someone asked:

Why does it only do jpegs?

The immediate answer was:

Because that is what it was designed to do in the beginning ...

Taking a look back at the original program, however, it became obvious that even with the small enhancements it had received already, the program had grown from doing one image file to a directory full of N files. So why should it not support other formats? The enlightenment suite of software addresses thumb-nailing and scaling by default. Adding support for an ad-hoc image scaling program should not be too difficult.

Goals

There were three goals that emerged in order to accommodate non jpeg image format support in etu:

  1. The infrastructure around etu needed to be in sync with how other enlightenment software is built.
  2. Image type decoding beyond using filename extensions [2].
  3. Finding internal enlightenment APIs that could do the scaling and hence remain consistent with the overall goal of the program.

Infrastructure

A lot of software requires something to stand it up before it can be built. Usually standing up means something like bootstrapping, however, in the case of etu it only needed to conform to the enlightenment method of building software. The etu program could already be built from a very plain Makefile. The motivation for integrating it into how other enlightenment software is built was simple:

If it happens twice, it will happen again...

Qualifier; someone asked one question already which created the two former goals - if the software continues to work (hopefully it works well) there is a high probability of more questions; ergo more changes. To better track the nuances of a developing software system such as enlightenment it is a far wiser thing to make sure etu can plug in and leverage the pre-existing infrastructure of the entire software system.

Understanding the concept of adapting to someone (or some persons) software system configuration is key and requires a degree of adaptability; whether the adaptation consists of how it is built or something as simple as comment style. It is especially important in larger groups where the outside code is being created long after the system itself was started (which was the case with etu [3].

Regardless of motivation, the actual work while somewhat tedious was relatively simple. Using a pre existing eapp that was fairly small provided a basic framework pieces for the directory layout, auto-configuration and flag/library options.

Image Decoding

After discussing the issue with a C-hacker friend, the first approach to image type decoding was to actually use a two pass algorithm:

        Determine type by extension
        If (jpg,jpeg,JPG,JPEG,Jpeg...)
                        Load image into epeg
                                If fail
                                        Determine type using UNIX magic_number
                                        call non-epeg scaler
                                Else
                                        call epeg-scalar
        Else
                call non-epeg scaler

The two passes being if it is and oh nuts it is not.

There is a serious logic flaw in the above. Efficiency: if the image is not jpeg format, what if it is still a format that will not work? Do all of the formats have to be explicitly checked for? How much work in this tiny program would be expended doing so? Imagine having to build an internal translation table for magic numbers. The possibility of having to do all of that work not only seemed ugly but counterintuitive to the whole point of the program which is:

Leverage Enlightenment developed software at every possible turn to create a simple yet powerful ad-hoc image scaling program.

An obvious answer arrived simply by digging around the entire e17 repository - Imlib2 could determine the image type in a few relatively simple steps. The plus, etu only cares if the image is a jpeg or _not_ which makes the logic extraordinarily simple:

        Load image into Imlib2
        Get Image type
        Free Image from Imlib2
        If image is jpeg
                call epeg-scaler
        Else
                call non-epeg scaler

Much better, much simpler and hopefully faster.

The Non-Epeg Scaler

The last piece of the puzzle was the fall through to a non jpeg image. Of course long time users of Enlightenment already know the answer but at the time, the mentality was use anything and everything that already exists and is specific to the new(er) Enlightenment software system. Instead of taking the obvious route, the first route was to do something else altogether.

There exist with the ever-changing enlightenment system several libraries that do image scaling. The first pass of non-jpeg support for etu used one of them. As it turned out, that API was designed only for cache style systems, not ad-hoc resizing. Several hours of trying to shoehorn in another API finally resulted in abandoning the idea. The search almost led to abandoning non-jpeg support at all.

Then the obvious struck .... Imlib2 can do it, actually it already had code designed for that very purpose the difference between the existing code and etu is that etu can do larger grouped operations and has somewhat finer control. With the last piece of the puzzle in place, the rest was pretty simple.

Summary

Sometimes the answer is staring you right in the face, so much so that you actually used the same answer for a different problem. It is said the road less travelled is more interesting (or something to that effect), however, if someone else has been down the road, and has a map, and a guide to the best places to eat - then you might want to take advantage of that information - ultimately it could save a lot of time.

Footnotes
  1. Then there is acoms razor which states (paraphrasing) the simplest solution is often the correct one.
  2. I am not a big fan of using filename extensions by themselves and if I can avoid it - I will.
  3. By no means is the concept of style or config conformity unique to the Enlightenment Foundation. All of the BSD projects and the Linux kernel (and many more) have guides that cover everything from style to API design.
Credits

I would be remiss if I did not acknowledge the help I received from Rasterman himself (who basically steered me) and my good friend Gleicon da Silveira Moraes (aka Tuna) who was (and often is) the sounding board for my C past times.