[ome-devel] [ome-files] Copying ROI from C++ Array to VariantPixelBuffer

Roger Leigh rleigh at dundee.ac.uk
Tue May 15 12:08:09 BST 2018


On 15/05/18 00:19, Dennis Ai wrote:
> Hi OME Team,
>
> As part of the image acquisition pipeline we are developing, I would
> like to be able to selectively copy a 3D-ROI into a VariantPixelBuffer
> so it can be written to an OME-TIFF.  In the documentation
> <https://docs.openmicroscopy.org/ome-files-cpp/0.5.0/ome-files/api/html/classome_1_1files_1_1VariantPixelBuffer.html#a78436203a3b2fabbcf6c20d8753329df>
> for VariantPixelBuffer, it says that adding support for subsetting
> dimensions is a to-do.

Yes, I am afraid that this is still a to-do item.  I had hoped that we
would be able to swap out VariantPixelBuffer for a better implementation
in the long run, like Eigen or a custom mdarray_span to work seamlessly
with any other representation.  Unfortunately, it's still just a thin
wrapper around Boost.MultiArray.

However... I think you can make it work in just a few lines of code if
you create the buffer stepwise *and* (due to limitations in the
multi_array library), you start with a view of the full data:

- create a PixelBuffer<float>::array_ref_type using your existing data
array as the source.  This is just a boost::multi_array_ref; make sure
it spans the whole range in each dimension
- call reshape() to subset to the desired size
- then create a std::shared_ptr<PixelBuffer<float>> of the appropriate
size and assign the array
[https://docs.openmicroscopy.org/ome-files-cpp/0.5.0/ome-files/api/html/classome_1_1files_1_1PixelBuffer.html#a319ca86b4a672f2e6ca8f05a7c5304ea]
- you can now create a VariantPixelBuffer with this specific type of
pixelbuffer as a constructor argument
[https://docs.openmicroscopy.org/ome-files-cpp/0.5.0/ome-files/api/html/classome_1_1files_1_1VariantPixelBuffer.html#aa1d5d838a1503acde32b514211d752a4]

It's not fully zero copy; it can be, but only if you're not subsetting,
and this is in part due to limitations in the wrapped multi_array
library.  While the assignment operator uses the reference, it does copy
the referenced content into the internal buffer.

> The function prototype would look something like this.  It would allow
> us to copy a buffer into a ROI of the pixel buffer as defined by an
> x-offset, y-offset, z-offset, and width (x), height (y), and depth (z).
>
> void CopyROI(float* buffer, int x, int y, int z, int width, int height,
> int depth)
>
> I am happy to write my own extension method, but was wondering what
> would be the best way to implement this.  Would it be to use
> |boost::static_visitor|?

If the above suggestion doesn't work, this would be the most general and
performant method to copy the specific region needed into a pixel
buffer.  It can be more performant because it will std::copy/memcpy
contiguous rows or blocks where possible.  I would start by looking at
the existing implementation of the read and write visitors used for TIFF
(libtiff) in
https://github.com/ome/ome-files-cpp/blob/master/lib/ome/files/tiff/IFD.cpp#L73
which are fairly comprehensive and are backed by a lot of unit tests for
all the edge cases.  However, you probably only need to look at the read
visitor for copying from an existing buffer into a VariantPixelBuffer,
and you can ignore all the TIFF-specific special-cases and
considerations, so it can likely be much simpler.

I do hope that in the future we will be able to offer you a much simpler
and more performant zero-copy array view type which will make
interfacing with OME Files much nicer.


Kind regards,
Roger

--
Dr Roger Leigh -- Open Microscopy Environment
Wellcome Trust Centre for Gene Regulation and Expression,
College of Life Sciences, University of Dundee, Dow Street,
Dundee DD1 5EH Scotland UK   Tel: (01382) 386364

The University of Dundee is a registered Scottish Charity, No: SC015096


More information about the ome-devel mailing list