private static bool IsPartOfTheLetter(Bitmap downscaled, int x, int y)
        {
            const int marginsBlackThreshold       = 200;
            const int marginsTransparentThreshold = 240;

            int suit = 0;

            for (int i = x - 1; i <= x + 1; i++)
            {
                for (int j = y - 1; j <= y + 1; j++)
                {
                    if (i < 0 || j < 0 || i >= downscaled.Width || j >= downscaled.Height)
                    {
                        continue;
                    }
                    Color pixel = downscaled.GetPixel(i, j);
                    if (pixel.A > marginsBlackThreshold && BitmapUtils.GetGrayscale(pixel) < marginsBlackThreshold)
                    {
                        suit++;
                    }
                }
            }

            return(suit > 2);
        }
        private int GetFormType(Bitmap prepForm)
        {
            const double markerDist = 10.0 / 165.0;
            const double xOff       = 10.0 / 165.0;
            const double yOff       = 2.5 / 255.0;

            for (int i = 0; i < formCount; i++)
            {
                double x = (xOff + i * markerDist) * prepForm.Width;
                double y = yOff * prepForm.Height;
                if (BitmapUtils.GetGrayscale(prepForm.GetPixel((int)x, (int)y)) < 128)
                {
                    return(i);
                }
            }

            throw new MarkersNotFoundException("Couldn't determine form type");
        }
        private Bitmap PrepareLetterImage(Bitmap image, int formType)
        {
            Bitmap standartImage = new Bitmap(Font.imagePixelW, Font.imagePixelH, PixelFormat.Format32bppArgb);

            //remove black borders
            using (Graphics gr = Graphics.FromImage(image))
            {
                int pixelThicknessH = (int)(borderCutThickness * image.Width);
                int pixelThicknessV = (int)(borderCutThickness * image.Height);
                gr.FillRectangle(Brushes.White, new Rectangle(0, 0, pixelThicknessH, image.Height));                             //left
                gr.FillRectangle(Brushes.White, new Rectangle(0, 0, image.Width, pixelThicknessV));                              //top
                gr.FillRectangle(Brushes.White, new Rectangle(image.Width - pixelThicknessH, 0, pixelThicknessH, image.Height)); //right
                gr.FillRectangle(Brushes.White, new Rectangle(0, image.Height - pixelThicknessV, image.Width, image.Height));    //bottom
            }

            //copy over the image
            using (Graphics gr = Graphics.FromImage(standartImage))
            {
                int topOffset = (int)(Font.imagePixelH / 2 - Font.imagePixelW * lineHeights[formType]);

                gr.Clear(Color.Transparent);
                gr.DrawImage(image, new Rectangle(0, topOffset, Font.imagePixelW, Font.imagePixelW));
            }

            //make white transparent
            BitmapData data = standartImage.LockBits(new Rectangle(0, 0, standartImage.Width, standartImage.Height), ImageLockMode.ReadWrite, standartImage.PixelFormat);

            unsafe
            {
                byte *arr          = (byte *)data.Scan0;
                int   channelCount = Image.GetPixelFormatSize(standartImage.PixelFormat) / 8;
                for (int i = 0; i < standartImage.Width * standartImage.Height * channelCount; i += channelCount)
                {
                    int grayscale = BitmapUtils.GetGrayscale(arr[i], arr[i + 1], arr[i + 2]);
                    if (grayscale > 200)
                    {
                        arr[i + 3] = (byte)(255 - grayscale);
                    }
                }
            }
            standartImage.UnlockBits(data);

            return(standartImage);
        }
        private void FindCoreRegion()
        {
            int[] histogram = new int[Font.imagePixelH];

            foreach (FChar letter in smallLetters)
            {
                for (int i = 0; i < font.images[letter].Count; i++)
                {
                    Bitmap     image = font.images[letter][i];
                    BitmapData data  = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, image.PixelFormat);

                    unsafe
                    {
                        byte *arr          = (byte *)data.Scan0;
                        int   channelCount = Bitmap.GetPixelFormatSize(image.PixelFormat) / 8;

                        for (int j = 0; j < image.Width * image.Height * channelCount; j += channelCount)
                        {
                            if (BitmapUtils.GetGrayscale(arr[j], arr[j + 1], arr[j + 2]) < 128 && arr[j + 3] > 240)
                            {
                                histogram[j / channelCount / image.Width]++;
                            }
                        }
                    }

                    image.UnlockBits(data);
                }
            }

            int[] cumulativeHistogram = new int[Font.imagePixelH];
            cumulativeHistogram[0] = histogram[0];

            for (int i = 1; i < cumulativeHistogram.Length; i++)
            {
                cumulativeHistogram[i] = cumulativeHistogram[i - 1] + histogram[i];
            }

            double cutoffRatio = 0.05;
            int    total       = cumulativeHistogram.Last();

            int leftBorder = 0;

            for (int i = 0; i < cumulativeHistogram.Length; i++)
            {
                if ((double)cumulativeHistogram[i] / total > cutoffRatio)
                {
                    leftBorder = i;
                    break;
                }
            }

            int rightBorder = cumulativeHistogram.Length;

            for (int i = cumulativeHistogram.Length - 1; i >= 0; i--)
            {
                if ((double)cumulativeHistogram[i] / total < (1.0 - cutoffRatio))
                {
                    rightBorder = i;
                    break;
                }
            }

            coreRegionTop    = leftBorder * Font.cmPerPixelV;
            coreRegionBottom = rightBorder * Font.cmPerPixelV;
        }