/// <summary> /// Rotates this <see cref="Image"/> 90 degrees clockwise. /// </summary> /// <param name="dst">The destination <see cref="Image"/>. Can be <b>null</b>.</param> /// <returns> /// The destination <see cref="Image"/>. /// </returns> /// <exception cref="NotSupportedException"> /// <para>The depth of this <see cref="Image"/> is neither 1 nor 8 nor 24 nor 32 bits per pixel.</para> /// </exception> /// <remarks> /// <para>If <paramref name="dst"/> is <b>null</b> the method creates new destination <see cref="Image"/> with dimensions of this <see cref="Image"/>.</para> /// <para>If <paramref name="dst"/> equals this <see cref="Image"/>, the operation is performed in-place.</para> /// <para>Conversely, the <paramref name="dst"/> is reallocated to the dimensions of this <see cref="Image"/>.</para> /// </remarks> public Image Rotate270(Image dst) { if (this.BitsPerPixel != 1 && this.BitsPerPixel != 8 && this.BitsPerPixel != 24 && this.BitsPerPixel != 32) { throw new NotSupportedException(string.Format( CultureInfo.InvariantCulture, Properties.Resources.E_UnsupportedDepth, this.BitsPerPixel)); } bool inplace = dst == this; dst = this.CreateTemplate(dst, this.Height, this.Width, this.BitsPerPixel); IPP.Execute(() => { return(NativeMethods.rotate270( this.BitsPerPixel, this.Width, this.Height, this.Bits, this.Stride8, dst.Bits, dst.Stride8)); }); if (inplace) { this.Attach(dst); return(this); } return(dst); }
/// <summary> /// Converts this <see cref="ImageF"/> to a color 32-bit <see cref="Image"/>. /// </summary> /// <param name="dst">The destination <see cref="Image"/>. Can be <b>null</b>.</param> /// <param name="convertAlphaChannel">Determines whether this <see cref="ImageF"/> contains alpha channel.</param> /// <param name="rounding">The rounding mode.</param> /// <returns> /// The destination <see cref="Image"/>. /// </returns> /// <remarks> /// <para>If <paramref name="dst"/> is <b>null</b> the method creates new destination <see cref="Image"/> with dimensions of this <see cref="Image"/>.</para> /// <para>If <paramref name="dst"/> equals this <see cref="Image"/>, the operation is performed in-place.</para> /// <para>Conversely, the <paramref name="dst"/> is reallocated to the dimensions of this <see cref="Image"/>.</para> /// </remarks> public Image ConvertTo32(Image dst, bool convertAlphaChannel, MidpointRounding rounding) { // create destination if (dst == null) { dst = new Image(this.Width, this.Height, 32, this.HorizontalResolution, this.VerticalResolution, this.Transform); } else { dst.Reallocate(this.Width, this.Height, 32, this.HorizontalResolution, this.VerticalResolution, this.Transform); } IPP.Execute(() => { unsafe { fixed(ulong *bitsdst = dst.Bits) { return(NativeMethods._convert32fto32( 0, 0, this.Width, this.Height, this.Bits, this.Stride, (byte *)bitsdst, dst.Stride8, convertAlphaChannel, (int)rounding)); } } }); return(dst); }
public void MinMax(int x, int y, int width, int height, out uint min, out uint max) { this.ValidateArea(x, y, width, height); switch (this.BitsPerPixel) { case 1: if (NativeMethods.is_all_black(1, x, y, width, height, this.Bits, this.Stride)) { min = max = 1u; } else if (NativeMethods.is_all_white(1, x, y, width, height, this.Bits, this.Stride)) { min = max = 0u; } else { min = 0u; max = 1u; } break; case 8: case 16: uint localmin = 0; uint localmax = 0; IPP.Execute(() => { unsafe { fixed(ulong *bits = this.Bits) { return(NativeMethods.minmax( this.BitsPerPixel, x, y, width, height, (byte *)bits, this.Stride8, out localmin, out localmax)); } } }); min = localmin; max = localmax; break; default: throw new NotSupportedException(string.Format( CultureInfo.InvariantCulture, Properties.Resources.E_UnsupportedDepth, this.BitsPerPixel)); } }
/// <summary> /// Detects straight lines in this <see cref="Image"/>. /// </summary> /// <param name="maxLineCount">Minimum number of lines to detect.</param> /// <param name="threshold">Minimum number of points that are required to detect the line.</param> /// <param name="minLineLength">Minimum length of the line.</param> /// <param name="maxLineGap">Maximum length of the gap between lines.</param> /// <param name="deltaRho">Step of radial discretization.</param> /// <param name="deltaTheta">Step of angular discretization.</param> /// <returns> /// The detected lines. /// </returns> /// <exception cref="ArgumentException"> /// <para>The depth of this <see cref="Image"/> is not 8 bit per pixel.</para> /// </exception> public Line[] HoughProbLine(int maxLineCount, int threshold, int minLineLength, int maxLineGap, float deltaRho, float deltaTheta) { if (this.BitsPerPixel != 8) { throw new ArgumentException(Properties.Resources.E_UnsupportedDepth_8bpp); } int[] lines = new int[4 * maxLineCount]; int lineCount = 0; IPP.Execute(() => { unsafe { fixed(ulong *bits = this.Bits) { return(NativeMethods.houghprobline( 0, 0, this.Width, this.Height, (byte *)bits, this.Stride8, maxLineCount, threshold, minLineLength, maxLineGap, deltaRho, deltaTheta, out lineCount, lines)); } } }); // convert answer Line[] result = new Line[lineCount]; for (int i = 0, j = 0; i < lineCount; i++, j += 4) { result[i].X1 = lines[j]; result[i].Y1 = lines[j + 1]; result[i].X2 = lines[j + 2]; result[i].Y2 = lines[j + 3]; } return(result); }
public Image ColorKey(Image dst, Image background, uint color) { if (background == null) { throw new ArgumentNullException(nameof(background)); } if (this.BitsPerPixel != 8 && this.BitsPerPixel != 24 && this.BitsPerPixel != 32) { throw new NotSupportedException(string.Format( CultureInfo.InvariantCulture, Properties.Resources.E_UnsupportedDepth, this.BitsPerPixel)); } bool inplace = dst == this; dst = this.CreateTemplate(dst, this.BitsPerPixel); IPP.Execute(() => { return(NativeMethods.colorkey( this.BitsPerPixel, 0, 0, this.Width, this.Height, this.Bits, this.Stride8, background.Bits, background.Stride8, dst.Bits, dst.Stride8, color)); }); if (inplace) { this.Attach(dst); return(this); } return(dst); }
public byte Otsu(int x, int y, int width, int height) { this.ValidateArea(x, y, width, height); byte threshold = 0; IPP.Execute(() => { unsafe { fixed(ulong *bits = this.Bits) { return(NativeMethods.threshold_otsu(x, y, width, height, (byte *)bits, this.Stride8, out threshold)); } } }); return(threshold); }
/// <summary> /// Detects straight lines in this <see cref="Image"/>. /// </summary> /// <param name="maxLineCount">Minimum number of lines to detect.</param> /// <param name="threshold">Minimum number of points that are required to detect the line.</param> /// <param name="deltaRho">Step of radial discretization.</param> /// <param name="deltaTheta">Step of angular discretization.</param> /// <returns> /// The detected lines. /// </returns> /// <exception cref="ArgumentException"> /// <para>The depth of this <see cref="Image"/> is not 8 bit per pixel.</para> /// </exception> public PointPolarF[] HoughLine(int maxLineCount, int threshold, float deltaRho, float deltaTheta) { if (this.BitsPerPixel != 8) { throw new ArgumentException(Properties.Resources.E_UnsupportedDepth_8bpp); } float[] lines = new float[2 * maxLineCount]; int lineCount = 0; IPP.Execute(() => { unsafe { fixed(ulong *bits = this.Bits) { return(NativeMethods.houghline( 0, 0, this.Width, this.Height, (byte *)bits, this.Stride8, maxLineCount, threshold, deltaRho, deltaTheta, out lineCount, lines)); } } }); // convert answer PointPolarF[] result = new PointPolarF[lineCount]; for (int i = 0, j = 0; i < lineCount; i++, j += 2) { result[i].Rho = lines[j]; result[i].Theta = lines[j + 1]; } return(result); }
/// <summary> /// Suppresses the lines on the <see cref="Image"/>. /// </summary> /// <returns> /// A new <see cref="Image"/> with lines suppressed. /// </returns> /// <exception cref="NotSupportedException"> /// The <see cref="Image{T}.BitsPerPixel"/> is not 1 or 8. /// </exception> public Image SuppressLines() { if (this.BitsPerPixel != 1 && this.BitsPerPixel != 8) { throw new NotSupportedException( string.Format(CultureInfo.InvariantCulture, Properties.Resources.E_UnsupportedDepth, this.BitsPerPixel)); } // IPP does not support 1bpp images - convert to 8bpp Image src; bool convert1bpp = false; if (this.BitsPerPixel == 1) { src = this.Convert1To8(null); convert1bpp = true; } else { src = this; } Image dst = src.Clone(false); IPP.Execute(() => { return(NativeMethods.supresslines( src.Width, src.Height, src.Stride, src.Bits, dst.Bits)); }); // convert back to 1bpp if (convert1bpp) { dst.Convert8To1(dst, 1); } return(dst); }
public Image Canny(Image dst, float thresholdLow, float thresholdHigh, BorderType borderType, uint borderValue) { if (this.BitsPerPixel != 8) { throw new NotSupportedException(Properties.Resources.E_UnsupportedDepth_8bpp); } bool inplace = dst == this; dst = this.CreateTemplate(dst, this.BitsPerPixel); IPP.Execute(() => { unsafe { fixed(ulong *bitssrc = this.Bits, bitsdst = dst.Bits) { return(NativeMethods.canny( 0, 0, this.Width, this.Height, (byte *)bitssrc, this.Stride8, (byte *)bitsdst, dst.Stride8, thresholdLow, thresholdHigh, borderType, borderValue)); } } }); if (inplace) { this.Attach(dst); return(this); } return(dst); }
public Image ThresholdLTGT(Image dst, int x, int y, int width, int height, uint thresholdLT, uint valueLT, uint thresholdGT, uint valueGT) { this.ValidateArea(x, y, width, height); if (this.BitsPerPixel != 8 && this.BitsPerPixel != 24 && this.BitsPerPixel != 32) { throw new NotSupportedException(string.Format( CultureInfo.InvariantCulture, Properties.Resources.E_UnsupportedDepth, this.BitsPerPixel)); } dst = this.Copy(dst, false); IPP.Execute(() => { unsafe { fixed(ulong *bitssrc = this.Bits, bitsdst = dst.Bits) { return(NativeMethods.threshold_ltgt_8bpp( this.BitsPerPixel, x, y, width, height, (byte *)bitssrc, this.Stride8, (byte *)bitsdst, dst.Stride8, thresholdLT, valueLT, thresholdGT, valueGT)); } } }); return(dst); }
/// <summary> /// Mirrors this <see cref="Image"/> about the specified axis. /// </summary> /// <param name="dst">The destination <see cref="Image"/>. Can be <b>null</b>.</param> /// <param name="flip">The axis to flip the image about.</param> /// <returns> /// The destination <see cref="Image"/>. /// </returns> /// <exception cref="NotSupportedException"> /// <para>The depth of this <see cref="Image"/> is neither 8 nor 24 nor 32 bits per pixel.</para> /// </exception> /// <remarks> /// <para>If <paramref name="dst"/> is <b>null</b> the method creates new destination <see cref="Image"/> with dimensions of this <see cref="Image"/>.</para> /// <para>If <paramref name="dst"/> equals this <see cref="Image"/>, the operation is performed in-place.</para> /// <para>Conversely, the <paramref name="dst"/> is reallocated to the dimensions of this <see cref="Image"/>.</para> /// </remarks> public Image Flip(Image dst, FlipAxis flip) { if (this.BitsPerPixel != 8 && this.BitsPerPixel != 24 && this.BitsPerPixel != 32) { throw new NotSupportedException(string.Format( CultureInfo.InvariantCulture, Properties.Resources.E_UnsupportedDepth, this.BitsPerPixel)); } if (flip == Imaging.FlipAxis.None) { return(this.Copy(dst, true)); } else { dst = this.Copy(dst, false); IPP.Execute(() => { return(NativeMethods.mirror( this.BitsPerPixel, 0, 0, this.Width, this.Height, this.Bits, this.Stride8, dst == this ? null : dst.Bits, dst.Stride8, flip)); }); return(dst); } }
/// <summary> /// Create a <see cref="IntegralImage"/> from the specified <see cref="Image"/>. /// </summary> /// <param name="image">The source <see cref="Image"/>.</param> /// <returns> /// The <see cref="IntegralImage"/> this method creates. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="image"/> is <b>null</b>. /// </exception> /// <remarks> /// <para>The size of resulting integral image is (<paramref name="image"/>.width + 1) * (<paramref name="image"/>.height + 1).</para> /// </remarks> public static IntegralImage FromImage(Image image) { if (image == null) { throw new ArgumentNullException(nameof(image)); } int bitsPerPixel = image.BitsPerPixel; if (image.BitsPerPixel > 16) { throw new NotSupportedException(); } int width = image.Width; int height = image.Height; IntegralImage dst = new IntegralImage(width + 1, height + 1); #if false // IPP version is approximately twice faster unsafe { fixed(ulong *bitssrc = image.Bits) { fixed(int *bitsdst = dst.Bits) { byte *ptrsrc = (byte *)bitssrc; uint *ptrdst = (uint *)bitsdst; int stridesrc = image.Stride8; int stridedst = dst.Width; ptrdst += stridedst; for (int iy = 0; iy < height; iy++, ptrsrc += stridesrc, ptrdst += stridedst) { // sum current line Vectors.CumulativeSum(width, ptrsrc, ptrdst + 1); // sum with previous line if (iy > 0) { Vectors.Add(stridedst, ptrdst - stridedst, ptrdst); } } } } } #else IPP.Execute(() => { unsafe { fixed(ulong *bitssrc = image.Bits) { fixed(int *bitsdst = dst.Bits) { return(NativeMethods.integral32s( width, height, (byte *)bitssrc, image.Stride8, bitsdst, dst.Width, 0)); } } } }); #endif return(dst); }
public Image Affine(Image dst, System.Windows.Media.Matrix matrix, BorderType borderType, uint borderValue) { const float Eps = 1e-8f; if (matrix.IsIdentity) { return(this.Copy(dst, true)); } // IPP does not support 1bpp images - convert to 8bpp Image src; bool convert1bpp = false; if (this.BitsPerPixel == 1) { src = this.Convert1To8(null); borderValue = borderValue != 0 ? 0u : 255u; convert1bpp = true; } else { src = this; } // calculate new image size and position PointD tr = TransformPoint(src.Width, 0); PointD br = TransformPoint(src.Width, src.Height); PointD bl = TransformPoint(0, src.Height); double x1dst = Core.MinMax.Min(bl.X, tr.X, br.X, 0.0); double x2dst = Core.MinMax.Max(bl.X, tr.X, br.X, 0.0); double y1dst = Core.MinMax.Min(bl.Y, tr.Y, br.Y, 0.0); double y2dst = Core.MinMax.Max(bl.Y, tr.Y, br.Y, 0.0); // translate matrix so the transformed image fits into new frame matrix.OffsetX = -Core.MinMax.Min(x1dst, x2dst); matrix.OffsetY = -Core.MinMax.Min(y1dst, y2dst); // note: add epsilon to avoid rounding problems int widthdst = (int)Math.Floor(x2dst - x1dst + Eps); int heightdst = (int)Math.Floor(y2dst - y1dst + Eps); bool inplace = dst == this; dst = src.CreateTemplate(dst, widthdst, heightdst, src.BitsPerPixel); IPP.Execute(() => { return(NativeMethods.affine( src.BitsPerPixel, src.Width, src.Height, src.Stride, src.Bits, dst.Width, dst.Height, dst.Stride, dst.Bits, matrix.M11, matrix.M12, matrix.OffsetX, matrix.M21, matrix.M22, matrix.OffsetY, (int)borderType, borderValue)); }); dst.AppendTransform(new MatrixTransform(matrix)); // convert back to 1bpp if (convert1bpp) { dst.Convert8To1(dst, 1); /*using (Pix pixs = transformedImage.CreatePix()) * { * using (Pix pixd = pixs.pixOtsu(false)) * { * if (pixd != null) * { * return pixd.CreateImage(transformedImage.HorizontalResolution, transformedImage.VerticalResolution); * } * } * }*/ } if (inplace) { this.Attach(dst); return(this); } return(dst); PointD TransformPoint(int ptx, int pty) { return(new PointD( (matrix.M11 * ptx) + (matrix.M12 * pty) + matrix.OffsetX, (matrix.M21 * ptx) + (matrix.M22 * pty) + matrix.OffsetY)); } }
/// <summary> /// Scales the <see cref="Image"/> vertically and horizontally without changing its resolution. /// </summary> /// <param name="dst">The destination <see cref="Image"/>. Can be <b>null</b>.</param> /// <param name="width">The desired width of the image, in pixels.</param> /// <param name="height">The desired height of the image, in pixels.</param> /// <param name="options">The scaling options.</param> /// <returns> /// The destination <see cref="Image"/>. /// </returns> public Image ScaleToSize(Image dst, int width, int height, ScalingOptions options) { if (width == this.Width && height == this.Height) { return(this.Copy(dst, true)); } if (width <= 0) { throw new ArgumentException(Properties.Resources.E_InvalidWidth, nameof(width)); } if (height <= 0) { throw new ArgumentException(Properties.Resources.E_InvalidHeight, nameof(height)); } System.Windows.Media.Matrix matrix = System.Windows.Media.Matrix.Identity; matrix.Scale((double)width / this.Width, (double)height / this.Height); #if false dst = this.Affine(dst, matrix, BorderType.BorderConst, this.WhiteColor); Debug.Assert(width == dst.Width && height == dst.Height, "Image dimensions are wrong."); return(dst); #else // IPP does not support 1bpp images - convert to 8bpp Image src; bool convert1bpp = false; if (this.BitsPerPixel == 1) { src = this.Convert1To8(null); convert1bpp = true; } else { src = this; } bool inplace = dst == this; dst = src.CreateTemplate(dst, width, height, src.BitsPerPixel); IPP.Execute(() => { return(NativeMethods.resize( src.BitsPerPixel, src.Width, src.Height, src.Bits, src.Stride8, dst.Width, dst.Height, dst.Bits, dst.Stride8, options.InterpolationType, options.Antialiasing, options.ValueB, options.ValueC, options.Lobes, BorderType.BorderConst, src.WhiteColor)); }); dst.AppendTransform(new MatrixTransform(matrix)); // convert back to 1bpp if (convert1bpp) { dst.Convert8To1(dst, 1); } if (inplace) { this.Attach(dst); return(this); } return(dst); #endif }
public static void Execute(Func <int> action) { int retCode = action(); IPP.ProcessErrorCode(retCode); }