Class ContourPlot.PixelConvertingSpliterator<P extends ContourPlot.PixelBase,T>

java.lang.Object
gov.nih.mipav.model.algorithms.ContourPlot.PixelConvertingSpliterator<P,T>
Type Parameters:
P - the pixel type of the underlying Spliterator
T - the type of elements returned by the PixelConvertingSpliterator
All Implemented Interfaces:
Spliterator<T>
Enclosing class:
ContourPlot

public static class ContourPlot.PixelConvertingSpliterator<P extends ContourPlot.PixelBase,T> extends Object implements Spliterator<T>
The PixelConvertingSpliterator enables iterating an ContourPlot.Img with a different datatype than ContourPlot.Pixel (ContourPlot.ImgBase.spliterator()). This can come in handy if a Consumer would be easier to write when not restricted to the Pixel datatype.

For example, a specific operation should be applied to each pixel of the Img which is specified as a function that takes a 3-dimensional vector as argument with red, green and blue component e.g.
applyOperation(Vector3D vec){...}}
To obtain a spliterator of the Img that will accept a Consumer<Vector3D> a PixelConvertingSpliterator can be created from an ordinary Spliterator<Pixel> providing the following functions:

  • element allocator: a function to create (allocate) an object of the desired datatype (Vector3D in this example)
  • from Pixel converter: a function to convert a Pixel object to an object of the desired datatype e.g.
    void convertPixel(Pixel px, Vector3D vec)
  • to Pixel converter: a function to convert an object of the desired datatype to a Pixel object e.g.
    void convertVector(Vector3D vec, Pixel px)

A PixelConvertingSpliterator<Vector3D> would then be created like this:
 
 Img img=loadImgFromSomewhere();
 Spliterator<Vector3D> split = new PixelConvertingSpliterator<>(
       img.spliterator(),
       ()->{return new Vector3D();},
       MyConverter::convertPixel,
       MyConverter::convertVector
       );
 StreamSupport.stream(split, true)
       .forEach(VectorOperations::applyOperation);
 

The reason for not simply doing an 'on the fly' conversion inside a Spliterator<Pixel> or using the Stream.map(java.util.function.Function) function is, that these methods are prone to excessive object allocation (allocating a new object for every pixel). When using the PixelConvertingSpliterator there is only one object allocation per split, and the object will be reused for each pixel within that split.

Since:
1.4
Author:
hageldave
  • Field Details

  • Constructor Details

    • PixelConvertingSpliterator

      public PixelConvertingSpliterator(Spliterator<? extends P> delegate, Supplier<T> elementAllocator, BiConsumer<P,T> fromPixelConverter, BiConsumer<T,P> toPixelConverter)
      Constructs a new PixelConvertingSpliterator.
      Parameters:
      delegate - the Spliterator<Pixel> this spliterator delegates to.
      elementAllocator - method for allocating an object of this spliterator's element type.
      fromPixelConverter - method for setting up an element of this spliterator according to its underlying pixel.
      toPixelConverter - method for adopting an underlying pixel value according to an element of this spliterator.
      Since:
      1.4
    • PixelConvertingSpliterator

      public PixelConvertingSpliterator(Spliterator<? extends P> delegate, ContourPlot.PixelConvertingSpliterator.PixelConverter<P,T> converter)
  • Method Details

    • tryAdvance

      public boolean tryAdvance(Consumer<? super T> action)
      Specified by:
      tryAdvance in interface Spliterator<P extends ContourPlot.PixelBase>
    • forEachRemaining

      public void forEachRemaining(Consumer<? super T> action)
      Specified by:
      forEachRemaining in interface Spliterator<P extends ContourPlot.PixelBase>
    • trySplit

      public Spliterator<T> trySplit()
      Specified by:
      trySplit in interface Spliterator<P extends ContourPlot.PixelBase>
    • estimateSize

      public long estimateSize()
      Specified by:
      estimateSize in interface Spliterator<P extends ContourPlot.PixelBase>
    • characteristics

      public int characteristics()
      Specified by:
      characteristics in interface Spliterator<P extends ContourPlot.PixelBase>
    • getDoubletArrayElementSpliterator

      public static ContourPlot.PixelConvertingSpliterator<ContourPlot.PixelBase,double[]> getDoubletArrayElementSpliterator(Spliterator<? extends ContourPlot.PixelBase> pixelSpliterator)
      Example implementation of a PixelConvertingSpliterator<double[]>.

      The elements of the returned spliterator will be double[] of length 3 with normalized red, green and blue channels on index 0, 1 and 2.

      Code:

       
       Supplier<double[]> arrayAllocator = () -> {
          return new double[3];
       };
       BiConsumer<Pixel, double[]> convertToArray = (px, array) -> {
          array[0]=px.r_normalized();
          array[1]=px.g_normalized();
          array[2]=px.b_normalized();
       };
       BiConsumer<double[], Pixel> convertToPixel = (array, px) -> {
          px.setRGB_fromNormalized_preserveAlpha(
             // clamp values between zero and one
             Math.min(1, Math.max(0, array[0])),
             Math.min(1, Math.max(0, array[1])),
             Math.min(1, Math.max(0, array[2])));
       };
       PixelConvertingSpliterator<double[]> arraySpliterator = new PixelConvertingSpliterator<>(
          pixelSpliterator,
          arrayAllocator,
          convertToArray,
          convertToPixel);
       
       
      Parameters:
      pixelSpliterator - the Spliterator<Pixel> to which the returned spliterator delegates to.
      Returns:
      a spliterator with float[] elements consisting of normalized RGB channels.
      Since:
      1.4
    • getDoubleArrayConverter

      public static ContourPlot.PixelConvertingSpliterator.PixelConverter<ContourPlot.PixelBase,double[]> getDoubleArrayConverter()
      Returns:
      Exemplary PixelConverter that converts to double[].