The graphics brethren: basegfx and basebmp
Started in late 2002, OOo's module basegfx is now a pretty mature collection of data structures and algorithms for graphics processing. The set of exported headers sport abstract data types such as:
- points, vectors, boxes, ranges, bezier curves
- matrices
- polygons and collections of polygons ("poly-polygons")
- 1D, 2D, 3D
- integer and double-precision floating point
In addition, especially the polygon ADTs are shipped with a set of associated algorithms (provided as free functions, instead of member functions):
- a poly-polygon clipper (comparable to what gpc is doing)
- a poly-polygon triangulator (convert a polygon to triangles, which can be fed to a GPU)
- a function to generate stroked paths from a given polygon
- plus a lot of basic, but very useful stuff (like svg im/export, scan conversion, arc and circle generation, etc.)
What's missing, though, is everything related to bitmaps. That's where basebmp comes into play, started a few weeks ago and set to provide for pixel processing, what basegfx provides for the symbolic graphics primitives.
I've initially started this work by using AGG, but quickly found out that adding pixel formats other than integer true color ones is pretty hard (Because the code is largely undocumented. Because the assumption that pixel values can be modified by shift left and right operations, and are PODs (i.e. non-class types) is all over the place. And because basically, a way to somehow get a hold to the famous extra level of indirection is missing. Which, as usual, would have solved this software engineering problem). Instead of starting from scratch, we've based this on vigra, a framework for generic image processing, which provides an elegant way to add 'special processing' before an actual pixel gets assigned a value.
In order to really get to the point here, I first need to sketch the way generic bitmap processing works: it's the idea of separating data access and the actual bitmap manipulation algorithm, using C++ templates. The concept is borrowed from the STL - bitmap pixel can be accessed by (two-dimensional) iterators, which in a very basic sense behave like a pointer:
while( i!=end )
*i++ = rand();
If i is a bitmap iterator, the pixel will be set to
random values with this algorithm. The type of i can be chosen freely,
and so can the actual pixel format of the bitmap. If one wants to
e.g. add palette lookup to this algorithm (or scale the random values
into the appropriate color range) without changing the algorithm's code, either extremely ugly hacks
involving proxy objects are necessary (because operator*() is expected
to return an lvalue, which gets assigned the new value directly), or
one needs a direct way to 'see' both the iterator and the new value
prior to assignment:
while( i!=end )
acc.set(i++, rand());
The acc variable is a pixel accessor in vigra lingo,
which takes the iterator and the new value, and accesses the
corresponding pixel. Now, adding palette lookup, scaling, blending,
mask operations and much more is as easy as providing a different
accessor to the algorithms is. Plus, it's completely orthogonal to
both the iterator implementation, and the algorithm used. That means,
you define a set of iterators (for packed-pixel images, for r8g8b8
images, for r5g6r5 images), a set of accessors (for true color pixel,
for palette lookup, for blitting through a binary mask), and a set of
algorithms. And you combine all those freely, i.e. you have the
cartesian product of variations to choose from.
Posted at 02:00AM Jul 17, 2006 by thorsten in OpenOffice.org |