Package net.imglib2.img.planar

Source Code of net.imglib2.img.planar.PlanarImg$PlanarContainerSampler

/*
* #%L
* ImgLib2: a general-purpose, multidimensional image processing library.
* %%
* Copyright (C) 2009 - 2014 Stephan Preibisch, Tobias Pietzsch, Barry DeZonia,
* Stephan Saalfeld, Albert Cardona, Curtis Rueden, Christian Dietz, Jean-Yves
* Tinevez, Johannes Schindelin, Lee Kamentsky, Larry Lindsey, Grant Harris,
* Mark Hiner, Aivar Grislis, Martin Horn, Nick Perry, Michael Zinsmaier,
* Steffen Jaensch, Jan Funke, Mark Longair, and Dimiter Prodanov.
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
*    this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
*    this list of conditions and the following disclaimer in the documentation
*    and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* #L%
*/

package net.imglib2.img.planar;

import java.util.ArrayList;

import net.imglib2.Cursor;
import net.imglib2.FlatIterationOrder;
import net.imglib2.Interval;
import net.imglib2.img.AbstractNativeImg;
import net.imglib2.img.NativeImg;
import net.imglib2.img.basictypeaccess.PlanarAccess;
import net.imglib2.img.basictypeaccess.array.ArrayDataAccess;
import net.imglib2.type.NativeType;
import net.imglib2.util.Fraction;
import net.imglib2.util.Intervals;
import net.imglib2.view.iteration.SubIntervalIterable;

/**
* A {@link NativeImg} that stores data in an list of primitive arrays, one per
* image plane.
* <p>
* The {@link PlanarImg} provides access to the underlying data arrays via the
* {@link #getPlane(int)} method.
* </p>
*
* @author Jan Funke
* @author Stephan Preibisch
* @author Stephan Saalfeld
* @author Johannes Schindelin
* @author Tobias Pietzsch
*/
public class PlanarImg< T extends NativeType< T >, A extends ArrayDataAccess< A > > extends AbstractNativeImg< T, A > implements PlanarAccess< A >, SubIntervalIterable< T >
{
  final protected int numSlices;

  /*
   * duplicate of long[] dimension as an int array.
   */
  final protected int[] dimensions;

  final protected int[] sliceSteps;

  final protected ArrayList< A > mirror;

  public PlanarImg( final long[] dim, final Fraction entitiesPerPixel )
  {
    this( null, dim, entitiesPerPixel );
  }

  PlanarImg( final A creator, final long[] dim, final Fraction entitiesPerPixel )
  {
    super( dim, entitiesPerPixel );

    dimensions = new int[ n ];
    for ( int d = 0; d < n; ++d )
      dimensions[ d ] = ( int ) dim[ d ];

    if ( n > 2 )
    {
      sliceSteps = new int[ n ];
      sliceSteps[ 2 ] = 1;
      for ( int i = 3; i < n; ++i )
      {
        final int j = i - 1;
        sliceSteps[ i ] = dimensions[ j ] * sliceSteps[ j ];
      }
    }
    else
    {
      sliceSteps = null;
    }

    // compute number of slices
    int s = 1;
    for ( int d = 2; d < n; ++d )
      s *= dimensions[ d ];
    numSlices = s;

    mirror = new ArrayList< A >( numSlices );

    if ( creator == null )
    {
      for ( int i = 0; i < numSlices; ++i )
        mirror.add( null );
    }
    else
    {
      final int numEntitiesPerSlice = (int)entitiesPerPixel.mulCeil( ( ( n > 1 ) ? dimensions[ 1 ] : 1 *  dimensions[ 0 ] );
      for ( int i = 0; i < numSlices; ++i )
        mirror.add( creator.createArray( numEntitiesPerSlice ) );
    }
  }

  /**
   * This interface is implemented by all samplers on the {@link PlanarImg}.
   * It allows the container to ask for the slice the sampler is currently in.
   */
  public interface PlanarContainerSampler
  {
    /**
     * @return the index of the slice the sampler is currently accessing.
     */
    public int getCurrentSliceIndex();
  }

  @Override
  public A update( final Object c )
  {
    final int i = ( ( PlanarContainerSampler ) c ).getCurrentSliceIndex();
    return mirror.get( i < 0 ? 0 : ( i >= numSlices ? numSlices - 1 : i ) );
  }

  /**
   * @return total number of image planes
   */
  public int numSlices()
  {
    return numSlices;
  }

  /**
   * For a given >=2d location, estimate the pixel index in the stack slice.
   *
   * @param l
   * @return
   *
   *         TODO: remove this method? (it doesn't seem to be used anywhere)
   */
  public final int getIndex( final int[] l )
  {
    if ( n > 1 )
      return l[ 1 ] * dimensions[ 0 ] + l[ 0 ];
    return l[ 0 ];
  }

  /**
   * Compute a global position from the index of a slice and an index within
   * that slice.
   *
   * @param sliceIndex
   *            index of slice
   * @param indexInSlice
   *            index of element within slice
   * @param position
   *            receives global position of element
   *
   *            TODO: move this method to AbstractPlanarCursor? (that seems to
   *            be the only place where it is needed)
   */
  public void indexToGlobalPosition( int sliceIndex, final int indexInSlice, final int[] position )
  {
    if ( n > 1 )
    {
      position[ 1 ] = indexInSlice / dimensions[ 0 ];
      position[ 0 ] = indexInSlice - position[ 1 ] * dimensions[ 0 ];

      if ( n > 2 )
      {
        final int maxDim = n - 1;

        for ( int d = 2; d < maxDim; ++d )
        {
          final int j = sliceIndex / dimensions[ d ];
          position[ d ] = sliceIndex - j * dimensions[ d ];
          sliceIndex = j;
        }
        position[ maxDim ] = sliceIndex;
      }
    }
    else
    {
      position[ 0 ] = indexInSlice;
    }
  }

  /**
   * Compute a global position from the index of a slice and an index within
   * that slice.
   *
   * @param sliceIndex
   *            index of slice
   * @param indexInSlice
   *            index of element within slice
   * @param dim
   *            which dimension of the position we are interested in
   * @return dimension dim of global position
   *
   *         TODO: move this method to AbstractPlanarCursor? (that seems to be
   *         the only place where it is needed)
   */
  public int indexToGlobalPosition( final int sliceIndex, final int indexInSlice, final int dim )
  {
    if ( dim == 0 )
      return indexInSlice % dimensions[ 0 ];
    else if ( dim == 1 )
      return indexInSlice / dimensions[ 0 ];
    else if ( dim < n )
      return ( sliceIndex / sliceSteps[ dim ] ) % dimensions[ dim ];
    else
      return 0;
  }

  @Override
  public PlanarCursor< T > cursor()
  {
    if ( n == 1 )
      return new PlanarCursor1D< T >( this );
    else if ( n == 2 )
      return new PlanarCursor2D< T >( this );
    else
      return new PlanarCursor< T >( this );
  }

  @Override
  public PlanarLocalizingCursor< T > localizingCursor()
  {
    if ( n == 1 )
      return new PlanarLocalizingCursor1D< T >( this );
    else if ( n == 2 )
      return new PlanarLocalizingCursor2D< T >( this );
    else
      return new PlanarLocalizingCursor< T >( this );
  }

  @Override
  public PlanarRandomAccess< T > randomAccess()
  {
    if ( n == 1 )
      return new PlanarRandomAccess1D< T >( this );
    return new PlanarRandomAccess< T >( this );
  }

  @Override
  public FlatIterationOrder iterationOrder()
  {
    return new FlatIterationOrder( this );
  }

  @Override
  public A getPlane( final int no )
  {
    return mirror.get( no );
  }

  @Override
  public void setPlane( final int no, final A plane )
  {
    mirror.set( no, plane );
  }

  @Override
  public PlanarImgFactory< T > factory()
  {
    return new PlanarImgFactory< T >();
  }

  @Override
  public PlanarImg< T, ? > copy()
  {
    final PlanarImg< T, ? > copy = factory().create( dimension, firstElement().createVariable() );

    final PlanarCursor< T > cursor1 = this.cursor();
    final PlanarCursor< T > cursor2 = copy.cursor();

    while ( cursor1.hasNext() )
      cursor2.next().set( cursor1.next() );

    return copy;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public boolean supportsOptimizedCursor( final Interval interval )
  {
    // first check whether the interval is completely contained.
    if ( !Intervals.contains( this, interval ) )
      return false;

    // we want to optimize exactly one plane
    if ( correspondsToPlane( interval ) )
    {
      return true;
    }
    else
    {
      // we want to optimize a set of planes

      // find the first dimension in which image and interval differ
      int dimIdx = 0;
      for ( ; dimIdx < n; ++dimIdx )
        if ( interval.dimension( dimIdx ) != dimension( dimIdx ) )
          break;

      // in the dimension after that, image and interval may differ
      ++dimIdx;

      // but image extents of all higher dimensions must equal 1
      for ( int d = dimIdx; d < n; ++d )
        if ( interval.dimension( d ) != 1 )
          return false;

      return true;
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public Object subIntervalIterationOrder( final Interval interval )
  {
    return new FlatIterationOrder( interval );
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public Cursor< T > cursor( final Interval interval )
  {
    assert supportsOptimizedCursor( interval );

    if ( correspondsToPlane( interval ) )
      return new PlanarPlaneSubsetCursor< T >( this, interval );
    return new PlanarSubsetCursor< T >( this, interval );
  }

  private boolean correspondsToPlane( final Interval interval )
  {
    // check if interval describes one plane
    if ( interval.dimension( 0 ) != dimension[ 0 ] )
      return false;

    if ( interval.dimension( 1 ) != dimension[ 1 ] )
      return false;

    for ( int d = 2; d < interval.numDimensions(); ++d )
    {
      if ( interval.dimension( d ) != 1 )
        return false;
    }

    return true;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public Cursor< T > localizingCursor( final Interval interval )
  {

    assert supportsOptimizedCursor( interval );

    if ( correspondsToPlane( interval ) )
      return new PlanarPlaneSubsetLocalizingCursor< T >( this, interval );
    return new PlanarSubsetLocalizingCursor< T >( this, interval );
  }
}
TOP

Related Classes of net.imglib2.img.planar.PlanarImg$PlanarContainerSampler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.