public static NikseBitmap CropTopAndBottom(NikseBitmap bmp, out int topCropping)
        {
            int startTop = 0;
            int maxTop = bmp.Height - 2;
            if (maxTop > bmp.Height)
            {
                maxTop = bmp.Height;
            }

            for (int y = 0; y < maxTop; y++)
            {
                bool allTransparent = true;
                for (int x = 1; x < bmp.Width - 1; x++)
                {
                    int a = bmp.GetAlpha(x, y);
                    if (a != 0)
                    {
                        allTransparent = false;
                        break;
                    }
                }

                if (!allTransparent)
                {
                    break;
                }

                startTop++;
            }

            //if (startTop > 9)
            //startTop -= 5; // if top space > 9, then allways leave blank 5 pixels on top (so . is not confused with ').
            topCropping = startTop;

            int height = bmp.Height;
            bool bottomCroppingDone = false;
            for (int y = bmp.Height - 1; y > 3; y--)
            {
                for (int x = 1; x < bmp.Width - 1; x++)
                {
                    int a = bmp.GetAlpha(x, y);
                    if (a != 0)
                    {
                        bottomCroppingDone = true;
                        break;
                    }
                }

                height = y;
                if (bottomCroppingDone)
                {
                    break;
                }
            }

            return bmp.CopyRectangle(new Rectangle(0, startTop, bmp.Width, height - startTop + 1));
        }
        public static NikseBitmap CropTopAndBottom(NikseBitmap bmp, out int topCropping, int maxDifferentPixelsOnLine)
        {
            int startTop = 0;
            int maxTop = bmp.Height - 2;
            if (maxTop > bmp.Height)
                maxTop = bmp.Height;

            for (int y = 0; y < maxTop; y++)
            {
                int difference = 0;
                bool allTransparent = true;
                for (int x = 1; x < bmp.Width - 1; x++)
                {
                    int a = bmp.GetAlpha(x, y);
                    if (a != 0)
                    {
                        difference++;
                        if (difference >= maxDifferentPixelsOnLine)
                        {
                            allTransparent = false;
                            break;
                        }
                    }
                }
                if (!allTransparent)
                    break;
                startTop++;
            }
            if (startTop > 9)
                startTop -= 5; // if top space > 9, then allways leave blank 5 pixels on top (so . is not confused with ').
            topCropping = startTop;

            for (int y = bmp.Height - 1; y > 3; y--)
            {
                int difference = 0;
                bool allTransparent = true;
                for (int x = 1; x < bmp.Width - 1; x++)
                {
                    int a = bmp.GetAlpha(x, y);
                    if (a != 0)
                    {
                        difference++;
                        if (difference >= maxDifferentPixelsOnLine)
                        {
                            allTransparent = false;
                            break;
                        }
                    }
                }
                if (allTransparent == false)
                    return bmp.CopyRectangle(new Rectangle(0, startTop, bmp.Width - 1, y - startTop + 1));
            }
            return bmp;
        }
        internal static unsafe int IsBitmapsAlike(NikseBitmap bmp1, Ocr.Binary.BinaryOcrBitmap bmp2)
        {
            int different = 0;
            int maxDiff = bmp1.Width * bmp1.Height / 5;

            for (int x = 1; x < bmp1.Width; x++)
            {
                for (int y = 1; y < bmp1.Height; y++)
                {
                    if (bmp1.GetAlpha(x, y) < 100 && bmp2.GetPixel(x, y) > 0)
                        different++;
                }
                if (different > maxDiff)
                    return different + 10;
            }
            return different;
        }
        private static List<Point> IsVerticalLineTransparetNew(NikseBitmap bmp, int x, out bool right, out bool clean)
        {
            right = false;
            bool left = false;
            clean = true;
            var points = new List<Point>();
            int y = 0;
            while (y < bmp.Height)
            {
                if (bmp.GetAlpha(x, y) > 100)
                {
                    clean = false;
                    if (x == 0)
                        return null;

                    if (x < bmp.Width - 1 && y < bmp.Height - 1 && bmp.GetAlpha(x + 1, y) == 0 && bmp.GetAlpha(x + 1, y + 1) == 0)
                    {
                        //if pixels to the left - move right?
                        if (bmp.GetAlpha(x - 1, y) > 0)
                        {
                            x++; //(requires search for min/max x in points
                            right = true;
                        }
                        else if (x > 0 && bmp.GetAlpha(x - 1, y) == 0)
                        {
                            x--; //(requires search for min/max x in points
                            left = true;
                        }
                        else
                        {
                            return null;
                        }

                    }
                    else if (x < bmp.Width - 1 && y == bmp.Height - 1 && bmp.GetAlpha(x + 1, y) == 0 && bmp.GetAlpha(x + 1, y - 1) == 0)
                    {
                        //if pixels to the left - move right?
                        if (bmp.GetAlpha(x - 1, y) > 0)
                        {
                            x++; //(requires search for min/max x in points
                            right = true;
                        }
                        else
                        {
                            return null;
                        }
                        right = true;
                    }
                    else if (bmp.GetAlpha(x - 1, y) == 0)
                    {
                        x--;
                        left = true;
                    }
                    else if (y > 5 && bmp.GetAlpha(x - 1, y - 1) == 0)
                    {
                        x--;
                        y--;
                        left = true;
                        while (points.Count > 0 && points[points.Count - 1].Y > y)
                            points.RemoveAt(points.Count - 1);
                    }
                    else if (y > 5 && bmp.GetAlpha(x - 1, y - 2) == 0)
                    {
                        x--;
                        y -= 2;
                        left = true;
                        while (points.Count > 0 && points[points.Count - 1].Y > y)
                            points.RemoveAt(points.Count - 1);
                    }
                    else
                    {
                        return null;
                    }

                    if (left && right)
                        return null;
                }
                else
                {
                    points.Add(new Point(x, y));
                    y++;
                }
            }
            return points;
        }
 private static bool IsVerticalLineTransparentAlphaOnly(NikseBitmap bmp, ref int y, int x)
 {
     bool allTransparent = true;
     for (y = 0; y < bmp.Height - 1; y++)
     {
         int a = bmp.GetAlpha(x, y);
         if (a == 0) // still dark color...
         {
         }
         else
         {
             allTransparent = false;
             break;
         }
     }
     return allTransparent;
 }
 private static void RemoveBlackBarRight(NikseBitmap bmp)
 {
     int xRemoveBlackBar = bmp.Width - 1;
     for (int yRemoveBlackBar = 0; yRemoveBlackBar < bmp.Height; yRemoveBlackBar++)
     {
         byte[] c = bmp.GetPixelColors(xRemoveBlackBar, yRemoveBlackBar);
         if (c[0] == 0 || IsColorClose(c[0], c[1], c[2], c[3], Color.Black, 280))
         {
             if (bmp.GetAlpha(xRemoveBlackBar - 1, yRemoveBlackBar) == 0)
                 bmp.SetPixel(xRemoveBlackBar, yRemoveBlackBar, Color.Transparent);
         }
     }
 }
        public static List<ImageSplitterItem> SplitVertical(NikseBitmap bmp, int minLineHeight)
        { // split into lines
            int startY = 0;
            int size = 0;
            var parts = new List<ImageSplitterItem>();
            for (int y = 0; y < bmp.Height; y++)
            {
                bool allTransparent = true;
                for (int x = 0; x < bmp.Width; x++)
                {
                    int a = bmp.GetAlpha(x, y);
                    if (a != 0)
                    {
                        allTransparent = false;
                        break;
                    }
                }
                if (allTransparent)
                {
                    if (size > 2 && size <= minLineHeight)
                    {
                        size++; // at least 'lineMinHeight' pixels, like top of 'i'
                    }
                    else
                    {
                        if (size > 2)
                        {
                            NikseBitmap part = bmp.CopyRectangle(new Rectangle(0, startY, bmp.Width, size + 1));
                            //                            part.Save("c:\\line_0_to_width.bmp");
                            parts.Add(new ImageSplitterItem(0, startY, part));
                            //                            bmp.Save("c:\\original.bmp");
                        }
                        size = 0;
                        startY = y;
                    }
                }
                else
                {
                    size++;
                }

            }
            if (size > 2)
            {
                if (size == bmp.Height)
                {
                    if (size > 100)
                        return SplitVerticalTransparentOrBlack(bmp);
                    else
                        parts.Add(new ImageSplitterItem(0, startY, bmp));
                }
                else
                {
                    parts.Add(new ImageSplitterItem(0, startY, bmp.CopyRectangle(new Rectangle(0, startY, bmp.Width, size + 1))));
                }
            }
            return parts;
        }
        internal static int IsBitmapsAlike(Ocr.Binary.BinaryOcrBitmap bmp1, NikseBitmap bmp2)
        {
            int different = 0;
            int maxDiff = bmp1.Width * bmp1.Height / 5;

            for (int x = 1; x < bmp1.Width; x++)
            {
                for (int y = 1; y < bmp1.Height; y++)
                {
                    //if (!IsColorClose(bmp1.GetPixel(x, y), bmp2.GetPixel(x, y), 20))
                    if (bmp1.GetPixel(x, y) > 0 && bmp2.GetAlpha(x, y) < 100)
                        different++;
                }
                if (different > maxDiff)
                    return different + 10;
            }
            return different;
        }
        private static void RemoveBlackBarRight(NikseBitmap bmp)
        {
            int xRemoveBlackBar = bmp.Width - 1;
            for (int yRemoveBlackBar = 0; yRemoveBlackBar < bmp.Height; yRemoveBlackBar++)
            {
                byte[] colors = bmp.GetPixelColors(xRemoveBlackBar, yRemoveBlackBar);
                if (colors[0] != 0 && !IsColorClose(colors[0], colors[1], colors[2], colors[3], Color.Black, 280))
                {
                    continue;
                }

                if (bmp.GetAlpha(xRemoveBlackBar - 1, yRemoveBlackBar) == 0)
                {
                    bmp.SetPixel(xRemoveBlackBar, yRemoveBlackBar, Color.Transparent);
                }
            }
        }
        private static bool IsVerticalLineTransparentAlphaOnly(NikseBitmap bmp, ref int y, int x)
        {
            bool allTransparent = true;
            for (y = 0; y < bmp.Height - 1; y++)
            {
                int a = bmp.GetAlpha(x, y);
                if (a == 0)
                {
                    continue;
                }

                allTransparent = false;
                break;
            }

            return allTransparent;
        }
        private static List <ImageSplitterItem> SplitVerticalAggresive(NikseBitmap bmp, int minLineHeight, double averageLineHeight)
        {
            int startY = 0;
            int size   = 0;
            var parts  = new List <ImageSplitterItem>();

            for (int y = 0; y < bmp.Height; y++)
            {
                int  a;
                bool allTransparent = true;
                for (int x = 0; x < bmp.Width; x++)
                {
                    a = bmp.GetAlpha(x, y);
                    if (a != 0)
                    {
                        allTransparent = false;
                        break;
                    }
                }

                if (size > 5 && size >= minLineHeight && size > averageLineHeight && !allTransparent && bmp.Width > 50 && y < bmp.Height - 5)
                {
                    var leftX = 0;
                    while (leftX < bmp.Width)
                    {
                        a = bmp.GetAlpha(leftX, y);
                        if (a != 0)
                        {
                            break;
                        }
                        leftX++;
                    }
                    var rightX = bmp.Width;
                    while (rightX > 0)
                    {
                        a = bmp.GetAlpha(rightX, y - 1);
                        if (a != 0)
                        {
                            break;
                        }
                        rightX--;
                    }
                    if (leftX >= rightX)
                    {
                        allTransparent = true;
                    }

                    leftX = 0;
                    while (leftX < bmp.Width)
                    {
                        a = bmp.GetAlpha(leftX, y - 1);
                        if (a != 0)
                        {
                            break;
                        }
                        leftX++;
                    }
                    rightX = bmp.Width;
                    while (rightX > 0)
                    {
                        a = bmp.GetAlpha(rightX, y);
                        if (a != 0)
                        {
                            break;
                        }
                        rightX--;
                    }
                    if (leftX >= rightX)
                    {
                        allTransparent = true;
                    }
                }

                if (allTransparent)
                {
                    if (size > 2 && size <= minLineHeight)
                    {
                        size++; // at least 'lineMinHeight' pixels, like top of 'i'
                    }
                    else
                    {
                        if (size > 2)
                        {
                            var part = bmp.CopyRectangle(new Rectangle(0, startY, bmp.Width, size + 1));
                            parts.Add(new ImageSplitterItem(0, startY, part));
                        }
                        size   = 0;
                        startY = y;
                    }
                }
                else
                {
                    size++;
                }
            }
            if (size > 2)
            {
                if (size == bmp.Height)
                {
                    if (size > 100)
                    {
                        return(SplitVerticalTransparentOrBlack(bmp));
                    }
                    parts.Add(new ImageSplitterItem(0, startY, bmp));
                }
                else
                {
                    parts.Add(new ImageSplitterItem(0, startY, bmp.CopyRectangle(new Rectangle(0, startY, bmp.Width, size + 1))));
                }
            }
            if (parts.Count == 1 && averageLineHeight > 5 && bmp.Height > averageLineHeight * 3)
            {
                return(parts);
            }
            return(parts);
        }
        /// <summary>
        /// split into lines
        /// </summary>
        public static List <ImageSplitterItem> SplitVertical(NikseBitmap bmp, int minLineHeight, double averageLineHeight = -1)
        {
            int startY = 0;
            int size   = 0;
            var parts  = new List <ImageSplitterItem>();

            for (int y = 0; y < bmp.Height; y++)
            {
                bool allTransparent = true;
                for (int x = 0; x < bmp.Width; x++)
                {
                    int a = bmp.GetAlpha(x, y);
                    if (a != 0)
                    {
                        allTransparent = false;
                        break;
                    }
                }
                if (allTransparent)
                {
                    if (size > 1 && size <= minLineHeight)
                    {
                        size++; // at least 'lineMinHeight' pixels, like top of 'i'
                    }
                    else
                    {
                        if (size > 1)
                        {
                            var part = bmp.CopyRectangle(new Rectangle(0, startY, bmp.Width, size + 1));
                            parts.Add(new ImageSplitterItem(0, startY, part));
                        }
                        size   = 0;
                        startY = y;
                    }
                }
                else
                {
                    size++;
                }
            }
            if (size > 1)
            {
                if (size == bmp.Height)
                {
                    if (size > 100)
                    {
                        return(SplitVerticalTransparentOrBlack(bmp));
                    }
                    parts.Add(new ImageSplitterItem(0, startY, bmp));
                }
                else
                {
                    parts.Add(new ImageSplitterItem(0, startY, bmp.CopyRectangle(new Rectangle(0, startY, bmp.Width, size + 1))));
                }
            }
            if (parts.Count == 1 && averageLineHeight > 5 && bmp.Height > averageLineHeight * 3)
            {
                return(SplitVerticalAggresive(bmp, minLineHeight, averageLineHeight));
            }
            return(parts);
        }
        public static NikseBitmap CropTopAndBottom(NikseBitmap bmp, out int topCropping, int maxDifferentPixelsOnLine)
        {
            int startTop = 0;
            int maxTop   = bmp.Height - 2;

            if (maxTop > bmp.Height)
            {
                maxTop = bmp.Height;
            }

            for (int y = 0; y < maxTop; y++)
            {
                int  difference     = 0;
                bool allTransparent = true;
                for (int x = 1; x < bmp.Width - 1; x++)
                {
                    int a = bmp.GetAlpha(x, y);
                    if (a != 0)
                    {
                        difference++;
                        if (difference >= maxDifferentPixelsOnLine)
                        {
                            allTransparent = false;
                            break;
                        }
                    }
                }
                if (!allTransparent)
                {
                    break;
                }
                startTop++;
            }
            if (startTop > 9)
            {
                startTop -= 5; // if top space > 9, then allways leave blank 5 pixels on top (so . is not confused with ').
            }
            topCropping = startTop;

            for (int y = bmp.Height - 1; y > 3; y--)
            {
                int  difference     = 0;
                bool allTransparent = true;
                for (int x = 1; x < bmp.Width - 1; x++)
                {
                    int a = bmp.GetAlpha(x, y);
                    if (a != 0)
                    {
                        difference++;
                        if (difference >= maxDifferentPixelsOnLine)
                        {
                            allTransparent = false;
                            break;
                        }
                    }
                }
                if (allTransparent == false)
                {
                    return(bmp.CopyRectangle(new Rectangle(0, startTop, bmp.Width - 1, y - startTop + 1)));
                }
            }
            return(bmp);
        }
        private static List <Point> IsVerticalLineTransparetNew(NikseBitmap bmp, int x, out bool right, out bool clean)
        {
            right = false;
            bool left       = false;
            int  leftCount  = 0;
            int  rightCount = 0;

            clean = true;
            var points   = new List <Point>();
            int y        = 0;
            int maxSlide = bmp.Height / 4;

            while (y < bmp.Height)
            {
                if (bmp.GetAlpha(x, y) > 100)
                {
                    clean = false;
                    if (x == 0)
                    {
                        return(null);
                    }

                    if (x < bmp.Width - 1 && y < bmp.Height - 1 && bmp.GetAlpha(x + 1, y) == 0 && bmp.GetAlpha(x + 1, y + 1) == 0)
                    {
                        //if pixels to the left - move right?
                        if (bmp.GetAlpha(x - 1, y) > 0)
                        {
                            x++; //(requires search for min/max x in points
                            right = true;
                        }
                        else if (x > 0 && bmp.GetAlpha(x - 1, y) == 0)
                        {
                            x--; //(requires search for min/max x in points
                            left = true;
                        }
                        else
                        {
                            return(null);
                        }
                    }
                    else if (x < bmp.Width - 1 && y == bmp.Height - 1 && bmp.GetAlpha(x + 1, y) == 0 && bmp.GetAlpha(x + 1, y - 1) == 0)
                    {
                        //if pixels to the left - move right?
                        if (bmp.GetAlpha(x - 1, y) > 0)
                        {
                            x++; //(requires search for min/max x in points
                        }
                        else
                        {
                            return(null);
                        }
                        right = true;
                    }
                    else if (bmp.GetAlpha(x - 1, y) == 0)
                    {
                        x--;
                        left = true;
                    }
                    else if (y > 5 && bmp.GetAlpha(x - 1, y - 1) == 0)
                    {
                        x--;
                        y--;
                        left = true;
                        while (points.Count > 0 && points[points.Count - 1].Y > y)
                        {
                            points.RemoveAt(points.Count - 1);
                        }
                    }
                    else if (y > 5 && bmp.GetAlpha(x - 1, y - 2) == 0)
                    {
                        x--;
                        y   -= 2;
                        left = true;
                        while (points.Count > 0 && points[points.Count - 1].Y > y)
                        {
                            points.RemoveAt(points.Count - 1);
                        }
                    }
                    else
                    {
                        return(null);
                    }

                    if (left)
                    {
                        leftCount++;
                    }

                    if (right)
                    {
                        rightCount++;
                    }

                    if (leftCount > maxSlide || rightCount > maxSlide)
                    {
                        return(null);
                    }
                }
                else
                {
                    points.Add(new Point(x, y));
                    y++;
                }
            }
            return(points);
        }
        public static List <ImageSplitterItem> SplitVertical(NikseBitmap bmp, int minLineHeight)
        { // split into lines
            int startY = 0;
            int size   = 0;
            var parts  = new List <ImageSplitterItem>();

            for (int y = 0; y < bmp.Height; y++)
            {
                bool allTransparent = true;
                for (int x = 0; x < bmp.Width; x++)
                {
                    int a = bmp.GetAlpha(x, y);
                    if (a != 0)
                    {
                        allTransparent = false;
                        break;
                    }
                }
                if (allTransparent)
                {
                    if (size > 2 && size <= minLineHeight)
                    {
                        size++; // at least 'lineMinHeight' pixels, like top of 'i'
                    }
                    else
                    {
                        if (size > 2)
                        {
                            NikseBitmap part = bmp.CopyRectangle(new Rectangle(0, startY, bmp.Width, size + 1));
                            //                            part.Save("c:\\line_0_to_width.bmp");
                            parts.Add(new ImageSplitterItem(0, startY, part));
                            //                            bmp.Save("c:\\original.bmp");
                        }
                        size   = 0;
                        startY = y;
                    }
                }
                else
                {
                    size++;
                }
            }
            if (size > 2)
            {
                if (size == bmp.Height)
                {
                    if (size > 100)
                    {
                        return(SplitVerticalTransparentOrBlack(bmp));
                    }
                    else
                    {
                        parts.Add(new ImageSplitterItem(0, startY, bmp));
                    }
                }
                else
                {
                    parts.Add(new ImageSplitterItem(0, startY, bmp.CopyRectangle(new Rectangle(0, startY, bmp.Width, size + 1))));
                }
            }
            return(parts);
        }
        /// <summary>
        /// split into lines
        /// </summary>
        public static List<ImageSplitterItem> SplitToLinesNew(ImageSplitterItem item, int minLineHeight, double averageLineHeight = -1)
        {
            var bmp = new NikseBitmap(item.NikseBitmap);
            var parts = new List<ImageSplitterItem>();
            bool started = false;
            var splitLines = new Dictionary<int, List<Point>>();
            var startY = 0;
            for (int y = minLineHeight; y < bmp.Height - minLineHeight; y++)
            {
                if (startY == y && bmp.IsLineTransparent(y))
                {
                    startY++;
                    continue;
                }

                var points = new List<Point>();
                var yChange = 0;
                var completed = false;
                var backJump = 0;
                int x = 0;
                var maxUp = Math.Min(10, minLineHeight / 2);
                while (x < bmp.Width)
                {
                    var a1 = bmp.GetAlpha(x, y + yChange);
                    var a2 = bmp.GetAlpha(x, y + 1 + yChange);
                    if (a1 > 150 || a2 > 150)
                    {
                        if (x > 1 && yChange < 8 && y + 3 + yChange < bmp.Height &&
                            bmp.GetAlpha(x - 1, y + yChange) < 150 && bmp.GetAlpha(x - 1, y + yChange) < 150 &&
                            bmp.GetAlpha(x - 1, y + 1 + yChange) < 150 && bmp.GetAlpha(x - 1, y + 2 + yChange) < 150 &&
                            bmp.GetAlpha(x - 1, y + 2 + yChange) < 150 && bmp.GetAlpha(x - 1, y + 3 + yChange) < 150 &&
                            bmp.GetAlpha(x, y + 2 + yChange) < 150 && bmp.GetAlpha(x, y + 3 + yChange) < 150)
                        {
                            yChange += 2;
                        }

                        else if (x > 1 && yChange < 8 && y + 4 + yChange < bmp.Height &&
                                 bmp.GetAlpha(x - 1, y + yChange) < 150 && bmp.GetAlpha(x - 1, y + yChange) < 150 &&
                                 bmp.GetAlpha(x - 1, y + 1 + yChange) < 150 && bmp.GetAlpha(x - 1, y + 2 + yChange) < 150 &&
                                 bmp.GetAlpha(x - 1, y + 2 + yChange) < 150 && bmp.GetAlpha(x - 1, y + 3 + yChange) < 150 &&
                                 bmp.GetAlpha(x - 1, y + 3 + yChange) < 150 && bmp.GetAlpha(x - 1, y + 4 + yChange) < 150 &&
                                 bmp.GetAlpha(x, y + 3 + yChange) < 150 && bmp.GetAlpha(x, y + 4 + yChange) < 150)
                        {
                            yChange += 3;
                        }

                        else if (x > 1 && yChange < 7 && y + 5 + yChange < bmp.Height &&
                                 bmp.GetAlpha(x - 1, y + yChange) < 150 && bmp.GetAlpha(x - 1, y + yChange) < 150 &&
                                 bmp.GetAlpha(x - 1, y + 1 + yChange) < 150 && bmp.GetAlpha(x - 1, y + 2 + yChange) < 150 &&
                                 bmp.GetAlpha(x - 1, y + 2 + yChange) < 150 && bmp.GetAlpha(x - 1, y + 3 + yChange) < 150 &&
                                 bmp.GetAlpha(x - 1, y + 3 + yChange) < 150 && bmp.GetAlpha(x - 1, y + 4 + yChange) < 150 &&
                                 bmp.GetAlpha(x - 1, y + 4 + yChange) < 150 && bmp.GetAlpha(x - 1, y + 5 + yChange) < 150 &&
                                 bmp.GetAlpha(x, y + 4 + yChange) < 150 && bmp.GetAlpha(x, y + 5 + yChange) < 150)
                        {
                            yChange += 4;
                        }

                        else if (x > 1 && yChange > -7 &&
                                 bmp.GetAlpha(x - 1, y + yChange) < 150 && bmp.GetAlpha(x - 1, y + yChange) < 150 &&
                                 bmp.GetAlpha(x - 1, y - 1 + yChange) < 150 && bmp.GetAlpha(x - 1, y - 2 + yChange) < 150 &&
                                 bmp.GetAlpha(x - 1, y - 2 + yChange) < 150 && bmp.GetAlpha(x - 1, y - 3 + yChange) < 150 &&
                                 bmp.GetAlpha(x, y - 2 + yChange) < 150 && bmp.GetAlpha(x, y - 3 + yChange) < 150)
                        {
                            yChange -= 2;
                        }

                        else if (x > 1 && yChange > -7 &&
                                 bmp.GetAlpha(x - 1, y + yChange) < 150 && bmp.GetAlpha(x - 1, y + yChange) < 150 &&
                                 bmp.GetAlpha(x - 1, y - 1 + yChange) < 150 && bmp.GetAlpha(x - 1, y - 2 + yChange) < 150 &&
                                 bmp.GetAlpha(x - 1, y - 2 + yChange) < 150 && bmp.GetAlpha(x - 1, y - 3 + yChange) < 150 &&
                                 bmp.GetAlpha(x - 1, y - 3 + yChange) < 150 && bmp.GetAlpha(x - 1, y - 4 + yChange) < 150 &&
                                 bmp.GetAlpha(x, y - 3 + yChange) < 150 && bmp.GetAlpha(x, y - 4 + yChange) < 150)
                        {
                            yChange -= 3;
                        }

                        else if (x > 1 && yChange > -7 &&
                                 bmp.GetAlpha(x - 1, y + yChange) < 150 && bmp.GetAlpha(x - 1, y + yChange) < 150 &&
                                 bmp.GetAlpha(x - 1, y - 1 + yChange) < 150 && bmp.GetAlpha(x - 1, y - 2 + yChange) < 150 &&
                                 bmp.GetAlpha(x - 1, y - 2 + yChange) < 150 && bmp.GetAlpha(x - 1, y - 3 + yChange) < 150 &&
                                 bmp.GetAlpha(x - 1, y - 3 + yChange) < 150 && bmp.GetAlpha(x - 1, y - 4 + yChange) < 150 &&
                                 bmp.GetAlpha(x - 1, y - 4 + yChange) < 150 && bmp.GetAlpha(x - 1, y - 5 + yChange) < 150 &&
                                 bmp.GetAlpha(x, y - 4 + yChange) < 150 && bmp.GetAlpha(x, y - 5 + yChange) < 150)
                        {
                            yChange -= 4;
                        }

                        else if (x > 10 && backJump < 3 && x > 5 && yChange > -7) // go left + up + check 12 pixels right
                        {
                            var done = false;
                            for (int i = 1; i < maxUp; i++)
                            {
                                for (int k = 1; k < 9; k++)
                                {
                                    if (CanGoUpAndRight(bmp, i, 12, x - k, y + yChange, minLineHeight))
                                    {
                                        backJump++;
                                        x -= k;
                                        points.RemoveAll(p => p.X > x);
                                        done = true;
                                        yChange -= (i + 1);
                                        break;
                                    }
                                }

                                if (done)
                                {
                                    break;
                                }
                            }

                            if (!done)
                            {
                                started = true;
                                break;
                            }
                        }

                        else
                        {
                            started = true;
                            break;
                        }
                    }

                    if (started)
                    {
                        points.Add(new Point(x, y + yChange));
                    }

                    completed = x == bmp.Width - 1;
                    x++;
                }

                if (completed)
                {
                    splitLines.Add(y, points);
                }

            }

            var transparentColor = Color.FromArgb(0, 0, 0, 0);
            foreach (var line in splitLines)
            {
                var key = line.Key;
                if (key - startY > minLineHeight && line.Value.Count > 0)
                {
                    var maxY = line.Value.Max(p => p.Y);
                    var part = bmp.CopyRectangle(new Rectangle(0, startY, bmp.Width, maxY - startY));
                    //part.GetBitmap().Save(@"j:\temp\split_" + parts.Count + "_before.bmp");

                    foreach (var point in line.Value)
                    {
                        // delete down
                        for (var y = point.Y - 1; y < startY + part.Height; y++)
                        {
                            part.SetPixel(point.X, y - startY, transparentColor);
                        }
                    }
                    //part.GetBitmap().Save(@"j:\temp\split_" + parts.Count + "_after.bmp");

                    if (!part.IsImageOnlyTransparent() && part.GetNonTransparentHeight() >= minLineHeight)
                    {
                        var minY = line.Value.Min(p => p.Y);
                        // bmp.GetBitmap().Save(@"j:\temp\main_" + parts.Count + "_before.bmp");
                        foreach (var point in line.Value)
                        {
                            // delete up
                            for (var y = point.Y; y >= minY; y--)
                            {
                                bmp.SetPixel(point.X, y, transparentColor);
                            }
                        }
                        // bmp.GetBitmap().Save(@"j:\temp\main_" + parts.Count + "_after.bmp");

                        //    part.GetBitmap().Save(@"j:\temp\split_" + parts.Count + "_after.bmp");
                        var croppedTop = part.CropTopTransparent(0);
                        parts.Add(new ImageSplitterItem(0 + item.X, startY + croppedTop + item.Y, part));

                        startY = key + 1;
                    }

                }
            }

            if (bmp.Height - startY > 1 && parts.Count > 0)
            {
                var part = bmp.CopyRectangle(new Rectangle(0, startY, bmp.Width, bmp.Height - startY));
                if (!part.IsImageOnlyTransparent())
                {
                    //part.GetBitmap().Save(@"j:\temp\split_" + parts.Count + ".bmp");
                    var croppedTop = part.CropTopTransparent(0);
                    parts.Add(new ImageSplitterItem(0 + item.X, startY + croppedTop + item.Y, part));
                }
            }

            if (parts.Count <= 1)
            {
                return new List<ImageSplitterItem> { item };
            }

            return parts;
        }