通过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来处理。