[C#] How to cut a large image into small images through the Bitmap class, or cut out the area of interest from a large image

Install "System.Drawing.Common" via NuGet 

 Implement large image cutting through Bitmap class

using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing.Imaging;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
...

namespace ManualCounterPoint
{
    class CutRange
    {
        public int Start { set; get; } = -1;
        public int End { set; get; } = -1;
    }

    class CutROI
    {
        public int X { set; get; } = -1;
        public int Y { set; get; } = -1;
        public int Width { set; get; } = -1;
        public int Height { set; get; } = -1;
    }
    class CutResultJson
    {
        public string SrcImagePath { set; get; } = "";
        public List<CutRange> XRanges { set; get; } = new List<CutRange>();
        public List<CutRange> YRanges { set; get; } = new List<CutRange>();
        public Dictionary<string, CutROI> ImageInfos { set; get; } = new Dictionary<string, CutROI>();
    }
    class ImageCutter
    {
        public static string Cut(string imgPath, List<CutRange> xRanges, List<CutRange> yRanges,  string saveDir, string fileExt)
        {
            try
            {
                if (System.IO.Directory.Exists(saveDir))
                {
                    System.IO.Directory.Delete(saveDir, true);
                }
                if (!System.IO.Directory.Exists(saveDir))
                {
                    System.IO.Directory.CreateDirectory(saveDir);
                }
                xRanges.Sort((x, y) => { return x.Start.CompareTo(y.Start); });
                yRanges.Sort((x, y) => { return x.Start.CompareTo(y.Start); });
                CutResultJson resultJson = new CutResultJson();
                resultJson.SrcImagePath = imgPath;
                resultJson.XRanges = xRanges;
                resultJson.YRanges = yRanges;

                Bitmap srcImg = new Bitmap(imgPath);
                for (int j = 0; j < yRanges.Count; j++)
                {
                    for (int i = 0; i < xRanges.Count; i++)
                    {
                        string cutImgName = $"{j}_{i}_{xRanges[i].Start}_{yRanges[j].Start}" + "." + fileExt;
                        int cutHeight = yRanges[j].End - yRanges[j].Start;
                        int cutWidth = xRanges[i].End - xRanges[i].Start;
                        Bitmap cutImg = new Bitmap(cutWidth, cutHeight);
                        int cutOffsetX = 0;
                        for (int offsetX = xRanges[i].Start; offsetX < xRanges[i].End; offsetX++)
                        {
                            int cutOffsetY = 0;
                            for (int offsetY = yRanges[j].Start; offsetY < yRanges[j].End; offsetY++)
                            {
                                if (offsetX >= 0 && offsetX < srcImg.Width && offsetY >= 0 && offsetY < srcImg.Height)
                                {
                                    cutImg.SetPixel(cutOffsetX, cutOffsetY, srcImg.GetPixel(offsetX, offsetY));
                                    
                                }
                                cutOffsetY++;
                            }
                            cutOffsetX++;
                        }
                        resultJson.ImageInfos[cutImgName] = new CutROI() { 
                            X= xRanges[i].Start, Y= yRanges[j].Start, Height = cutHeight, Width = cutWidth 
                        };

                        ImageFormat format = ImageFormat.Png;
                        switch (fileExt.ToLower())
                        {
                            case "png":
                                format = ImageFormat.Png;
                                break;
                            case "bmp":
                                format = ImageFormat.Bmp;
                                break;
                            case "jpg":
                                format = ImageFormat.Jpeg;
                                break;
                        }
                        var saveCutPath = System.IO.Path.Combine(saveDir, cutImgName);
                        cutImg.Save(saveCutPath, format);
                        cutImg.Dispose();
                    }
                }

                srcImg.Dispose();
                var resultPath = System.IO.Path.Combine(saveDir, "cut_result.json");
                JsonUtils.ToJsonFile(resultJson, resultPath);
                return "";
            }catch(Exception ex)
            {
                return $"发生错误:{ex.Message}";
            }
        }
    }

...
}

Implementation idea: Carry out image cutting according to the incoming cutting area list in the x direction and y direction, use Bitmap to read the original image, and use pixel copy (GetPixel and SetPixel) to save the image of the specified area of ​​the original image as Small picture.

Bad place

Using the Bitmap class for pixel copying will be slower and is more suitable for cutting images smaller than 10000X10000. If you want to cut very large images, consider using Opencv to process them.

Guess you like

Origin blog.csdn.net/u011775793/article/details/135295280