/// <summary>Compute distance maps</summary>
 public void ComputeDistanceMaps()
 {
     //for (int j=0;j<_strokes.Count;j++)
     Parallel.For(0, _strokes.Count, j =>
     {
         ColorStroke cs = _strokes[j];
         if (cs.DistanceMap == null)
         {
             cs.DistanceMap = GetPixelDistances(cs.StrokeCoords, _edges, ImageWidth, ImageHeight, MAXITER);
         }
     });
 }
            /// <summary>Clones this object</summary>
            public ColorStroke Clone()
            {
                List <int[]> newc = new List <int[]>();

                foreach (int[] k in this.StrokeCoords)
                {
                    newc.Add(new int[] { k[0], k[1] });
                }

                ColorStroke cs = new ColorStroke(newc, this.StrokeColor);

                if (DistanceMap != null)
                {
                    cs.DistanceMap = (float[])this.DistanceMap.Clone();
                }
                return(cs);
            }
예제 #3
0
        /// <summary>
        /// Sirve como la función hash predeterminada.
        /// </summary>
        /// <returns>Código hash para el objeto actual.</returns>
        public override int GetHashCode()
        {
            int hash  = 17; // Un número primo
            int prime = 31; // Otro número primo.

            hash = hash * prime + MetadataItemName.GetHashCode();
            hash = hash * prime + PdfPageN.GetHashCode();
            hash = hash * prime + IsLastPage.GetHashCode();
            hash = hash * prime + ((PdfRectangle == null) ? 0 : PdfRectangle.GetHashCode());
            hash = hash * prime + (RegexPattern ?? "").GetHashCode();
            hash = hash * prime + Position.GetHashCode();
            hash = hash * prime + (SourceTypeName ?? "").GetHashCode();

            hash = hash * prime + ((ColorFill == null) ? 0 : ColorFill.GetHashCode());
            hash = hash * prime + ((ColorStroke == null) ? 0 : ColorStroke.GetHashCode());
            hash = hash * prime + ((FontSize == null) ? 0 : FontSize.GetHashCode());
            hash = hash * prime + ((FontType == null) ? 0 : FontType.GetHashCode());


            return(hash);
        }
        /// <summary>Save strokes to a file</summary>
        /// <param name="curFile">File to save to</param>
        public void SaveStrokes(string curFile)
        {
            if (curFile == "")
            {
                return;
            }

            using (StreamWriter sw = new StreamWriter(curFile + ".strokes"))
            {
                for (int i = 0; i < _strokes.Count; i++)
                {
                    ColorStroke cs = _strokes[i];

                    sw.WriteLine("Color " + cs.StrokeColor.R.ToString() + " " + cs.StrokeColor.G.ToString() + " " + cs.StrokeColor.B.ToString() + " " + cs.StrokeCoords.Count);
                    foreach (int[] p in cs.StrokeCoords)
                    {
                        sw.WriteLine(p[0] + " " + p[1]);
                    }
                }
            }
        }
        /// <summary>Retrieves stroke closest to XY position</summary>
        public ColorStroke getClosestStroke(int x, int y, out float dist)
        {
            if (x < 0 || y < 0 || x >= ImageWidth || y >= ImageHeight || _strokes.Count == 0)
            {
                dist = float.PositiveInfinity;
                return(null);
            }

            ColorStroke closest      = _strokes[0];
            float       smallestDist = float.MaxValue;

            for (int k = 0; k < _strokes.Count; k++)
            {
                ColorStroke cs = _strokes[k];

                if (cs.DistanceMap != null && smallestDist > cs.DistanceMap[x + ImageWidth * y])
                {
                    smallestDist = cs.DistanceMap[x + ImageWidth * y];
                    closest      = cs;
                }
            }
            dist = smallestDist;
            return(closest);
        }
예제 #6
0
        /// <summary>
        /// Determina si el objeto especificado es igual al objeto actual.
        /// </summary>
        /// <param name="obj">Objeto que se va a comparar con el objeto actual.</param>
        /// <returns>Es true si el objeto especificado es igual al objeto actual;
        /// en caso contrario, es false.</returns>
        public override bool Equals(object obj)
        {
            PdfTagPattern input = (obj as PdfTagPattern);

            if (input == null)
            {
                throw new ArgumentException("Parámetro de tipo incorrecto.");
            }

            bool equalsTextString = false;
            bool equalsRectangle  = false;

            if (input.SourceTypeName.Equals("TextStringInfos")) // Comprobamos si las propiedades de los textString coinciden
            {
                if (FontSize != null && input.FontSize != null &&
                    ColorFill != null && input.ColorFill != null &&
                    ColorStroke != null && input.ColorStroke != null &&
                    FontType != null && input.FontType != null &&
                    TsType != null && input.TsType != null)
                {
                    if (ColorFill.Equals(input.ColorFill) &&
                        ColorStroke.Equals(input.ColorStroke) &&
                        FontSize.Equals(input.FontSize) &&
                        FontType.Equals(input.FontType) &&
                        TsType.Equals(input.TsType))
                    {
                        if ((TsType.Equals("X") || TsType.Equals("Y")) &&
                            TsCoordinate.Equals(input.TsCoordinate))
                        {
                            equalsTextString = true;
                        }
                        else if (TsType.Equals("NA"))
                        {
                            equalsTextString = true;
                        }
                    }
                }
            }
            else
            {
                equalsTextString = true;
            }

            if (PdfRectangle != null && input.PdfRectangle != null) // Comprobamos si el rectángulo coincide   && FontType==null
            {
                equalsRectangle = PdfRectangle.Equals(input.PdfRectangle);
            }
            else
            {
                equalsRectangle = true;
            }


            return((MetadataItemName == input.MetadataItemName &&
                    PdfPageN == input.PdfPageN &&
                    IsLastPage == input.IsLastPage &&
                    equalsRectangle &&
                    RegexPattern == input.RegexPattern &&
                    Position == input.Position &&
                    SourceTypeName == input.SourceTypeName) &&
                   equalsTextString);
        }
        /// <summary>Retrieve color strokes from an image. Remove color strokes from image.</summary>
        /// <param name="bmpSource">Source bitmap</param>
        /// <param name="colorDifThresh">Color difference threshold to consider as not Black and White</param>
        /// <returns></returns>
        public static List <ColorStroke> GetColorStrokes(Bitmap bmpSource, int colorDifThresh)
        {
            //Step 1: identify regions in the image that are not B&W

            //{X, Y, R,G,B} of pixel
            List <int[]> colorPixels = new List <int[]>();

            int        W             = bmpSource.Width;
            BitmapData bitmapData    = bmpSource.LockBits(new Rectangle(0, 0, bmpSource.Width, bmpSource.Height), ImageLockMode.ReadWrite, bmpSource.PixelFormat);
            int        bytesPerPixel = Bitmap.GetPixelFormatSize(bmpSource.PixelFormat) / 8;
            int        byteCount     = bitmapData.Stride * bmpSource.Height;

            byte[] pixels        = new byte[byteCount];
            IntPtr ptrFirstPixel = bitmapData.Scan0;

            Marshal.Copy(ptrFirstPixel, pixels, 0, pixels.Length);
            int heightInPixels = bitmapData.Height;
            int widthInBytes   = bitmapData.Width * bytesPerPixel;

            int xx, yy;

            yy = 0;

            for (int y = 0; y < heightInPixels; y++)
            {
                int currentLine = y * bitmapData.Stride;
                xx = 0;
                for (int x = 0; x < widthInBytes; x = x + bytesPerPixel)
                {
                    int vB = pixels[currentLine + x];
                    int vG = pixels[currentLine + x + 1];
                    int vR = pixels[currentLine + x + 2];

                    if (Math.Abs(vR - vG) > colorDifThresh || Math.Abs(vR - vB) > colorDifThresh || Math.Abs(vB - vG) > colorDifThresh)
                    {
                        //deserves attention
                        colorPixels.Add(new int[] { xx, yy, vR, vG, vB });

                        pixels[currentLine + x]     = 255;
                        pixels[currentLine + x + 1] = 255;
                        pixels[currentLine + x + 2] = 255;
                    }



                    xx++;
                }
                yy++;
            }

            // copy modified bytes back
            Marshal.Copy(pixels, 0, ptrFirstPixel, pixels.Length);
            bmpSource.UnlockBits(bitmapData);

            List <ColorStroke> ans = new List <ColorStroke>();

            //Step 2: group regions correctly
            while (colorPixels.Count > 0)
            {
                List <int[]> regionPixels = new List <int[]>();

                regionPixels.Add(colorPixels[colorPixels.Count - 1]);
                colorPixels.RemoveAt(colorPixels.Count - 1);

                bool foundCandidates = true;
                while (foundCandidates)
                {
                    foundCandidates = false;
                    for (int k = 0; k < regionPixels.Count; k++)
                    {
                        List <int[]> regionCandidates = colorPixels.Where(p =>
                                                                          Math.Abs(p[0] - regionPixels[k][0]) < 3 && Math.Abs(p[1] - regionPixels[k][1]) < 3 &&                                                //pixel is near
                                                                          Math.Abs(p[2] - regionPixels[k][2]) + Math.Abs(p[3] - regionPixels[k][3]) + Math.Abs(p[4] - regionPixels[k][4]) < 3 * colorDifThresh //color is similar
                                                                          ).ToList <int[]>();

                        if (regionCandidates.Count > 0)
                        {
                            foundCandidates = true;
                            foreach (int[] pt in regionCandidates)
                            {
                                regionPixels.Add(pt);
                                colorPixels.Remove(pt);
                            }
                        }
                    }
                }

                if (regionPixels.Count > 20)
                {
                    //average color
                    int[]        avgColor = new int[] { 0, 0, 0 };
                    List <int[]> coords   = new List <int[]>();
                    foreach (int[] pt in regionPixels)
                    {
                        for (int k = 0; k < 3; k++)
                        {
                            avgColor[k] += pt[k + 2];
                        }
                        coords.Add(new int[] { pt[0], pt[1] });
                    }

                    for (int k = 0; k < 3; k++)
                    {
                        avgColor[k] /= regionPixels.Count;
                    }

                    ColorStroke cs = new ColorStroke(coords, Color.FromArgb(avgColor[0], avgColor[1], avgColor[2]));
                    ans.Add(cs);
                }
            }


            return(ans);
        }
        /// <summary>Compose image from current strokes</summary>
        /// <returns></returns>
        public Bitmap ComposeImage()
        {
            Bitmap     bmpSource  = new Bitmap(ImageWidth, ImageHeight);
            BitmapData bitmapData = bmpSource.LockBits(new Rectangle(0, 0, bmpSource.Width, bmpSource.Height), ImageLockMode.ReadWrite, bmpSource.PixelFormat);


            int bytesPerPixel = Bitmap.GetPixelFormatSize(bmpSource.PixelFormat) / 8;
            int byteCount     = bitmapData.Stride * bmpSource.Height;

            byte[] pixels        = new byte[byteCount];
            IntPtr ptrFirstPixel = bitmapData.Scan0;

            Marshal.Copy(ptrFirstPixel, pixels, 0, pixels.Length);
            int heightInPixels = bitmapData.Height;
            int widthInBytes   = bitmapData.Width * bytesPerPixel;

            //int xx, yy;
            //yy = 0;

            Parallel.For(0, heightInPixels, y =>
                         //for (int y = 0; y < heightInPixels; y++)
            {
                int yy = y;

                int currentLine = y * bitmapData.Stride;
                int xx          = 0;
                for (int x = 0; x < widthInBytes; x = x + bytesPerPixel)
                {
                    float rC = 255, gC = 255, bC = 255;
                    if (_edges.BinarySearch(xx + ImageWidth * yy) >= 0)
                    {
                        rC = 0; gC = 0; bC = 0;
                    }

                    float totWeight = 0;
                    for (int j = 0; j < _strokes.Count; j++)
                    {
                        ColorStroke cs = _strokes[j];
                        if (cs.DistanceMap != null)
                        {
                            float myWeight = 1.0f / (1e-5f + cs.DistanceMap[xx + ImageWidth * yy]);

                            float rN = cs.StrokeColor.R;
                            float gN = cs.StrokeColor.G;
                            float bN = cs.StrokeColor.B;

                            if (myWeight > 1E-4f * totWeight)
                            {
                                myWeight = (float)Math.Pow(myWeight, 1.7f);

                                if (myWeight + totWeight > 0)
                                {
                                    float temp = 1.0f / (myWeight + totWeight);

                                    rC = (rN * myWeight + rC * totWeight) * temp;
                                    gC = (gN * myWeight + gC * totWeight) * temp;
                                    bC = (bN * myWeight + bC * totWeight) * temp;

                                    totWeight += myWeight;
                                }

                                if (float.IsNaN(rC))
                                {
                                }
                            }
                        }
                    }

                    pixels[currentLine + x]     = (byte)bC;
                    pixels[currentLine + x + 1] = (byte)gC;
                    pixels[currentLine + x + 2] = (byte)rC;
                    pixels[currentLine + x + 3] = 255;


                    xx++;
                }
                yy++;
            });

            // copy modified bytes back
            Marshal.Copy(pixels, 0, ptrFirstPixel, pixels.Length);
            bmpSource.UnlockBits(bitmapData);

            return(bmpSource);
        }
        /// <summary>Adds a new stroke to this drawing</summary>
        /// <param name="coords">Coordinates of the stroke</param>
        /// <param name="c">Stroke color</param>
        public void AddStroke(List <int[]> coords, Color c)
        {
            ColorStroke cs = new ColorStroke(coords, c);

            _strokes.Add(cs);
        }