@Test
  public final void testErosionCubicMeshC6() {
    ImageStack mask = createCubicMeshImage();
    invertGray8Stack(mask);

    ImageStack marker = ImageStack.create(20, 20, 20, 8);
    marker.setVoxel(5, 5, 5, 255);
    invertGray8Stack(marker);

    GeodesicReconstruction3DHybrid0Gray8 algo = new GeodesicReconstruction3DHybrid0Gray8();
    algo.setReconstructionType(GeodesicReconstructionType.BY_EROSION);
    algo.setConnectivity(6);

    ImageStack result = algo.applyTo(marker, mask);

    assertEquals(0, result.getVoxel(5, 15, 5), .01);
    assertEquals(255, result.getVoxel(0, 0, 0), .01);

    int sizeX = mask.getWidth();
    int sizeY = mask.getHeight();
    int sizeZ = mask.getSize();

    for (int z = 0; z < sizeZ; z++) {
      for (int y = 0; y < sizeY; y++) {
        for (int x = 0; x < sizeX; x++) {
          assertEquals(result.getVoxel(x, y, z), mask.getVoxel(x, y, z), .01);
        }
      }
    }
  }
  @Test
  public final void testRegionalMaxima_CubicMeshC26() {
    // load the reference image, and get its size
    ImageStack image = createCubicMeshImage();
    int sizeX = image.getWidth();
    int sizeY = image.getHeight();
    int sizeZ = image.getSize();

    // create test image: add a band with value 127 in the middle
    int zMid = sizeZ / 2;
    for (int y = 0; y < sizeY; y++) {
      for (int x = 0; x < sizeX; x++) {
        double val = image.getVoxel(x, y, zMid);
        if (val == 255) image.setVoxel(x, y, zMid, 127);
      }
    }

    ImageStack maxima = MinimaAndMaxima3D.regionalMaxima(image, 26);

    for (int z = 0; z < sizeZ; z++) {
      for (int y = 0; y < sizeY; y++) {
        for (int x = 0; x < sizeX; x++) {
          int v0 = (int) image.getVoxel(x, y, z);
          int v = (int) maxima.getVoxel(x, y, z);
          if (v0 == 255) assertEquals(255, v);
          else assertEquals(0, v);
        }
      }
    }
  }
  public void run(ImageProcessor ip) {

    dimz = stack.getSize();
    dimy = stack.getWidth();
    dimx = stack.getHeight();

    SaveDialog sd = new SaveDialog("Save Measurements as Text...", "res", ".dat");
    String name = sd.getFileName();
    if (name == null) return;

    String directory = sd.getDirectory();

    nb = calculnb(stack); // -1;
    IJ.showStatus("Measure parameters for the " + nb + " objects ...");
    if (nb < 1) {
      IJ.showMessage("volume must be labeled");
    } else {
      double[] volume_m = new double[nb];
      int[] volume_p = new int[nb];
      double[] surface = new double[nb];
      double[] surfacenb = new double[nb];
      double[][][] I = new double[3][3][nb];
      double[][] J = new double[3][nb];
      double[][][] dir = new double[3][3][nb];
      double[] xg = new double[nb];
      double[] yg = new double[nb];
      double[] zg = new double[nb];
      byte[] bord = new byte[nb];
      //       		double[] a = new double[nb];
      //       		double[] b = new double[nb];
      //       		double[] c = new double[nb];
      //       		double[] Fab = new double[nb];
      //       		double[] Fac = new double[nb];
      //       		double[] Fbc = new double[nb];
      //       		double[] sp = new double[nb];
      double[][] lmin = new double[nb][3];
      double[][] lmax = new double[nb][3];
      IJ.showStatus("Measure surfaces ...");
      calculmarchsurfstack(stack, nb, surface, volume_m);
      calculmarchsurfstacknb(stack, nb, surfacenb);
      // calculvolumestack(stack,nb,volume_p);
      IJ.showStatus("Measure volumes and inertia ...");
      calculcgstack(stack, nb, volume_p, xg, yg, zg);
      calculinertiestack(stack, nb, xg, yg, zg, I);
      inertie(nb, I, J, dir);
      IJ.showStatus("Measure bounding boxes ...");
      boitestack(stack, nb, xg, yg, zg, dir, lmin, lmax);
      borderstack(stack, nb, bord);
      IJ.showStatus("Save results ...");
      sauvegarde(
          volume_p, volume_m, surface, surfacenb, xg, yg, zg, J, dir, nb, bord, lmin, lmax,
          directory, name);
      volume_m = null;
      volume_p = null;
      surface = null;
      xg = null;
      yg = null;
      zg = null;
    }
  }
  @Test
  public final void testDilationCochleaVolumeC6() {
    String fileName = getClass().getResource("/files/bat-cochlea-volume.tif").getFile();
    ImagePlus imagePlus = IJ.openImage(fileName);

    assertNotNull(imagePlus);

    assertTrue(imagePlus.getStackSize() > 0);

    ImageStack mask = imagePlus.getStack();
    // Ensure regularity of the mask
    mask = Morphology.opening(mask, CubeStrel.fromRadius(1));

    int width = mask.getWidth();
    int height = mask.getHeight();
    int depth = mask.getSize();
    int bitDepth = mask.getBitDepth();
    ImageStack marker = ImageStack.create(width, height, depth, bitDepth);

    marker.setVoxel(20, 80, 50, 255);

    GeodesicReconstruction3DHybrid0Gray8 algo = new GeodesicReconstruction3DHybrid0Gray8();
    algo.setConnectivity(6);
    algo.verbose = false;

    ImageStack result = algo.applyTo(marker, mask);

    for (int z = 0; z < depth; z++) {
      for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
          assertEquals(result.getVoxel(x, y, z), mask.getVoxel(x, y, z), .01);
        }
      }
    }
  }
 /**
  * Splits the specified RGB stack into three 8-bit grayscale stacks. Deletes the source stack if
  * keepSource is false.
  */
 public static ImageStack[] splitRGB(ImageStack rgb, boolean keepSource) {
   int w = rgb.getWidth();
   int h = rgb.getHeight();
   ImageStack[] channels = new ImageStack[3];
   for (int i = 0; i < 3; i++) channels[i] = new ImageStack(w, h);
   byte[] r, g, b;
   ColorProcessor cp;
   int slice = 1;
   int inc = keepSource ? 1 : 0;
   int n = rgb.getSize();
   for (int i = 1; i <= n; i++) {
     IJ.showStatus(i + "/" + n);
     r = new byte[w * h];
     g = new byte[w * h];
     b = new byte[w * h];
     cp = (ColorProcessor) rgb.getProcessor(slice);
     slice += inc;
     cp.getRGB(r, g, b);
     if (!keepSource) rgb.deleteSlice(1);
     channels[0].addSlice(null, r);
     channels[1].addSlice(null, g);
     channels[2].addSlice(null, b);
     IJ.showProgress((double) i / n);
   }
   return channels;
 }
  @Test
  public final void testDilationHilbertCurveC26() {
    String fileName = getClass().getResource("/files/hilbert3d.tif").getFile();
    ImagePlus imagePlus = IJ.openImage(fileName);

    assertNotNull(imagePlus);

    assertTrue(imagePlus.getStackSize() > 0);

    ImageStack mask = imagePlus.getStack();

    int width = mask.getWidth();
    int height = mask.getHeight();
    int depth = mask.getSize();
    int bitDepth = mask.getBitDepth();
    ImageStack marker = ImageStack.create(width, height, depth, bitDepth);

    marker.setVoxel(3, 0, 0, 255);

    GeodesicReconstruction3DHybrid0Gray8 algo = new GeodesicReconstruction3DHybrid0Gray8();
    algo.setConnectivity(26);
    algo.verbose = false;

    ImageStack result = algo.applyTo(marker, mask);

    for (int z = 0; z < depth; z++) {
      for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
          assertEquals(result.getVoxel(x, y, z), mask.getVoxel(x, y, z), .01);
        }
      }
    }
  }
  @Test
  public final void testApplyTo() {
    GeodesicReconstructionByDilation3DGray8 algo = new GeodesicReconstructionByDilation3DGray8();

    String fileName = getClass().getResource("/files/bat-cochlea-volume.tif").getFile();
    ImagePlus imagePlus = IJ.openImage(fileName);
    assertNotNull(imagePlus);

    assertTrue(imagePlus.getStackSize() > 0);

    ImageStack mask = imagePlus.getStack();
    int width = mask.getWidth();
    int height = mask.getHeight();
    int depth = mask.getSize();
    int bitDepth = mask.getBitDepth();
    ImageStack marker = ImageStack.create(width, height, depth, bitDepth);

    marker.setVoxel(20, 80, 50, 255);

    ImageStack result = algo.applyTo(marker, mask);

    for (int z = 0; z < depth; z++) {
      for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
          assertEquals(result.getVoxel(x, y, z), mask.getVoxel(x, y, z), .01);
        }
      }
    }
  }
  private final void assertStackEquals(ImageStack image, ImageStack image2) {
    int sizeX = image.getWidth();
    int sizeY = image.getHeight();
    int sizeZ = image.getSize();

    assertEquals(sizeX, image2.getWidth());
    assertEquals(sizeY, image2.getHeight());
    assertEquals(sizeZ, image2.getSize());

    for (int z = 0; z < sizeZ; z++) {
      for (int y = 0; y < sizeY; y++) {
        for (int x = 0; x < sizeX; x++) {
          assertEquals(image.getVoxel(x, y, z), image2.getVoxel(x, y, z), .01);
        }
      }
    }
  }
Exemple #9
0
 private void doHSRGBProjection(ImagePlus rgbImp) {
   ImageStack stack = rgbImp.getStack();
   ImageStack stack2 = new ImageStack(stack.getWidth(), stack.getHeight());
   for (int i = startSlice; i <= stopSlice; i++) stack2.addSlice(null, stack.getProcessor(i));
   startSlice = 1;
   stopSlice = stack2.getSize();
   doRGBProjection(stack2);
 }
  private final void invertGray8Stack(ImageStack image) {
    int sizeX = image.getWidth();
    int sizeY = image.getHeight();
    int sizeZ = image.getSize();

    for (int z = 0; z < sizeZ; z++) {
      for (int y = 0; y < sizeY; y++) {
        for (int x = 0; x < sizeX; x++) {
          image.setVoxel(x, y, z, 255 - image.getVoxel(x, y, z));
        }
      }
    }
  }
 public DataImporter(final String resultsFilePath, final boolean readWeights) {
   super();
   final ImageStack file = IJ.openImage(resultsFilePath).getImageStack();
   slices = file.getSize();
   for (int i = 1; i <= file.getSize(); i++) {
     for (int y = 0; y < file.getHeight(); y++) {
       final float[] point = new float[14];
       for (int x = 0; x < file.getWidth(); x++) {
         point[x] = file.getProcessor(i).getf(x, y);
       }
       this.add(point);
     }
   }
 }
  void borderstack(final ImageStack stack1, int nb, byte[] b) {
    final AtomicInteger ai = new AtomicInteger(0);
    final int dimX = stack1.getWidth();
    final int dimY = stack1.getHeight();
    final int dimZ = stack1.getSize();
    final byte[][] bord = new byte[dimZ][nb];

    for (int ithread = 0; ithread < threads.length; ithread++) {

      // Concurrently run in as many threads as CPUs

      threads[ithread] =
          new Thread() {

            public void run() {
              for (int superi = ai.getAndIncrement();
                  superi < dimZ;
                  superi = ai.getAndIncrement()) {
                int k = superi;
                ImageProcessor ip = stack1.getProcessor(k + 1);
                for (int j = 0; j < dimY; j++) {
                  for (int i = 0; i < dimX; i++) {
                    int val = (int) (ip.getPixelValue(i, j));
                    if ((val != 0)
                        && (i == 0
                            || j == 0
                            || k == 0
                            || i == dimX - 1
                            || j == dimY - 1
                            || k == dimZ - 1))
                      // bord[k][val-2]=1;
                      bord[k][val - 1] = 1;
                  }
                }
              }
            }
          };
    }
    startAndJoin(threads);
    for (int i = 0; i < dimZ; i++) {
      for (int j = 0; j < nb; j++) {
        b[j] *= (1 - bord[i][j]);
      }
    }
    for (int j = 0; j < nb; j++) {
      b[j] = (byte) (1 - b[j]);
    }
  }
Exemple #13
0
 public void reduceStack(ImagePlus imp, int factor) {
   ImageStack stack = imp.getStack();
   boolean virtual = stack.isVirtual();
   int n = stack.getSize();
   ImageStack stack2 = new ImageStack(stack.getWidth(), stack.getHeight());
   for (int i = 1; i <= n; i += factor) {
     if (virtual) IJ.showProgress(i, n);
     stack2.addSlice(stack.getSliceLabel(i), stack.getProcessor(i));
   }
   imp.setStack(null, stack2);
   if (virtual) {
     IJ.showProgress(1.0);
     imp.setTitle(imp.getTitle());
   }
   Calibration cal = imp.getCalibration();
   if (cal.scaled()) cal.pixelDepth *= factor;
 }
  /**
   * Constructor that builds up a VectorProcessor froma a stack of {@link FloatProcessor}s This is
   * the constructor that is being used in @link{KMeans}
   *
   * @param stack a stack of {@link FloatProcessor}s.
   */
  public VectorProcessor(final ImageStack stack) {
    /* Calls the constructor
    @link{VectorProcessor(final int width, final int height, final int numberOfValues)}*/
    this(stack.getWidth(), stack.getHeight(), stack.getSize());

    /* Gets the images in the stack and puts them into an array of Object*/
    final Object[] slices = stack.getImageArray();
    /* For each image (= component) in the stack */
    for (int i = 0; i < numberOfValues; ++i) {
      /* get the pixels as an array of float */
      final float[] values = (float[]) slices[i];
      /* for each pixel */
      for (int j = 0; j < values.length; j++) {
        /* store the value */
        pixels[j][i] = values[j];
      }
    }
  }
  private ImageStack createInvertedLeveledCubeGraphImage() {
    ImageStack stack = createCubeGraphImage();
    for (int z = 0; z < stack.getSize(); z++) {
      for (int y = 0; y < stack.getHeight(); y++) {
        for (int x = 0; x < stack.getWidth(); x++) {
          stack.setVoxel(x, y, z, 255 - stack.getVoxel(x, y, z));
        }
      }
    }
    stack.setVoxel(5, 1, 1, 32);
    stack.setVoxel(9, 5, 1, 64);
    stack.setVoxel(9, 9, 5, 96);
    stack.setVoxel(9, 5, 9, 128);
    stack.setVoxel(5, 1, 9, 160);
    stack.setVoxel(1, 5, 9, 192);
    stack.setVoxel(1, 9, 5, 224);

    return stack;
  }
Exemple #16
0
 ImagePlus duplicateStack(ImagePlus img1) {
   ImageStack stack1 = img1.getStack();
   int width = stack1.getWidth();
   int height = stack1.getHeight();
   int n = stack1.getSize();
   ImageStack stack2 = img1.createEmptyStack();
   try {
     for (int i = 1; i <= n; i++) {
       ImageProcessor ip1 = stack1.getProcessor(i);
       ip1.resetRoi();
       ImageProcessor ip2 = ip1.crop();
       stack2.addSlice(stack1.getSliceLabel(i), ip2);
     }
   } catch (OutOfMemoryError e) {
     stack2.trim();
     stack2 = null;
     return null;
   }
   return new ImagePlus("Duplicate", stack2);
 }
  @Test
  public final void testErosionCochleaVolumeC26() {
    String fileName = getClass().getResource("/files/bat-cochlea-volume.tif").getFile();
    ImagePlus imagePlus = IJ.openImage(fileName);

    assertNotNull(imagePlus);
    assertTrue(imagePlus.getStackSize() > 0);

    ImageStack mask = imagePlus.getStack();
    // Ensure regularity of the mask
    mask = Morphology.opening(mask, CubeStrel.fromRadius(1));
    invertGray8Stack(mask);

    int width = mask.getWidth();
    int height = mask.getHeight();
    int depth = mask.getSize();
    int bitDepth = mask.getBitDepth();
    ImageStack marker = ImageStack.create(width, height, depth, bitDepth);
    marker.setVoxel(20, 80, 50, 255);
    invertGray8Stack(marker);

    GeodesicReconstruction3DHybrid0Gray8 algo =
        new GeodesicReconstruction3DHybrid0Gray8(GeodesicReconstructionType.BY_EROSION);
    algo.setConnectivity(26);

    ImageStack result = algo.applyTo(marker, mask);

    for (int z = 0; z < depth; z++) {
      for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
          if (Math.abs(result.getVoxel(x, y, z) - mask.getVoxel(x, y, z)) > .1) {
            System.out.println("x=" + x + " y=" + y + " z=" + z);
            System.out.println("  mask = " + (int) mask.getVoxel(x, y, z));
            System.out.println("  res  = " + (int) result.getVoxel(x, y, z));
            assertTrue(false);
          }
        }
      }
    }
  }
  public int calculnb(final ImageStack stack1) {
    final AtomicInteger ai = new AtomicInteger(1);
    final int dimX = stack1.getWidth();
    final int dimY = stack1.getHeight();
    final int dimZ = stack1.getSize();
    final int[] value = new int[dimZ];

    for (int ithread = 0; ithread < threads.length; ithread++) {

      // Concurrently run in as many threads as CPUs

      threads[ithread] =
          new Thread() {

            public void run() {
              for (int superi = ai.getAndIncrement();
                  superi <= dimZ;
                  superi = ai.getAndIncrement()) {
                int current = superi;
                ImageProcessor ip = stack1.getProcessor(current);
                for (int j = 0; j < dimY; j++) {
                  for (int i = 0; i < dimX; i++) {
                    int val = (int) (ip.getPixelValue(i, j));
                    if (val > value[current - 1]) value[current - 1] = val;
                  }
                }
              }
            }
          };
    }
    startAndJoin(threads);

    int val = 0;
    for (int i = 0; i < dimZ; i++) {
      if (val < value[i]) val = value[i];
    }
    return val;
  }
  void calculvolumestack(final ImageStack stack1, int nb, int v[]) {
    final AtomicInteger ai = new AtomicInteger(1);
    final int dimX = stack1.getWidth();
    final int dimY = stack1.getHeight();
    final int dimZ = stack1.getSize();
    final int[][] vol = new int[dimZ][nb];

    for (int ithread = 0; ithread < threads.length; ithread++) {

      // Concurrently run in as many threads as CPUs

      threads[ithread] =
          new Thread() {

            public void run() {
              for (int superi = ai.getAndIncrement();
                  superi <= dimZ;
                  superi = ai.getAndIncrement()) {
                int current = superi;
                ImageProcessor ip = stack1.getProcessor(current);
                for (int j = 0; j < dimY; j++) {
                  for (int i = 0; i < dimX; i++) {
                    int val = (int) (ip.getPixelValue(i, j));
                    // if (val!=0) vol[current-1][val-2]++;
                    if (val != 0) vol[current - 1][val - 1]++;
                  }
                }
              }
            }
          };
    }
    startAndJoin(threads);
    for (int i = 0; i < dimZ; i++) {
      for (int j = 0; j < nb; j++) {
        v[j] += vol[i][j];
      }
    }
  }
    public void makeTransition(ImagePlus imp, int from, int num) {
      if (from > imp.getStackSize()) {
        IJ.error("Need a following slice to which to transit.");
        return;
      }
      num++; // so that really num slices are added
      ImageStack stack = imp.getStack();
      int[] before = (int[]) (stack.getProcessor(from).convertToRGB().getPixels());
      int[] after = (int[]) (stack.getProcessor(from + 1).convertToRGB().getPixels());

      for (int z = 1; z < num; z++) {
        ColorProcessor bp = new ColorProcessor(stack.getWidth(), stack.getHeight());
        int[] pixels = (int[]) bp.getPixels();
        double dp = z;
        double dn = num - z;

        for (int i = 0; i < pixels.length; i++) {
          pixels[i] = interpolate(before[i], dp, after[i], dn);
        }
        new ImagePlus("slice + " + z, bp).show();
        stack.addSlice("", bp, from + z - 1);
      }
    }
  @Test
  public final void testRegionalMaxima_BatCochlea() {
    String fileName = getClass().getResource("/files/bat-cochlea-volume.tif").getFile();
    ImagePlus imagePlus = IJ.openImage(fileName);
    assertNotNull(imagePlus);
    assertTrue(imagePlus.getStackSize() > 0);

    // load the reference image, and get its size
    ImageStack image = imagePlus.getStack();
    int sizeX = image.getWidth();
    int sizeY = image.getHeight();
    int sizeZ = image.getSize();

    // create test image:
    // use cochlea volume, but add a band with value 127 in the middle
    int zMid = sizeZ / 2;
    for (int y = 0; y < sizeY; y++) {
      for (int x = 0; x < sizeX; x++) {
        double val = image.getVoxel(x, y, zMid);
        if (val == 255) image.setVoxel(x, y, zMid, 127);
      }
    }

    ImageStack maxima = MinimaAndMaxima3D.regionalMaxima(image);

    for (int z = 0; z < sizeZ; z++) {
      for (int y = 0; y < sizeY; y++) {
        for (int x = 0; x < sizeX; x++) {
          int v0 = (int) image.getVoxel(x, y, z);
          int v = (int) maxima.getVoxel(x, y, z);
          if (v0 == 255) assertEquals(255, v);
          else assertEquals(0, v);
        }
      }
    }
  }
    ImageProcessor setup(ImagePlus imp) {

      ImageProcessor ip;
      int type = imp.getType();
      if (type != ImagePlus.COLOR_RGB) return null;
      ip = imp.getProcessor();
      int id = imp.getID();
      int slice = imp.getCurrentSlice();

      if ((id != previousImageID) | (slice != previousSlice) | (flag)) {
        flag = false; // if true, flags a change from HSB to RGB or viceversa
        numSlices = imp.getStackSize();
        stack = imp.getStack();
        width = stack.getWidth();
        height = stack.getHeight();
        numPixels = width * height;

        hSource = new byte[numPixels];
        sSource = new byte[numPixels];
        bSource = new byte[numPixels];

        // restore = (int[])ip.getPixelsCopy(); //This runs into trouble sometimes, so do it the
        // long way:
        int[] temp = (int[]) ip.getPixels();
        restore = new int[numPixels];
        for (int i = 0; i < numPixels; i++) restore[i] = temp[i];

        fillMask = new int[numPixels];

        // Get hsb or rgb from image.
        ColorProcessor cp = (ColorProcessor) ip;
        IJ.showStatus("Gathering data");

        if (isRGB) cp.getRGB(hSource, sSource, bSource);
        else cp.getHSB(hSource, sSource, bSource);

        IJ.showStatus("done");

        // Create a spectrum ColorModel for the Hue histogram plot.
        Color c;
        byte[] reds = new byte[256];
        byte[] greens = new byte[256];
        byte[] blues = new byte[256];
        for (int i = 0; i < 256; i++) {
          c = Color.getHSBColor(i / 255f, 1f, 1f);

          reds[i] = (byte) c.getRed();
          greens[i] = (byte) c.getGreen();
          blues[i] = (byte) c.getBlue();
        }
        ColorModel cm = new IndexColorModel(8, 256, reds, greens, blues);

        // Make an image with just the hue from the RGB image and the spectrum LUT.
        // This is just for a hue histogram for the plot.  Do not show it.
        // ByteProcessor bpHue = new ByteProcessor(width,height,h,cm);
        ByteProcessor bpHue = new ByteProcessor(width, height, hSource, cm);
        ImagePlus impHue = new ImagePlus("Hue", bpHue);
        // impHue.show();

        ByteProcessor bpSat = new ByteProcessor(width, height, sSource, cm);
        ImagePlus impSat = new ImagePlus("Sat", bpSat);
        // impSat.show();

        ByteProcessor bpBri = new ByteProcessor(width, height, bSource, cm);
        ImagePlus impBri = new ImagePlus("Bri", bpBri);
        // impBri.show();

        plot.setHistogram(impHue, 0);
        splot.setHistogram(impSat, 1);
        bplot.setHistogram(impBri, 2);

        updateLabels();
        updatePlot();
        updateScrollBars();
        imp.updateAndDraw();
      }
      previousImageID = id;
      previousSlice = slice;
      return ip;
    }
  public static boolean write(ImagePlus imp, String path) {
    if (null == imp) return false;

    ImageStack stack = imp.getStack();

    float pixelWidth = (float) imp.getCalibration().pixelWidth;
    float pixelHeight = (float) imp.getCalibration().pixelHeight;
    float pixelDepth = (float) imp.getCalibration().pixelDepth;
    String unitString = imp.getCalibration().getXUnit();

    int size1 = stack.getWidth();
    int size2 = stack.getHeight();
    int size3 = stack.getSize();

    // IJ.log("/"+size1+"/");

    File outputFile = new File(path);

    try {
      // Construct the BufferedOutputStream object
      BufferedOutputStream bufferedOutput =
          new BufferedOutputStream(new FileOutputStream(outputFile));
      DataOutputStream dataOut = new DataOutputStream(bufferedOutput);

      // Start writing to the output stream

      int zero = 0;
      dataOut.writeInt(zero);
      dataOut.writeInt(zero);
      dataOut.writeInt(zero);

      int version = 1;
      dataOut.writeInt(reverse(version));

      // type of data
      // type= 2 - int
      // type= 5 - float
      int type = 5;
      dataOut.writeInt(reverse(type));

      dataOut.writeInt(reverse(size1));
      dataOut.writeInt(reverse(size2));
      dataOut.writeInt(reverse(size3));

      // Spatial calibration
      dataOut.writeInt(reverse(unitStringToInt(unitString)));
      dataOut.writeInt(reverse(Float.floatToIntBits(pixelWidth)));
      dataOut.writeInt(reverse(Float.floatToIntBits(pixelHeight)));
      dataOut.writeInt(reverse(Float.floatToIntBits(pixelDepth)));

      // write pixels
      for (int z = 0; z < size3; ++z) {
        for (int x = 0; x < size1; ++x) {
          for (int y = 0; y < size2; ++y) {
            dataOut.writeInt(reverse(Float.floatToIntBits((float) stack.getVoxel(x, y, z))));
          }
        }
      }

      // cleanup output stream
      dataOut.flush();
      dataOut.close();

    } catch (Exception e) {
      e.printStackTrace();
      return false;
    }
    return true;
  }
  void boitestack(
      final ImageStack stack1,
      final int nb,
      final double[] xg,
      final double[] yg,
      final double[] zg,
      final double[][][] dir,
      double[][] lmin,
      double[][] lmax) {
    final AtomicInteger ai = new AtomicInteger(0);
    final int dimX = stack1.getWidth();
    final int dimY = stack1.getHeight();
    final int dimZ = stack1.getSize();
    final double[][][] lmint = new double[dimZ][nb][3];
    final double[][][] lmaxt = new double[dimZ][nb][3];

    for (int k = 0; k < nb; k++) {
      lmin[k][0] = 100000;
      lmin[k][1] = 100000;
      lmin[k][2] = 100000;
      lmax[k][0] = -100000;
      lmax[k][1] = -100000;
      lmax[k][2] = -100000;
    }

    for (int ithread = 0; ithread < threads.length; ithread++) {

      // Concurrently run in as many threads as CPUs

      threads[ithread] =
          new Thread() {

            public void run() {
              for (int superi = ai.getAndIncrement();
                  superi < dimZ;
                  superi = ai.getAndIncrement()) {
                int k = superi;
                ImageProcessor ip = stack1.getProcessor(k + 1);
                for (int l = 0; l < nb; l++) {
                  lmint[k][l][0] = 100000;
                  lmint[k][l][1] = 100000;
                  lmint[k][l][2] = 100000;
                  lmaxt[k][l][0] = -100000;
                  lmaxt[k][l][1] = -100000;
                  lmaxt[k][l][2] = -100000;
                }
                for (int j = 0; j < dimY; j++) {
                  for (int i = 0; i < dimX; i++) {
                    int pix = (int) (ip.getPixelValue(i, j));
                    if (pix != 0) {
                      //								double v1 =
                      // (i-xg[pix-2])*dir[0][0][pix-2]+(j-yg[pix-2])*dir[1][0][pix-2]+(k-zg[pix-2])*dir[2][0][pix-2];
                      //							    double v2 =
                      // (i-xg[pix-2])*dir[0][1][pix-2]+(j-yg[pix-2])*dir[1][1][pix-2]+(k-zg[pix-2])*dir[2][1][pix-2];
                      //							    double v3 =
                      // (i-xg[pix-2])*dir[0][2][pix-2]+(j-yg[pix-2])*dir[1][2][pix-2]+(k-zg[pix-2])*dir[2][2][pix-2];
                      //							    if (v1<lmint[k][pix-2][0]) lmint[k][pix-2][0]=v1;
                      //							    if (v1>lmaxt[k][pix-2][0]) lmaxt[k][pix-2][0]=v1;
                      //							    if (v2<lmint[k][pix-2][1]) lmint[k][pix-2][1]=v2;
                      //							    if (v2>lmaxt[k][pix-2][1]) lmaxt[k][pix-2][1]=v2;
                      //							    if (v3<lmint[k][pix-2][2]) lmint[k][pix-2][2]=v3;
                      //							    if (v3>lmaxt[k][pix-2][2]) lmaxt[k][pix-2][2]=v3;
                      double v1 =
                          (i - xg[pix - 1]) * dir[0][0][pix - 1]
                              + (j - yg[pix - 1]) * dir[1][0][pix - 1]
                              + (k - zg[pix - 1]) * dir[2][0][pix - 1];
                      double v2 =
                          (i - xg[pix - 1]) * dir[0][1][pix - 1]
                              + (j - yg[pix - 1]) * dir[1][1][pix - 1]
                              + (k - zg[pix - 1]) * dir[2][1][pix - 1];
                      double v3 =
                          (i - xg[pix - 1]) * dir[0][2][pix - 1]
                              + (j - yg[pix - 1]) * dir[1][2][pix - 1]
                              + (k - zg[pix - 1]) * dir[2][2][pix - 1];
                      if (v1 < lmint[k][pix - 1][0]) lmint[k][pix - 1][0] = v1;
                      if (v1 > lmaxt[k][pix - 1][0]) lmaxt[k][pix - 1][0] = v1;
                      if (v2 < lmint[k][pix - 1][1]) lmint[k][pix - 1][1] = v2;
                      if (v2 > lmaxt[k][pix - 1][1]) lmaxt[k][pix - 1][1] = v2;
                      if (v3 < lmint[k][pix - 1][2]) lmint[k][pix - 1][2] = v3;
                      if (v3 > lmaxt[k][pix - 1][2]) lmaxt[k][pix - 1][2] = v3;
                    }
                  }
                }
              }
            }
          };
    }
    startAndJoin(threads);
    for (int i = 0; i < dimZ; i++) {
      for (int j = 0; j < nb; j++) {
        for (int l = 0; l < 3; l++) {
          if (lmint[i][j][l] < lmin[j][l]) lmin[j][l] = lmint[i][j][l];
          if (lmaxt[i][j][l] > lmax[j][l]) lmax[j][l] = lmaxt[i][j][l];
        }
      }
      lmint[i] = null;
      lmaxt[i] = null;
    }
  }
  void calculinertiestack(
      final ImageStack stack1,
      int nb,
      final double[] xg,
      final double[] yg,
      final double[] zg,
      double[][][] I) {
    final AtomicInteger ai = new AtomicInteger(0);
    final int dimX = stack1.getWidth();
    final int dimY = stack1.getHeight();
    final int dimZ = stack1.getSize();
    final double[][][][] inert = new double[dimZ][nb][3][3];

    for (int ithread = 0; ithread < threads.length; ithread++) {

      // Concurrently run in as many threads as CPUs

      threads[ithread] =
          new Thread() {

            public void run() {
              for (int superi = ai.getAndIncrement();
                  superi < dimZ;
                  superi = ai.getAndIncrement()) {
                int k = superi;
                ImageProcessor ip = stack1.getProcessor(k + 1);
                for (int j = 0; j < dimY; j++) {
                  for (int i = 0; i < dimX; i++) {
                    int pix = (int) (ip.getPixelValue(i, j));
                    if (pix != 0) {
                      //
                      // inert[k][pix-2][0][0]+=(i-yg[pix-2])*(i-yg[pix-2])+(k-zg[pix-2])*(k-zg[pix-2])+1.0/6.0;
                      //						         inert[k][pix-2][0][1]-=(j-xg[pix-2])*(i-yg[pix-2]);
                      //						         inert[k][pix-2][0][2]-=(j-xg[pix-2])*(k-zg[pix-2]);
                      //
                      // inert[k][pix-2][1][1]+=(j-xg[pix-2])*(j-xg[pix-2])+(k-zg[pix-2])*(k-zg[pix-2])+1.0/6.0;
                      //						         inert[k][pix-2][1][2]-=(i-yg[pix-2])*(k-zg[pix-2]);
                      //
                      // inert[k][pix-2][2][2]+=(j-xg[pix-2])*(j-xg[pix-2])+(i-yg[pix-2])*(i-yg[pix-2])+1.0/6.0;
                      inert[k][pix - 1][0][0] +=
                          (j - yg[pix - 1]) * (j - yg[pix - 1])
                              + (k - zg[pix - 1]) * (k - zg[pix - 1])
                              + 1.0 / 6.0;
                      inert[k][pix - 1][0][1] -= (i - xg[pix - 1]) * (j - yg[pix - 1]);
                      inert[k][pix - 1][0][2] -= (i - xg[pix - 1]) * (k - zg[pix - 1]);
                      inert[k][pix - 1][1][1] +=
                          (i - xg[pix - 1]) * (i - xg[pix - 1])
                              + (k - zg[pix - 1]) * (k - zg[pix - 1])
                              + 1.0 / 6.0;
                      inert[k][pix - 1][1][2] -= (j - yg[pix - 1]) * (k - zg[pix - 1]);
                      inert[k][pix - 1][2][2] +=
                          (i - xg[pix - 1]) * (i - xg[pix - 1])
                              + (j - yg[pix - 1]) * (j - yg[pix - 1])
                              + 1.0 / 6.0;
                    }
                  }
                }
              }
            }
          };
    }
    startAndJoin(threads);
    for (int i = 0; i < dimZ; i++) {
      for (int j = 0; j < nb; j++) {
        for (int l = 0; l < 3; l++) {
          for (int m = 0; m <= l; m++) {
            I[l][m][j] += inert[i][j][l][m];
          }
        }
      }
      inert[i] = null;
    }
    for (int j = 0; j < nb; j++) {
      I[1][0][j] = I[0][1][j];
      I[2][0][j] = I[0][2][j];
      I[2][1][j] = I[1][2][j];
    }
  }
  void calculcgstack(
      final ImageStack stack1,
      int nb,
      final int[] v,
      final double[] xg,
      final double[] yg,
      final double[] zg) {
    final AtomicInteger ai = new AtomicInteger(0);
    final int dimX = stack1.getWidth();
    final int dimY = stack1.getHeight();
    final int dimZ = stack1.getSize();
    final int[][] vol = new int[dimZ][nb];
    final int[][] tmpxg = new int[dimZ][nb];
    final int[][] tmpyg = new int[dimZ][nb];
    final int[][] tmpzg = new int[dimZ][nb];

    for (int ithread = 0; ithread < threads.length; ithread++) {

      // Concurrently run in as many threads as CPUs

      threads[ithread] =
          new Thread() {

            public void run() {
              for (int superi = ai.getAndIncrement();
                  superi < dimZ;
                  superi = ai.getAndIncrement()) {
                int k = superi;
                ImageProcessor ip = stack1.getProcessor(k + 1);
                for (int j = 0; j < dimY; j++) {
                  for (int i = 0; i < dimX; i++) {
                    int pix = (int) (ip.getPixelValue(i, j));
                    if (pix != 0) {
                      //						          tmpxg[k][pix-2] += j;
                      //						          tmpyg[k][pix-2] += i;
                      //						          tmpzg[k][pix-2] += k;
                      //						          vol[k][pix-2]++;
                      tmpxg[k][pix - 1] += i;
                      tmpyg[k][pix - 1] += j;
                      tmpzg[k][pix - 1] += k;
                      vol[k][pix - 1]++;
                    }
                  }
                }
              }
            }
          };
    }
    startAndJoin(threads);
    for (int i = 0; i < dimZ; i++) {
      for (int j = 0; j < nb; j++) {
        v[j] += vol[i][j];
        xg[j] += tmpxg[i][j];
        yg[j] += tmpyg[i][j];
        zg[j] += tmpzg[i][j];
      }
    }

    for (int i = 0; i < nb; i++) {
      xg[i] = (1.0 * xg[i] / v[i]);
      yg[i] = (1.0 * yg[i] / v[i]);
      zg[i] = (1.0 * zg[i] / v[i]);
    }
  }
  void calculsurfacemarch3stack(final ImageStack stack1, int nb, final double[] tri, double[] s2) {
    final AtomicInteger ai = new AtomicInteger(0);
    final int dimX = stack1.getWidth();
    final int dimY = stack1.getHeight();
    final int dimZ = stack1.getSize();
    final double[][] surf = new double[dimZ][nb];

    for (int ithread = 0; ithread < threads.length; ithread++) {

      // Concurrently run in as many threads as CPUs

      threads[ithread] =
          new Thread() {

            public void run() {
              for (int superi = ai.getAndIncrement();
                  superi < dimZ - 1;
                  superi = ai.getAndIncrement()) {
                int k = superi;
                ImageProcessor ip1, ip2;
                ip1 = stack1.getProcessor(k + 1);
                ip2 = stack1.getProcessor(k + 2);
                for (int j = 0; j < dimY - 1; j++) {
                  for (int i = 0; i < dimX - 1; i++) {
                    int[] p = new int[8];
                    int p1, p2, p3, p4, p5, p6, p7, p8, ptot;
                    int[] nontab = new int[8];

                    ptot = (short) 0;
                    p[0] = (int) ip1.getPixelValue(i, j);
                    p[1] = (int) ip1.getPixelValue(i, j + 1);
                    p[2] = (int) ip2.getPixelValue(i, j);
                    p[3] = (int) ip2.getPixelValue(i, j + 1);
                    p[4] = (int) ip1.getPixelValue(i + 1, j);
                    p[5] = (int) ip1.getPixelValue(i + 1, j + 1);
                    p[6] = (int) ip2.getPixelValue(i + 1, j);
                    p[7] = (int) ip2.getPixelValue(i + 1, j + 1);

                    int pixcoul = 0;

                    for (int l = 0; l < 8; l++) nontab[l] = 0;

                    int cpt = 0;

                    // look for different colors
                    for (int l = 0; l < 8; l++) {
                      if (p[l] != 0 && appart(p[l], nontab, 8) == 1) {
                        nontab[cpt] = p[l];
                        cpt++;
                      }
                    }

                    for (int mm = 0; mm < cpt; mm++) {
                      p1 = 0;
                      p2 = 0;
                      p3 = 0;
                      p4 = 0;
                      p5 = 0;
                      p6 = 0;
                      p7 = 0;
                      p8 = 0;

                      if (p[0] != 0 && p[0] == nontab[mm]) {
                        pixcoul = nontab[mm];
                        p1 = 1;
                      }

                      if (p[1] != 0 && p[1] == nontab[mm]) {
                        pixcoul = nontab[mm];
                        p2 = 4;
                      }

                      if (p[2] != 0 && p[2] == nontab[mm]) {
                        pixcoul = nontab[mm];
                        p3 = 2;
                      }

                      if (p[3] != 0 && p[3] == nontab[mm]) {
                        pixcoul = nontab[mm];
                        p4 = 8;
                      }

                      if (p[4] != 0 && p[4] == nontab[mm]) {
                        pixcoul = nontab[mm];
                        p5 = 16;
                      }

                      if (p[5] != 0 && p[5] == nontab[mm]) {
                        pixcoul = nontab[mm];
                        p6 = 64;
                      }

                      if (p[6] != 0 && p[6] == nontab[mm]) {
                        pixcoul = nontab[mm];
                        p7 = 32;
                      }

                      if (p[7] != 0 && p[7] == nontab[mm]) {
                        pixcoul = nontab[mm];
                        p8 = 128;
                      }

                      ptot = (p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8);

                      if (pixcoul != 0) {
                        surf[k][(int) (pixcoul - 1)] += tri[(int) (ptot)];
                        // surf[k][(int)(pixcoul-2)]+=tri[(int)(ptot)];
                      }
                    }
                  }
                }
              }
            }
          };
    }
    startAndJoin(threads);
    for (int i = 0; i < dimZ; i++) {
      for (int j = 0; j < nb; j++) {
        s2[j] += surf[i][j];
      }
    }
  }