[C#] 如何通过Bitmap类把大图像切成小图像,或者从大图像中切取你感兴趣的区域

通过NuGet安装“System.Drawing.Common” 

 通过Bitmap类来实现大图像切割

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

...
}

实现思路:根据传入的x方向和y方向的切割区域列表进行图像切割,中间使用Bitmap来进行原始图像读取,并通过像素复制(GetPixel和SetPixel)来把原始图像指定区域的图像,保存为小图。

不好的地方

采用Bitmap类进行像素复制,速度会比较慢,比适合用来切小于超过10000X10000的图像,如果要切超大图像,考虑用Opencv来处理。

猜你喜欢

转载自blog.csdn.net/u011775793/article/details/135295280
今日推荐