package gdsc.utils;
/*-----------------------------------------------------------------------------
* GDSC Plugins for ImageJ
*
* Copyright (C) 2011 Alex Herbert
* Genome Damage and Stability Centre
* University of Sussex, UK
*
* 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.
*---------------------------------------------------------------------------*/
import ij.IJ;
import ij.ImagePlus;
import ij.ImageStack;
import ij.gui.GenericDialog;
import ij.io.FileSaver;
import ij.measure.Measurements;
import ij.plugin.filter.PlugInFilter;
import ij.process.ImageProcessor;
import ij.process.ImageStatistics;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import gdsc.UsageTracker;
/**
* Scales all planes in an image to the given maximim
*/
public class Image_Scaler implements PlugInFilter
{
private static final String TITLE = "Image Scaler";
private ImagePlus imp;
private static double maxValue = 255;
private static String listFile = "";
/*
* (non-Javadoc)
*
* @see ij.plugin.filter.PlugInFilter#setup(java.lang.String, ij.ImagePlus)
*/
public int setup(String arg, ImagePlus imp)
{
UsageTracker.recordPlugin(this.getClass(), arg);
if (!showDialog())
{
return DONE;
}
this.imp = imp;
return DOES_ALL | NO_IMAGE_REQUIRED;
}
private boolean showDialog()
{
GenericDialog gd = new GenericDialog(TITLE);
gd.addMessage("Rescales the maxima of the image(s) to the given value.\nProcesses the image stack or a set of input images.");
gd.addNumericField("Max", maxValue, 2);
gd.addMessage("List file containing full image path, one image per line.");
gd.addStringField("List file", listFile);
gd.showDialog();
gd.addHelp(gdsc.help.URL.UTILITY);
if (gd.wasCanceled())
return false;
maxValue = gd.getNextNumber();
listFile = gd.getNextString();
return true;
}
/*
* (non-Javadoc)
*
* @see ij.plugin.filter.PlugInFilter#run(ij.process.ImageProcessor)
*/
public void run(ImageProcessor inputProcessor)
{
boolean listExists = (listFile != null && !listFile.equals(""));
if (imp == null && !listExists)
return;
if (listExists)
{
run(listFile, maxValue);
}
else
{
run(new ImagePlus[] { imp }, maxValue);
}
}
/**
* Scales all the images by the same factor so that one image has the specified maximum.
*
* @param listFile File listing all the images to scale
* @param maxValue
*/
public void run(String listFile, double maxValue)
{
boolean listExists = (listFile != null && !listFile.equals(""));
if (!listExists)
return;
if (!new File(listFile).exists())
return;
double[] limits = new double[] { Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY };
// Read all images sequentially and find the limits
try
{
BufferedReader input = new BufferedReader(new FileReader(listFile));
String line = null; //not declared within while loop
while ((line = input.readLine()) != null)
{
if (!new File(line).exists())
continue;
ImagePlus imp = new ImagePlus(line);
if (imp != null)
{
updateMinAndMax(imp, limits);
}
imp.flush();
imp = null; // Free memory
}
input.close();
}
catch (Exception e)
{
IJ.error("Failed to read images in input list file: " + listFile);
return;
}
if (limits[1] <= limits[0])
return;
double scaleFactor = maxValue / limits[1];
// Rewrite images
try
{
BufferedReader input = new BufferedReader(new FileReader(listFile));
String line = null; //not declared within while loop
while ((line = input.readLine()) != null)
{
if (!new File(line).exists())
continue;
ImagePlus imp = new ImagePlus(line);
if (imp != null)
{
multiply(imp, scaleFactor);
new FileSaver(imp).save();
}
imp.flush();
imp = null; // Free memory
}
input.close();
}
catch (Exception e)
{
IJ.error("Failed to re-write images in input list file: " + listFile);
}
}
/**
* Scales all the images by the same factor so that one image has the specified maximum.
*
* @param images
* @param maxValue
*/
public void run(ImagePlus[] images, double maxValue)
{
double[] limits = new double[] { Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY };
for (ImagePlus imp : images)
{
updateMinAndMax(imp, limits);
}
if (limits[1] <= limits[0])
return;
double scaleFactor = maxValue / limits[1];
for (ImagePlus imp : images)
{
multiply(imp, scaleFactor);
}
}
private void updateMinAndMax(ImagePlus imp, double[] limits)
{
ImageStack stack = imp.getImageStack();
for (int slice = 1; slice <= stack.getSize(); slice++)
{
ImageStatistics stats = ImageStatistics.getStatistics(stack.getProcessor(slice), Measurements.MIN_MAX,
null);
if (limits[0] > stats.min)
limits[0] = stats.min;
if (limits[1] < stats.max)
limits[1] = stats.max;
}
}
private void multiply(ImagePlus imp, double scaleFactor)
{
ImageStack stack = imp.getImageStack();
for (int slice = 1; slice <= stack.getSize(); slice++)
{
stack.getProcessor(slice).multiply(scaleFactor);
}
if (imp.isVisible())
{
imp.resetDisplayRange();
imp.updateAndDraw();
}
}
}