package ij.plugin.filter;
import ij.*;
import ij.gui.*;
import ij.process.*;
import ij.measure.*;
import ij.util.*;
import ij.plugin.frame.ContrastAdjuster;
import java.awt.*;
import java.util.*;
public class LutApplier implements PlugInFilter {
ImagePlus imp;
int min, max;
boolean canceled;
public int setup(String arg, ImagePlus imp) {
this.imp = imp;
int baseOptions = DOES_8G+DOES_8C+DOES_16+DOES_RGB;
return baseOptions;
}
public void run(ImageProcessor ip) {
apply(imp, ip);
}
void apply(ImagePlus imp, ImageProcessor ip) {
if (ip.getMinThreshold()!=ImageProcessor.NO_THRESHOLD) {
imp.unlock();
IJ.runPlugIn("ij.plugin.Thresholder", "skip");
return;
}
min = (int)imp.getDisplayRangeMin();
max = (int)imp.getDisplayRangeMax();
int depth = imp.getBitDepth();
if ((depth==8||depth==24) && min==0 && max==255) {
IJ.error("Apply LUT", "The display range must first be updated\n"
+"using Image>Adjust>Brightness/Contrast\n"
+"or threshold levels defined using\n"
+"Image>Adjust>Threshold.");
return;
}
if (imp.getType()==ImagePlus.COLOR_RGB) {
if (imp.getStackSize()>1)
applyRGBStack(imp);
else {
ip.reset();
Undo.setup(Undo.TRANSFORM, imp);
ip.setMinAndMax(min, max);
}
((ColorProcessor)ip).caSnapshot(false);
resetContrastAdjuster();
return;
}
ip.resetMinAndMax();
int range = 256;
if (depth==16) {
range = 65536;
int defaultRange = imp.getDefault16bitRange();
if (defaultRange>0)
range = (int)Math.pow(2,defaultRange)-1;
}
int tableSize = depth==16?65536:256;
int[] table = new int[tableSize];
for (int i=0; i<tableSize; i++) {
if (i<=min)
table[i] = 0;
else if (i>=max)
table[i] = range-1;
else
table[i] = (int)(((double)(i-min)/(max-min))*range);
}
ImageProcessor mask = imp.getMask();
if (imp.getStackSize()>1) {
ImageStack stack = imp.getStack();
int flags = IJ.setupDialog(imp, 0);
if (flags==PlugInFilter.DONE) {
ip.setMinAndMax(min, max);
return;
}
if (flags==PlugInFilter.DOES_STACKS) {
int current = imp.getCurrentSlice();
for (int i=1; i<=imp.getStackSize(); i++) {
imp.setSlice(i);
ip = imp.getProcessor();
if (mask!=null) ip.snapshot();
ip.applyTable(table);
ip.reset(mask);
}
imp.setSlice(current);
Undo.reset();
} else {
ip.applyTable(table);
ip.reset(mask);
}
} else {
ip.applyTable(table);
ip.reset(mask);
}
if (depth==16)
imp.setDisplayRange(0,range-1);
resetContrastAdjuster();
}
private void resetContrastAdjuster() {
ContrastAdjuster.update();
}
void applyRGBStack(ImagePlus imp) {
int current = imp.getCurrentSlice();
int n = imp.getStackSize();
if (!IJ.showMessageWithCancel("Update Entire Stack?",
"Apply brightness and contrast settings\n"+
"to all "+n+" slices in the stack?\n \n"+
"NOTE: There is no Undo for this operation.")) {
canceled = true;
return;
}
for (int i=1; i<=n; i++) {
if (i!=current) {
imp.setSlice(i);
ImageProcessor ip = imp.getProcessor();
ip.setMinAndMax(min, max);
IJ.showProgress((double)i/n);
}
}
imp.setSlice(current);
}
}