/**
 * Gaussian downsampling of an image with ImageJ on-board tools.
 *
 * Motivation:
 * Sound downsampling of an image requires the elimination of image frequencies
 * higher than half the sampling frequency in the result image (see the
 * Nyquist-Shannon sampling theorem).  The exclusive tool for this is Gaussian
 * convolution.
 *
 * This script calculates the required Gaussian kernel for a given target size,
 * smoothes the image and resamples it.
 *
 * Furthermore, you can define the "intrinsic" Gaussian kernel of the source and
 * target images.  An optimal sampler is identified by sigma=0.5.  If your
 * source image was blurred already, you may set a higher source sigma for a
 * sharper result.  Setting target sigma to values smaller than 0.5 makes the
 * result appear sharper and therefore eventually aliased.
 *
 * http://pacific.mpi-cbg.de/wiki/index.php/Downsample
 */

var imp = WindowManager.getCurrentImage();
var width = 0;
var height = 0;
var sourceSigma = 0.5;
var targetSigma = 0.5;
var widthField;
var heightField;
var fieldWithFocus;

var textListener = new java.awt.event.TextListener(
	{
		textValueChanged : function( e )
		{
			var source = e.getSource();
			var newWidth = Math.round( widthField.getText() );
			var newHeight = Math.round( heightField.getText() );
        	
        	if ( source == widthField && fieldWithFocus == widthField && newWidth )
        	{
            	newHeight = Math.round( newWidth * imp.getHeight() / imp.getWidth() );
            	heightField.setText( newHeight );
            }
            else if ( source == heightField && fieldWithFocus == heightField && newHeight )
            {
            	newWidth = Math.round( newHeight * imp.getWidth() / imp.getHeight() );
            	widthField.setText( newWidth );
            }
        } 
	} );

var focusListener = new java.awt.event.FocusListener(
	{
		focusGained : function ( e )
		{
        	fieldWithFocus = e.getSource();
        },
		focusLost : function( e ){} 
	} );

if ( imp )
{
	width = imp.getWidth();
	height = imp.getHeight();
	
	gd = new GenericDialog( "Downsample" );
	gd.addNumericField( "width :", width, 0 );
	gd.addNumericField( "height :", height, 0 );
	gd.addNumericField( "source sigma :", sourceSigma, 2 );
	gd.addNumericField( "target sigma :", targetSigma, 2 );
	var fields = gd.getNumericFields();
	
	widthField = fields.get( 0 );
	heightField = fields.get( 1 );
	fieldWithFocus = widthField;
	
	widthField.addFocusListener( focusListener );
	widthField.addTextListener( textListener );
	heightField.addFocusListener( focusListener );
	heightField.addTextListener( textListener );
		
	gd.showDialog();
	if ( gd.wasOKed() )
	{
		width = gd.getNextNumber();
		height = gd.getNextNumber();
		sourceSigma = gd.getNextNumber();
		targetSigma = gd.getNextNumber();
		
		if ( width <= imp.getWidth() )
		{
			var s;
			if ( fieldWithFocus == widthField )
				s = targetSigma * imp.getWidth() / width;
			else
				s = targetSigma * imp.getHeight() / height;

			IJ.run( "Gaussian Blur...", "sigma=" + Math.sqrt( s * s - sourceSigma * sourceSigma ) + " stack" );
			IJ.run( "Scale...", "x=- y=- width=" + width + " height=" + height + " process title=-" );
			IJ.run( "Canvas Size...", "width=" + width + " height=" + height + " position=Center" );
		}
		else
			IJ.showMessage( "You try to upsample the image.  You need an interpolator for that not a downsampler." );
	}
}
else
	IJ.showMessage( "You should have at least one image open." );
