Proposal: User-provided pixel bits without copy

Developers
2014-02-12
2014-05-23
  • Hi,
    FreeImage lacks a feature, present in many other image manipulation suits:
    The possibility to wrap any foreign pixel data without allocating internal storage.

    This makes common scenarios perform much worse then needed, like simply saving a screenshot; others are completely impossible - manipulate user data directly (in-place spawRgb, flip, etc).

    I propose a simple patch to enable these scenarios:
    https://sourceforge.net/p/freeimage/patches/86/

    The implementation is trivial:
    There is a new internal FreeImage_AllocateHeaderT2 function that accepts BYTE* bits, unsigned pitch arguments.
    If these are provided the FIBITMAP will be allocated as "header only", but bits and pitch will be stored within the FREEIMAGEHEADER and the resulting FIBITMAP will have pixels (HasPixels() will return true).

    • GetBits() and GetPitch return the correct values - either offsets (as usual) or the stored values (user-provided bits and pitch).
    • Clone() creates a new FIBITMAP with copy of the user pixel data.
    • Unload's implementation does not need to change - it just release a "header only" dib.

    Interesting ramification: The data does not have to be the same alignment as the default 4 byte alignment!
    This enables the possibility to access buffers with, for instance, stricter alignment like the ones, used in low-level APIs like OpenCL or intrinsics.

    Interesting future extension: It should easy be to implement loading into user-provided buffer.
    All is needed is to have a new load method that takes an dib as an argument, and a way to attach user pixels to a header-only dib. The latter is trivial.
    Here a possible user scenario:
    - User Loads using LOAD_NO_PIXELS flag, available today.
    - User examines the returned dib and attaches a (possibly preallocated) pixel buffer of the correct format.
    - User Loads again, passing the modified dib as an argument, receiving complete dib with pixels, stored in provided location.
    (Internally FreeImage will skip allocation and use the passed dib as if it is complete)

    All this combined will make FreeImage much more flexible in what it does best - lightweight image I/O.

    thanks
    MihailNaydenov

     
  • Another use-case is to define a "view" (Viewport in ImageMagic, ROI in OpenCV).
    This has many uses - one can slice a big image into many smaller ones without allocating and then copying each slice; some image operations require a final crop stage on the result (rotate is a classic example), now this cropping can be "virtual", without allocation and copy.
    I have added a small test-case as a comment to the patch.

     
  • Hervé Drolon
    Hervé Drolon
    2014-04-05

    Hi to all,

    The patch provided by Mihail is now merged with the CVS.
    Many thanks Mihail for this very good addition to the library !
    This is both very simple to use and powerful for FreeImage interoperability with e.g. OpenCV or QT.

    Hervé

     
  • Jorge Diogo
    Jorge Diogo
    2014-04-14

    Hi,

    This is really an improvement and thanks for adding it to FreeImage, but I've noticed that there is another issue preventing a copy-free loading and saving of an image buffer which is the vertical flip. FreeImage loads images bottom up with the last image row being the first in memory.
    If there was a way, maybe a Load/Save flag so that the image could be loaded/saved with the top row being the first in memory this would completely avoid the copy (flip) in all the cases where the image is needed in top-bottom vertical orientation.

    Best Regards!

     
  • @Jorge Diogo Vertical flip is copy-free! Just do it yourself before save (and after). To add the suggested flag all plugins must be changed!