Hi,
I have modified VirtualStack to add save support, so u can process your stack and it will save the modified files in a directory with a "tmp" extension, but close immediately you stack else it will overwrite the modification by the original images. I do not how to handle the fact that the stack is modified; any suggestions or help appreciated. Thomas package ij; import ij.process.*; import ij.io.*; import java.io.*; import java.awt.image.ColorModel; /** * This class represents an array of disk-resident images. * * @author thomas * @created 14 mai 2007 */ public class VirtualStack extends ImageStack { final static int INITIAL_SIZE = 100; String path; String save; int nSlices; int current; String[] names; ImageProcessor processor; /** * Creates a new, empty virtual stack. * * @param width Description of the Parameter * @param height Description of the Parameter * @param cm Description of the Parameter * @param path Description of the Parameter */ public VirtualStack(int width, int height, ColorModel cm, String path) { super(width, height, cm); this.path = path; names = new String[INITIAL_SIZE]; //IJ.log("VirtualStack: "+path); current = -1; processor = null; File p = new File(path); File sa = new File(p.getParent() + File.separator + p.getName() + "tmp"); sa.mkdir(); save = sa.getPath(); } /** * Adds an image to the end of the stack. * * @param name The feature to be added to the Slice attribute */ public void addSlice(String name) { if (name == null) { throw new IllegalArgumentException("'name' is null!"); } nSlices++; //IJ.log("addSlice: "+nSlices+" "+name); if (nSlices == names.length) { String[] tmp = new String[nSlices * 2]; System.arraycopy(names, 0, tmp, 0, nSlices); names = tmp; } names[nSlices - 1] = name; } /** * Does nothing. * * @param sliceLabel The feature to be added to the Slice attribute * @param pixels The feature to be added to the Slice attribute */ public void addSlice(String sliceLabel, Object pixels) { } /** * Does nothing.. * * @param sliceLabel The feature to be added to the Slice attribute * @param ip The feature to be added to the Slice attribute */ public void addSlice(String sliceLabel, ImageProcessor ip) { } /** * Does noting. * * @param sliceLabel The feature to be added to the Slice attribute * @param ip The feature to be added to the Slice attribute * @param n The feature to be added to the Slice attribute */ public void addSlice(String sliceLabel, ImageProcessor ip, int n) { } /** * Deletes the specified slice, were 1<=n<=nslices. * * @param n Description of the Parameter */ public void deleteSlice(int n) { if (n < 1 || n > nSlices) { throw new IllegalArgumentException("Argument out of range: " + n); } if (nSlices < 1) { return; } for (int i = n; i < nSlices; i++) { names[i - 1] = names[i]; } names[nSlices - 1] = null; nSlices--; } /** * Deletes the last slice in the stack. */ public void deleteLastSlice() { if (nSlices > 0) { deleteSlice(nSlices); } } /** * Returns the pixel array for the specified slice, were 1<=n<=nslices. * * @param n Description of the Parameter * @return The pixels value */ public Object getPixels(int n) { ImageProcessor ip = getProcessor(n); if (ip != null) { return ip.getPixels(); } else { return null; } } /** * Assigns a pixel array to the specified slice, *were 1<=n<=nslices. * * @param pixels The new pixels value * @param n The new pixels value */ public void setPixels(Object pixels, int n) { } /** * Returns an ImageProcessor for the specified slice, *were 1<=n<=nslices. Returns null if the stack is empty. * * @param n Description of the Parameter * @return The processor value */ public ImageProcessor getProcessor(int n) { //IJ.log("getProcessor: "+n+" "+names[n-1]); ImagePlus plus; if (current == -1) { plus = new Opener().openImage(path, names[0]); processor = plus.getProcessor(); current = n; return processor; } if (current != n) { if (processor != null) { FileSaver fs = new FileSaver(new ImagePlus("tmp", processor)); fs.saveAsTiff(save + File.separator + names[current - 1]); } current = n; plus = new Opener().openImage(path, names[current - 1]); if (plus != null) { processor = plus.getProcessor(); } } return processor; } /** * Returns the number of slices in this stack. * * @return The size value */ public int getSize() { return nSlices; } /** * Returns the file name of the Nth image. * * @param n Description of the Parameter * @return The sliceLabel value */ public String getSliceLabel(int n) { return names[n - 1]; } /** * Returns null. * * @return The imageArray value */ public Object[] getImageArray() { return null; } /** * Does nothing. * * @param label The new sliceLabel value * @param n The new sliceLabel value */ public void setSliceLabel(String label, int n) { } /** * Always return true. * * @return The virtual value */ public boolean isVirtual() { return true; } /** * Does nothing. */ public void trim() { } /** * Returns the path to the directory containing the images. * * @return The directory value */ public String getDirectory() { return path; } /** * Returns the file name of the specified slice, were 1<=n<=nslices. * * @param n Description of the Parameter * @return The fileName value */ public String getFileName(int n) { return names[n - 1]; } } -- /*****************************************************/ Thomas Boudier, MCU Université Paris 6, UMR 7101 / IFR 83. Bat A 328, Jussieu. Tel : 01 44 27 35 78 Fax : 01 44 27 25 08 /****************************************************/ |
Hi Thomas,
It is very unexpected that you have placed the FileSaver under getProcessor and not under setPixels. Any reason for that? Please check the ImagePlus class and note where does the line changed = true; occurs. There is where any file saving should happen. Albert |
Hi,
There is a boolean changes in imageplus but i do not know how to get its value from virtaul stack. The idea to put it in getprocessor was to save any previous changes before displaying a new slice. Thomas Albert Cardona a écrit : > Hi Thomas, > > It is very unexpected that you have placed the FileSaver under > getProcessor and not under setPixels. Any reason for that? Please check > the ImagePlus class and note where does the line changed = true; occurs. > There is where any file saving should happen. > > Albert > > -- /*****************************************************/ Thomas Boudier, MCU Université Paris 6, UMR 7101 / IFR 83. Bat A 328, Jussieu. Tel : 01 44 27 35 78 Fax : 01 44 27 25 08 /****************************************************/ |
Hi Thomas,
> There is a boolean changes in imageplus but i do not know how to get > its value from virtaul stack. Add an ImageListener so that when the ImagePlus containing your VirtualStack is sent to the listener through the method imageUpdated(ImagePlus imp), then save whatever may have changed. This though can be severe overkill. Another option is to keep a pointer of the ImagePlus containing the VirtualStack, then read its 'updated' boolean field. And of course if there is a call to setPixels, save the image. You may need an extended ImageProcessor as well to detect changes in the pixels arrays, for example when methods setPixel and friends are called. So your Opener should place the opened images in your extended ImageProcessor (make a constructor in an extended ImageProcessor that keeps the real ImageProcessor, and proxies method calls to it -so that you can catch the changes). > The idea to put it in getprocessor was to save any previous changes > before displaying a new slice. I think the above is not going to work, because no changes can be made: setPixels goes nowhere in your stack, and the ImageProcessor representing each slice is thrown away when browsing through the slices. Albert |
Free forum by Nabble | Edit this page |