@@ -20,7 +20,8 @@ public class VirtualStack extends ImageStack {
2020 private int delay ;
2121 private Properties properties ;
2222 private boolean generateData ;
23- private int [] indexes ; // used to translate non-CZT hyperstack slice numbers
23+ private int [] indexes ; // used to translate non-CZT hyperstack slice numbers (0-based)
24+ private boolean translating ; // translation indexes was actually used, then also translate labels&names
2425
2526
2627 /** Default constructor. */
@@ -80,17 +81,27 @@ public void addSlice(String fileName) {
8081 if (fileName .startsWith ("." ))
8182 return ;
8283 if (names ==null )
83- throw new IllegalArgumentException ("VirtualStack(w,h,cm,path) constructor not used" );
84+ throw new IllegalArgumentException ("VirtualStack(w,h,cm,path) constructor not used" );
85+ if (indexes != null )
86+ throw new IllegalArgumentException ("Virtual hyperstack with non-czt order cannot be modified" );
8487 nSlices ++;
85- if (nSlices ==names .length ) {
86- String [] tmp = new String [nSlices *2 ];
87- System .arraycopy (names , 0 , tmp , 0 , nSlices );
88+ expandArrays (nSlices );
89+ names [nSlices -1 ] = fileName ;
90+ }
91+
92+ /** Expands the 'names' and 'labels' arrays if existing and smaller than minSize.
93+ * This should be called each time the stack is enlarged */
94+ protected void expandArrays (int minSize ) {
95+ if (names != null && names .length < minSize ) {
96+ String [] tmp = new String [minSize *2 ];
97+ System .arraycopy (names , 0 , tmp , 0 , names .length );
8898 names = tmp ;
89- tmp = new String [nSlices *2 ];
90- System .arraycopy (labels , 0 , tmp , 0 , nSlices );
99+ }
100+ if (labels != null && labels .length < minSize ) {
101+ String [] tmp = new String [minSize *2 ];
102+ System .arraycopy (labels , 0 , tmp , 0 , labels .length );
91103 labels = tmp ;
92104 }
93- names [nSlices -1 ] = fileName ;
94105 }
95106
96107 /** Does nothing. */
@@ -101,7 +112,7 @@ public void addSlice(String sliceLabel, Object pixels) {
101112 public void addSlice (String sliceLabel , ImageProcessor ip ) {
102113 }
103114
104- /** Does noting . */
115+ /** Does nothing . */
105116 public void addSlice (String sliceLabel , ImageProcessor ip , int n ) {
106117 }
107118
@@ -111,9 +122,16 @@ public void deleteSlice(int n) {
111122 return ;
112123 if (n <1 || n >nSlices )
113124 throw new IllegalArgumentException ("Argument out of range: " +n );
125+ if (names ==null )
126+ throw new IllegalArgumentException ("VirtualStack(w,h,cm,path) constructor not used" );
127+ if (translating )
128+ throw new IllegalArgumentException ("Virtual hyperstack with non-czt order cannot be modified" );
114129 for (int i =n ; i <nSlices ; i ++)
115130 names [i -1 ] = names [i ];
116131 names [nSlices -1 ] = null ;
132+ if (labels != null )
133+ for (int i =n ; i <nSlices ; i ++)
134+ labels [i -1 ] = labels [i ];
117135 nSlices --;
118136 }
119137
@@ -147,7 +165,7 @@ public void setPixels(Object pixels, int n) {
147165 * {@link <a href="https://wsr.imagej.net/plugins/Test_Virtual_Stack2.java#gemsiv">Example</a>}
148166 */
149167 public ImageProcessor getProcessor (int n ) {
150- if (path ==null ) { //Help>Examples? JavaScript>Terabyte VirtualStack
168+ if (path ==null ) { //Help>Examples> JavaScript>Terabyte VirtualStack
151169 ImageProcessor ip = null ;
152170 int w =getWidth (), h =getHeight ();
153171 switch (bitDepth ) {
@@ -194,11 +212,11 @@ public ImageProcessor getProcessor(int n) {
194212 String info = (String )imp .getProperty ("Info" );
195213 if (info !=null ) {
196214 if (FolderOpener .useInfo (info ))
197- labels [ n - 1 ] = info ;
215+ setSliceLabel ( info , n ) ;
198216 } else {
199217 String sliceLabel = imp .getStack ().getSliceLabel (1 );
200218 if (FolderOpener .useInfo (sliceLabel ))
201- labels [ n - 1 ] = "Label: " +sliceLabel ;
219+ setSliceLabel ( "Label: " +sliceLabel , n ) ;
202220 }
203221 depthThisImage = imp .getBitDepth ();
204222 ip = imp .getProcessor ();
@@ -230,7 +248,8 @@ public ImageProcessor getProcessor(int n) {
230248 ip .setSliceNumber (n );
231249 return ip ;
232250 }
233-
251+
252+ /** Draw label for Help>Examples>JavaScript>Terabyte VirtualStack */
234253 private void label (ImageProcessor ip , String msg , Color color ) {
235254 int size = getHeight ()/20 ;
236255 if (size <9 ) size =9 ;
@@ -257,9 +276,13 @@ public int getSize() {
257276
258277 /** Returns the label of the Nth image. */
259278 public String getSliceLabel (int n ) {
279+ if (translating )
280+ n = translate (n );
260281 if (labels ==null )
261282 return null ;
262- String label = labels [n -1 ];
283+ String label = (n <=labels .length ) ? labels [n -1 ] : null ; //subclass may have grown stack without adding labels
284+ if (names == null )
285+ return label ;
263286 if (label ==null )
264287 return names [n -1 ];
265288 else {
@@ -275,11 +298,26 @@ public Object[] getImageArray() {
275298 return null ;
276299 }
277300
278- /** Does nothing . */
301+ /** Sets the label of the specified slice, where {@literal 1<=n<=nSlices} . */
279302 public void setSliceLabel (String label , int n ) {
303+ if (n <= 0 || n > getSize ())
304+ throw new IllegalArgumentException (outOfRange +n );
305+ if (translating )
306+ n = translate (n );
307+ if (labels == null )
308+ labels = new String [getSize ()];
309+ expandArrays (nSlices );
310+ labels [n -1 ] = label ;
311+ }
312+
313+ /** Sets the array of slice labels. The array size must be the stack size or larger */
314+ protected void setSliceLabels (String [] labels ) {
315+ if (labels != null && labels .length < getSize ())
316+ throw new IllegalArgumentException ("Labels array too short: " +labels .length );
317+ this .labels = labels ;
280318 }
281319
282- /** Always return true. */
320+ /** Always returns true. */
283321 public boolean isVirtual () {
284322 return true ;
285323 }
@@ -327,14 +365,15 @@ public Properties getProperties() {
327365 return properties ;
328366 }
329367
330- /** Sets the table that translates slice numbers of hyperstacks not in default CZT order. */
368+ /** Sets the (0-based) table that translates slice numbers of hyperstacks not in default CZT order. */
331369 public void setIndexes (int [] indexes ) {
332370 this .indexes = indexes ;
333371 }
334372
335373 /** Translates slice numbers of hyperstacks not in default CZT order. */
336374 public int translate (int n ) {
337375 int n2 = (indexes !=null &&indexes .length ==getSize ()) ? indexes [n -1 ]+1 : n ;
376+ if (indexes != null ) translating = true ;
338377 //IJ.log("translate: "+n+" "+n2+" "+getSize()+" "+(indexes!=null?indexes.length:null));
339378 return n2 ;
340379 }
@@ -346,7 +385,8 @@ public void reduce(int factor) {
346385 nSlices = nSlices /factor ;
347386 for (int i =0 ; i <nSlices ; i ++) {
348387 names [i ] = names [i *factor ];
349- labels [i ] = labels [i *factor ];
388+ if (labels != null )
389+ labels [i ] = labels [i *factor ];
350390 }
351391 ImagePlus imp = WindowManager .getCurrentImage ();
352392 if (imp !=null ) {
0 commit comments