Contenu | Menu

We have the typed images, and a generic image definition, with a basic (and very fragile, for the moment) text input/output format. It's time to decide how to organise the input-output to external standard formats, like PNG, TIFF, JPEG...

standard libraries

The first decision is to use only the standard and well-known, well-tested, well-distributed libraries to do it, and only #include the relevant headers; it may seem obvious, but it was not done like that until now. This means that:

This should not be a problem, as packages systems handle the dependencies. We may also provide an "all-inclusive" binary version of megawave, for quick tests. And it would solve all sorts of API/compiler/standard compatability issues.

And by "standard libraries", I mean libpng, libtiff, libjpeg, jasper, giflib, netpbm, ...

By the way, I can't find any "standard" library for the BMP files. But who need BMP file?

structures and formats

The main question is then «how should we handle the multiplicity?». We currently have 3 internal raster image formats (based on uint8, uint16 and flt32); we may add sooner or later the other natural types (uint32, uint64 and flt64), counting to 6. If we implement the color images as different structures (which is not certain), it would double this number. Then, later, why not 3D-images (if they are not the same thing as movies).

The natural image file formats are png and jpeg. Legacy formats, like pnm, tiff, gif can be useful too. And jpeg2000. Same for scientific data formats like netcdf of dicom. And then we will have to think about extracting frames from mpeg, avc, vp (and variants), huffyuv (lossless) video?

Basically, we have many internal structures, and we want to be able to fill them from many different kinds of external files.

in / out matrix

Let's just consider 3 internal structures, and 3 file formats. The naive design, ie one function per input/output couple, looks like that:
design 1.png
design 1.dot design 1.svg

So, 9 functions for the moment, with lots of code duplication. Then, if we want to add one file format, we need to write 4 functions (the generic load_foo plus the three load_foo_xx interfaces), and modify 3 other ones (load_xximage). This will grow exponentially, the the result will be a lot of unmaintainable code.

multiple in / multiple out

One simplification is to remove the matrix, and allow direct dialogue between the "image" side and the "file" side.
design 2 direct.png
design 2 direct.dot design 2 direct.svg

The it would be somehow more easy to add a new format, we still need to update many new functions each time we want to add support for a new format; this big "cross-interaction" at the center has to be removed.

front-ends

The same design, with front-ends added, limits the dependencies.
design 2 indirect.png
design 2 indirect.dot design 2 indirect.svg

Now, each time we add a new format, there is one new function to write (load_foo) and one to update (load_file). And the two different parts of the code ("image" and "file") are connected by a single interface.

One problem remains: the load_file functions must be able to return different outputs, depending on who called them.

This could be done by:

details

The solution is to split the process in two parts:

  1. gather meta-information from the file (shape, data type, layers...), then create the empty mw_xximage structure and allocate the correct memory size
  2. gather the image data, filled in the memory area whose address is passed as a parameter

This work-flow would look like that:
design detail.png
design detail.dot design detail.svg

This design is modular; for example,