| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635 | 
							- using Masuit.Tools.Systems;
 
- using SixLabors.ImageSharp;
 
- using SixLabors.ImageSharp.PixelFormats;
 
- using SixLabors.ImageSharp.Processing;
 
- // ReSharper disable AccessToDisposedClosure
 
- namespace Masuit.Tools.Media;
 
- /// <summary>
 
- /// 图像边框移除器
 
- /// </summary>
 
- public class ImageBorderRemover
 
- {
 
-     /// <summary>
 
-     /// 检测图片边框信息(支持多色边框)
 
-     /// </summary>
 
-     /// <param name="imagePath">图片路径</param>
 
-     /// <param name="tolerance">颜色容差(0-100),默认10</param>
 
-     /// <param name="maxLayers">最大检测边框层数,默认3</param>
 
-     /// <param name="useDownscaling">是否使用缩小采样优化性能,默认true</param>
 
-     /// <param name="downscaleFactor">缩小采样比例(1-10),默认4</param>
 
-     /// <returns>边框检测结果</returns>
 
-     public static BorderDetectionResult DetectBorders(string imagePath, int tolerance = 10, int maxLayers = 3, bool useDownscaling = true, int downscaleFactor = 4)
 
-     {
 
-         using (Image<Rgba32> image = Image.Load<Rgba32>(imagePath))
 
-         {
 
-             return DetectBorders(image, tolerance, maxLayers, useDownscaling, downscaleFactor);
 
-         }
 
-     }
 
-     /// <summary>
 
-     /// 检测图片边框信息(从已加载的图像)
 
-     /// </summary>
 
-     /// <param name="image">已加载的图像</param>
 
-     /// <param name="tolerance">颜色容差(0-100),默认10</param>
 
-     /// <param name="maxLayers">最大检测边框层数,默认3</param>
 
-     /// <param name="useDownscaling">是否使用缩小采样优化性能,默认true</param>
 
-     /// <param name="downscaleFactor">缩小采样比例(1-10),默认4</param>
 
-     /// <returns>边框检测结果</returns>
 
-     public static BorderDetectionResult DetectBorders(Image<Rgba32> image, int tolerance = 10, int maxLayers = 3, bool useDownscaling = true, int downscaleFactor = 4)
 
-     {
 
-         var result = new BorderDetectionResult
 
-         {
 
-             ImageWidth = image.Width,
 
-             ImageHeight = image.Height,
 
-             BorderColors = new List<Rgba32>(),
 
-             BorderLayers = 0
 
-         };
 
-         byte toleranceValue = (byte)(tolerance * 2.55);
 
-         // 使用多层边框检测算法
 
-         var (top, bottom, left, right, layers, colors) = FindContentBordersWithLayers(image, toleranceValue, maxLayers, useDownscaling, downscaleFactor);
 
-         // 设置内容边界
 
-         result.ContentTop = top;
 
-         result.ContentBottom = bottom;
 
-         result.ContentLeft = left;
 
-         result.ContentRight = right;
 
-         result.BorderLayers = layers;
 
-         result.BorderColors = colors;
 
-         return result;
 
-     }
 
-     /// <summary>
 
-     /// 自动移除图片的多层边框(仅当至少有两边存在边框时才裁剪)
 
-     /// </summary>
 
-     /// <param name="inputPath">输入图片路径</param>
 
-     /// <param name="tolerance">颜色容差(0-100),默认10</param>
 
-     /// <param name="maxLayers">最大检测边框层数,默认3</param>
 
-     /// <param name="useDownscaling">是否使用缩小采样优化性能,默认true</param>
 
-     /// <param name="downscaleFactor">缩小采样比例(1-10),默认4</param>
 
-     /// <returns>是否执行了裁剪操作</returns>
 
-     public static void RemoveBorders(string inputPath, int tolerance = 10, int maxLayers = 3, bool useDownscaling = true, int downscaleFactor = 4)
 
-     {
 
-         RemoveBorders(inputPath, inputPath, tolerance, maxLayers, useDownscaling, downscaleFactor);
 
-     }
 
-     /// <summary>
 
-     /// 自动移除图片的多层边框(仅当至少有两边存在边框时才裁剪)
 
-     /// </summary>
 
-     /// <param name="inputPath">输入图片路径</param>
 
-     /// <param name="outputPath">输出图片路径</param>
 
-     /// <param name="tolerance">颜色容差(0-100),默认10</param>
 
-     /// <param name="maxLayers">最大检测边框层数,默认3</param>
 
-     /// <param name="useDownscaling">是否使用缩小采样优化性能,默认true</param>
 
-     /// <param name="downscaleFactor">缩小采样比例(1-10),默认4</param>
 
-     /// <returns>是否执行了裁剪操作</returns>
 
-     public static void RemoveBorders(string inputPath, string outputPath, int tolerance = 10, int maxLayers = 3, bool useDownscaling = true, int downscaleFactor = 4)
 
-     {
 
-         using Image<Rgba32> image = Image.Load<Rgba32>(inputPath);
 
-         var hasCropped = RemoveBorders(image, tolerance, maxLayers, useDownscaling, downscaleFactor);
 
-         // 决定是否保存
 
-         if (hasCropped)
 
-         {
 
-             image.Save(outputPath);
 
-         }
 
-     }
 
-     /// <summary>
 
-     /// 自动移除图片的多层边框(仅当至少有两边存在边框时才裁剪)
 
-     /// </summary>
 
-     /// <param name="input">输入图片路径</param>
 
-     /// <param name="tolerance">颜色容差(0-100),默认10</param>
 
-     /// <param name="maxLayers">最大检测边框层数,默认3</param>
 
-     /// <param name="useDownscaling">是否使用缩小采样优化性能,默认true</param>
 
-     /// <param name="downscaleFactor">缩小采样比例(1-10),默认4</param>
 
-     /// <returns>是否执行了裁剪操作</returns>
 
-     public static PooledMemoryStream RemoveBorders(Stream input, int tolerance = 10, int maxLayers = 3, bool useDownscaling = true, int downscaleFactor = 4)
 
-     {
 
-         var format = Image.DetectFormat(input);
 
-         input.Seek(0, SeekOrigin.Begin);
 
-         Image<Rgba32> image = Image.Load<Rgba32>(input);
 
-         RemoveBorders(image, tolerance, maxLayers, useDownscaling, downscaleFactor);
 
-         var stream = new PooledMemoryStream();
 
-         image.Save(stream, format);
 
-         return stream;
 
-     }
 
-     private static bool RemoveBorders(Image<Rgba32> image, int tolerance, int maxLayers, bool useDownscaling, int downscaleFactor)
 
-     {
 
-         // 保存原始尺寸用于比较
 
-         int originalWidth = image.Width;
 
-         int originalHeight = image.Height;
 
-         // 使用多层检测方法获取边框信息
 
-         var borderInfo = DetectBorders(image, tolerance, maxLayers, useDownscaling, downscaleFactor);
 
-         bool hasCropped = false;
 
-         if (borderInfo.CanBeCropped)
 
-         {
 
-             int newWidth = borderInfo.ContentRight - borderInfo.ContentLeft + 1;
 
-             int newHeight = borderInfo.ContentBottom - borderInfo.ContentTop + 1;
 
-             if (newWidth > 0 && newHeight > 0 && (newWidth != originalWidth || newHeight != originalHeight))
 
-             {
 
-                 image.Mutate(x => x.Crop(new Rectangle(borderInfo.ContentLeft, borderInfo.ContentTop, newWidth, newHeight)));
 
-                 hasCropped = true;
 
-             }
 
-         }
 
-         return hasCropped;
 
-     }
 
-     /// <summary>
 
-     /// 查找内容边界(支持多层边框检测)
 
-     /// </summary>
 
-     private static (int top, int bottom, int left, int right, int layers, List<Rgba32> colors) FindContentBordersWithLayers(Image<Rgba32> image, byte tolerance, int maxLayers, bool useDownscaling, int downscaleFactor)
 
-     {
 
-         // 如果启用缩小采样且图像足够大
 
-         Image<Rgba32> workingImage;
 
-         float scale = 1f;
 
-         bool isDownscaled = false;
 
-         if (useDownscaling && image.Width > 500 && image.Height > 500)
 
-         {
 
-             // 计算缩小尺寸
 
-             int newWidth = image.Width / downscaleFactor;
 
-             int newHeight = image.Height / downscaleFactor;
 
-             scale = (float)image.Width / newWidth;
 
-             // 创建缩小版本用于检测
 
-             workingImage = image.Clone(ctx => ctx.Resize(newWidth, newHeight));
 
-             isDownscaled = true;
 
-         }
 
-         else
 
-         {
 
-             workingImage = image;
 
-         }
 
-         int width = workingImage.Width;
 
-         int height = workingImage.Height;
 
-         int top = 0;
 
-         int bottom = height - 1;
 
-         int left = 0;
 
-         int right = width - 1;
 
-         int layers = 0;
 
-         var borderColors = new List<Rgba32>();
 
-         // 检测多层边框
 
-         for (int layer = 0; layer < maxLayers; layer++)
 
-         {
 
-             bool borderFound = false;
 
-             // 并行检测四个方向的边框层
 
-             var results = new (int borderSize, Rgba32? color)[4];
 
-             Parallel.Invoke(() =>
 
-             {
 
-                 if (top < height / 2)
 
-                 {
 
-                     Rgba32? layerColor = null;
 
-                     int newTop = DetectLayerBorderTop(workingImage, top, bottom, left, right, tolerance, ref layerColor);
 
-                     results[0] = (newTop - top, layerColor);
 
-                     if (newTop > top) borderFound = true;
 
-                     top = newTop;
 
-                 }
 
-             }, () =>
 
-             {
 
-                 if (bottom > height / 2)
 
-                 {
 
-                     Rgba32? layerColor = null;
 
-                     int newBottom = DetectLayerBorderBottom(workingImage, top, bottom, left, right, tolerance, ref layerColor);
 
-                     results[1] = (newBottom - bottom, layerColor);
 
-                     if (newBottom < bottom) borderFound = true;
 
-                     bottom = newBottom;
 
-                 }
 
-             }, () =>
 
-             {
 
-                 if (left < width / 2)
 
-                 {
 
-                     Rgba32? layerColor = null;
 
-                     int newLeft = DetectLayerBorderLeft(workingImage, top, bottom, left, right, tolerance, ref layerColor);
 
-                     results[2] = (newLeft - left, layerColor);
 
-                     if (newLeft > left) borderFound = true;
 
-                     left = newLeft;
 
-                 }
 
-             }, () =>
 
-             {
 
-                 if (right > width / 2)
 
-                 {
 
-                     Rgba32? layerColor = null;
 
-                     int newRight = DetectLayerBorderRight(workingImage, top, bottom, left, right, tolerance, ref layerColor);
 
-                     results[3] = (newRight - right, layerColor);
 
-                     if (newRight < right) borderFound = true;
 
-                     right = newRight;
 
-                 }
 
-             });
 
-             // 收集检测到的边框颜色
 
-             foreach (var (borderSize, color) in results)
 
-             {
 
-                 if (color.HasValue && borderSize > 0)
 
-                 {
 
-                     borderColors.Add(color.Value);
 
-                 }
 
-             }
 
-             if (borderFound)
 
-             {
 
-                 layers++;
 
-             }
 
-             else
 
-             {
 
-                 break; // 没有检测到更多边框层
 
-             }
 
-         }
 
-         // 如果是缩小采样版本,映射回原图坐标
 
-         if (isDownscaled)
 
-         {
 
-             top = (int)(top * scale);
 
-             bottom = (int)(bottom * scale);
 
-             left = (int)(left * scale);
 
-             right = (int)(right * scale);
 
-             // 确保边界在图像范围内
 
-             top = Clamp(top, 0, image.Height - 1);
 
-             bottom = Clamp(bottom, top, image.Height - 1);
 
-             left = Clamp(left, 0, image.Width - 1);
 
-             right = Clamp(right, left, image.Width - 1);
 
-             // 释放缩小图像
 
-             workingImage.Dispose();
 
-         }
 
-         return (top, bottom, left, right, layers, borderColors);
 
-     }
 
-     private static int Clamp(int value, int min, int max)
 
-     {
 
-         return value < min ? min : value > max ? max : value;
 
-     }
 
-     /// <summary>
 
-     /// 检测顶部边框层(优化版)
 
-     /// </summary>
 
-     private static int DetectLayerBorderTop(Image<Rgba32> image, int currentTop, int currentBottom, int currentLeft, int currentRight, byte tolerance, ref Rgba32? borderColor)
 
-     {
 
-         int newTop = currentTop;
 
-         Rgba32? detectedColor = null;
 
-         // 使用采样检测代替全行扫描
 
-         int sampleCount = Math.Min(50, currentRight - currentLeft + 1);
 
-         int stepX = Math.Max(1, (currentRight - currentLeft) / sampleCount);
 
-         // 从当前顶部开始向下扫描
 
-         for (int y = currentTop; y <= currentBottom; y++)
 
-         {
 
-             Rgba32? rowColor = null;
 
-             bool isUniform = true;
 
-             // 采样检查行是否统一颜色
 
-             for (int x = currentLeft; x <= currentRight; x += stepX)
 
-             {
 
-                 if (!rowColor.HasValue)
 
-                 {
 
-                     rowColor = image[x, y];
 
-                     continue;
 
-                 }
 
-                 if (!IsSimilarColor(image[x, y], rowColor.Value, tolerance))
 
-                 {
 
-                     isUniform = false;
 
-                     break;
 
-                 }
 
-             }
 
-             // 如果是统一颜色行
 
-             if (isUniform && rowColor.HasValue)
 
-             {
 
-                 // 第一行总是被认为是边框
 
-                 if (y == currentTop)
 
-                 {
 
-                     detectedColor = rowColor;
 
-                     newTop = y + 1;
 
-                     continue;
 
-                 }
 
-                 // 后续行必须与第一行颜色相似
 
-                 if (detectedColor.HasValue && IsSimilarColor(rowColor.Value, detectedColor.Value, tolerance))
 
-                 {
 
-                     newTop = y + 1;
 
-                 }
 
-                 else
 
-                 {
 
-                     break;
 
-                 }
 
-             }
 
-             else
 
-             {
 
-                 break;
 
-             }
 
-         }
 
-         if (newTop > currentTop)
 
-         {
 
-             borderColor = detectedColor;
 
-             return newTop;
 
-         }
 
-         return currentTop;
 
-     }
 
-     /// <summary>
 
-     /// 检测底部边框层(优化版)
 
-     /// </summary>
 
-     private static int DetectLayerBorderBottom(Image<Rgba32> image, int currentTop, int currentBottom, int currentLeft, int currentRight, byte tolerance, ref Rgba32? borderColor)
 
-     {
 
-         int newBottom = currentBottom;
 
-         Rgba32? detectedColor = null;
 
-         // 使用采样检测代替全行扫描
 
-         int sampleCount = Math.Min(50, currentRight - currentLeft + 1);
 
-         int stepX = Math.Max(1, (currentRight - currentLeft) / sampleCount);
 
-         // 从当前底部开始向上扫描
 
-         for (int y = currentBottom; y >= currentTop; y--)
 
-         {
 
-             Rgba32? rowColor = null;
 
-             bool isUniform = true;
 
-             // 采样检查行是否统一颜色
 
-             for (int x = currentLeft; x <= currentRight; x += stepX)
 
-             {
 
-                 if (!rowColor.HasValue)
 
-                 {
 
-                     rowColor = image[x, y];
 
-                     continue;
 
-                 }
 
-                 if (!IsSimilarColor(image[x, y], rowColor.Value, tolerance))
 
-                 {
 
-                     isUniform = false;
 
-                     break;
 
-                 }
 
-             }
 
-             if (isUniform && rowColor.HasValue)
 
-             {
 
-                 if (y == currentBottom)
 
-                 {
 
-                     detectedColor = rowColor;
 
-                     newBottom = y - 1;
 
-                     continue;
 
-                 }
 
-                 if (detectedColor.HasValue && IsSimilarColor(rowColor.Value, detectedColor.Value, tolerance))
 
-                 {
 
-                     newBottom = y - 1;
 
-                 }
 
-                 else
 
-                 {
 
-                     break;
 
-                 }
 
-             }
 
-             else
 
-             {
 
-                 break;
 
-             }
 
-         }
 
-         if (newBottom < currentBottom)
 
-         {
 
-             borderColor = detectedColor;
 
-             return newBottom;
 
-         }
 
-         return currentBottom;
 
-     }
 
-     /// <summary>
 
-     /// 检测左侧边框层(优化版)
 
-     /// </summary>
 
-     private static int DetectLayerBorderLeft(Image<Rgba32> image, int currentTop, int currentBottom, int currentLeft, int currentRight, byte tolerance, ref Rgba32? borderColor)
 
-     {
 
-         int newLeft = currentLeft;
 
-         Rgba32? detectedColor = null;
 
-         // 使用采样检测代替全列扫描
 
-         int sampleCount = Math.Min(50, currentBottom - currentTop + 1);
 
-         int stepY = Math.Max(1, (currentBottom - currentTop) / sampleCount);
 
-         // 从当前左侧开始向右扫描
 
-         for (int x = currentLeft; x <= currentRight; x++)
 
-         {
 
-             Rgba32? colColor = null;
 
-             bool isUniform = true;
 
-             // 采样检查列是否统一颜色
 
-             for (int y = currentTop; y <= currentBottom; y += stepY)
 
-             {
 
-                 if (!colColor.HasValue)
 
-                 {
 
-                     colColor = image[x, y];
 
-                     continue;
 
-                 }
 
-                 if (!IsSimilarColor(image[x, y], colColor.Value, tolerance))
 
-                 {
 
-                     isUniform = false;
 
-                     break;
 
-                 }
 
-             }
 
-             if (isUniform && colColor.HasValue)
 
-             {
 
-                 if (x == currentLeft)
 
-                 {
 
-                     detectedColor = colColor;
 
-                     newLeft = x + 1;
 
-                     continue;
 
-                 }
 
-                 if (detectedColor.HasValue && IsSimilarColor(colColor.Value, detectedColor.Value, tolerance))
 
-                 {
 
-                     newLeft = x + 1;
 
-                 }
 
-                 else
 
-                 {
 
-                     break;
 
-                 }
 
-             }
 
-             else
 
-             {
 
-                 break;
 
-             }
 
-         }
 
-         if (newLeft > currentLeft)
 
-         {
 
-             borderColor = detectedColor;
 
-             return newLeft;
 
-         }
 
-         return currentLeft;
 
-     }
 
-     /// <summary>
 
-     /// 检测右侧边框层(优化版)
 
-     /// </summary>
 
-     private static int DetectLayerBorderRight(Image<Rgba32> image, int currentTop, int currentBottom, int currentLeft, int currentRight, byte tolerance, ref Rgba32? borderColor)
 
-     {
 
-         int newRight = currentRight;
 
-         Rgba32? detectedColor = null;
 
-         // 使用采样检测代替全列扫描
 
-         int sampleCount = Math.Min(50, currentBottom - currentTop + 1);
 
-         int stepY = Math.Max(1, (currentBottom - currentTop) / sampleCount);
 
-         // 从当前右侧开始向左扫描
 
-         for (int x = currentRight; x >= currentLeft; x--)
 
-         {
 
-             Rgba32? colColor = null;
 
-             bool isUniform = true;
 
-             // 采样检查列是否统一颜色
 
-             for (int y = currentTop; y <= currentBottom; y += stepY)
 
-             {
 
-                 if (!colColor.HasValue)
 
-                 {
 
-                     colColor = image[x, y];
 
-                     continue;
 
-                 }
 
-                 if (!IsSimilarColor(image[x, y], colColor.Value, tolerance))
 
-                 {
 
-                     isUniform = false;
 
-                     break;
 
-                 }
 
-             }
 
-             if (isUniform && colColor.HasValue)
 
-             {
 
-                 if (x == currentRight)
 
-                 {
 
-                     detectedColor = colColor;
 
-                     newRight = x - 1;
 
-                     continue;
 
-                 }
 
-                 if (detectedColor.HasValue && IsSimilarColor(colColor.Value, detectedColor.Value, tolerance))
 
-                 {
 
-                     newRight = x - 1;
 
-                 }
 
-                 else
 
-                 {
 
-                     break;
 
-                 }
 
-             }
 
-             else
 
-             {
 
-                 break;
 
-             }
 
-         }
 
-         if (newRight < currentRight)
 
-         {
 
-             borderColor = detectedColor;
 
-             return newRight;
 
-         }
 
-         return currentRight;
 
-     }
 
-     /// <summary>
 
-     /// 颜色相似度比较(SIMD优化)
 
-     /// </summary>
 
-     private static bool IsSimilarColor(Rgba32 color1, Rgba32 color2, byte tolerance)
 
-     {
 
-         // 使用快速比较算法
 
-         int diffR = Math.Abs(color1.R - color2.R);
 
-         int diffG = Math.Abs(color1.G - color2.G);
 
-         int diffB = Math.Abs(color1.B - color2.B);
 
-         // 快速路径:如果任一通道差异超过容差
 
-         if (diffR > tolerance || diffG > tolerance || diffB > tolerance)
 
-             return false;
 
-         // 精确比较
 
-         return diffR <= tolerance && diffG <= tolerance && diffB <= tolerance;
 
-     }
 
- }
 
- /// <summary>
 
- /// 边框检测结果(包含多层边框信息)
 
- /// </summary>
 
- public struct BorderDetectionResult
 
- {
 
-     /// <summary>原始图片宽度</summary>
 
-     public int ImageWidth { get; set; }
 
-     /// <summary>原始图片高度</summary>
 
-     public int ImageHeight { get; set; }
 
-     /// <summary>内容上边界位置</summary>
 
-     public int ContentTop { get; set; }
 
-     /// <summary>内容下边界位置</summary>
 
-     public int ContentBottom { get; set; }
 
-     /// <summary>内容左边界位置</summary>
 
-     public int ContentLeft { get; set; }
 
-     /// <summary>内容右边界位置</summary>
 
-     public int ContentRight { get; set; }
 
-     /// <summary>检测到的边框层数</summary>
 
-     public int BorderLayers { get; set; }
 
-     /// <summary>边框颜色层次(从外到内)</summary>
 
-     public List<Rgba32> BorderColors { get; set; }
 
-     /// <summary>顶部边框总宽度(像素)</summary>
 
-     public int TopBorderWidth => ContentTop;
 
-     /// <summary>底部边框总宽度(像素)</summary>
 
-     public int BottomBorderWidth => ImageHeight - 1 - ContentBottom;
 
-     /// <summary>左侧边框总宽度(像素)</summary>
 
-     public int LeftBorderWidth => ContentLeft;
 
-     /// <summary>右侧边框总宽度(像素)</summary>
 
-     public int RightBorderWidth => ImageWidth - 1 - ContentRight;
 
-     /// <summary>是否有顶部边框</summary>
 
-     public bool HasTopBorder => TopBorderWidth > 0;
 
-     /// <summary>是否有底部边框</summary>
 
-     public bool HasBottomBorder => BottomBorderWidth > 0;
 
-     /// <summary>是否有左侧边框</summary>
 
-     public bool HasLeftBorder => LeftBorderWidth > 0;
 
-     /// <summary>是否有右侧边框</summary>
 
-     public bool HasRightBorder => RightBorderWidth > 0;
 
-     /// <summary>是否有任意边框</summary>
 
-     public bool HasAnyBorder => BorderCount > 0;
 
-     /// <summary>是否满足裁剪条件(至少两个边)</summary>
 
-     public bool CanBeCropped => BorderCount >= 2;
 
-     public int BorderCount => (HasTopBorder ? 1 : 0) + (HasBottomBorder ? 1 : 0) + (HasLeftBorder ? 1 : 0) + (HasRightBorder ? 1 : 0);
 
-     /// <summary>内容区域宽度</summary>
 
-     public int ContentWidth => ContentRight - ContentLeft + 1;
 
-     /// <summary>内容区域高度</summary>
 
-     public int ContentHeight => ContentBottom - ContentTop + 1;
 
- }
 
 
  |