use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.
the class ImageJCommandListener method commandExecuting.
// I know, I could create a hashtable and then map methods of this class to each command key ... this is just easier, and performance-wise nobody cares
// Or even a hastable with String command keys and then a number as value, and use a gigantic switch block. So much pain to write. WHAT I REALLY WANT is a switch that takes a String and is fast because it has its own hash setup.
public String commandExecuting(final String command) {
// Utils.log2("Command: " + command);
// 1 - check source
ImagePlus current = WindowManager.getCurrentImage();
// not a trakem2 display: continue happily
if (!(current instanceof FakeImagePlus))
return command;
// 2 - identify project
final FakeImagePlus fimp = (FakeImagePlus) current;
final Display display = fimp.getDisplay();
final LayerSet layer_set = display.getLayer().getParent();
final Project project = display.getProject();
final ProjectTree ptree = project.getProjectTree();
final Displayable active = display.getActive();
final Selection selection = display.getSelection();
// FILE menu
if (command.equals("Save")) {
project.save();
return null;
} else // EDIT menu
if (command.equals("Undo")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Cut")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Copy")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Copy to System")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Paste")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Clear")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Clear Outside")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Fill")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Draw")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Invert")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else // EDIT - SELECTION menu
if (command.equals("Select All")) {
if (ProjectToolbar.SELECT == Toolbar.getToolId()) {
selection.selectAll();
return null;
}
return command;
} else if (command.equals("Select None")) {
if (ProjectToolbar.SELECT == Toolbar.getToolId()) {
display.select(null);
return null;
}
return command;
} else if (command.equals("Restore Selection")) {
if (ProjectToolbar.SELECT == Toolbar.getToolId()) {
selection.restore();
return null;
}
return command;
} else // IMAGE - TYPE menu
if (command.equals("8-bit")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("16-bit")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("32-bit")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("8-bit Color")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("RGB Color")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("RGB Stack") || command.equals("HSB Stack")) {
Utils.showMessage("Can't convert to " + command);
return null;
} else // IMAGE - ADJUST menu
if (command.equals("Brightness/Contrast...")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Window/Level...")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Color Balance...")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Threshold...")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Size...")) {
if (null != active)
selection.specify();
return null;
} else if (command.equals("Canvas Size...")) {
display.resizeCanvas();
return null;
} else // IMAGE menu
if (command.equals("Show Info...")) {
// TODO perhaps it should show only for images ...
if (null == active) {
ptree.showInfo(project.getRootProjectThing());
} else {
ProjectThing pt = project.findProjectThing(active);
if (null != pt)
ptree.showInfo(pt);
}
return null;
} else // IMAGE - COLOR menu
if (in(command, new String[] { "RGB Split", "RGB Merge...", "Stack to RGB", "Make Composite" })) {
notAvailable(command);
return null;
} else if (command.equals("Show LUT")) {
return setTempCurrentImage(command, active);
} else if (command.equals("Edit LUT...")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Average Color")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("RGB to CIELAB")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("RGB to Luminance")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else // IMAGE STACK menu
if (in(command, new String[] { "Add Slice", "Delete Slice" })) {
Utils.showMessage("Go to the Layer Tree and right-click to add/delete a layer.");
return null;
} else if (command.equals("Next Slice [>]")) {
display.nextLayer(IJ.shiftKeyDown() ? Event.SHIFT_MASK : 0);
return null;
} else if (command.equals("Previous Slice [<]")) {
display.previousLayer(IJ.shiftKeyDown() ? Event.SHIFT_MASK : 0);
return null;
} else if (in(command, new String[] { "Set Slice", "Images to Stack", "Stack to Images", "Make Montage..." })) {
notAvailable(command);
return null;
} else if (command.equals("Reslice [/]...")) {
// TODO
niy(command);
return null;
} else if (command.equals("Z Project...")) {
// TODO
niy(command);
return null;
} else if (command.equals("3D Project...")) {
// TODO
niy(command);
return null;
} else if (command.equals("Plot Z-axis Profile")) {
// TODO
niy(command);
return null;
} else if (command.equals("Start Animation [\\]")) {
// TODO
niy(command);
return null;
} else if (command.equals("Stop Animation")) {
// TODO
niy(command);
return null;
} else // IMAGE menu again
if (command.equals("Crop")) {
notAvailable(command);
return null;
} else if (in(command, new String[] { "Translate...", "Scale..." })) {
if (null != active)
selection.specify();
return null;
} else if (command.equals("Duplicate...")) {
if (null != active && active.getClass().equals(Patch.class)) {
// TODO stacks?
// 2.5 security factor: for awt in non-1.6.0 machines
project.getLoader().releaseToFit((long) (project.getLoader().estimateImageFileSize((Patch) active, 0) * 2.5));
new ImagePlus(active.getTitle(), ((Patch) active).getImageProcessor().duplicate()).show();
}
return null;
} else if (command.equals("Rename...")) {
if (null != active) {
active.adjustProperties();
Display.updateSelection();
}
return null;
} else // IMAGE ROTATE menu
if (command.equals("Flip Horizontally")) {
selection.apply(2, new double[] { -1, 1 });
return null;
} else if (command.equals("Flip Vertically")) {
selection.apply(2, new double[] { 1, -1 });
return null;
} else if (command.equals("Rotate 90 Degrees Right")) {
selection.apply(1, new double[] { 90 });
return null;
} else if (command.equals("Rotate 90 Degrees Left")) {
selection.apply(1, new double[] { -90 });
return null;
} else if (command.equals("Arbitrarily...")) {
if (null != active)
selection.specify();
return null;
} else // IMAGE ZOOM menu
if (command.equals("To Selection")) {
Roi roi = fimp.getRoi();
if (null != roi) {
Rectangle b = roi.getBounds();
b.x -= b.width / 2;
b.y -= b.height / 2;
b.width *= 2;
b.height *= 2;
display.getCanvas().showCentered(b);
}
return null;
} else if (command.equals("View 100%")) {
// TODO
niy(command);
return null;
} else // ANALYZE menu
if (command.equals("Measure")) {
// Minimal measurement: area of closed ROIs, length of unclosed ROIs, calibrated.
Roi roi = fimp.getRoi();
if (null != roi) {
Calibration cal = fimp.getCalibration();
AffineTransform caff = new AffineTransform();
caff.scale(cal.pixelWidth, cal.pixelHeight);
if (M.isAreaROI(roi)) {
Area area = M.getArea(roi);
area = area.createTransformedArea(caff);
ResultsTable rt = Utils.createResultsTable("ROI area", new String[] { "area", "perimeter" });
rt.incrementCounter();
rt.addLabel("units", cal.getUnit());
rt.addValue(0, Math.abs(AreaCalculations.area(area.getPathIterator(null))));
rt.addValue(1, roi.getLength());
rt.show("ROI area");
} else {
ResultsTable rt = Utils.createResultsTable("ROI length", new String[] { "length" });
rt.incrementCounter();
rt.addLabel("units", cal.getUnit());
rt.addValue(0, roi.getLength());
rt.show("ROI length");
}
return null;
} else if (null != active) {
// Measure the active displayable
if (active.getClass() == Patch.class) {
// measure like 'm' would in ImageJ for an image
ImagePlus imp = ((Patch) active).getImagePlus();
imp.setCalibration(active.getLayer().getParent().getCalibrationCopy());
IJ.run(imp, "Measure", "");
} else {
// Call measure like ProjectThing does
ProjectThing pt = active.getProject().findProjectThing(active);
if (active instanceof Profile)
((ProjectThing) pt.getParent()).measure();
else
pt.measure();
}
return null;
}
Utils.log("Draw a ROI or select an object!");
return null;
} else if (in(command, new String[] { "Analyze Particles...", "Histogram", "Plot Profile", "Surface Plot...", "Color Inspector 3D", "3D Surface Plot", "Color Histogram" })) {
return setTempCurrentImage(command, active);
} else if (command.equals("Label")) {
notAvailable(command);
return null;
} else // PLUGINS menu
if (command.equals("Volume Viewer")) {
return runOnVirtualLayerSet(command, layer_set, display);
} else if (command.equals("3D Viewer")) {
// it's virtual and non-caching, will appear as a regular ImageJ stack
layer_set.createLayerStack(Displayable.class, ImagePlus.COLOR_RGB, display.getDisplayChannelAlphas()).getImagePlus().show();
return command;
} else // PROCESS menu and submenus
if (in(command, new String[] { "FFT", "Fast FFT (2D/3D)" })) {
return setTempCurrentImage(command, active);
} else if (in(command, new String[] { "Bandpass Filter...", "Custom Filter...", "FD Math...", "Swap Quadrants", "Convolve...", "Gaussian Blur...", "Median...", "Mean...", "Minimum...", "Maximum...", "Unsharp Mask...", "Variance...", "Show Circular Masks...", "Subtract Background..." })) {
return duplicate(command, active);
} else if (in(command, new String[] { "Smooth", "Sharpen", "Find Edges", "Enhance Contrast", "Add Noise", "Add Specified Noise...", "Salt and Pepper", "Despeckle", "Remove Outliers...", "North", "Northeast", "East", "Southeast", "South", "Southwest", "West", "Northwest", "Make Binary", "Convert to Mask", "Find Maxima...", "Erode", "Dilate", "Open ", "Close-", "Outline", "Fill Holes", "Skeletonize", "Distance Map", "Ultimate Points", "Watershed", "Add...", "Subtract...", "Multiply...", "Divide...", "AND...", "OR...", "XOR...", "Min...", "Max...", "Gamma...", "Log", "Exp", "Square", "Square Root", "Reciprocal", "NaN Background", "Abs" })) {
return duplicate(command, active);
}
/*else {
// continue happily
//Utils.log2("Skipping " + command);
}*/
// If it's part of "Save As", ignore it
Menu menu = Menus.getSaveAsMenu();
for (int i = menu.getItemCount() - 1; i > -1; i--) {
if (command.equals(menu.getItem(i).getActionCommand())) {
notAvailable(command);
return null;
}
}
// Give it back to ImageJ
return command;
}
use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.
the class ImageJCommandListener method duplicate.
/**
* Duplicate the active image (if any) and set it as active, so the command is run on it.
*/
private String duplicate(final String command, final Displayable active) {
if (!isPatch(command, active))
return null;
Patch pa = (Patch) active;
Project project = pa.getProject();
project.getLoader().releaseToFit((long) (project.getLoader().estimateImageFileSize(pa, 0) * 5));
// don't show it yet
ImagePlus imp = new ImagePlus("Copy of " + pa.getTitle(), pa.getImageProcessor().duplicate());
WindowManager.setTempCurrentImage(imp);
imp.show();
// now execute command
return command;
}
use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.
the class ImageJCommandListener method setTempCurrentImage.
/**
* Set as current image the Patch ImagePlus only for half a second, for a plugin to see it and grab a pointer.
* YES this is a tremendous hack that may not work in all situations, but will be reasonably ok for PlugInFilter operations.
* This action is intended for commands that don't alter the original image.
*/
private String setTempCurrentImage(final String command, final Displayable active) {
if (!isPatch(command, active))
return null;
final Patch pa = (Patch) active;
final Project project = pa.getProject();
WindowManager.setTempCurrentImage(pa.getImagePlus());
project.getLoader().releaseToFit((long) (project.getLoader().estimateImageFileSize(pa, 0) * 5));
return command;
}
use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.
the class Loader method addNewImage.
/**
* Mipmaps for this image are generated asynchronously.
*/
public Patch addNewImage(final ImagePlus imp, final double x, final double y) {
String filename = imp.getTitle();
if (!filename.toLowerCase().endsWith(".tif"))
filename += ".tif";
final String path = getStorageFolder() + "/" + filename;
new FileSaver(imp).saveAsTiff(path);
final Patch pa = new Patch(Project.findProject(this), imp.getTitle(), x, y, imp);
addedPatchFrom(path, pa);
if (isMipMapsRegenerationEnabled())
regenerateMipMaps(pa);
return pa;
}
use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.
the class Loader method insertGrid.
/**
* Insert grid in layer (with optional stitching)
*
* @param layer The Layer to inser the grid into
* @param dir The base dir of the images to open
* @param first_image_name name of the first image in the list
* @param cols The list of columns, containing each an array of String file names in each column.
* @param bx The top-left X coordinate of the grid to insert
* @param by The top-left Y coordinate of the grid to insert
* @param bt_overlap bottom-top overlap of the images
* @param lr_overlap left-right overlap of the images
* @param link_images Link images to their neighbors
* @param stitch_tiles montage option
* @param cc_percent_overlap tiles overlap
* @param cc_scale tiles scaling previous to stitching (1 = no scaling)
* @param min_R regression threshold (minimum acceptable R)
* @param homogenize_contrast contrast homogenization option
* @param stitching_rule stitching rule (upper left corner or free)
*/
private void insertGrid(final Layer layer, final String dir_, final String first_image_name, final int n_images, final ArrayList<String[]> cols, final double bx, final double by, final double bt_overlap, final double lr_overlap, final boolean link_images, final boolean stitch_tiles, final boolean homogenize_contrast, final StitchingTEM.PhaseCorrelationParam pc_param, final Worker worker) {
// create a Worker, then give it to the Bureaucrat
try {
String dir = dir_;
final ArrayList<Patch> al = new ArrayList<Patch>();
Utils.showProgress(0.0D);
// less repaints on IJ status bar
opener.setSilentMode(true);
int x = 0;
int y = 0;
int largest_y = 0;
ImagePlus img = null;
// open the selected image, to use as reference for width and height
// w1nd0wz safe
dir = dir.replace('\\', '/');
if (!dir.endsWith("/"))
dir += "/";
String path = dir + first_image_name;
// TODO arbitrary x3 factor
releaseToFit(new File(path).length() * 3);
IJ.redirectErrorMessages();
ImagePlus first_img = openImagePlus(path);
if (null == first_img) {
Utils.log("Selected image to open first is null.");
return;
}
if (null == first_img)
return;
final int first_image_width = first_img.getWidth();
final int first_image_height = first_img.getHeight();
final int first_image_type = first_img.getType();
// start
final Patch[][] pall = new Patch[cols.size()][((String[]) cols.get(0)).length];
int width, height;
// counter
int k = 0;
boolean auto_fix_all = false;
boolean ignore_all = false;
boolean resize = false;
if (!ControlWindow.isGUIEnabled()) {
// headless mode: autofix all
auto_fix_all = true;
resize = true;
}
// Accumulate mipmap generation tasks
final ArrayList<Future<?>> fus = new ArrayList<Future<?>>();
startLargeUpdate();
for (int i = 0; i < cols.size(); i++) {
final String[] rows = (String[]) cols.get(i);
if (i > 0) {
x -= lr_overlap;
}
for (int j = 0; j < rows.length; j++) {
if (Thread.currentThread().isInterrupted()) {
Display.repaint(layer);
rollback();
return;
}
if (j > 0) {
y -= bt_overlap;
}
// get file name
final String file_name = (String) rows[j];
path = dir + file_name;
if (null != first_img && file_name.equals(first_image_name)) {
img = first_img;
// release pointer
first_img = null;
} else {
// open image
releaseToFit(first_image_width, first_image_height, first_image_type, 1.5f);
try {
IJ.redirectErrorMessages();
img = openImagePlus(path);
} catch (final OutOfMemoryError oome) {
printMemState();
throw oome;
}
}
if (null == img) {
Utils.log("null image! skipping.");
pall[i][j] = null;
continue;
}
width = img.getWidth();
height = img.getHeight();
int rw = width;
int rh = height;
if (width != first_image_width || height != first_image_height) {
int new_width = first_image_width;
int new_height = first_image_height;
if (!auto_fix_all && !ignore_all) {
final GenericDialog gdr = new GenericDialog("Size mismatch!");
gdr.addMessage("The size of " + file_name + " is " + width + " x " + height);
gdr.addMessage("but the selected image was " + first_image_width + " x " + first_image_height);
gdr.addMessage("Adjust to selected image dimensions?");
gdr.addNumericField("width: ", (double) first_image_width, 0);
// should not be editable ... or at least, explain in some way that the dimensions can be edited just for this image --> done below
gdr.addNumericField("height: ", (double) first_image_height, 0);
gdr.addMessage("[If dimensions are changed they will apply only to this image]");
gdr.addMessage("");
final String[] au = new String[] { "fix all", "ignore all" };
gdr.addChoice("Automate:", au, au[1]);
gdr.addMessage("Cancel == NO OK = YES");
gdr.showDialog();
if (gdr.wasCanceled()) {
resize = false;
// do nothing: don't fix/resize
}
resize = true;
// catch values
new_width = (int) gdr.getNextNumber();
new_height = (int) gdr.getNextNumber();
final int iau = gdr.getNextChoiceIndex();
if (new_width != first_image_width || new_height != first_image_height) {
auto_fix_all = false;
} else {
auto_fix_all = (0 == iau);
}
ignore_all = (1 == iau);
if (ignore_all)
resize = false;
}
if (resize) {
// resize Patch dimensions
rw = first_image_width;
rh = first_image_height;
}
}
// add new Patch at base bx,by plus the x,y of the grid
// will call back and cache the image
final Patch patch = new Patch(layer.getProject(), img.getTitle(), bx + x, by + y, img);
if (width != rw || height != rh)
patch.setDimensions(rw, rh, false);
addedPatchFrom(path, patch);
if (// prevent it
homogenize_contrast)
// prevent it
setMipMapsRegeneration(false);
else
fus.add(regenerateMipMaps(patch));
//
// after the above two lines! Otherwise it will paint fine, but throw exceptions on the way
layer.add(patch, true);
// otherwise when reopening it has to fetch all ImagePlus and scale and zip them all! This method though creates the awt and the snap, thus filling up memory and slowing down, but it's worth it.
patch.updateInDatabase("tiff_snapshot");
pall[i][j] = patch;
al.add(patch);
if (ControlWindow.isGUIEnabled()) {
// northwest to prevent screwing up Patch coordinates.
layer.getParent().enlargeToFit(patch, LayerSet.NORTHWEST);
}
y += img.getHeight();
Utils.showProgress((double) k / n_images);
k++;
}
x += img.getWidth();
if (largest_y < y) {
largest_y = y;
}
// resetting!
y = 0;
}
// build list
final Patch[] pa = new Patch[al.size()];
int f = 0;
// list in row-first order
for (int j = 0; j < pall[0].length; j++) {
// 'j' is row
for (int i = 0; i < pall.length; i++) {
// 'i' is column
pa[f++] = pall[i][j];
}
}
// optimize repaints: all to background image
Display.clearSelection(layer);
// make the first one be top, and the rest under it in left-right and top-bottom order
for (int j = 0; j < pa.length; j++) {
layer.moveBottom(pa[j]);
}
// make picture
// getFlatImage(layer, layer.getMinimalBoundingBox(Patch.class), 0.25, 1, ImagePlus.GRAY8, Patch.class, null, false).show();
// optimize repaints: all to background image
Display.clearSelection(layer);
if (homogenize_contrast) {
if (null != worker)
worker.setTaskName("Enhancing contrast");
// 0 - check that all images are of the same type
int tmp_type = pa[0].getType();
for (int e = 1; e < pa.length; e++) {
if (pa[e].getType() != tmp_type) {
// can't continue
tmp_type = Integer.MAX_VALUE;
Utils.log("Can't homogenize histograms: images are not all of the same type.\nFirst offending image is: " + al.get(e));
break;
}
}
if (Integer.MAX_VALUE != tmp_type) {
// checking on error flag
// Set min and max for all images
// 1 - fetch statistics for each image
final ArrayList<ImageStatistics> al_st = new ArrayList<ImageStatistics>();
// list of Patch ordered by stdDev ASC
final ArrayList<Patch> al_p = new ArrayList<Patch>();
int type = -1;
for (int i = 0; i < pa.length; i++) {
if (Thread.currentThread().isInterrupted()) {
Display.repaint(layer);
rollback();
return;
}
ImagePlus imp = fetchImagePlus(pa[i]);
// speed-up trick: extract data from smaller image
if (imp.getWidth() > 1024) {
releaseToFit(1024, (int) ((imp.getHeight() * 1024) / imp.getWidth()), imp.getType(), 1.1f);
// cheap and fast nearest-point resizing
imp = new ImagePlus(imp.getTitle(), imp.getProcessor().resize(1024));
}
if (-1 == type)
type = imp.getType();
final ImageStatistics i_st = imp.getStatistics();
// order by stdDev, from small to big
int q = 0;
for (final ImageStatistics st : al_st) {
q++;
if (st.stdDev > i_st.stdDev)
break;
}
if (q == al.size()) {
// append at the end. WARNING if importing thousands of images, this is a potential source of out of memory errors. I could just recompute it when I needed it again below
al_st.add(i_st);
al_p.add(pa[i]);
} else {
al_st.add(q, i_st);
al_p.add(q, pa[i]);
}
}
// shallow copy of the ordered list
final ArrayList<Patch> al_p2 = new ArrayList<Patch>(al_p);
// 2 - discard the first and last 25% (TODO: a proper histogram clustering analysis and histogram examination should apply here)
if (pa.length > 3) {
// under 4 images, use them all
int i = 0;
while (i <= pa.length * 0.25) {
al_p.remove(i);
i++;
}
final int count = i;
i = pa.length - 1 - count;
while (i > (pa.length * 0.75) - count) {
al_p.remove(i);
i--;
}
}
// 3 - compute common histogram for the middle 50% images
final Patch[] p50 = new Patch[al_p.size()];
al_p.toArray(p50);
final StackStatistics stats = new StackStatistics(new PatchStack(p50, 1));
// 4 - compute autoAdjust min and max values
// extracting code from ij.plugin.frame.ContrastAdjuster, method autoAdjust
int autoThreshold = 0;
double min = 0;
double max = 0;
// once for 8-bit and color, twice for 16 and 32-bit (thus the 2501 autoThreshold value)
final int limit = stats.pixelCount / 10;
final int[] histogram = stats.histogram;
// else autoThreshold /= 2;
if (ImagePlus.GRAY16 == type || ImagePlus.GRAY32 == type)
autoThreshold = 2500;
else
autoThreshold = 5000;
final int threshold = stats.pixelCount / autoThreshold;
int i = -1;
boolean found = false;
int count;
do {
i++;
count = histogram[i];
if (count > limit)
count = 0;
found = count > threshold;
} while (!found && i < 255);
final int hmin = i;
i = 256;
do {
i--;
count = histogram[i];
if (count > limit)
count = 0;
found = count > threshold;
} while (!found && i > 0);
final int hmax = i;
if (hmax >= hmin) {
min = stats.histMin + hmin * stats.binSize;
max = stats.histMin + hmax * stats.binSize;
if (min == max) {
min = stats.min;
max = stats.max;
}
}
// 5 - compute common mean within min,max range
final double target_mean = getMeanOfRange(stats, min, max);
Utils.log2("Loader min,max: " + min + ", " + max + ", target mean: " + target_mean);
// 6 - apply to all
for (i = al_p2.size() - 1; i > -1; i--) {
// the order is different, thus getting it from the proper list
final Patch p = (Patch) al_p2.get(i);
final double dm = target_mean - getMeanOfRange((ImageStatistics) al_st.get(i), min, max);
// displacing in the opposite direction, makes sense, so that the range is drifted upwards and thus the target 256 range for an awt.Image will be closer to the ideal target_mean
p.setMinAndMax(min - dm, max - dm);
// OBSOLETE and wrong //p.putMinAndMax(fetchImagePlus(p));
}
setMipMapsRegeneration(true);
if (isMipMapsRegenerationEnabled()) {
// recreate files
for (final Patch p : al) fus.add(regenerateMipMaps(p));
}
Display.repaint(layer, new Rectangle(0, 0, (int) layer.getParent().getLayerWidth(), (int) layer.getParent().getLayerHeight()), 0);
// make picture
// getFlatImage(layer, layer.getMinimalBoundingBox(Patch.class), 0.25, 1, ImagePlus.GRAY8, Patch.class, null, false).show();
}
}
if (stitch_tiles) {
// Wait until all mipmaps for the new images have been generated before attempting to register
Utils.wait(fus);
// create undo
layer.getParent().addTransformStep(new HashSet<Displayable>(layer.getDisplayables(Patch.class)));
// wait until repainting operations have finished (otherwise, calling crop on an ImageProcessor fails with out of bounds exception sometimes)
if (null != Display.getFront())
Display.getFront().getCanvas().waitForRepaint();
if (null != worker)
worker.setTaskName("Stitching");
StitchingTEM.stitch(pa, cols.size(), bt_overlap, lr_overlap, true, pc_param).run();
}
// link with images on top, bottom, left and right.
if (link_images) {
if (null != worker)
worker.setTaskName("Linking");
for (int i = 0; i < pall.length; i++) {
// 'i' is column
for (int j = 0; j < pall[0].length; j++) {
// 'j' is row
final Patch p = pall[i][j];
// can happen if a slot is empty
if (null == p)
continue;
if (i > 0 && null != pall[i - 1][j])
p.link(pall[i - 1][j]);
if (i < pall.length - 1 && null != pall[i + 1][j])
p.link(pall[i + 1][j]);
if (j > 0 && null != pall[i][j - 1])
p.link(pall[i][j - 1]);
if (j < pall[0].length - 1 && null != pall[i][j + 1])
p.link(pall[i][j + 1]);
}
}
}
commitLargeUpdate();
// resize LayerSet
// int new_width = x;
// int new_height = largest_y;
// Math.abs(bx) + new_width, Math.abs(by) + new_height);
layer.getParent().setMinimumDimensions();
// update indexes
// so its done once only
layer.updateInDatabase("stack_index");
// create panels in all Displays showing this layer
/* // not needed anymore
Iterator it = al.iterator();
while (it.hasNext()) {
Display.add(layer, (Displayable)it.next(), false); // don't set it active, don't want to reload the ImagePlus!
}
*/
// update Displays
Display.update(layer);
layer.recreateBuckets();
// debug:
} catch (final Throwable t) {
IJError.print(t);
rollback();
setMipMapsRegeneration(true);
}
}
Aggregations