diff --git a/ShareX.HelpersLib/Helpers/ImageHelpers.cs b/ShareX.HelpersLib/Helpers/ImageHelpers.cs index 5f80e86cc..9fb41280d 100644 --- a/ShareX.HelpersLib/Helpers/ImageHelpers.cs +++ b/ShareX.HelpersLib/Helpers/ImageHelpers.cs @@ -267,7 +267,7 @@ public static Bitmap CropBitmap(Bitmap bmp, Rectangle rect) } /// Automatically crop image to remove transparent outside area. - public static Bitmap AutoCropImage(Bitmap bmp) + public static Bitmap AutoCropTransparent(Bitmap bmp) { Rectangle source = new Rectangle(0, 0, bmp.Width, bmp.Height); Rectangle rect = source; @@ -354,7 +354,7 @@ public static Bitmap AutoCropImage(Bitmap bmp) } /// Automatically crop image to remove transparent outside area. Only checks center pixels. - public static Bitmap QuickAutoCropImage(Bitmap bmp) + public static Bitmap QuickAutoCropTransparent(Bitmap bmp) { Rectangle source = new Rectangle(0, 0, bmp.Width, bmp.Height); Rectangle rect = source; @@ -1645,5 +1645,126 @@ public static void DrawColorPickerIcon(Graphics g, Color color, Rectangle rect, g.DrawRectangleProper(Pens.Black, holeRect); } } + + public static Rectangle FindAutoCropRectangle(Bitmap bmp, bool sameColorCrop = false) + { + Rectangle source = new Rectangle(0, 0, bmp.Width, bmp.Height); + Rectangle crop = source; + + using (UnsafeBitmap unsafeBitmap = new UnsafeBitmap(bmp, true, ImageLockMode.ReadOnly)) + { + bool leave = false; + + ColorBgra checkColor = unsafeBitmap.GetPixel(0, 0); + + // Find X (Left to right) + for (int x = 0; x < bmp.Width && !leave; x++) + { + for (int y = 0; y < bmp.Height; y++) + { + if (unsafeBitmap.GetPixel(x, y) != checkColor) + { + crop.X = x; + leave = true; + break; + } + } + } + + // If all pixels same color + if (!leave) + { + return crop; + } + + leave = false; + + if (!sameColorCrop) + { + checkColor = unsafeBitmap.GetPixel(0, 0); + } + + // Find Y (Top to bottom) + for (int y = 0; y < bmp.Height && !leave; y++) + { + for (int x = 0; x < bmp.Width; x++) + { + if (unsafeBitmap.GetPixel(x, y) != checkColor) + { + crop.Y = y; + leave = true; + break; + } + } + } + + leave = false; + + if (!sameColorCrop) + { + checkColor = unsafeBitmap.GetPixel(bmp.Width - 1, 0); + } + + // Find Width (Right to left) + for (int x = bmp.Width - 1; x >= 0 && !leave; x--) + { + for (int y = 0; y < bmp.Height; y++) + { + if (unsafeBitmap.GetPixel(x, y) != checkColor) + { + crop.Width = x - crop.X + 1; + leave = true; + break; + } + } + } + + leave = false; + + if (!sameColorCrop) + { + checkColor = unsafeBitmap.GetPixel(0, bmp.Height - 1); + } + + // Find Height (Bottom to top) + for (int y = bmp.Height - 1; y >= 0 && !leave; y--) + { + for (int x = 0; x < bmp.Width; x++) + { + if (unsafeBitmap.GetPixel(x, y) != checkColor) + { + crop.Height = y - crop.Y + 1; + leave = true; + break; + } + } + } + } + + return crop; + } + + /// + /// If crop rectangle and source image rectangle is same then null will be returned. + /// After auto crop, source image will be disposed. + /// + public static Bitmap AutoCropImage(Bitmap bmp, bool sameColorCrop = false) + { + Rectangle source = new Rectangle(0, 0, bmp.Width, bmp.Height); + Rectangle rect = FindAutoCropRectangle(bmp, sameColorCrop); + + if (source != rect) + { + Bitmap croppedBitmap = CropBitmap(bmp, rect); + + if (croppedBitmap != null) + { + bmp.Dispose(); + return croppedBitmap; + } + } + + return null; + } } } \ No newline at end of file diff --git a/ShareX.ScreenCaptureLib/Shapes/ShapeManager.cs b/ShareX.ScreenCaptureLib/Shapes/ShapeManager.cs index 4bd7972ff..f673939af 100644 --- a/ShareX.ScreenCaptureLib/Shapes/ShapeManager.cs +++ b/ShareX.ScreenCaptureLib/Shapes/ShapeManager.cs @@ -1430,6 +1430,16 @@ private void ChangeCanvasSize() } } + private void AutoCropImage() + { + Bitmap bmp = ImageHelpers.AutoCropImage((Bitmap)Form.Canvas); + + if (bmp != null) + { + UpdateCanvas(bmp); + } + } + private void RotateImage(RotateFlipType type) { Image img = (Image)Form.Canvas.Clone(); diff --git a/ShareX.ScreenCaptureLib/Shapes/ShapeManagerMenu.cs b/ShareX.ScreenCaptureLib/Shapes/ShapeManagerMenu.cs index a4d4750a7..0c5305e5c 100644 --- a/ShareX.ScreenCaptureLib/Shapes/ShapeManagerMenu.cs +++ b/ShareX.ScreenCaptureLib/Shapes/ShapeManagerMenu.cs @@ -618,6 +618,11 @@ internal void CreateToolbar() tsmiCanvasSize.MouseDown += (sender, e) => ChangeCanvasSize(); tsddbImage.DropDownItems.Add(tsmiCanvasSize); + ToolStripMenuItem tsmiAutoCropImage = new ToolStripMenuItem("Auto crop image"); + tsmiAutoCropImage.Image = Resources.image_crop; + tsmiAutoCropImage.MouseDown += (sender, e) => AutoCropImage(); + tsddbImage.DropDownItems.Add(tsmiAutoCropImage); + tsddbImage.DropDownItems.Add(new ToolStripSeparator()); ToolStripMenuItem tsmiRotate90Clockwise = new ToolStripMenuItem(Resources.ShapeManager_CreateToolbar_Rotate90Clockwise);