这段时间项目进行过程中,需要用到图片拼接和裁剪的功能,因为拼接出来的图片超大,BitMap有大小限制,就使用GDAL进行图像的拼接和裁剪,下面是一些用法。
1,需要引用GDAL 的dll包,这个可以在管理GuGet程序包里下载引用
图像拼接
/// <summary>
///
/// </summary>
/// <param name="srcDs">小图数据</param>
/// <param name="outDs">输出的大图数据</param>
/// <param name="x">小图序号</param>
/// <param name="startPix_X">起始X坐标</param>
/// <param name="startPix_Y"><起始y坐标/param>
private static void SaveBitMapBuffer(Dataset srcDs, Dataset outDs, int x, int startPix_X, int startPix_Y)
{
if (srcDs.RasterCount < 1)
{
return;
}
int width = srcDs.RasterXSize;
int height = srcDs.RasterYSize;
byte[] buf = new byte[width * height];
srcDs.ReadRaster(0, 0, width, height, buf, width, height, 1, new int[] { 1 }, 0, 0, 0);
outDs.WriteRaster(x * width - x * startPix_X, startPix_Y * x, width, height, buf, width, height, 1, new int[] { 1 }, 0, 0, 0);
}
//因为拼接成的图片不止一张,fileNameTable 的key是输出文件名,value是存放小图路径名的集合,
//如果只是拼接一张图片的话可以直接传入一个输出文件名outFileName和list集合
public static void CombineTiles(Dictionary<string, List<string>> fileNameTable,int startPix_X, int startPix_Y )
{
if (fileNameTable.Count < 1)
{
return;
}
try
{
Gdal.AllRegister();
foreach (KeyValuePair<string, List<string>> kvp in fileNameTable)
{
string outFileName = kvp.Key;
List<string> fileNames = kvp.Value;
int imageWidth;
int imageHeight;
using (Dataset fristFileDs = Gdal.Open(kvp.Value[0], Access.GA_ReadOnly))
{
//合成图片的大小
imageWidth = fristFileDs.RasterXSize * fileNames.Count - (startPix_X* (fileNames.Count - 1));
imageHeight = fristFileDs.RasterYSize + (startPix_Y * (fileNames.Count - 1));
}
Driver driver = Gdal.GetDriverByName("GTiff");
if (File.Exists(outFileName))
{
File.Delete(outFileName);
}
using (Dataset outDs = driver.Create(outFileName, imageWidth, imageHeight, 1, DataType.GDT_Byte, null))
{
for (int i = 0; i < fileNames.Count; i++)
{
string file = fileNames[i];
if (File.Exists(file))
{
using (Dataset srcDs = Gdal.Open(file, Access.GA_ReadOnly))
{
if (srcDs != null)
{
SaveBitMapBuffer(srcDs, outDs, i, startPix_X, startPix_Y);
}
}
//srcDs.Dispose();
//srcDs.CommitTransaction();
}
Console.WriteLine("写入图片数量:" + (i + 1) + ",剩余数量:" + (fileNames.Count - 1 - i));
}
//outDs.FlushCache();
// outDs.Dispose();
}
}
}
catch
{
throw;
}
}
裁图部分
// loopNum 循环次数
static void TestCutPicture(String srcFileName, int startX, int startY, int dWidth, int dHeight, int loopNum)
{
Gdal.AllRegister();
Dataset srcDs;
try
{
srcDs = Gdal.Open(srcFileName, Access.GA_ReadOnly);
}
catch
{
Console.WriteLine("文件被其他线程访问!");
return;
}
//Dataset srcDs = Gdal.Open(srcFileName, Access.GA_ReadOnly);
DataType srcType = srcDs.GetRasterBand(1).DataType;
int bandCount = srcDs.RasterCount;
double[] adfGeoTransform = new double[6];
srcDs.GetGeoTransform(adfGeoTransform);
int[] dataArray = new int[dWidth * dHeight * bandCount];
int[] bandArray = new int[1];
bandArray[0] = 1;
try
{
for (int i = 1; i <= loopNum; i++)
{
SavePath = "";//保存路径 + 文件名
Driver drv = Gdal.GetDriverByName("GTIFF");
Dataset dstDs = drv.Create(SavePath.Replace(" ", ""), dWidth, dHeight, bandCount, srcType, null);
dstDs.SetGeoTransform(adfGeoTransform);
dstDs.SetProjection(srcDs.GetProjectionRef());
srcDs.ReadRaster(startX, startY, dWidth, dHeight, dataArray, dWidth, dHeight, bandCount, bandArray, 0, 0, 0);
dstDs.WriteRaster(0, 0, dWidth, dHeight, dataArray, dWidth, dHeight, bandCount, bandArray, 0, 0, 0);
dstDs.FlushCache();
dstDs.Dispose();
startX = (int)(startX + dWidth );
Console.WriteLine(SavePath+" 创建成功!");
}
}
catch (Exception ex)
{
return;
}
srcDs.Dispose();
}
OK,结束,因为代码是直接从项目上拷下来的,也许有一些地方不适用,欢迎留言评论,我看到会回复的。