public static List <ImageSplitterItem> SplitVertical(NikseBitmap bmp) { // 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 < 6) { size++; // at least 5 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)); } 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> SplitToLinesByMinTransparentHorizontalLines(NikseBitmap bmp, int minLineHeight, int minTransparentLines) { var parts = new List <ImageSplitterItem>(); var startY = 0; var lastTransparentY = -1; var keysInSequence = 0; for (int y = minLineHeight; y < bmp.Height - minLineHeight; y++) { var isLineTransparent = bmp.IsLineTransparent(y); if (startY == y && isLineTransparent) { startY++; continue; // skip start } if (isLineTransparent) { if (lastTransparentY == y - 1) { if (keysInSequence == 0) { keysInSequence++; } keysInSequence++; } if (keysInSequence > 2 && lastTransparentY - startY > minLineHeight) { var part = bmp.CopyRectangle(new Rectangle(0, startY, bmp.Width, lastTransparentY - startY - 1)); if (!part.IsImageOnlyTransparent() && part.GetNonTransparentHeight() >= minLineHeight) { var croppedTop = part.CropTopTransparent(0); parts.Add(new ImageSplitterItem(0, startY + croppedTop, part)); startY = lastTransparentY + 1; } } lastTransparentY = y; } else { keysInSequence = 0; lastTransparentY = -1; } } if (bmp.Height - startY > 1) { var part = bmp.CopyRectangle(new Rectangle(0, startY, bmp.Width, bmp.Height - startY)); if (!part.IsImageOnlyTransparent()) { var croppedTop = part.CropTopTransparent(0); parts.Add(new ImageSplitterItem(0, startY + croppedTop, part)); } } return(parts); }
public static List <ImageSplitterItem> SplitVerticalTransparentOrBlack(NikseBitmap bmp, int lineMinHeight) { 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++) { Color c = bmp.GetPixel(x, y); if (c.A > 20 && c.R + c.G + c.B > 20) { allTransparent = false; break; } } if (allTransparent) { if (size > 2 && size <= 15) { size++; // at least 15 pixels, like top of 'i' or top of 'È' } else { if (size > 8) { 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) { 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); }
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 = 0; x < bmp.Width; 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 h = bmp.Height; bool bottomCroppingDone = false; for (int y = bmp.Height - 1; y > 3; y--) { for (int x = 0; x < bmp.Width; x++) { int a = bmp.GetAlpha(x, y); if (a != 0) { bottomCroppingDone = true; break; } } h = y; if (bottomCroppingDone) { break; } } if (h - startTop + 1 <= 0) { return(new NikseBitmap(0, 0)); } return(bmp.CopyRectangle(new Rectangle(0, startTop, bmp.Width, h - startTop + 1))); }
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 = 0; x < bmp.Width; x++) { int a = bmp.GetAlpha(x, y); if (a != 0) { allTransparent = false; break; } } if (!allTransparent) { break; } startTop++; } topCropping = startTop; int h = bmp.Height; bool bottomCroppingDone = false; for (int y = bmp.Height - 1; y > 3; y--) { for (int x = 0; x < bmp.Width; x++) { int a = bmp.GetAlpha(x, y); if (a != 0) { bottomCroppingDone = true; break; } } h = y; if (bottomCroppingDone) { break; } } if (h - startTop + 1 <= 0) { return(new NikseBitmap(0, 0)); } return(bmp.CopyRectangle(new Rectangle(0, startTop, bmp.Width, h - startTop + 1))); }
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 List <ImageSplitterItem> SplitToLinesTransparentOrBlack(NikseBitmap bmp) { 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++) { var c = bmp.GetPixel(x, y); if (c.A > 20 && c.R + c.G + c.B > 20) { allTransparent = false; break; } } if (allTransparent) { if (size > 2 && size <= 15) { size++; // at least 15 pixels, like top of 'i' or top of 'È' } else { if (size > 8) { 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) { parts.Add(size == bmp.Height ? new ImageSplitterItem(0, startY, bmp) : new ImageSplitterItem(0, startY, bmp.CopyRectangle(new Rectangle(0, startY, bmp.Width, size + 1)))); } return(parts); }
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; }
public static List<ImageSplitterItem> SplitVerticalTransparentOrBlack(NikseBitmap bmp) { 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++) { Color c = bmp.GetPixel(x, y); if (c.A > 20 && c.R + c.G + c.B > 20) { allTransparent = false; break; } } if (allTransparent) { if (size > 2 && size <= 15) { size++; // at least 15 pixels, like top of 'i' or top of 'È' } else { if (size > 8) { 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) 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; }
private static IEnumerable <ImageSplitterItem> SplitHorizontalNew(ImageSplitterItem lineSplitterItem, int xOrMorePixelsMakesSpace) { var bmp = new NikseBitmap(lineSplitterItem.NikseBitmap); bmp.AddTransparentLineRight(); var parts = new List <ImageSplitterItem>(); int startX = 0; int width = 0; int spacePixels = 0; int subtractSpacePixels = 0; for (int x = 0; x < bmp.Width; x++) { bool right; bool clean; List <Point> points = IsVerticalLineTransparetNew(bmp, x, out right, out clean); if (points != null && clean) { spacePixels++; } if (right && points != null) { int add = FindMaxX(points, x) - x; width += add; subtractSpacePixels = add; } var newStartX = points != null?FindMinX(points, x) : 0; if (points == null) { width++; } else if (width > 0 && newStartX > startX + 1) { var bmp0 = new NikseBitmap(bmp); // remove pixels after current; for (int index = 0; index < points.Count; index++) { var p = points[index]; bmp0.MakeVerticalLinePartTransparent(p.X, p.X + index, p.Y); } width = FindMaxX(points, x) - startX; width--; startX++; var b1 = bmp0.CopyRectangle(new Rectangle(startX, 0, width, bmp.Height)); int addY; b1 = CropTopAndBottom(b1, out addY); if (spacePixels >= xOrMorePixelsMakesSpace && parts.Count > 0) { parts.Add(new ImageSplitterItem(" ") { Y = addY + lineSplitterItem.Y }); } if (b1.Width > 0 && b1.Height > 0) { parts.Add(new ImageSplitterItem(startX + lineSplitterItem.X, addY + lineSplitterItem.Y, b1)); //y is what? } // remove pixels before next letter; const int begin = 0; foreach (var p in points) { bmp.MakeVerticalLinePartTransparent(begin, p.X, p.Y); } width = 1; startX = FindMinX(points, x); spacePixels = -subtractSpacePixels; subtractSpacePixels = 0; } else if (clean) { width = 1; startX = newStartX; } } return(parts); }
private static List <ImageSplitterItem> SplitHorizontal(ImageSplitterItem verticalItem, int xOrMorePixelsMakesSpace) { // split line into letters NikseBitmap bmp = verticalItem.NikseBitmap; var parts = new List <ImageSplitterItem>(); int size = 0; int startX = 0; int lastEndX = 0; bool spaceJustAdded = false; for (int x = 0; x < bmp.Width - 1; x++) { int y; bool allTransparent = IsVerticalLineTransparent(bmp, out y, x); // check if line is transparent and cursive bool cursiveOk = false; int tempY; if (allTransparent == false && size > 5 && y > 3 && x < bmp.Width - 2 && !IsVerticalLineTransparent(bmp, out tempY, x + 1)) { //Add space? if (lastEndX > 0 && lastEndX + xOrMorePixelsMakesSpace < startX) { int cleanCount = 0; for (int j = lastEndX; j < startX; j++) { if (IsVerticalLineTransparentAlphaOnly(bmp, j)) { cleanCount++; } } if (cleanCount > 0 && !spaceJustAdded) { parts.Add(new ImageSplitterItem(" ")); spaceJustAdded = true; } } var cursivePoints = new List <Point>(); cursiveOk = IsCursiveVerticalLineTransparent(bmp, size, y, x, cursivePoints); if (cursiveOk) { // make letter image int end = x + 1 - startX; if (startX > 0) { startX--; end++; } NikseBitmap b1 = bmp.CopyRectangle(new Rectangle(startX, 0, end, bmp.Height)); // b1.Save(@"d:\temp\cursive.bmp"); // just for debugging // make non-black/transparent stuff from other letter transparent foreach (Point p in cursivePoints) { for (int fixY = p.Y; fixY < bmp.Height; fixY++) { b1.SetPixel(p.X - startX, fixY, Color.Transparent); } } RemoveBlackBarRight(b1); // b1.Save(@"d:\temp\cursive-cleaned.bmp"); // just for debugging // crop and save image int addY; b1 = CropTopAndBottom(b1, out addY); parts.Add(new ImageSplitterItem(startX, verticalItem.Y + addY, b1)); spaceJustAdded = false; size = 0; startX = x + 1; lastEndX = x; } } if (!cursiveOk) { if (allTransparent) { if (size > 0) { if (size > 1) { //Add space? if (lastEndX > 0 && lastEndX + xOrMorePixelsMakesSpace < startX) { int cleanCount = 0; for (int j = lastEndX; j < startX; j++) { if (IsVerticalLineTransparentAlphaOnly(bmp, j)) { cleanCount++; } } if (cleanCount > 2 && !spaceJustAdded) { parts.Add(new ImageSplitterItem(" ")); } } if (startX > 0) { startX--; } lastEndX = x; int end = x + 1 - startX; NikseBitmap part = bmp.CopyRectangle(new Rectangle(startX, 0, end, bmp.Height)); RemoveBlackBarRight(part); int addY; // part.Save("c:\\before" + startX.ToString() + ".bmp"); // just for debugging part = CropTopAndBottom(part, out addY); // part.Save("c:\\after" + startX.ToString() + ".bmp"); // just for debugging parts.Add(new ImageSplitterItem(startX, verticalItem.Y + addY, part)); spaceJustAdded = false; // part.Save(@"d:\temp\cursive.bmp"); // just for debugging } size = 0; } startX = x + 1; } else { size++; } } } if (size > 0) { if (lastEndX > 0 && lastEndX + xOrMorePixelsMakesSpace < startX && !spaceJustAdded) { parts.Add(new ImageSplitterItem(" ")); } if (startX > 0) { startX--; } lastEndX = bmp.Width - 1; int end = lastEndX + 1 - startX; NikseBitmap part = bmp.CopyRectangle(new Rectangle(startX, 0, end, bmp.Height - 1)); int addY; part = CropTopAndBottom(part, out addY); parts.Add(new ImageSplitterItem(startX, verticalItem.Y + addY, part)); //part.Save(@"d:\temp\cursive.bmp"); // just for debugging } return(parts); }
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); }
internal static ImageSplitterItem GetExpandedSelection(NikseBitmap bitmap, List<ImageSplitterItem> expandSelectionList, bool rightToLeft) { if (rightToLeft) { int minimumX = expandSelectionList[expandSelectionList.Count - 1].X - expandSelectionList[expandSelectionList.Count - 1].NikseBitmap.Width; int maximumX = expandSelectionList[0].X; int minimumY = expandSelectionList[0].Y; int maximumY = expandSelectionList[0].Y + expandSelectionList[0].NikseBitmap.Height; foreach (ImageSplitterItem item in expandSelectionList) { if (item.Y < minimumY) minimumY = item.Y; if (item.Y + item.NikseBitmap.Height > maximumY) maximumY = item.Y + item.NikseBitmap.Height; } var part = bitmap.CopyRectangle(new Rectangle(minimumX, minimumY, maximumX - minimumX, maximumY - minimumY)); return new ImageSplitterItem(minimumX, minimumY, part); } else { int minimumX = expandSelectionList[0].X; int maximumX = expandSelectionList[expandSelectionList.Count - 1].X + expandSelectionList[expandSelectionList.Count - 1].NikseBitmap.Width; int minimumY = expandSelectionList[0].Y; int maximumY = expandSelectionList[0].Y + expandSelectionList[0].NikseBitmap.Height; foreach (ImageSplitterItem item in expandSelectionList) { if (item.Y < minimumY) minimumY = item.Y; if (item.Y + item.NikseBitmap.Height > maximumY) maximumY = item.Y + item.NikseBitmap.Height; } var part = bitmap.CopyRectangle(new Rectangle(minimumX, minimumY, maximumX - minimumX, maximumY - minimumY)); return new ImageSplitterItem(minimumX, minimumY, part); } }
private static IEnumerable<ImageSplitterItem> SplitHorizontalNew(ImageSplitterItem lineSplitterItem, int xOrMorePixelsMakesSpace) { var bmp = new NikseBitmap(lineSplitterItem.NikseBitmap); bmp.AddTransparentLineRight(); var parts = new List<ImageSplitterItem>(); int startX = 0; int width = 0; int spacePixels = 0; int subtractSpacePixels = 0; for (int x = 0; x < bmp.Width; x++) { bool right; bool clean; List<Point> points = IsVerticalLineTransparetNew(bmp, x, out right, out clean); if (points != null && clean) { spacePixels++; } if (right && points != null) { int add = FindMaxX(points, x) - x; width = width + add; subtractSpacePixels = add; } if (points == null) { width++; } else if (width > 1) { var bmp0 = new NikseBitmap(bmp); // remove pixels after current; int k = 0; foreach (Point p in points) { bmp0.MakeVerticalLinePartTransparent(p.X, p.X + k, p.Y); k++; } width = FindMaxX(points, x) - startX; width++; NikseBitmap b1 = bmp0.CopyRectangle(new Rectangle(startX, 0, width, bmp.Height)); if (spacePixels >= xOrMorePixelsMakesSpace && parts.Count > 0) parts.Add(new ImageSplitterItem(" ")); int addY; b1 = CropTopAndBottom(b1, out addY); parts.Add(new ImageSplitterItem(startX + lineSplitterItem.X, addY + lineSplitterItem.Y, b1)); //y is what? // remove pixels before next letter; int begin = 0; foreach (Point p in points) { bmp.MakeVerticalLinePartTransparent(begin, p.X, p.Y); } width = 1; startX = FindMinX(points, x); spacePixels = -subtractSpacePixels; subtractSpacePixels = 0; } else { width = 1; startX = FindMinX(points, x); } } 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++) { if (bmp.IsLineTransparent(y)) { // check for appendix below text bool appendix = y >= bmp.Height - minLineHeight; if (!appendix && y < bmp.Height - 10 && size > minLineHeight && minLineHeight > 15) { bool yp1 = bmp.IsLineTransparent(y + 1); bool yp2 = bmp.IsLineTransparent(y + 2); bool yp3 = bmp.IsLineTransparent(y + 3); bool yp4 = bmp.IsLineTransparent(y + 4); bool yp5 = bmp.IsLineTransparent(y + 5); if (!yp1 || !yp2 || !yp3 || !yp4 || !yp5) { bool yp6 = bmp.IsLineTransparent(y + 6); bool yp7 = bmp.IsLineTransparent(y + 7); bool yp8 = bmp.IsLineTransparent(y + 8); bool yp9 = bmp.IsLineTransparent(y + 9); if (yp6 && yp7 && yp8 && yp9) { appendix = true; } } } if (appendix || 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); }
/// <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 && 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 && 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 > 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); }
private CompareMatch GetCompareMatchNew(ImageSplitterItem targetItem, NikseBitmap parentBitmap, out CompareMatch secondBestGuess, List<ImageSplitterItem> list, int listIndex) { double maxDiff = (double)numericUpDownMaxErrorPct.Value; secondBestGuess = null; int index = 0; int smallestDifference = 10000; int smallestIndex = -1; NikseBitmap target = targetItem.NikseBitmap; if (_binaryOcrDb == null) { secondBestGuess = null; return null; } foreach (BinaryOcrBitmap compareItem in _binaryOcrDb.CompareImages) { // check for expand match! if (compareItem.ExpandCount > 0 && compareItem.Width > target.Width && parentBitmap.Width >= compareItem.Width + targetItem.X) // && parentBitmap.Height >= compareItem.Bitmap.Height + targetItem.Y) //NIXE-debug-test- what not correct? { int minY = targetItem.Y; for (int j = 1; j < compareItem.ExpandCount; j++) { if (list != null && list.Count > listIndex + j && list[listIndex + j].Y < minY) minY = list[listIndex + j].Y; } if (parentBitmap.Height >= compareItem.Height + minY) { var cutBitmap = parentBitmap.CopyRectangle(new Rectangle(targetItem.X, minY, compareItem.Width, compareItem.Height)); int dif = NikseBitmapImageSplitter.IsBitmapsAlike(compareItem, cutBitmap); if (dif < smallestDifference) { bool allow = true; if (Math.Abs(target.Height - compareItem.Height) > 5 && compareItem.Text == "\"") allow = false; if (allow) { smallestDifference = dif; smallestIndex = index; if (dif == 0) break; // foreach ending } } } } index++; } // Search images with minor location changes FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, target, _binaryOcrDb); if (maxDiff > 0) { if (smallestDifference * 100.0 / (target.Width * target.Height) > _vobSubOcrSettings.AllowDifferenceInPercent && target.Width < 70) { if (smallestDifference > 2 && target.Width > 25) { var cutBitmap = target.CopyRectangle(new Rectangle(4, 0, target.Width - 4, target.Height)); FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, cutBitmap, _binaryOcrDb); double differencePercentage = smallestDifference * 100.0 / (target.Width * target.Height); } if (smallestDifference > 2 && target.Width > 12) { var cutBitmap = target.CopyRectangle(new Rectangle(1, 0, target.Width - 2, target.Height)); FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, cutBitmap, _binaryOcrDb); } if (smallestDifference > 2 && target.Width > 12) { var cutBitmap = target.CopyRectangle(new Rectangle(0, 0, target.Width - 2, target.Height)); FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, cutBitmap, _binaryOcrDb); } if (smallestDifference > 2 && target.Width > 12) { var cutBitmap = target.CopyRectangle(new Rectangle(1, 0, target.Width - 2, target.Height)); int topCrop = 0; var cutBitmap2 = NikseBitmapImageSplitter.CropTopAndBottom(cutBitmap, out topCrop, 2); if (cutBitmap2.Height != target.Height) FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, cutBitmap2, _binaryOcrDb); } if (smallestDifference > 2 && target.Width > 15) { var cutBitmap = target.CopyRectangle(new Rectangle(1, 0, target.Width - 2, target.Height)); int topCrop = 0; var cutBitmap2 = NikseBitmapImageSplitter.CropTopAndBottom(cutBitmap, out topCrop); if (cutBitmap2.Height != target.Height) FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, cutBitmap2, _binaryOcrDb); } if (smallestDifference > 2 && target.Width > 15) { var cutBitmap = target.CopyRectangle(new Rectangle(1, 0, target.Width - 2, target.Height)); int topCrop = 0; var cutBitmap2 = NikseBitmapImageSplitter.CropTopAndBottom(cutBitmap, out topCrop); if (cutBitmap2.Height != target.Height) FindBestMatchNew(ref index, ref smallestDifference, ref smallestIndex, cutBitmap2, _binaryOcrDb); } } } if (smallestIndex >= 0) { double differencePercentage = smallestDifference * 100.0 / (target.Width * target.Height); if (differencePercentage <= maxDiff) { var hit = _binaryOcrDb.CompareImages[smallestIndex]; string text = hit.Text; int h = hit.Height; if (text == "V" || text == "W" || text == "U" || text == "S" || text == "Z" || text == "O" || text == "X" || text == "Ø" || text == "C") { if (_binOcrLastLowercaseHeight > 3 && h - _nocrLastLowercaseHeight < 2) text = text.ToLower(); } else if (text == "v" || text == "w" || text == "u" || text == "s" || text == "z" || text == "o" || text == "x" || text == "ø" || text == "c") { if (_binOcrLastUppercaseHeight > 3 && _binOcrLastUppercaseHeight - h < 2) text = text.ToUpper(); } hit.Text = text; if (smallestDifference < 0.1) SetBinOcrLowercaseUppercase(hit.Height, hit.Text); return new CompareMatch(hit.Text, hit.Italic, hit.ExpandCount, hit.Text + "_" + hit.Hash.ToString()); } var guess = _binaryOcrDb.CompareImages[smallestIndex]; secondBestGuess = new CompareMatch(guess.Text, guess.Italic, guess.ExpandCount, guess.Text + "_" + guess.Hash.ToString()); } return null; }
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 CompareMatch GetCompareMatch(ImageSplitterItem targetItem, NikseBitmap parentBitmap, out CompareMatch secondBestGuess, List<ImageSplitterItem> list, int listIndex) { secondBestGuess = null; int index = 0; int smallestDifference = 10000; int smallestIndex = -1; NikseBitmap target = targetItem.NikseBitmap; if (_compareBitmaps == null) { secondBestGuess = null; return null; } foreach (CompareItem compareItem in _compareBitmaps) { // check for expand match! if (compareItem.ExpandCount > 0 && compareItem.Bitmap.Width > target.Width && parentBitmap.Width >= compareItem.Bitmap.Width + targetItem.X) // && parentBitmap.Height >= compareItem.Bitmap.Height + targetItem.Y) //NIXE-debug-test- what not correct? { int minY = targetItem.Y; for (int j = 1; j < compareItem.ExpandCount; j++) { if (list != null && list.Count > listIndex + j && list[listIndex + j].Y < minY) minY = list[listIndex + j].Y; } if (parentBitmap.Height >= compareItem.Bitmap.Height + minY) { var cutBitmap = parentBitmap.CopyRectangle(new Rectangle(targetItem.X, minY, compareItem.Bitmap.Width, compareItem.Bitmap.Height)); int dif = NikseBitmapImageSplitter.IsBitmapsAlike(compareItem.Bitmap, cutBitmap); if (dif < smallestDifference) { bool allow = true; if (Math.Abs(target.Height - compareItem.Bitmap.Height) > 5 && compareItem.Text == "\"") allow = false; if (allow) { smallestDifference = dif; smallestIndex = index; if (dif == 0) break; // foreach ending } } } } index++; } // Search images with minor location changes FindBestMatch(ref index, ref smallestDifference, ref smallestIndex, target, _compareBitmaps); if (smallestDifference * 100.0 / (target.Width * target.Height) > _vobSubOcrSettings.AllowDifferenceInPercent && target.Width < 70) { if (smallestDifference > 2 && target.Width > 25) { var cutBitmap = target.CopyRectangle(new Rectangle(4, 0, target.Width - 4, target.Height)); FindBestMatch(ref index, ref smallestDifference, ref smallestIndex, cutBitmap, _compareBitmaps); double differencePercentage = smallestDifference * 100.0 / (target.Width * target.Height); } if (smallestDifference > 2 && target.Width > 12) { var cutBitmap = target.CopyRectangle(new Rectangle(1, 0, target.Width - 2, target.Height)); FindBestMatch(ref index, ref smallestDifference, ref smallestIndex, cutBitmap, _compareBitmaps); } if (smallestDifference > 2 && target.Width > 12) { var cutBitmap = target.CopyRectangle(new Rectangle(0, 0, target.Width - 2, target.Height)); FindBestMatch(ref index, ref smallestDifference, ref smallestIndex, cutBitmap, _compareBitmaps); } if (smallestDifference > 2 && target.Width > 12) { var cutBitmap = target.CopyRectangle(new Rectangle(1, 0, target.Width - 2, target.Height)); int topCrop = 0; var cutBitmap2 = NikseBitmapImageSplitter.CropTopAndBottom(cutBitmap, out topCrop, 2); if (cutBitmap2.Height != target.Height) FindBestMatch(ref index, ref smallestDifference, ref smallestIndex, cutBitmap2, _compareBitmaps); } if (smallestDifference > 2 && target.Width > 15) { var cutBitmap = target.CopyRectangle(new Rectangle(1, 0, target.Width - 2, target.Height)); int topCrop = 0; var cutBitmap2 = NikseBitmapImageSplitter.CropTopAndBottom(cutBitmap, out topCrop); if (cutBitmap2.Height != target.Height) FindBestMatch(ref index, ref smallestDifference, ref smallestIndex, cutBitmap2, _compareBitmaps); } if (smallestDifference > 2 && target.Width > 15) { var cutBitmap = target.CopyRectangle(new Rectangle(1, 0, target.Width - 2, target.Height)); int topCrop = 0; var cutBitmap2 = NikseBitmapImageSplitter.CropTopAndBottom(cutBitmap, out topCrop); if (cutBitmap2.Height != target.Height) FindBestMatch(ref index, ref smallestDifference, ref smallestIndex, cutBitmap2, _compareBitmaps); } } if (smallestIndex >= 0) { double differencePercentage = smallestDifference * 100.0 / (target.Width * target.Height); double maxDiff = (double)numericUpDownMaxErrorPct.Value; if (differencePercentage <= maxDiff) { var hit = _compareBitmaps[smallestIndex]; return new CompareMatch(hit.Text, hit.Italic, hit.ExpandCount, hit.Name); } var guess = _compareBitmaps[smallestIndex]; secondBestGuess = new CompareMatch(guess.Text, guess.Italic, guess.ExpandCount, guess.Name); } return null; }