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); | |
} | |
} | |
} | |
} |