Warning: Can't synchronize with repository "(default)" (/home/git/ome.git does not appear to be a Git repository.). Look in the Trac log for more information.
Notice: In order to edit this ticket you need to be either: a Product Owner, The owner or the reporter of the ticket, or, in case of a Task not yet assigned, a team_member"

Task #11827 (closed)

Opened 10 years ago

Closed 10 years ago

Bug: C++ pixel buffer implementation

Reported by: rleigh Owned by: rleigh
Priority: minor Milestone: Unscheduled
Component: Bio-Formats Version: 5.0.0-beta2-RC3
Keywords: cpp Cc:
Resources: n.a. Referenced By: n.a.
References: n.a. Remaining Time: n.a.
Sprint: n.a.

Description

The Java implementation uses byte[] arrays. These have been replicated in C++ as std::vector<uint8_t>. However, this approach is fairly limited, since we could make it use the correct pixel type for ease of use and type-safety, as well as having correct dimensions of the contained pixel values to permit passing it to other methods etc.

Suggestion:

  • PixelBufferBase? base class from which PixelBuffer?<T> is derived. The latter is templated, but the untemplated base means the buffer can be passed to non-templated function.
  • The base class can contain generic metadata such as the dimensions and sizes of the buffer
  • Plus templated accessors (which could include index operators)

This can be passed around to openByte/saveBytes and the metadata binData methods, used internally by readers, etc.

Change History (4)

comment:1 Changed 10 years ago by rleigh

  • Owner changed from mlinkert to rleigh

comment:2 Changed 10 years ago by rleigh

  • Keywords cpp added

https://github.com/openmicroscopy/bioformats/pull/1204

Adds support for 9D pixel data arrays of any supported pixel type and endianness. Summary of the design:

  • For transfer and bulk processing of nD pixel data of any pixel type/endianness.
  • 9D array fully supports interleaving and all modulo attributes as first-class addressable dimensions.
  • nD data is stored in a 9D Boost.MultiArray?, which is contained in a PixelBuffer? object along with type/endianness information. PixelBuffer? is templated on pixeltype/endianness.
  • Note that some pixeltype/endian combinations will be the same underlying language type (e.g. one of the little/big variants will typically be the native type, and not all types have little/big variants); the PixelBufferBase? pixeltype/endiantype attributes are to work around this fact.
  • PixelBuffer?<T> contains the MultiArray? in a shared_ptr to multi_array_ref<T>, which also allows it to contain the derived multi_array<T>; this permits the memory backing the array to be referenced from an external source or contained internally, respectively. Allows zero-copy (or reduced-copy) I/O where file formats and library interfaces permit it.
  • MultiArray? size is fixed at construction; use of shared_ptr in PixelBuffer? allows replacement after PixelBuffer? construction to resize and change the backing store.
  • To allow transfer and storage of pixel data of arbitrary type, VariantPixelBuffer? can contain a shared_ptr to any PixelBuffer? specialised for pixel types in the OME data model using Boost.Variant.
  • Variant also permits generation of function objects (static_visitors) to process pixel data in any way. Because it's expanded once per pixeltype/endian combination, coverage for all pixel types is checked and enforced at compile time. Invalid/unsupported specialisations can be no-ops or throw an exception. This inheritance-free dynamic polymorphism is the primary reason for using Variant over simply storing a std::shared_ptr<PixelBufferBase>: it restricts the allowed types to only those explicitly supported, and it enforces complete support for these types. It can be significantly faster than inheritance since there's no virtual call overhead for every method call, though there is one-time overhead in iterating over the typelist to despatch the corresponding visitor, but when processing large amounts of pixel data this overhead will be dwarfed by the overhead of the algorithm itself.
  • VariantPixelBuffer? provides some generic methods which operate on all variant pixel buffer types using static_visitor plus some specialised methods to allow direct manipulation of pixel buffers of specific type (assign and at).
  • Public API uses VariantPixelBuffer?, but for cases where the pixeltype is fixed, PixelBuffer?<> specialised for that type will be possible.
  • Note that MASK types use bool, and this is typically stored as uint8_t/uint32_t; this allows proper array addressing and (de)referencing, so if stored as a bitmask it will require expansion. Bits are not suitable due to not being directly addressable.

Opening for initial review of the design but not yet for merging. This is the result of a few iterations of the design, which I feel now covers the needed uses well, at least at a basic level (storage and object structure); the API isn't fully complete. This should handle a large portion of the content of FormatTools?, and will later on also be able to replace the use of plane indices entirely when we switch to a truly nD API; for now it will be limited to 2D when using the existing openBytes interface. The range ctors/methods will allow specification of extents in all dimensions and so could be an alternative overloaded openBytes method (just pass in the buffer alone, which contains all the parameters you would normally provide in addition to the buffer).

I'll be adding additional functionality including:

  • I/O to/from streams (methods and stream operators for PixelBuffer? and VariantPixelBuffer?)
  • additional methods to expose more functionality, primarily getters and setters for the variant and specific pixel buffer members which aren't already exposed; also allow direct resizing of PixelBuffer? in addition to the VariantPixelBuffer? methods.
  • allow setting of dimension storage order as a string ("sXYZTCztc") instead of a numerical dimension list; can be fully described as model DimensionOrder?+interleaved. Note that modulo dimensions precede their parent dimension; interleaved precedes or follows "XY". Letters won't allow reverse ordering. A true nD model will allow much greater flexibility; for now 9D with these restrictions supports all existing cases.
  • subsetting of dimensions.
  • isSigned/isComplex as PixelProperties? static type info and PixelBuffer? methods.
  • pixelTypeFromBytes equivalent in PixelProperties?; also support complex.
  • any additional missing functionality?
  • implementing support in FormatReader? for readPlane/openBytes.
  • greater test coverage.
  • support in the TIFF reader for saving and loading pixel data (may be in a separate PR).
Last edited 10 years ago by rleigh (previous) (diff)

comment:3 Changed 10 years ago by rleigh

  • Status changed from new to accepted

comment:4 Changed 10 years ago by rleigh

  • Resolution set to fixed
  • Status changed from accepted to closed

PR ready now.

Note: See TracTickets for help on using tickets. You may also have a look at Agilo extensions to the ticket.

1.3.13-PRO © 2008-2011 Agilo Software all rights reserved (this page was served in: 0.66876 sec.)

We're Hiring!