[Fwd: Re: virtual stack]

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

[Fwd: Re: virtual stack]

Thomas Boudier
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
/****************************************************/
Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Re: virtual stack]

Albert Cardona
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
Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Re: virtual stack]

Thomas Boudier
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
/****************************************************/
Reply | Threaded
Open this post in threaded view
|

Re: [Fwd: Re: virtual stack]

Albert Cardona
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