/// <summary> /// Converts an unmanaged image to an complex image and uses zero padding if required. /// </summary> /// <param name="image"></param> /// <returns></returns> public static ComplexImage ToComplexImage(this UnmanagedImage image) { var result = new ComplexImage(image.Width, image.Height); ToComplexImageZeroPad(image, result); return(result); }
public static void CheckComparable([NotNull] ComplexImage image1, [NotNull] ComplexImage image2) { if (image1.Width != image2.Width || image1.Height != image2.Height) { throw new DimensionMismatchException(); } }
public static void Draw(this UnmanagedImage thisImage, ComplexImage srcImage, Rectangle clip) => Draw( thisImage, srcImage, clip.X, clip.Y, clip.Width, clip.Height );
/// <summary> /// Draws the absolut part of an complex image to the destination image. /// </summary> /// <param name="thisImage"></param> /// <param name="srcImage"></param> public static void Draw(this UnmanagedImage thisImage, ComplexImage srcImage) { var pb = Preferences.Supported.CheckAndGetPixelBytes(thisImage); var w = Math.Min(srcImage.Width, thisImage.Width); var h = Math.Min(srcImage.Height, thisImage.Height); DoDraw(thisImage.ImageData, thisImage.Stride, pb, srcImage, 0, w, h); }
/// <summary> /// Draws the real part of an complex image to the destination image. /// </summary> /// <param name="thisImage"></param> /// <param name="srcImage"></param> public static unsafe void DrawReals(this UnmanagedImage thisImage, ComplexImage srcImage) { const float norm = (float)byte.MaxValue / ComplexImage.MAX_MAGNITUDE; var pb = Preferences.Supported.CheckAndGetPixelBytes(thisImage); var w = Math.Min(srcImage.Width, thisImage.Width); var h = Math.Min(srcImage.Height, thisImage.Height); var dstPtr = (byte *)thisImage.ImageData; var dstStride = thisImage.Stride; var dstPadd = dstStride - (w * pb); var c0 = srcImage.Channel0; var c1 = srcImage.Channel1; var c2 = srcImage.Channel2; switch (pb) { case 3: for (int i0 = 0, n = srcImage.Width * h; i0 < n; i0 += srcImage.Width, dstPtr += dstPadd) { for (int i = i0, m = i0 + w; i < m; i++, dstPtr += pb) { dstPtr[RGB.R] = (c0[i].Real * norm).ClampToByte(); dstPtr[RGB.G] = (c1[i].Real * norm).ClampToByte(); dstPtr[RGB.B] = (c2[i].Real * norm).ClampToByte(); } } break; case 4: for (int i0 = 0, n = srcImage.Width * h; i0 < n; i0 += srcImage.Width, dstPtr += dstPadd) { for (int i = i0, m = i0 + w; i < m; i++, dstPtr += pb) { dstPtr[RGB.R] = (c0[i].Real * norm).ClampToByte(); dstPtr[RGB.G] = (c1[i].Real * norm).ClampToByte(); dstPtr[RGB.B] = (c2[i].Real * norm).ClampToByte(); dstPtr[RGB.A] = byte.MaxValue; } } break; //default: already caught at the beginning } }
/// <summary> /// Converts an unmanaged image to an complex image and uses zero padding if required. /// </summary> /// <param name="image"></param> /// <param name="dstWidth"></param> /// <param name="dstHeight"></param> /// <returns></returns> public static ComplexImage ToComplexImageZeroPad(this UnmanagedImage image, int dstWidth, int dstHeight) { if (dstWidth < 1 || dstHeight < 1) { throw new ArgumentOutOfRangeException(dstWidth < 1 ? nameof(dstWidth) : nameof(dstHeight)); } var result = new ComplexImage(dstWidth, dstHeight); ToComplexImageZeroPad(image, result); return(result); }
/// <summary> /// Draws the absolute part of an complex image to the destination image. /// </summary> /// <param name="dstPtr">pointer of the destination image, points to the first byte to draw.</param> /// <param name="stride">stride of the destination image</param> /// <param name="pixelBytes">number of byte per pixel of the destination image </param> /// <param name="srcImage">source image</param> /// <param name="i">start pixel of the source image</param> /// <param name="width">width to draw</param> /// <param name="height">height to draw</param> private static unsafe void DoDraw(IntPtr dstPtr, int stride, int pixelBytes, ComplexImage srcImage, int i, int width, int height) { const float norm = (float)byte.MaxValue / ComplexImage.MAX_MAGNITUDE; var srcPadd = ((i % srcImage.Width) + srcImage.Width) - width; // sum left and right padding var dstPadd = stride - (width * pixelBytes); var d = (byte *)dstPtr; var c0 = srcImage.Channel0; var c1 = srcImage.Channel1; var c2 = srcImage.Channel2; switch (pixelBytes) { case 3: for (var iToB = i + (height * srcImage.Width); i < iToB; i += srcPadd, d += dstPadd) { for (var iToL = i + width; i < iToL; i++, d += pixelBytes) { d[RGB.R] = (c0[i].Magnitude * norm).ClampToByte(); d[RGB.G] = (c1[i].Magnitude * norm).ClampToByte(); d[RGB.B] = (c2[i].Magnitude * norm).ClampToByte(); } } break; case 4: for (var iToB = i + (height * srcImage.Width); i < iToB; i += srcPadd, d += dstPadd) { for (var iToL = i + width; i < iToL; i++, d += pixelBytes) { d[RGB.R] = (c0[i].Magnitude * norm).ClampToByte(); d[RGB.G] = (c1[i].Magnitude * norm).ClampToByte(); d[RGB.B] = (c2[i].Magnitude * norm).ClampToByte(); d[RGB.A] = byte.MaxValue; } } break; //default: already caught at the beginning } }
public void CopyTo(ComplexImage destination) { if (Width != destination.Width || Height != destination.Height) { throw new ArgumentException( @"different " + (Width != destination.Width ? "width" : "height"), nameof(destination) ); } var n = Width * Height; Array.Copy(Channel0, destination.Channel0, n); Array.Copy(Channel1, destination.Channel1, n); Array.Copy(Channel2, destination.Channel2, n); }
/// <summary> /// Draws the absolut part of an complex image to the destination image using the clipping bounds (x, y, width, height). /// </summary> /// <param name="thisImage"></param> /// <param name="srcImage"></param> /// <param name="x">x of clip</param> /// <param name="y">y of clip</param> /// <param name="width">width of clip</param> /// <param name="height">height of clip</param> public static void Draw(this UnmanagedImage thisImage, ComplexImage srcImage, int x, int y, int width, int height) { //width,height required because of zero padding Debug.Assert(srcImage.Width >= width); Debug.Assert(srcImage.Height >= height); var pb = Preferences.Supported.CheckAndGetPixelBytes(thisImage); var dstPtr = thisImage.ImageData; //clipping if (x + width > thisImage.Width) { width = thisImage.Width - x; // right clip } if (y + height > thisImage.Height) { height = thisImage.Height - y; // bottom clip } if (x <= 0) { x = -x; // left clip } else { dstPtr += x * pb; x = 0; } if (y <= 0) { y = -y; // left clip } else { dstPtr += y * thisImage.Stride; y = 0; } DoDraw(dstPtr, thisImage.Stride, pb, srcImage, (y * srcImage.Width) + x, width, height); }
public static unsafe void ToComplexImageZeroPad(this UnmanagedImage image, [NotNull] ComplexImage outImage) { const float norm = ComplexImage.MAX_MAGNITUDE / (float)byte.MaxValue; //TODO: zero padding var wDst = outImage.Width; var w = Math.Min(image.Width, wDst); var h = Math.Min(image.Height, outImage.Height); var pb = ComplexImage.Compatible.CheckAndGetPixelBytes(image); var srcPadd = image.Stride - (w * pb); var dt = (byte *)image.ImageData; var c0Data = outImage.Channel0; var c1Data = outImage.Channel1; var c2Data = outImage.Channel2; for (var i0 = 0; i0 < wDst * h; i0 += wDst, dt += srcPadd) { for (var i = i0; i < i0 + w; i++, dt += pb) { c0Data[i] = dt[RGB.R] * norm; c1Data[i] = dt[RGB.G] * norm; c2Data[i] = dt[RGB.B] * norm; } } }
public ComplexImage(ComplexImage image) { C0 = new Complex2D(image.C0); C1 = new Complex2D(image.C1); C2 = new Complex2D(image.C2); }
public void ForEachColumn(Action <Complex[]> action, ComplexImage output) { C0.ForEachColumn(action, output.C0); C1.ForEachColumn(action, output.C1); C2.ForEachColumn(action, output.C2); }
public static unsafe void ToComplexImageSymmetric(this UnmanagedImage image, [NotNull] ComplexImage outImage) { const float norm = ComplexImage.MAX_MAGNITUDE / (float)byte.MaxValue; //TODO: zero padding var wDst = outImage.Width; var w = Math.Min(image.Width, wDst); var h = Math.Min(image.Height, outImage.Height); var pb = ComplexImage.Compatible.CheckAndGetPixelBytes(image); var srcPadd = image.Stride - (w * pb); var dt = (byte *)image.ImageData; var c0Data = outImage.Channel0; var c1Data = outImage.Channel1; var c2Data = outImage.Channel2; var w2 = w * 2; var wr = wDst % w2; var i = 0; for (int i0 = 0, i0To = wDst * h; i0 < i0To; i0 += wDst, dt += srcPadd) { for (; i < i0 + w; i++, dt += pb) { c0Data[i] = dt[RGB.R] * norm; c1Data[i] = dt[RGB.G] * norm; c2Data[i] = dt[RGB.B] * norm; } for (var j = i - 1; j < wDst; i++, j--) { c0Data[i] = c0Data[j]; c1Data[i] = c1Data[j]; c2Data[i] = c2Data[j]; } for (var iTo = (i0 + wDst) - w2; i + w2 < iTo; i += w2) { Array.Copy(c0Data, i0, c0Data, i, w2); Array.Copy(c1Data, i0, c1Data, i, w2); Array.Copy(c2Data, i0, c2Data, i, w2); } if (wr <= 0) { continue; } Array.Copy(c0Data, i0, c0Data, i, wr); Array.Copy(c1Data, i0, c1Data, i, wr); Array.Copy(c2Data, i0, c2Data, i, wr); } var lDst = wDst * outImage.Height; var l = h * wDst; var l2 = l * 2; for (var j = i - wDst; i < lDst; i += wDst, j -= wDst) { Array.Copy(c0Data, j, c0Data, i, wr); Array.Copy(c1Data, j, c1Data, i, wr); Array.Copy(c2Data, j, c2Data, i, wr); } var lr = lDst % l2; for (var iTo = i - l2; i < iTo; i += l2) { Array.Copy(c0Data, 0, c0Data, i, l2); Array.Copy(c1Data, 0, c1Data, i, l2); Array.Copy(c2Data, 0, c2Data, i, l2); } if (lr <= 0) { return; } Array.Copy(c0Data, 0, c0Data, i, lr); Array.Copy(c1Data, 0, c1Data, i, lr); Array.Copy(c2Data, 0, c2Data, i, lr); }