use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.
the class Loader method setMinAndMax.
public Bureaucrat setMinAndMax(final Collection<? extends Displayable> patches, final double min, final double max) {
final Worker worker = new Worker("Set min and max") {
@Override
public void run() {
try {
startedWorking();
if (Double.isNaN(min) || Double.isNaN(max)) {
Utils.log("WARNING:\nUnacceptable min and max values: " + min + ", " + max);
finishedWorking();
return;
}
final ArrayList<Future<?>> fus = new ArrayList<Future<?>>();
for (final Displayable d : patches) {
if (d.getClass() != Patch.class)
continue;
final Patch p = (Patch) d;
p.setMinAndMax(min, max);
// Will also flush the cache for Patch p:
fus.add(regenerateMipMaps(p));
}
Utils.wait(fus);
} catch (final Exception e) {
IJError.print(e);
} finally {
finishedWorking();
}
}
};
return Bureaucrat.createAndStart(worker, Project.findProject(this));
}
use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.
the class Loader method importStack.
/**
* Imports an image stack from a multitiff file and places each slice in the proper layer, creating new layers as it goes. If the given stack is null, popup a file dialog to choose one
*/
public Bureaucrat importStack(final Layer first_layer, final double x, final double y, final ImagePlus imp_stack_, final boolean ask_for_data, final String filepath_, final boolean one_patch_per_layer_) {
Utils.log2("Loader.importStack filepath: " + filepath_);
if (null == first_layer)
return null;
final Worker worker = new Worker("import stack") {
@Override
public void run() {
startedWorking();
try {
String filepath = filepath_;
boolean one_patch_per_layer = one_patch_per_layer_;
/* On drag and drop the stack is not null! */
// Utils.log2("imp_stack_ is " + imp_stack_);
ImagePlus[] stks = null;
boolean choose = false;
if (null == imp_stack_) {
stks = Utils.findOpenStacks();
choose = null == stks || stks.length > 0;
} else {
stks = new ImagePlus[] { imp_stack_ };
}
ImagePlus imp_stack = null;
// ask to open a stack if it's null
if (null == stks) {
// choose one
imp_stack = openStack();
} else if (choose) {
// choose one from the list
final GenericDialog gd = new GenericDialog("Choose one");
gd.addMessage("Choose a stack from the list or 'open...' to bring up a file chooser dialog:");
final String[] list = new String[stks.length + 1];
for (int i = 0; i < list.length - 1; i++) {
list[i] = stks[i].getTitle();
}
list[list.length - 1] = "[ Open stack... ]";
gd.addChoice("choose stack: ", list, list[0]);
gd.showDialog();
if (gd.wasCanceled()) {
finishedWorking();
return;
}
final int i_choice = gd.getNextChoiceIndex();
if (list.length - 1 == i_choice) {
// the open... command
imp_stack = first_layer.getProject().getLoader().openStack();
} else {
imp_stack = stks[i_choice];
}
} else {
imp_stack = imp_stack_;
}
// check:
if (null == imp_stack) {
finishedWorking();
return;
}
final String props = (String) imp_stack.getProperty("Info");
// check if it's amira labels stack to prevent missimports
if (null != props && -1 != props.indexOf("Materials {")) {
final YesNoDialog yn = new YesNoDialog(IJ.getInstance(), "Warning", "You are importing a stack of Amira labels as a regular image stack. Continue anyway?");
if (!yn.yesPressed()) {
finishedWorking();
return;
}
}
// String dir = imp_stack.getFileInfo().directory;
final double layer_width = first_layer.getLayerWidth();
final double layer_height = first_layer.getLayerHeight();
final double current_thickness = first_layer.getThickness();
double thickness = current_thickness;
boolean expand_layer_set = false;
boolean lock_stack = false;
// int anchor = LayerSet.NORTHWEST; //default
if (ask_for_data) {
// ask for slice separation in pixels
final GenericDialog gd = new GenericDialog("Slice separation?");
gd.addMessage("Please enter the slice thickness, in pixels");
// assuming pixelWidth == pixelHeight
gd.addNumericField("slice_thickness: ", Math.abs(imp_stack.getCalibration().pixelDepth / imp_stack.getCalibration().pixelHeight), 3);
if (layer_width != imp_stack.getWidth() || layer_height != imp_stack.getHeight()) {
gd.addCheckbox("Resize canvas to fit stack", true);
// gd.addChoice("Anchor: ", LayerSet.ANCHORS, LayerSet.ANCHORS[0]);
}
gd.addCheckbox("Lock stack", false);
final String[] importStackTypes = { "One slice per layer (Patches)", "Image volume (Stack)" };
if (imp_stack.getStack().isVirtual()) {
one_patch_per_layer = true;
}
gd.addChoice("Import stack as:", importStackTypes, importStackTypes[0]);
((Component) gd.getChoices().get(0)).setEnabled(!imp_stack.getStack().isVirtual());
gd.showDialog();
if (gd.wasCanceled()) {
if (null == stks) {
// flush only if it was not open before
flush(imp_stack);
}
finishedWorking();
return;
}
if (layer_width != imp_stack.getWidth() || layer_height != imp_stack.getHeight()) {
expand_layer_set = gd.getNextBoolean();
// anchor = gd.getNextChoiceIndex();
}
lock_stack = gd.getNextBoolean();
thickness = gd.getNextNumber();
// check provided thickness with that of the first layer:
if (thickness != current_thickness) {
if (1 == first_layer.getParent().size() && first_layer.isEmpty()) {
final YesNoCancelDialog yn = new YesNoCancelDialog(IJ.getInstance(), "Mismatch!", "The current layer's thickness is " + current_thickness + "\nwhich is " + (thickness < current_thickness ? "larger" : "smaller") + " than\nthe desired " + thickness + " for each stack slice.\nAdjust current layer's thickness to " + thickness + " ?");
if (yn.cancelPressed()) {
// was opened new
if (null != imp_stack_)
flush(imp_stack);
finishedWorking();
return;
} else if (yn.yesPressed()) {
first_layer.setThickness(thickness);
// The rest of layers, created new, will inherit the same thickness
}
} else {
final YesNoDialog yn = new YesNoDialog(IJ.getInstance(), "WARNING", "There's more than one layer or the current layer is not empty\nso the thickness cannot be adjusted. Proceed anyway?");
if (!yn.yesPressed()) {
finishedWorking();
return;
}
}
}
one_patch_per_layer = imp_stack.getStack().isVirtual() || 0 == gd.getNextChoiceIndex();
}
if (null == imp_stack.getStack()) {
Utils.showMessage("Not a stack.");
finishedWorking();
return;
}
// WARNING: there are fundamental issues with calibration, because the Layer thickness is disconnected from the Calibration pixelDepth
// set LayerSet calibration if there is no calibration
boolean calibrate = true;
if (ask_for_data && first_layer.getParent().isCalibrated()) {
if (!ControlWindow.isGUIEnabled()) {
Utils.log2("Loader.importStack: overriding LayerSet calibration with that of the imported stack.");
} else {
final YesNoDialog yn = new YesNoDialog("Calibration", "The layer set is already calibrated. Override with the stack calibration values?");
if (!yn.yesPressed()) {
calibrate = false;
}
}
}
if (calibrate) {
first_layer.getParent().setCalibration(imp_stack.getCalibration());
}
if (layer_width < imp_stack.getWidth() || layer_height < imp_stack.getHeight()) {
expand_layer_set = true;
}
if (imp_stack.getStack().isVirtual()) {
// do nothing
} else if (null == filepath) {
// try to get it from the original FileInfo
final FileInfo fi = imp_stack.getOriginalFileInfo();
if (null != fi && null != fi.directory && null != fi.fileName) {
filepath = fi.directory.replace('\\', '/');
if (!filepath.endsWith("/"))
filepath += '/';
filepath += fi.fileName;
}
Utils.log2("Getting filepath from FileInfo: " + filepath);
// check that file exists, otherwise save a copy in the storage folder
if (null == filepath || (!filepath.startsWith("http://") && !new File(filepath).exists())) {
filepath = handlePathlessImage(imp_stack);
}
} else {
filepath = filepath.replace('\\', '/');
}
// Import as Stack ZDisplayable object:
if (!one_patch_per_layer) {
final Stack st = new Stack(first_layer.getProject(), new File(filepath).getName(), x, y, first_layer, filepath);
first_layer.getParent().add(st);
finishedWorking();
return;
}
// Place the first slice in the current layer, and then query the parent LayerSet for subsequent layers, and create them if not present.
final Patch last_patch = Loader.this.importStackAsPatches(first_layer.getProject(), first_layer, x, y, imp_stack, null != imp_stack_ && null != imp_stack_.getCanvas(), filepath);
if (null != last_patch) {
last_patch.setLocked(lock_stack);
Display.updateCheckboxes(last_patch.getLinkedGroup(null), DisplayablePanel.LOCK_STATE, true);
}
if (expand_layer_set) {
last_patch.getLayer().getParent().setMinimumDimensions();
}
Utils.log2("props: " + props);
// check if it's an amira stack, then ask to import labels
if (null != props && -1 == props.indexOf("Materials {") && -1 != props.indexOf("CoordType")) {
final YesNoDialog yn = new YesNoDialog(IJ.getInstance(), "Amira Importer", "Import labels as well?");
if (yn.yesPressed()) {
// select labels
final Collection<AreaList> alis = AmiraImporter.importAmiraLabels(first_layer, last_patch.getX(), last_patch.getY(), imp_stack.getOriginalFileInfo().directory);
if (null != alis) {
// import all created AreaList as nodes in the ProjectTree under a new imported_segmentations node
first_layer.getProject().getProjectTree().insertSegmentations(alis);
// link them to the images
for (final AreaList ali : alis) {
ali.linkPatches();
}
}
}
}
// it is safe not to flush the imp_stack, because all its resources are being used anyway (all the ImageProcessor), and it has no awt.Image. Unless it's being shown in ImageJ, and then it will be flushed on its own when the user closes its window.
} catch (final Exception e) {
IJError.print(e);
}
finishedWorking();
}
};
return Bureaucrat.createAndStart(worker, first_layer.getProject());
}
use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.
the class Loader method makePrescaledTiles.
/**
* Generate 256x256 tiles, as many as necessary, to cover the given srcRect, starting at max_scale. Designed to be slow but memory-capable.
*
* filename = z + "/" + row + "_" + column + "_" + s + ".jpg";
*
* row and column run from 0 to n stepsize 1
* that is, row = y / ( 256 * 2^s ) and column = x / ( 256 * 2^s )
*
* z : z-level (slice)
* x,y: the row and column
* s: scale, which is 1 / (2^s), in integers: 0, 1, 2 ...
*
* var MAX_S = Math.floor( Math.log( MAX_Y + 1 ) / Math.LN2 ) - Math.floor( Math.log( Y_TILE_SIZE ) / Math.LN2 ) - 1;
*
* The module should not be more than 5
* At al levels, there should be an even number of rows and columns, except for the coarsest level.
* The coarsest level should be at least 5x5 tiles.
*
* Best results obtained when the srcRect approaches or is a square. Black space will pad the right and bottom edges when the srcRect is not exactly a square.
* Only the area within the srcRect is ever included, even if actual data exists beyond.
*
* @return The watcher thread, for joining purposes, or null if the dialog is canceled or preconditions are not passed.
* @throws IllegalArgumentException if the type is not ImagePlus.GRAY8 or Imageplus.COLOR_RGB.
*/
public Bureaucrat makePrescaledTiles(final Layer[] layers, final Class<?> clazz, final Rectangle srcRect, double max_scale_, final int c_alphas, final int type, String target_dir, final boolean from_original_images, final Saver saver, final int tileSide) {
if (null == layers || 0 == layers.length)
return null;
switch(type) {
case ImagePlus.GRAY8:
case ImagePlus.COLOR_RGB:
break;
default:
throw new IllegalArgumentException("Can only export for web with 8-bit or RGB");
}
// choose target directory
if (null == target_dir) {
final DirectoryChooser dc = new DirectoryChooser("Choose target directory");
target_dir = dc.getDirectory();
if (null == target_dir)
return null;
}
if (IJ.isWindows())
target_dir = target_dir.replace('\\', '/');
if (!target_dir.endsWith("/"))
target_dir += "/";
if (max_scale_ > 1) {
Utils.log("Prescaled Tiles: using max scale of 1.0");
// no point
max_scale_ = 1;
}
final String dir = target_dir;
final double max_scale = max_scale_;
final Worker worker = new Worker("Creating prescaled tiles") {
private void cleanUp() {
finishedWorking();
}
@Override
public void run() {
startedWorking();
try {
// project name
// String pname = layer[0].getProject().getTitle();
// create 'z' directories if they don't exist: check and ask!
// start with the highest scale level
final int[] best = determineClosestPowerOfTwo(srcRect.width > srcRect.height ? srcRect.width : srcRect.height);
final int edge_length = best[0];
final int n_edge_tiles = edge_length / tileSide;
Utils.log2("srcRect: " + srcRect);
Utils.log2("edge_length, n_edge_tiles, best[1] " + best[0] + ", " + n_edge_tiles + ", " + best[1]);
// thumbnail dimensions
// LayerSet ls = layer[0].getParent();
final double ratio = srcRect.width / (double) srcRect.height;
double thumb_scale = 1.0;
if (ratio >= 1) {
// width is larger or equal than height
thumb_scale = 192.0 / srcRect.width;
} else {
thumb_scale = 192.0 / srcRect.height;
}
// Figure out layer indices, given that layers are not necessarily evenly spaced
final TreeMap<Integer, Layer> indices = new TreeMap<Integer, Layer>();
final ArrayList<Integer> missingIndices = new ArrayList<Integer>();
final double resolution_z_px;
final int smallestIndex, largestIndex;
if (1 == layers.length) {
indices.put(0, layers[0]);
resolution_z_px = layers[0].getZ();
smallestIndex = 0;
largestIndex = 0;
} else {
// Ensure layers are sorted by Z index and are unique pointers and unique in Z coordinate:
final TreeMap<Double, Layer> t = new TreeMap<Double, Layer>();
for (final Layer l1 : new HashSet<Layer>(Arrays.asList(layers))) {
final Layer l2 = t.get(l1.getZ());
if (null == l2) {
t.put(l1.getZ(), l1);
} else {
// Ignore the layer with less objects
if (l1.getDisplayables().size() > l2.getDisplayables().size()) {
t.put(l1.getZ(), l1);
Utils.log("Ignoring duplicate layer: " + l2);
}
}
}
// What is the mode thickness, measured by Z(i-1) - Z(i)?
// (Distance between the Z of two consecutive layers)
final HashMap<Double, Integer> counts = new HashMap<Double, Integer>();
final Layer prev = t.get(t.firstKey());
double modeThickness = 0;
int modeThicknessCount = 0;
for (final Layer la : t.tailMap(prev.getZ(), false).values()) {
// Thickness with 3-decimal precision only
final double d = ((int) ((la.getZ() - prev.getZ()) * 1000 + 0.5)) / 1000.0;
Integer c = counts.get(d);
//
if (null == c)
c = 0;
++c;
counts.put(d, c);
//
if (c > modeThicknessCount) {
modeThicknessCount = c;
modeThickness = d;
}
}
// Not pixelDepth
resolution_z_px = modeThickness * prev.getParent().getCalibration().pixelWidth;
// Assign an index to each layer, approximating each layer at modeThickness intervals
for (final Layer la : t.values()) {
indices.put((int) (la.getZ() / modeThickness + 0.5), la);
}
// First and last
smallestIndex = indices.firstKey();
largestIndex = indices.lastKey();
Utils.logAll("indices: " + smallestIndex + ", " + largestIndex);
// Which indices are missing?
for (int i = smallestIndex + 1; i < largestIndex; ++i) {
if (!indices.containsKey(i)) {
missingIndices.add(i);
}
}
}
// JSON metadata for CATMAID
{
final StringBuilder sb = new StringBuilder("{");
final LayerSet ls = layers[0].getParent();
final Calibration cal = ls.getCalibration();
sb.append("\"volume_width_px\": ").append(srcRect.width).append(',').append('\n').append("\"volume_height_px\": ").append(srcRect.height).append(',').append('\n').append("\"volume_sections\": ").append(largestIndex - smallestIndex + 1).append(',').append('\n').append("\"extension\": \"").append(saver.getExtension()).append('\"').append(',').append('\n').append("\"resolution_x\": ").append(cal.pixelWidth).append(',').append('\n').append("\"resolution_y\": ").append(cal.pixelHeight).append(',').append('\n').append("\"resolution_z\": ").append(resolution_z_px).append(',').append('\n').append("\"units\": \"").append(cal.getUnit()).append('"').append(',').append('\n').append("\"offset_x_px\": 0,\n").append("\"offset_y_px\": 0,\n").append("\"offset_z_px\": ").append(indices.get(indices.firstKey()).getZ() * cal.pixelWidth / cal.pixelDepth).append(',').append('\n').append("\"missing_layers\": [");
for (final Integer i : missingIndices) sb.append(i - smallestIndex).append(',');
// remove last comma
sb.setLength(sb.length() - 1);
sb.append("]}");
if (!Utils.saveToFile(new File(dir + "metadata.json"), sb.toString())) {
Utils.logAll("WARNING: could not save " + dir + "metadata.json\nThe contents was:\n" + sb.toString());
}
}
for (final Map.Entry<Integer, Layer> entry : indices.entrySet()) {
if (this.quit) {
cleanUp();
return;
}
final int index = entry.getKey() - smallestIndex;
final Layer layer = entry.getValue();
// 1 - create a directory 'z' named as the layer's index
String tile_dir = dir + index;
File fdir = new File(tile_dir);
final int tag = 1;
// Ensure there is a usable directory:
while (fdir.exists() && !fdir.isDirectory()) {
fdir = new File(tile_dir + "_" + tag);
}
if (!fdir.exists()) {
fdir.mkdir();
Utils.log("Created directory " + fdir);
}
// if the directory exists already just reuse it, overwritting its files if so.
final String tmp = fdir.getAbsolutePath().replace('\\', '/');
if (!tile_dir.equals(tmp))
Utils.log("\tWARNING: directory will not be in the standard location.");
// debug:
Utils.log2("tile_dir: " + tile_dir + "\ntmp: " + tmp);
tile_dir = tmp;
if (!tile_dir.endsWith("/"))
tile_dir += "/";
// 2 - create layer thumbnail, max 192x192
ImagePlus thumb = getFlatImage(layer, srcRect, thumb_scale, c_alphas, type, clazz, true);
saver.save(thumb, tile_dir + "small");
// ImageSaver.saveAsJpeg(thumb.getProcessor(), tile_dir + "small.jpg", jpeg_quality, ImagePlus.COLOR_RGB != type);
flush(thumb);
thumb = null;
// 3 - fill directory with tiles
if (edge_length < tileSide) {
// edge_length is the largest length of the tileSide x tileSide tile map that covers an area equal or larger than the desired srcRect (because all tiles have to be tileSide x tileSide in size)
// create single tile per layer
makeTile(layer, srcRect, max_scale, c_alphas, type, clazz, tile_dir + "0_0_0", saver);
} else {
// create pyramid of tiles
if (from_original_images) {
Utils.log("Exporting from web using original images");
// Create a giant 8-bit image of the whole layer from original images
double scale = 1;
Utils.log("Export srcRect: " + srcRect);
// WARNING: the snapshot will most likely be smaller than the virtual square image being chopped into tiles
ImageProcessor snapshot = null;
if (ImagePlus.COLOR_RGB == type) {
Utils.log("WARNING: ignoring alpha masks for 'use original images' and 'RGB color' options");
snapshot = Patch.makeFlatImage(type, layer, srcRect, scale, (ArrayList<Patch>) (List) layer.getDisplayables(Patch.class, true), Color.black, true);
} else if (ImagePlus.GRAY8 == type) {
// Respect alpha masks and display range:
Utils.log("WARNING: ignoring scale for 'use original images' and '8-bit' options");
snapshot = ExportUnsignedShort.makeFlatImage((ArrayList<Patch>) (List) layer.getDisplayables(Patch.class, true), srcRect, 0).convertToByte(true);
} else {
Utils.log("ERROR: don't know how to generate mipmaps for type '" + type + "'");
cleanUp();
return;
}
int scale_pow = 0;
int n_et = n_edge_tiles;
final ExecutorService exe = Utils.newFixedThreadPool("export-for-web");
final ArrayList<Future<?>> fus = new ArrayList<Future<?>>();
try {
while (n_et >= best[1]) {
final int snapWidth = snapshot.getWidth();
final int snapHeight = snapshot.getHeight();
final ImageProcessor source = snapshot;
for (int row = 0; row < n_et; row++) {
for (int col = 0; col < n_et; col++) {
final String path = new StringBuilder(tile_dir).append(row).append('_').append(col).append('_').append(scale_pow).toString();
final int tileXStart = col * tileSide;
final int tileYStart = row * tileSide;
final int pixelOffset = tileYStart * snapWidth + tileXStart;
fus.add(exe.submit(new Callable<Boolean>() {
@Override
public Boolean call() {
if (ImagePlus.GRAY8 == type) {
final byte[] pixels = (byte[]) source.getPixels();
final byte[] p = new byte[tileSide * tileSide];
for (int y = 0, sourceIndex = pixelOffset; y < tileSide && tileYStart + y < snapHeight; sourceIndex = pixelOffset + y * snapWidth, y++) {
final int offsetL = y * tileSide;
for (int x = 0; x < tileSide && tileXStart + x < snapWidth; sourceIndex++, x++) {
p[offsetL + x] = pixels[sourceIndex];
}
}
return saver.save(new ImagePlus(path, new ByteProcessor(tileSide, tileSide, p, GRAY_LUT)), path);
} else {
final int[] pixels = (int[]) source.getPixels();
final int[] p = new int[tileSide * tileSide];
for (int y = 0, sourceIndex = pixelOffset; y < tileSide && tileYStart + y < snapHeight; sourceIndex = pixelOffset + y * snapWidth, y++) {
final int offsetL = y * tileSide;
for (int x = 0; x < tileSide && tileXStart + x < snapWidth; sourceIndex++, x++) {
p[offsetL + x] = pixels[sourceIndex];
}
}
return saver.save(new ImagePlus(path, new ColorProcessor(tileSide, tileSide, p)), path);
}
}
}));
}
}
//
scale_pow++;
// works as magnification
scale = 1 / Math.pow(2, scale_pow);
n_et /= 2;
//
Utils.wait(fus);
fus.clear();
// Scale snapshot in half with area averaging
final ImageProcessor nextSnapshot;
if (ImagePlus.GRAY8 == type) {
nextSnapshot = new ByteProcessor((int) (srcRect.width * scale), (int) (srcRect.height * scale));
final byte[] p1 = (byte[]) snapshot.getPixels();
final byte[] p2 = (byte[]) nextSnapshot.getPixels();
final int width1 = snapshot.getWidth();
final int width2 = nextSnapshot.getWidth();
final int height2 = nextSnapshot.getHeight();
int i = 0;
for (int y1 = 0, y2 = 0; y2 < height2; y1 += 2, y2++) {
final int offset1a = y1 * width1;
final int offset1b = (y1 + 1) * width1;
for (int x1 = 0, x2 = 0; x2 < width2; x1 += 2, x2++) {
p2[i++] = (byte) (((p1[offset1a + x1] & 0xff) + (p1[offset1a + x1 + 1] & 0xff) + (p1[offset1b + x1] & 0xff) + (p1[offset1b + x1 + 1] & 0xff)) / 4);
}
}
} else {
nextSnapshot = new ColorProcessor((int) (srcRect.width * scale), (int) (srcRect.height * scale));
final int[] p1 = (int[]) snapshot.getPixels();
final int[] p2 = (int[]) nextSnapshot.getPixels();
final int width1 = snapshot.getWidth();
final int width2 = nextSnapshot.getWidth();
final int height2 = nextSnapshot.getHeight();
int i = 0;
for (int y1 = 0, y2 = 0; y2 < height2; y1 += 2, y2++) {
final int offset1a = y1 * width1;
final int offset1b = (y1 + 1) * width1;
for (int x1 = 0, x2 = 0; x2 < width2; x1 += 2, x2++) {
final int ka = p1[offset1a + x1], kb = p1[offset1a + x1 + 1], kc = p1[offset1b + x1], kd = p1[offset1b + x1 + 1];
// Average each channel independently
p2[i++] = (((// red
((ka >> 16) & 0xff) + ((kb >> 16) & 0xff) + ((kc >> 16) & 0xff) + ((kd >> 16) & 0xff)) / 4) << 16) + (((// green
((ka >> 8) & 0xff) + ((kb >> 8) & 0xff) + ((kc >> 8) & 0xff) + ((kd >> 8) & 0xff)) / 4) << 8) + (// blue
(ka & 0xff) + (kb & 0xff) + (kc & 0xff) + (kd & 0xff)) / 4;
}
}
}
// Assign for next iteration
snapshot = nextSnapshot;
// Scale snapshot with a TransformMesh
/*
AffineModel2D aff = new AffineModel2D();
aff.set(0.5f, 0, 0, 0.5f, 0, 0);
ImageProcessor scaledSnapshot = new ByteProcessor((int)(snapshot.getWidth() * scale), (int)(snapshot.getHeight() * scale));
final CoordinateTransformMesh mesh = new CoordinateTransformMesh( aff, 32, snapshot.getWidth(), snapshot.getHeight() );
final mpicbg.ij.TransformMeshMapping<CoordinateTransformMesh> mapping = new mpicbg.ij.TransformMeshMapping<CoordinateTransformMesh>( mesh );
mapping.mapInterpolated(snapshot, scaledSnapshot, Runtime.getRuntime().availableProcessors());
// Assign for next iteration
snapshot = scaledSnapshot;
snapshotPixels = (byte[]) scaledSnapshot.getPixels();
*/
}
} catch (final Throwable t) {
IJError.print(t);
} finally {
exe.shutdown();
}
} else {
// max_scale; // WARNING if scale is different than 1, it will FAIL to set the next scale properly.
double scale = 1;
int scale_pow = 0;
// cached for local modifications in the loop, works as loop controler
int n_et = n_edge_tiles;
while (n_et >= best[1]) {
// best[1] is the minimal root found, i.e. 1,2,3,4,5 from which then powers of two were taken to make up for the edge_length
// 0 < scale <= 1, so no precision lost
final int tile_side = (int) (256 / scale);
for (int row = 0; row < n_et; row++) {
for (int col = 0; col < n_et; col++) {
final int i_tile = row * n_et + col;
Utils.showProgress(i_tile / (double) (n_et * n_et));
if (0 == i_tile % 100) {
// RGB int[] images
releaseToFit(tile_side * tile_side * 4 * 2);
}
if (this.quit) {
cleanUp();
return;
}
final Rectangle tile_src = new // TODO row and col are inverted
Rectangle(// TODO row and col are inverted
srcRect.x + tile_side * row, srcRect.y + tile_side * col, tile_side, // in absolute coords, magnification later.
tile_side);
// crop bounds
if (tile_src.x + tile_src.width > srcRect.x + srcRect.width)
tile_src.width = srcRect.x + srcRect.width - tile_src.x;
if (tile_src.y + tile_src.height > srcRect.y + srcRect.height)
tile_src.height = srcRect.y + srcRect.height - tile_src.y;
// negative tile sizes will be made into black tiles
// (negative dimensions occur for tiles beyond the edges of srcRect, since the grid of tiles has to be of equal number of rows and cols)
// should be row_col_scale, but results in transposed tiles in googlebrains, so I reversed the order.
makeTile(layer, tile_src, scale, c_alphas, type, clazz, new StringBuilder(tile_dir).append(col).append('_').append(row).append('_').append(scale_pow).toString(), saver);
}
}
scale_pow++;
// works as magnification
scale = 1 / Math.pow(2, scale_pow);
n_et /= 2;
}
}
}
}
} catch (final Exception e) {
IJError.print(e);
} finally {
Utils.showProgress(1);
}
cleanUp();
finishedWorking();
}
};
// watcher thread
return Bureaucrat.createAndStart(worker, layers[0].getProject());
}
use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.
the class Loader method importNextImage.
public Patch importNextImage(final Project project, final double x, final double y) {
if (null == last_opened_path) {
return importImage(project, x, y);
}
final int i_slash = last_opened_path.lastIndexOf("/");
final String dir_name = last_opened_path.substring(0, i_slash + 1);
final File dir = new File(dir_name);
final String last_file = last_opened_path.substring(i_slash + 1);
final String[] file_names = dir.list();
String next_file = null;
final String exts = "tiftiffjpgjpegpnggifzipdicombmppgm";
for (int i = 0; i < file_names.length; i++) {
if (last_file.equals(file_names[i]) && i < file_names.length - 1) {
// loop until finding a suitable next
for (int j = i + 1; j < file_names.length; j++) {
final String ext = file_names[j].substring(file_names[j].lastIndexOf('.') + 1).toLowerCase();
if (-1 != exts.indexOf(ext)) {
next_file = file_names[j];
break;
}
}
break;
}
}
if (null == next_file) {
Utils.showMessage("No more files after " + last_file);
return null;
}
releaseToFit(new File(dir_name + next_file).length() * 3);
IJ.redirectErrorMessages();
final ImagePlus imp = openImagePlus(dir_name + next_file);
if (null == imp)
return null;
if (0 == imp.getWidth() || 0 == imp.getHeight()) {
Utils.showMessage("Can't import image of zero width or height.");
flush(imp);
return null;
}
final String path = dir + "/" + next_file;
final Patch p = new Patch(project, imp.getTitle(), x, y, imp);
addedPatchFrom(path, p);
// WARNING may be altered concurrently
last_opened_path = path;
if (isMipMapsRegenerationEnabled())
regenerateMipMaps(p);
return p;
}
use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.
the class Loader method importImage.
/**
* Import an image into the given layer, in a separate task thread.
*/
public Bureaucrat importImage(final Layer layer, final double x, final double y, final String path, final boolean synch_mipmap_generation) {
final Worker worker = new Worker("Importing image") {
@Override
public void run() {
startedWorking();
try {
// //
if (null == layer) {
Utils.log("Can't import. No layer found.");
finishedWorking();
return;
}
final Patch p = importImage(layer.getProject(), x, y, path, synch_mipmap_generation);
if (null != p) {
synchronized (layer) {
layer.add(p);
}
layer.getParent().enlargeToFit(p, LayerSet.NORTHWEST);
}
// //
} catch (final Exception e) {
IJError.print(e);
}
finishedWorking();
}
};
return Bureaucrat.createAndStart(worker, layer.getProject());
}
Aggregations