The RAPP library design is based on a few basic principles:
Only native (C99) types in function arguments.
Although the interface may look simpler if images are encapsulated in structures, it is often more awkward to use that from higher-level code. Higher-level algorithm code often has its own encapsulated image object. By forcing the use of a RAPP image object, that code would either have to use the RAPP image object type also, or convert its own objects for RAPP function calls.
Images must be aligned in memory.
It is often significantly more efficient to process aligned data than misaligned data. This could be hidden from the user by using separate internal processing functions dependent on alignment. However, this would make it easy to unintentionally use slow operations on misaligned data. An interface that explicitly requires aligned images will force the user to align the data once and then benefit from the faster aligned processing functions. Also, the library will contain much fewer functions to test for correctness, which means less bugs.
Binary images are 1 bit per pixel.
Binary images are stored as 1 bit-per-pixel bitmaps. In this format it it more difficult to read and write individual pixels, but the processing of binary images can be accelerated more than an order of magnitude in many cases.
8-bit images are unsigned.
To keep the number of flavours per operation to a minimum, we want a single 8-bit data format. 8-bit unsigned integers is the obvious choice for unsigned data. For signed data, we add a bias of 128 and use the unsigned data format. With this convention, the processing functions do not need to know about the how the data is to be interpreted. To convert a pixel buffer between this unsigned-with-bias format and the standard two's complement representation, use rapp_pixop_flip_u8().
No internal memory allocation.
The caller is responsible for allocating pixel buffers. This makes it easier to use different memory areas for different buffers, and also optimize and reuse memory allocations between RAPP calls.
Errors are indicated by return value error codes.
All RAPP functions must validate its arguments and return an error code if there is an error. It is up to the user to check this return value and handle the error.
Favour maintainability over last-percent performance.
It might be slightly more optimal to implement platform-specific assembly functions. This is a nightmare to test and maintain. The unified vector abstraction layer in RAPP provides a platform-independent SIMD abstraction that makes it much easier to implement new functions on any SIMD hardware.