/// <summary> /// Divide by another float stack pixel-wise /// </summary> /// <param name="ims">The stack to divide by</param> public void Divide(ImageStack32F ims) { DisposeGuard(); if (ims.IsDisposed) { throw new ArgumentException("Can't divide by disposed image"); } if (!IsCompatible(ims)) { throw new ArgumentException("Given image has wrong dimensions or z versus t ordering"); } if (Stride == ims.Stride) { for (long i = 0; i < ImageNB / 4; i++) { ImageData[i] /= ims.ImageData[i]; } } else//need to go pixel-wise { for (int z = 0; z < ZPlanes; z++) { for (int t = 0; t < TimePoints; t++) { for (int y = 0; y < ImageHeight; y++) { for (int x = 0; x < ImageWidth; x++) { *this[x, y, z, t] /= *ims[x, y, z, t]; } } } } } }
/// <summary> /// Copy constructor /// </summary> /// <param name="ims">The image to copy</param> public ImageStack32F(ImageStack32F ims) { if (ims == null) throw new ArgumentNullException(nameof(ims)); if (ims.IsDisposed) throw new ArgumentException("Can't copy disposed stack"); InitializeAsCopy(ims); }
/// <summary> /// Compares every pixel in an image to a given value /// </summary> /// <param name="value">The value each pixel should have</param> /// <param name="image">The image to compare</param> private void CompareValImage(float value, ImageStack32F image) { float* imStart = image.ImageData; //only compare outside of stride padding for (long i = 0; i < image.ImageNB / 4; i++) { if (i % image.Stride < image.ImageWidth) Assert.AreEqual(value, imStart[i], Math.Abs(value / 1000), "Found non-matching pixel at position {0}", i); } }
/// <summary> /// Copy constructor /// </summary> /// <param name="ims">The image to copy</param> public ImageStack32F(ImageStack32F ims) { if (ims == null) { throw new ArgumentNullException(nameof(ims)); } if (ims.IsDisposed) { throw new ArgumentException("Can't copy disposed stack"); } InitializeAsCopy(ims); }
public void Construction_WithValidArguments_DimCorrect() { int w = 20; int h = 30; int z = 40; int t = 50; var ims = new ImageStack32F(w, h, z, t, ImageStack.SliceOrders.TBeforeZ); Assert.AreEqual(ims.ImageWidth, w, "Image width not correct."); Assert.AreEqual(ims.ImageHeight, h, "Image height not correct."); Assert.AreEqual(ims.ZPlanes, z, "Image z plane number not correct."); Assert.AreEqual(ims.TimePoints, t, "Number of timepoints not correct."); ims.Dispose(); }
/// <summary> /// Constructs a 16bit stack via rescaling of a 32bit float stack /// </summary> /// <param name="ims">The source stack to be copied</param> /// <param name="min">This value and below will be set to 0</param> /// <param name="max">This value and above will be set to 65535</param> public ImageStack16(ImageStack32F ims, float min, float max) { if (ims == null) { throw new ArgumentNullException(nameof(ims)); } if (ims.IsDisposed) { throw new ArgumentException("Can't copy disposed stack"); } if (max <= min) { throw new ArgumentException("max has to be strictly greater than min"); } SliceOrder = ims.SliceOrder; //initialize buffer and dimension properties according to source stack InitializeImageBuffer(ims.ImageWidth, ims.ImageHeight, ims.ZPlanes, ims.TimePoints, 2); //loop over pixels, assigning values for (int z = 0; z < ZPlanes; z++) { for (int t = 0; t < TimePoints; t++) { for (int y = 0; y < ImageHeight; y++) { for (int x = 0; x < ImageWidth; x++) { float temp = *ims[x, y, z, t]; temp = (temp - min) / (max - min) * ushort.MaxValue; if (temp < 0) { temp = 0; } else if (temp > ushort.MaxValue) { temp = ushort.MaxValue; } *this[x, y, z, t] = (byte)temp; } } } } }
/// <summary> /// Divide by another float stack pixel-wise /// </summary> /// <param name="ims">The stack to divide by</param> public void Divide(ImageStack32F ims) { DisposeGuard(); if (ims.IsDisposed) throw new ArgumentException("Can't divide by disposed image"); if (!IsCompatible(ims)) throw new ArgumentException("Given image has wrong dimensions or z versus t ordering"); if (Stride == ims.Stride) for (long i = 0; i < ImageNB / 4; i++) ImageData[i] /= ims.ImageData[i]; else//need to go pixel-wise for (int z = 0; z < ZPlanes; z++) for (int t = 0; t < TimePoints; t++) for (int y = 0; y < ImageHeight; y++) for (int x = 0; x < ImageWidth; x++) *this[x, y, z, t] /= *ims[x, y, z, t]; }
/// <summary> /// Constructs a 16bit stack via rescaling of a 32bit float stack /// </summary> /// <param name="ims">The source stack to be copied</param> /// <param name="min">This value and below will be set to 0</param> /// <param name="max">This value and above will be set to 65535</param> public ImageStack16(ImageStack32F ims, float min, float max) { if (ims == null) throw new ArgumentNullException(nameof(ims)); if (ims.IsDisposed) throw new ArgumentException("Can't copy disposed stack"); if (max <= min) throw new ArgumentException("max has to be strictly greater than min"); SliceOrder = ims.SliceOrder; //initialize buffer and dimension properties according to source stack InitializeImageBuffer(ims.ImageWidth, ims.ImageHeight, ims.ZPlanes, ims.TimePoints, 2); //loop over pixels, assigning values for (int z = 0; z < ZPlanes; z++) for (int t = 0; t < TimePoints; t++) for (int y = 0; y < ImageHeight; y++) for (int x = 0; x < ImageWidth; x++) { float temp = *ims[x, y, z, t]; temp = (temp - min) / (max - min) * ushort.MaxValue; if (temp < 0) temp = 0; else if (temp > ushort.MaxValue) temp = ushort.MaxValue; *this[x, y, z, t] = (byte)temp; } }
public void PixelPointerNull_AfterDispose() { var ims = new ImageStack32F(5, 5, 5, 5, ImageStack.SliceOrders.ZBeforeT); ims.Dispose(); Assert.IsTrue(ims[4, 0, 0, 0] == null); }
public void ShallowConstruction_OddStride() { float* buffer = (float*)Marshal.AllocHGlobal(51); try { var ims = new ImageStack32F(buffer, 51/4, 51, 1, 1, 1, ImageStack.SliceOrders.TBeforeZ); } finally { Marshal.FreeHGlobal((IntPtr)buffer); } }
public void Construction_WithInvalidHeight() { var ims = new ImageStack32F(20, 0, 40, 50, ImageStack.SliceOrders.TBeforeZ); ims.Dispose(); }
public void From16bit_Constructor_Correct() { Random rnd = new Random(); var ims16 = new ImageStack16(43, 43, 41, 41, ImageStack.SliceOrders.ZBeforeT); //quickly fill image with random values int* buffer = (int*)ims16.ImageData; long iter = ims16.ImageNB / 4; for (long i = 0; i < iter; i++) { buffer[i] = rnd.Next(); } var ims32 = new ImageStack32F(ims16); Assert.AreEqual(ims16.SliceOrder, ims32.SliceOrder); for (int z = 0; z < ims16.ZPlanes; z++) for (int t = 0; t < ims16.TimePoints; t++) for (int y = 0; y < ims16.ImageHeight; y++) for (int x = 0; x < ims16.ImageWidth; x++) Assert.AreEqual(*ims16[x, y, z, t], *ims32[x, y, z, t], *ims16[x, y, z, t] / 1000); ims16.Dispose(); ims32.Dispose(); }
public void CopyConstructor_Correct() { var ims = CreateDefaultStack(); ims.SetAll(33.37f); var copy = new ImageStack32F(ims); Assert.IsFalse(ims.ImageData == copy.ImageData, "Source and its copy point to the same buffer"); float* sourceStart = ims.ImageData; float* copyStart = copy.ImageData; for (long i = 0; i < ims.ImageNB / 4; i++) Assert.AreEqual(sourceStart[i], copyStart[i], sourceStart[i] / 1000, "Found non-matching pixel"); ims.Dispose(); copy.Dispose(); }
public void RangeCheck_OnPixelAccess() { var ims = new ImageStack32F(5, 5, 5, 5, ImageStack.SliceOrders.ZBeforeT); var p = ims[5, 0, 0, 0]; ims.Dispose(); }