/*-
* #%L
* Fiji distribution of ImageJ for the life sciences.
* %%
* Copyright (C) 2007 - 2017 Fiji developers.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-2.0.html>.
* #L%
*/
package mpicbg.spim.fusion;
import java.util.ArrayList;
import mpicbg.spim.registration.ViewDataBeads;
public class BlendingSimple extends CombinedPixelWeightener<BlendingSimple>
{
final int numDimensions;
final int numViews;
final double[] weights, border;
final double[][] scaling;
final int[][] imageSizes;
double percentScaling = 0.3;
protected BlendingSimple( final ArrayList<ViewDataBeads> views )
{
super( views );
numViews = views.size();
numDimensions = views.get( 0 ).getNumDimensions();
weights = new double[ numViews ];
scaling = new double[ numViews ][ numDimensions ];
border = new double[]{ 15,15,15 };
// cache image sizes
imageSizes = new int[ numViews ][];
for ( int i = 0; i < numViews; ++i )
{
imageSizes[ i ] = views.get( i ).getImageSize();
for ( int d = 0; d < numDimensions; ++d )
scaling[ i ][ d ] = 1;
scaling[ i ][ 2 ] = views.get( i ).getZStretching();
}
//setBorder( 15 );
}
public void setPercentScaling( final double p ) { this.percentScaling = p; }
public void setBorder( final double numPixels )
{
for ( int d = 0; d < border.length; ++d )
border[ d ] = numPixels;
}
public void setBorder( final double[] numPixels )
{
for ( int d = 0; d < border.length; ++d )
border[ d ] = numPixels[ d ];
}
public void setBlendingRange( final double ratio ) { this.percentScaling = ratio; }
@Override
public void close() {}
@Override
public double getWeight( final int view ) { return weights[ view ]; }
@Override
public void updateWeights( final int[][] locations, final boolean[] useView )
{
final double[][] tmp = new double[ locations.length ][ locations[ 0 ].length ];
for ( int i = 0; i < locations.length; ++i )
for ( int d = 0; d < locations[ 0 ].length; ++d )
tmp[ i ][ d ] = locations[ i ][ d ];
updateWeights( tmp, useView );
}
@Override
public void updateWeights( final double[][] locations, final boolean[] useView )
{
/*
// check which location are inside its respective view
int num = 0;
for ( final boolean use : useView )
if ( use )
++num;
// if there is only one or no view at this point we can save some work
if ( num <= 1 )
{
for ( int i = 0; i < useView.length; ++i )
if ( useView[i] )
weights[i] = 1;
else
weights[i] = 0;
}
else*/
for ( int i = 0; i < useView.length; ++i )
{
if ( useView[ i ] )
weights[ i ] = computeWeight( locations[ i ], imageSizes[ i ], border, scaling[ i ], percentScaling );
else
weights[ i ] = 0;
}
}
final public static double computeWeight( final int[] location, final int[] dimensions, final double[] border, final double[] dimensionScaling, final double percentScaling )
{
final double[] tmp = new double[ location.length ];
for ( int d = 0; d < location.length; ++d )
tmp[ d ] = location[ d ];
return computeWeight( tmp, dimensions, border, dimensionScaling, percentScaling );
}
final public static double computeWeight( final double[] location, final int[] dimensions, final double[] border, final double[] dimensionScaling, final double percentScaling )
{
// compute multiplicative distance to the respective borders [0...1]
double minDistance = 1;
for ( int dim = 0; dim < location.length; ++dim )
{
// the position in the image
final double localImgPos = location[ dim ];
// the distance to the border that is closer
double value;
if ( dimensionScaling != null && dimensionScaling[ dim ] != 0 )
{
value = Math.max( 0, Math.min( localImgPos - border[ dim ]/dimensionScaling[ dim ], (dimensions[ dim ] - 1) - localImgPos - border[ dim ]/dimensionScaling[ dim ] ) );
value *= dimensionScaling[ dim ];
}
else
{
value = Math.max( 0, Math.min( localImgPos - border[ dim ], (dimensions[ dim ] - 1) - localImgPos - border[ dim ] ) );
}
final double imgAreaBlend = Math.round( percentScaling * 0.5 * dimensions[ dim ] * dimensionScaling[ dim ] );
if ( value < imgAreaBlend )
value = value / imgAreaBlend;
else
value = 1;
minDistance *= value;
}
if ( minDistance == 1 )
return 1;
else if ( minDistance == 0)
return 0;
else
return ( Math.cos( (1 - minDistance) * Math.PI ) + 1 ) / 2;
}
}