use of ini.trakem2.display.Layer in project TrakEM2 by trakem2.
the class TMLHandler method getProjectData.
/**
* returns 4 objects packed in an array:
* <pre>
* [0] = root TemplateThing
* [1] = root ProjectThing (contains Project instance)
* [2] = root LayerThing (contains the top-level LayerSet)
* [3] = expanded states of all ProjectThing objects
* </pre>
* <p>
* Also, triggers the reconstruction of links and assignment of Displayable objects to their layer.
* </p>
*/
public Object[] getProjectData(final boolean open_displays) {
if (null == project)
return null;
this.open_displays = open_displays;
// Links exist between Displayable objects.
for (final Displayable d : ht_displayables.values()) {
String olinks = ht_links.get(d);
// not linked
if (null == olinks)
continue;
String[] links = olinks.split(",");
Long lid = null;
for (int i = 0; i < links.length; i++) {
try {
lid = new Long(links[i]);
} catch (NumberFormatException nfe) {
Utils.log2("Ignoring incorrectly formated link '" + links[i] + "' for ob " + d);
continue;
}
Displayable partner = ht_displayables.get(lid);
if (null != partner)
d.link(partner, false);
else
Utils.log("TMLHandler: can't find partner with id=" + links[i] + " for Displayable with id=" + d.getId());
}
}
// 1.2 - Reconstruct linked properties
for (final Map.Entry<Displayable, Map<Long, Map<String, String>>> lpe : all_linked_props.entrySet()) {
final Displayable origin = lpe.getKey();
for (final Map.Entry<Long, Map<String, String>> e : lpe.getValue().entrySet()) {
final Displayable target = ht_displayables.get(e.getKey());
if (null == target) {
Utils.log("Setting linked properties for origin " + origin.getId() + ":\n\t* Could not find target displayable #" + e.getKey());
continue;
}
origin.setLinkedProperties(target, e.getValue());
}
}
// 2 - Add Displayable objects to ProjectThing that can contain them
for (final Map.Entry<Long, ProjectThing> entry : ht_oid_pt.entrySet()) {
ProjectThing pt = entry.getValue();
Object od = ht_displayables.remove(entry.getKey());
// Utils.log("==== processing: Displayable [" + od + "] vs. ProjectThing [" + pt + "]");
if (null != od) {
pt.setObject(od);
} else {
Utils.log("#### Failed to find a Displayable for ProjectThing " + pt + " #####");
}
}
// 3 - Assign a layer pointer to ZDisplayable objects
for (final ZDisplayable zd : ht_zdispl.values()) {
// zd.setLayer((Layer)zd.getLayerSet().getLayers().get(0));
zd.setLayer(zd.getLayerSet().getLayer(0));
}
// 4 - Assign layers to Treeline nodes
for (final Layer la : al_layers) {
final List<Node<?>> list = node_layer_table.remove(la.getId());
if (null == list)
continue;
for (final Node<?> nd : list) nd.setLayer(la);
}
if (!node_layer_table.isEmpty()) {
Utils.log("ERROR: node_layer_table is not empty!");
}
// 5 - Assign root nodes to Treelines, now that all nodes have a layer
for (final Map.Entry<Tree<?>, Node<?>> e : tree_root_nodes.entrySet()) {
if (null == e.getValue()) {
// Utils.log2("Ignoring, applies to new Treeline format only.");
continue;
}
// Can't compile with <?>
// will generate node caches of each Treeline
e.getKey().setRoot((Node) e.getValue());
}
tree_root_nodes.clear();
// Assign colors to nodes
for (final Map.Entry<Color, Collection<Node<?>>> e : node_colors.entrySet()) {
for (final Node<?> nd : e.getValue()) {
nd.setColor(e.getKey());
}
}
node_colors.clear();
// 6 - Run legacy operations
for (final Runnable r : legacy) {
r.run();
}
try {
// Create a table with all layer ids vs layer instances:
final HashMap<Long, Layer> ht_lids = new HashMap<Long, Layer>();
for (final Layer layer : al_layers) {
ht_lids.put(new Long(layer.getId()), layer);
}
// Spawn threads to recreate buckets, starting from the subset of displays to open
int n = Runtime.getRuntime().availableProcessors();
switch(n) {
case 1:
break;
case 2:
case 3:
case 4:
n--;
break;
default:
n -= 2;
break;
}
final ExecutorService exec = Utils.newFixedThreadPool(n, "TMLHandler-recreateBuckets");
final Set<Long> dlids = new HashSet<Long>();
final LayerSet layer_set = (LayerSet) root_lt.getObject();
final List<Future<?>> fus = new ArrayList<Future<?>>();
final List<Future<?>> fus2 = new ArrayList<Future<?>>();
for (final HashMap<String, String> ht_attributes : al_displays) {
String ob = ht_attributes.get("layer_id");
if (null == ob)
continue;
final Long lid = new Long(ob);
dlids.add(lid);
final Layer la = ht_lids.get(lid);
if (null == la) {
ht_lids.remove(lid);
continue;
}
// to open later:
new Display(project, Long.parseLong(ht_attributes.get("id")), la, ht_attributes);
fus.add(exec.submit(new Runnable() {
public void run() {
la.recreateBuckets();
}
}));
}
fus.add(exec.submit(new Runnable() {
public void run() {
// only for ZDisplayable
layer_set.recreateBuckets(false);
}
}));
// Ensure launching:
if (dlids.isEmpty() && layer_set.size() > 0) {
dlids.add(layer_set.getLayer(0).getId());
}
final List<Layer> layers = layer_set.getLayers();
for (final Long lid : new HashSet<Long>(dlids)) {
fus.add(exec.submit(new Runnable() {
public void run() {
int start = layer_set.indexOf(layer_set.getLayer(lid.longValue()));
int next = start + 1;
int prev = start - 1;
while (next < layer_set.size() || prev > -1) {
if (prev > -1) {
final Layer lprev = layers.get(prev);
synchronized (dlids) {
if (dlids.add(lprev.getId())) {
// returns true if not there already
fus2.add(exec.submit(new Runnable() {
public void run() {
lprev.recreateBuckets();
}
}));
}
}
prev--;
}
if (next < layers.size()) {
final Layer lnext = layers.get(next);
synchronized (dlids) {
if (dlids.add(lnext.getId())) {
// returns true if not there already
fus2.add(exec.submit(new Runnable() {
public void run() {
lnext.recreateBuckets();
}
}));
}
}
next++;
}
}
Utils.log2("done recreateBuckets chunk");
}
}));
}
Utils.wait(fus);
exec.submit(new Runnable() {
public void run() {
Utils.log2("waiting for TMLHandler fus...");
Utils.wait(fus2);
Utils.log2("done waiting TMLHandler fus.");
exec.shutdown();
}
});
} catch (Throwable t) {
IJError.print(t);
}
return new Object[] { root_tt, root_pt, root_lt, ht_pt_expanded };
}
use of ini.trakem2.display.Layer in project TrakEM2 by trakem2.
the class ProjectThing method createChild.
public ProjectThing createChild(String type) {
// create the Displayable
TemplateThing tt = template.getChildTemplate(type);
if (null == tt) {
Utils.log2("Can't create a child of type " + type);
return null;
}
Object ob = project.makeObject(tt);
Layer layer = null;
if (ob instanceof Displayable) {
// which layer to add it to? Get it from the front Display
layer = Display.getFrontLayer(this.project);
if (null == layer) {
Utils.showMessage("Open a display first!");
((DBObject) ob).removeFromDatabase();
return null;
}
}
// wrap it in a new ProjectThing
ProjectThing pt = null;
try {
pt = new ProjectThing(tt, project, ob);
} catch (Exception e) {
IJError.print(e);
return null;
}
// add it here as child
addChild(pt);
// finally, add it to the layer if appropriate
if (null != layer) {
if (ob instanceof ZDisplayable) {
layer.getParent().add((ZDisplayable) ob);
} else {
layer.add((Displayable) ob);
}
}
// finally, return it to be added to the ProjectTree as a new node
return pt;
}
use of ini.trakem2.display.Layer in project TrakEM2 by trakem2.
the class ProjectTree method mousePressed.
public void mousePressed(final MouseEvent me) {
super.dispatcher.execSwing(new Runnable() {
public void run() {
if (!me.getSource().equals(ProjectTree.this) || !project.isInputEnabled()) {
return;
}
final int x = me.getX();
final int y = me.getY();
// find the node and set it selected
final TreePath path = getPathForLocation(x, y);
if (null == path) {
return;
}
ProjectTree.this.setSelectionPath(path);
selected_node = (DefaultMutableTreeNode) path.getLastPathComponent();
if (2 == me.getClickCount() && !me.isPopupTrigger() && MouseEvent.BUTTON1 == me.getButton()) {
// show in the front Display
if (null == selected_node)
return;
Object obt = selected_node.getUserObject();
if (!(obt instanceof ProjectThing))
return;
ProjectThing thing = (ProjectThing) obt;
thing.setVisible(true);
Object obd = thing.getObject();
if (obd instanceof Displayable) {
// additionaly, get the front Display (or make a new one if none) and show in it the layer in which the Displayable object is contained.
Displayable displ = (Displayable) obd;
Display.showCentered(displ.getLayer(), displ, true, me.isShiftDown());
}
return;
} else if (me.isPopupTrigger() || (ij.IJ.isMacOSX() && me.isControlDown()) || MouseEvent.BUTTON2 == me.getButton() || 0 != (me.getModifiers() & Event.META_MASK)) {
// the last block is from ij.gui.ImageCanvas, aparently to make the right-click work on windows?
JPopupMenu popup = getPopupMenu(selected_node);
if (null == popup)
return;
popup.show(ProjectTree.this, x, y);
return;
}
}
});
}
use of ini.trakem2.display.Layer in project TrakEM2 by trakem2.
the class FSLoader method importStackAsPatches.
/**
* Returns the last Patch.
*/
protected Patch importStackAsPatches(final Project project, final Layer first_layer, final double x, final double y, final ImagePlus imp_stack, final boolean as_copy, final String filepath) {
Utils.log2("FSLoader.importStackAsPatches filepath=" + filepath);
String target_dir = null;
if (as_copy) {
DirectoryChooser dc = new DirectoryChooser("Folder to save images");
target_dir = dc.getDirectory();
// user canceled dialog
if (null == target_dir)
return null;
if (IJ.isWindows())
target_dir = target_dir.replace('\\', '/');
if (target_dir.length() - 1 != target_dir.lastIndexOf('/')) {
target_dir += "/";
}
}
// Double.MAX_VALUE is a flag to indicate "add centered"
double pos_x = Double.MAX_VALUE != x ? x : first_layer.getLayerWidth() / 2 - imp_stack.getWidth() / 2;
double pos_y = Double.MAX_VALUE != y ? y : first_layer.getLayerHeight() / 2 - imp_stack.getHeight() / 2;
final double thickness = first_layer.getThickness();
final String title = Utils.removeExtension(imp_stack.getTitle()).replace(' ', '_');
Utils.showProgress(0);
Patch previous_patch = null;
final int n = imp_stack.getStackSize();
final ImageStack stack = imp_stack.getStack();
final boolean virtual = stack.isVirtual();
final VirtualStack vs = virtual ? (VirtualStack) stack : null;
for (int i = 1; i <= n; i++) {
Layer layer = first_layer;
double z = first_layer.getZ() + (i - 1) * thickness;
// will create new layer if not found
if (i > 1)
layer = first_layer.getParent().getLayer(z, thickness, true);
if (null == layer) {
Utils.log("Display.importStack: could not create new layers.");
return null;
}
String patch_path = null;
ImagePlus imp_patch_i = null;
if (virtual) {
// because we love inefficiency, every time all this is done again
// VirtualStack vs = (VirtualStack)imp_stack.getStack();
String vs_dir = vs.getDirectory().replace('\\', '/');
if (!vs_dir.endsWith("/"))
vs_dir += "/";
String iname = vs.getFileName(i);
patch_path = vs_dir + iname;
Utils.log2("virtual stack: patch path is " + patch_path);
releaseToFit(new File(patch_path).length() * 3);
Utils.log2(i + " : " + patch_path);
imp_patch_i = openImage(patch_path);
} else {
ImageProcessor ip = stack.getProcessor(i);
if (as_copy)
ip = ip.duplicate();
imp_patch_i = new ImagePlus(title + "__slice=" + i, ip);
}
String label = stack.getSliceLabel(i);
if (null == label)
label = "";
Patch patch = null;
if (as_copy) {
patch_path = target_dir + cleanSlashes(imp_patch_i.getTitle()) + ".zip";
ini.trakem2.io.ImageSaver.saveAsZip(imp_patch_i, patch_path);
patch = new Patch(project, label + " " + title + " " + i, pos_x, pos_y, imp_patch_i);
} else if (virtual) {
patch = new Patch(project, label, pos_x, pos_y, imp_patch_i);
} else {
patch_path = filepath + "-----#slice=" + i;
// Utils.log2("path is "+ patch_path);
final AffineTransform atp = new AffineTransform();
atp.translate(pos_x, pos_y);
patch = new Patch(project, getNextId(), label + " " + title + " " + i, imp_stack.getWidth(), imp_stack.getHeight(), imp_stack.getWidth(), imp_stack.getHeight(), imp_stack.getType(), false, imp_stack.getProcessor().getMin(), imp_stack.getProcessor().getMax(), atp);
patch.addToDatabase();
// Utils.log2("type is " + imp_stack.getType());
}
Utils.log2("B: " + i + " : " + patch_path);
addedPatchFrom(patch_path, patch);
if (!as_copy && !virtual) {
if (// each slice separately
virtual)
// each slice separately
cache(patch, imp_patch_i);
else
// uses the entire stack, shared among all Patch instances
cache(patch, imp_stack);
}
// submit for regeneration
if (isMipMapsRegenerationEnabled())
regenerateMipMaps(patch);
if (null != previous_patch)
patch.link(previous_patch);
layer.add(patch);
previous_patch = patch;
Utils.showProgress(i * (1.0 / n));
}
Utils.showProgress(1.0);
// return the last patch
return previous_patch;
}
use of ini.trakem2.display.Layer in project TrakEM2 by trakem2.
the class FSLoader method generateMipMaps.
/**
* Given an image and its source file name (without directory prepended), generate
* a pyramid of images until reaching an image not smaller than 32x32 pixels.
* <p>
* Such images are stored as jpeg 85% quality in a folder named trakem2.mipmaps.
* </p>
* <p>
* The Patch id and the right extension will be appended to the filename in all cases.
* </p>
* <p>
* Any equally named files will be overwritten.
* </p>
*/
protected boolean generateMipMaps(final Patch patch) {
Utils.log2("mipmaps for " + patch);
final String path = getAbsolutePath(patch);
if (null == path) {
Utils.log("generateMipMaps: null path for Patch " + patch);
cannot_regenerate.add(patch);
return false;
}
if (hs_unloadable.contains(patch)) {
FilePathRepair.add(patch);
return false;
}
synchronized (gm_lock) {
try {
if (null == dir_mipmaps)
createMipMapsDir(null);
if (null == dir_mipmaps || isURL(dir_mipmaps))
return false;
} catch (Exception e) {
IJError.print(e);
}
}
/**
* Record Patch as modified
*/
touched_mipmaps.add(patch);
/**
* Remove serialized features, if any
*/
removeSerializedFeatures(patch);
/**
* Remove serialized pointmatches, if any
*/
removeSerializedPointMatches(patch);
/**
* Alpha mask: setup to check if it was modified while regenerating.
*/
final long alpha_mask_id = patch.getAlphaMaskId();
final int resizing_mode = patch.getProject().getMipMapsMode();
try {
ImageProcessor ip;
ByteProcessor alpha_mask = null;
ByteProcessor outside_mask = null;
int type = patch.getType();
// Aggressive cache freeing
releaseToFit(patch.getOWidth() * patch.getOHeight() * 4 + MIN_FREE_BYTES);
// Obtain an image which may be coordinate-transformed, and an alpha mask.
Patch.PatchImage pai = patch.createTransformedImage();
if (null == pai || null == pai.target) {
Utils.log("Can't regenerate mipmaps for patch " + patch);
cannot_regenerate.add(patch);
return false;
}
ip = pai.target;
// can be null
alpha_mask = pai.mask;
// can be null
outside_mask = pai.outside;
pai = null;
// Old style:
// final String filename = new StringBuilder(new File(path).getName()).append('.').append(patch.getId()).append(mExt).toString();
// New style:
final String filename = createMipMapRelPath(patch, mExt);
int w = ip.getWidth();
int h = ip.getHeight();
// sigma = sqrt(2^level - 0.5^2)
// where 0.5 is the estimated sigma for a full-scale image
// which means sigma = 0.75 for the full-scale image (has level 0)
// prepare a 0.75 sigma image from the original
double min = patch.getMin(), max = patch.getMax();
// (The -1,-1 are flags really for "not set")
if (-1 == min && -1 == max) {
switch(type) {
case ImagePlus.COLOR_RGB:
case ImagePlus.COLOR_256:
case ImagePlus.GRAY8:
patch.setMinAndMax(0, 255);
break;
// Find and flow through to default:
case ImagePlus.GRAY16:
((ij.process.ShortProcessor) ip).findMinAndMax();
patch.setMinAndMax(ip.getMin(), ip.getMax());
break;
case ImagePlus.GRAY32:
((FloatProcessor) ip).findMinAndMax();
patch.setMinAndMax(ip.getMin(), ip.getMax());
break;
}
// may have changed
min = patch.getMin();
max = patch.getMax();
}
// Set for the level 0 image, which is a duplicate of the one in the cache in any case
ip.setMinAndMax(min, max);
// ImageJ no longer stretches the bytes for ByteProcessor with setMinAndmax
if (ByteProcessor.class == ip.getClass()) {
if (0 != min && 255 != max) {
final byte[] b = (byte[]) ip.getPixels();
final double scale = 255 / (max - min);
for (int i = 0; i < b.length; ++i) {
final int val = b[i] & 0xff;
if (val < min)
b[i] = 0;
else
b[i] = (byte) Math.min(255, ((val - min) * scale));
}
}
}
// Proper support for LUT images: treat them as RGB
if (ip.isColorLut() || type == ImagePlus.COLOR_256) {
ip = ip.convertToRGB();
type = ImagePlus.COLOR_RGB;
}
final int first_mipmap_level_saved = patch.getProject().getFirstMipMapLevelSaved();
if (Loader.AREA_DOWNSAMPLING == resizing_mode) {
long t0 = System.currentTimeMillis();
final ImageBytes[] b = DownsamplerMipMaps.create(patch, type, ip, alpha_mask, outside_mask);
long t1 = System.currentTimeMillis();
for (int i = 0; i < b.length; ++i) {
if (i < first_mipmap_level_saved) {
// Ignore level i
if (null != b[i])
CachingThread.storeForReuse(b[i].c);
} else {
boolean written = mmio.save(getLevelDir(dir_mipmaps, i) + filename, b[i].c, b[i].width, b[i].height, 0.85f);
if (!written) {
Utils.log("Failed to save mipmap with area downsampling at level=" + i + " for patch " + patch);
cannot_regenerate.add(patch);
break;
}
}
}
long t2 = System.currentTimeMillis();
System.out.println("MipMaps with area downsampling: creation took " + (t1 - t0) + "ms, saving took " + (t2 - t1) + "ms, total: " + (t2 - t0) + "ms\n");
} else if (Loader.GAUSSIAN == resizing_mode) {
if (ImagePlus.COLOR_RGB == type) {
// TODO releaseToFit proper
releaseToFit(w * h * 4 * 10);
final ColorProcessor cp = (ColorProcessor) ip;
final FloatProcessorT2 red = new FloatProcessorT2(w, h, 0, 255);
cp.toFloat(0, red);
final FloatProcessorT2 green = new FloatProcessorT2(w, h, 0, 255);
cp.toFloat(1, green);
final FloatProcessorT2 blue = new FloatProcessorT2(w, h, 0, 255);
cp.toFloat(2, blue);
FloatProcessorT2 alpha;
final FloatProcessorT2 outside;
if (null != alpha_mask) {
alpha = new FloatProcessorT2(alpha_mask);
} else {
alpha = null;
}
if (null != outside_mask) {
outside = new FloatProcessorT2(outside_mask);
if (null == alpha) {
alpha = outside;
alpha_mask = outside_mask;
}
} else {
outside = null;
}
final String target_dir0 = getLevelDir(dir_mipmaps, 0);
if (Thread.currentThread().isInterrupted())
return false;
// Generate level 0 first:
if (0 == first_mipmap_level_saved) {
boolean written;
if (null == alpha) {
written = mmio.save(cp, target_dir0 + filename, 0.85f, false);
} else {
written = mmio.save(target_dir0 + filename, P.asRGBABytes((int[]) cp.getPixels(), (byte[]) alpha_mask.getPixels(), null == outside ? null : (byte[]) outside_mask.getPixels()), w, h, 0.85f);
}
if (!written) {
Utils.log("Failed to save mipmap for COLOR_RGB, 'alpha = " + alpha + "', level = 0 for patch " + patch);
cannot_regenerate.add(patch);
}
}
// Generate all other mipmap levels
// TODO: for best performance, it should start from a direct Gaussian downscaling at the first level to write.
// the scale level. Proper scale is: 1 / pow(2, k)
int k = 0;
do {
if (Thread.currentThread().isInterrupted())
return false;
// 1 - Prepare values for the next scaled image
k++;
// 2 - Check that the target folder for the desired scale exists
final String target_dir = getLevelDir(dir_mipmaps, k);
if (null == target_dir)
break;
// 3 - Blur the previous image to 0.75 sigma, and scale it
// will resize 'red' FloatProcessor in place.
final byte[] r = gaussianBlurResizeInHalf(red);
// idem
final byte[] g = gaussianBlurResizeInHalf(green);
// idem
final byte[] b = gaussianBlurResizeInHalf(blue);
// idem
final byte[] a = null == alpha ? null : gaussianBlurResizeInHalf(alpha);
if (null != outside) {
final byte[] o;
if (alpha != outside)
// idem
o = gaussianBlurResizeInHalf(outside);
else
o = a;
// If there was no alpha mask, alpha is the outside itself
for (int i = 0; i < o.length; i++) {
// TODO I am sure there is a bitwise operation to do this in one step. Some thing like: a[i] &= 127;
if ((o[i] & 0xff) != 255)
a[i] = 0;
}
}
w = red.getWidth();
h = red.getHeight();
// 4 - Compose ColorProcessor
if (first_mipmap_level_saved < k) {
// Skip saving this mipmap level
continue;
}
if (null == alpha) {
// 5 - Save as jpeg
if (!mmio.save(target_dir + filename, new byte[][] { r, g, b }, w, h, 0.85f)) {
Utils.log("Failed to save mipmap for COLOR_RGB, 'alpha = " + alpha + "', level = " + k + " for patch " + patch);
cannot_regenerate.add(patch);
break;
}
} else {
if (!mmio.save(target_dir + filename, new byte[][] { r, g, b, a }, w, h, 0.85f)) {
Utils.log("Failed to save mipmap for COLOR_RGB, 'alpha = " + alpha + "', level = " + k + " for patch " + patch);
cannot_regenerate.add(patch);
break;
}
}
} while (// not smaller than 32x32
w >= 32 && h >= 32);
} else {
long t0 = System.currentTimeMillis();
// Greyscale:
releaseToFit(w * h * 4 * 10);
if (Thread.currentThread().isInterrupted())
return false;
final FloatProcessorT2 fp = new FloatProcessorT2((FloatProcessor) ip.convertToFloat());
if (ImagePlus.GRAY8 == type) {
// for 8-bit, the min,max has been applied when going to FloatProcessor
// just set it
fp.setMinMax(0, 255);
} else {
fp.setMinAndMax(patch.getMin(), patch.getMax());
}
// fp.debugMinMax(patch.toString());
FloatProcessorT2 alpha, outside;
if (null != alpha_mask) {
alpha = new FloatProcessorT2(alpha_mask);
} else {
alpha = null;
}
if (null != outside_mask) {
outside = new FloatProcessorT2(outside_mask);
if (null == alpha) {
alpha = outside;
alpha_mask = outside_mask;
}
} else {
outside = null;
}
// the scale level. Proper scale is: 1 / pow(2, k)
int k = 0;
do {
if (Thread.currentThread().isInterrupted())
return false;
if (0 != k) {
// not doing so at the end because it would add one unnecessary blurring
gaussianBlurResizeInHalf(fp);
if (null != alpha) {
gaussianBlurResizeInHalf(alpha);
if (alpha != outside && outside != null) {
gaussianBlurResizeInHalf(outside);
}
}
}
w = fp.getWidth();
h = fp.getHeight();
// 1 - check that the target folder for the desired scale exists
final String target_dir = getLevelDir(dir_mipmaps, k);
if (null == target_dir)
break;
if (k < first_mipmap_level_saved) {
// Skip saving this mipmap level
k++;
continue;
}
if (null != alpha) {
// If there was no alpha mask, alpha is the outside itself
if (!mmio.save(target_dir + filename, new byte[][] { fp.getScaledBytePixels(), P.merge(alpha.getBytePixels(), null == outside ? null : outside.getBytePixels()) }, w, h, 0.85f)) {
Utils.log("Failed to save mipmap for GRAY8, 'alpha = " + alpha + "', level = " + k + " for patch " + patch);
cannot_regenerate.add(patch);
break;
}
} else {
// 3 - save as 8-bit jpeg
if (!mmio.save(target_dir + filename, new byte[][] { fp.getScaledBytePixels() }, w, h, 0.85f)) {
Utils.log("Failed to save mipmap for GRAY8, 'alpha = " + alpha + "', level = " + k + " for patch " + patch);
cannot_regenerate.add(patch);
break;
}
}
// 4 - prepare values for the next scaled image
k++;
} while (// not smaller than 32x32
fp.getWidth() >= 32 && fp.getHeight() >= 32);
long t1 = System.currentTimeMillis();
System.out.println("MipMaps took " + (t1 - t0));
}
} else {
Utils.log("ERROR: unknown image resizing mode for mipmaps: " + resizing_mode);
}
return true;
} catch (Throwable e) {
Utils.log("*** ERROR: Can't generate mipmaps for patch " + patch);
IJError.print(e);
cannot_regenerate.add(patch);
return false;
} finally {
// flush any cached tiles
flushMipMaps(patch.getId());
// flush any cached layer screenshots
if (null != patch.getLayer()) {
try {
patch.getLayer().getParent().removeFromOffscreens(patch.getLayer());
} catch (Exception e) {
IJError.print(e);
}
}
// gets executed even when returning from the catch statement or within the try/catch block
synchronized (gm_lock) {
regenerating_mipmaps.remove(patch);
}
// Has the alpha mask changed?
if (patch.getAlphaMaskId() != alpha_mask_id) {
Utils.log2("Alpha mask changed: resubmitting mipmap regeneration for " + patch);
regenerateMipMaps(patch);
}
}
}
Aggregations