Esempio n. 1
0
        /// <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);
        }
Esempio n. 2
0
        /// <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);
        }
Esempio n. 3
0
        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));
            }
        }
Esempio n. 4
0
        /// <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);
        }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        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);
        }
Esempio n. 7
0
        /// <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);
        }
Esempio n. 8
0
        /// <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);
        }
Esempio n. 9
0
        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);
        }
Esempio n. 10
0
        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);
        }
Esempio n. 11
0
        /// <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);
            }
        }
Esempio n. 12
0
        /// <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);
        }
Esempio n. 13
0
        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));
            }
        }
Esempio n. 14
0
        /// <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
        }