/** Frees memory by deleting a few slices from the end of the stack. */ public void trim() { int n = (int) Math.round(Math.log(nSlices) + 1.0); for (int i = 0; i < n; i++) { deleteLastSlice(); System.gc(); } }
/** Attemps to open a tiff file as a stack. Returns an ImagePlus object if successful. */ public ImagePlus openTiffStack(FileInfo[] info) { if (info.length > 1 && !allSameSizeAndType(info)) return null; FileInfo fi = info[0]; if (fi.nImages > 1) return new FileOpener(fi).open(false); // open contiguous images as stack else { ColorModel cm = createColorModel(fi); ImageStack stack = new ImageStack(fi.width, fi.height, cm); Object pixels = null; long skip = fi.getOffset(); int imageSize = fi.width * fi.height * fi.getBytesPerPixel(); if (info[0].fileType == FileInfo.GRAY12_UNSIGNED) { imageSize = (int) (fi.width * fi.height * 1.5); if ((imageSize & 1) == 1) imageSize++; // add 1 if odd } if (info[0].fileType == FileInfo.BITMAP) { int scan = (int) Math.ceil(fi.width / 8.0); imageSize = scan * fi.height; } long loc = 0L; int nChannels = 1; try { InputStream is = createInputStream(fi); ImageReader reader = new ImageReader(fi); IJ.resetEscape(); for (int i = 0; i < info.length; i++) { nChannels = 1; Object[] channels = null; if (!silentMode) IJ.showStatus("Reading: " + (i + 1) + "/" + info.length); if (IJ.escapePressed()) { IJ.beep(); IJ.showProgress(1.0); return null; } fi.stripOffsets = info[i].stripOffsets; fi.stripLengths = info[i].stripLengths; int bpp = info[i].getBytesPerPixel(); if (info[i].samplesPerPixel > 1 && !(bpp == 3 || bpp == 4 || bpp == 6)) { nChannels = fi.samplesPerPixel; channels = new Object[nChannels]; for (int c = 0; c < nChannels; c++) { pixels = reader.readPixels(is, c == 0 ? skip : 0L); channels[c] = pixels; } } else pixels = reader.readPixels(is, skip); if (pixels == null && channels == null) break; loc += imageSize * nChannels + skip; if (i < (info.length - 1)) { skip = info[i + 1].getOffset() - loc; if (info[i + 1].compression >= FileInfo.LZW) skip = 0; if (skip < 0L) { IJ.error("Opener", "Unexpected image offset"); break; } } if (fi.fileType == FileInfo.RGB48) { Object[] pixels2 = (Object[]) pixels; stack.addSlice(null, pixels2[0]); stack.addSlice(null, pixels2[1]); stack.addSlice(null, pixels2[2]); isRGB48 = true; } else if (nChannels > 1) { for (int c = 0; c < nChannels; c++) { if (channels[c] != null) stack.addSlice(null, channels[c]); } } else stack.addSlice(null, pixels); IJ.showProgress(i, info.length); } is.close(); } catch (Exception e) { IJ.handleException(e); } catch (OutOfMemoryError e) { IJ.outOfMemory(fi.fileName); stack.deleteLastSlice(); stack.deleteLastSlice(); } IJ.showProgress(1.0); if (stack.getSize() == 0) return null; if (fi.fileType == FileInfo.GRAY16_UNSIGNED || fi.fileType == FileInfo.GRAY12_UNSIGNED || fi.fileType == FileInfo.GRAY32_FLOAT || fi.fileType == FileInfo.RGB48) { ImageProcessor ip = stack.getProcessor(1); ip.resetMinAndMax(); stack.update(ip); } // if (fi.whiteIsZero) // new StackProcessor(stack, stack.getProcessor(1)).invert(); ImagePlus imp = new ImagePlus(fi.fileName, stack); new FileOpener(fi).setCalibration(imp); imp.setFileInfo(fi); if (fi.info != null) imp.setProperty("Info", fi.info); if (fi.description != null && fi.description.contains("order=zct")) new HyperStackConverter().shuffle(imp, HyperStackConverter.ZCT); int stackSize = stack.getSize(); if (nChannels > 1 && (stackSize % nChannels) == 0) { imp.setDimensions(nChannels, stackSize / nChannels, 1); imp = new CompositeImage(imp, IJ.COMPOSITE); imp.setOpenAsHyperStack(true); } else if (imp.getNChannels() > 1) imp = makeComposite(imp, fi); IJ.showProgress(1.0); return imp; } }