Based on the original stackoverflow post: https://stackoverflow.com/questions/248141/remove-surrounding-whitespace-from-an-image
Updated to work with SKBitmap.
Based on the original stackoverflow post: https://stackoverflow.com/questions/248141/remove-surrounding-whitespace-from-an-image
Updated to work with SKBitmap.
| using SkiaSharp; | |
| using System; | |
| // | |
| // Based on the original stackoverflow post: https://stackoverflow.com/questions/248141/remove-surrounding-whitespace-from-an-image | |
| // | |
| namespace BlahBlah | |
| { | |
| public static class BitmapExtensions | |
| { | |
| public static SKBitmap TrimWhitespace(this SKBitmap bmp) | |
| { | |
| int w = bmp.Width; | |
| int h = bmp.Height; | |
| // get all the pixels here - this can take a while so dont want it in the loops below | |
| // maybe theres a more efficient way? loading all the pixels could be greedy | |
| var pixels = bmp.Pixels; | |
| bool IsTransparent(SKColor color) | |
| { | |
| return (color.Red == 0 && color.Green == 0 && color.Blue == 0 && color.Alpha == 0) || | |
| (color == SKColors.Transparent); | |
| } | |
| Func<int, bool> allWhiteRow = row => | |
| { | |
| for (int i = 0; i < w; ++i) | |
| { | |
| var px = row * w + i; | |
| if (!IsTransparent(pixels[px])) | |
| return false; | |
| } | |
| return true; | |
| }; | |
| Func<int, bool> allWhiteColumn = col => | |
| { | |
| for (int i = 0; i < h; ++i) | |
| { | |
| var px = col * h + i; | |
| if (!IsTransparent(pixels[px])) | |
| return false; | |
| } | |
| return true; | |
| }; | |
| int topmost = 0; | |
| for (int row = 0; row < h; ++row) | |
| { | |
| if (allWhiteRow(row)) | |
| topmost = row; | |
| else break; | |
| } | |
| int bottommost = 0; | |
| for (int row = h - 1; row >= 0; --row) | |
| { | |
| if (allWhiteRow(row)) | |
| bottommost = row; | |
| else break; | |
| } | |
| int leftmost = 0, rightmost = 0; | |
| for (int col = 0; col < w; ++col) | |
| { | |
| if (allWhiteColumn(col)) | |
| leftmost = col; | |
| else | |
| break; | |
| } | |
| for (int col = w - 1; col >= 0; --col) | |
| { | |
| if (allWhiteColumn(col)) | |
| rightmost = col; | |
| else | |
| break; | |
| } | |
| if (rightmost == 0) rightmost = w; // As reached left | |
| if (bottommost == 0) bottommost = h; // As reached top. | |
| int croppedWidth = rightmost - leftmost; | |
| int croppedHeight = bottommost - topmost; | |
| if (croppedWidth == 0) // No border on left or right | |
| { | |
| leftmost = 0; | |
| croppedWidth = w; | |
| } | |
| if (croppedHeight == 0) // No border on top or bottom | |
| { | |
| topmost = 0; | |
| croppedHeight = h; | |
| } | |
| try | |
| { | |
| var target = new SKBitmap(croppedWidth, croppedHeight); | |
| using var canvas = new SKCanvas(target); | |
| using var img = SKImage.FromBitmap(bmp); | |
| canvas.DrawImage(img, | |
| new SKRect(leftmost, topmost, rightmost, bottommost), | |
| new SKRect(0, 0, croppedWidth, croppedHeight)); | |
| return target; | |
| } | |
| catch (Exception ex) | |
| { | |
| throw new Exception( | |
| string.Format("Values are topmost={0} btm={1} left={2} right={3} croppedWidth={4} croppedHeight={5}", topmost, bottommost, leftmost, rightmost, croppedWidth, croppedHeight), | |
| ex); | |
| } | |
| } | |
| } | |
| } |