c#|GDAL-读取影像的金字塔,生成快视图

之前使用GDAL提取快视图时,使用的是直接读取原始影像的方式,但之前遇到一次原始影像有坏块的情况,无法读取,所以想试试通过读取金字塔来生成快视图 我觉得从原理上来说,这样也应该会更快一些,不过没有验证过
经测试,GDAL自身在RASTERIO时,如果有抽稀的操作,会自动去读取金字塔,这种实现没有意义!这个思路是错误的,仅留作存档
////// 读取影像的金字塔,从中提取取一个合适的级别,转成JPG格式,从而生成快视图 ////// 源影像 /// 生成JPG文件的路径 /// 输入的参考比例(例如,输入10,表示生成一个长宽均为源影像1/10的格式,但由于各级金字塔的比例不一定与该值完全相等,为避免进行重采样计算,程序会找一个最接近的等级,所以最终的快视图比例与这个值不一定相等) /// 生成的快视图宽度方向像素数 /// 生成的快视图高度方向像素数 /// 【c#|GDAL-读取影像的金字塔,生成快视图】错误信息 /// 是否生成成功 public bool pyramidToQuickshow(Dataset dsin, string quickshowPath,int scale,out int quickShowWidth,out int quickShowHeight, out string errMsg) { #region 一些基本检查 quickShowWidth = 0; quickShowHeight = 0; errMsg = ""; //确认是8BIT的影像数据 if (dsin.GetRasterBand(1).DataType != DataType.GDT_Byte) { errMsg = "暂不支持8位BYTE之外的数据"; return false; } //确认影像已经有金字塔 string[] files = dsin.GetFileList(); bool findRRD = false; for (int i = 0; i < files.Length; i++) { if (files[i].ToLower().EndsWith(".rrd")) { findRRD = true; break; } } int pyramidCount = ds.GetRasterBand(1).GetOverviewCount(); if (!findRRD && pyramidCount == 0) { errMsg = "影像文件未建立金字塔"; return false; } #endregion //用于输出的Driver,因为GDAL的JPEG Driver似乎不支持直接生成文件并写入,所以用一个内存Driver写入 //并复制一个JPEG Driver drijpg = Gdal.GetDriverByName("JPEG"); Driver drimen = Gdal.GetDriverByName("MEM"); int rasterCount = dsin.RasterCount; //波段数 #region 找出与输入的scale最接近的金字塔等级,并将其确认为提取的等级,并记录该等级金字塔的长宽 int resLevel = 0, minVal = 0, resScale = 0; for (int i = 0; i < pyramidCount; i++) { Band tmpBand = ds.GetRasterBand(1).GetOverview(i); if (i == 0) { minVal = Math.Abs(ds.RasterXSize / tmpBand.XSize - scale); resScale = ds.RasterXSize / tmpBand.XSize; quickShowWidth = tmpBand.XSize; quickShowHeight = tmpBand.YSize; } else { int tmpInt = Math.Abs(ds.RasterXSize / tmpBand.XSize - scale); if (tmpInt < minVal) { minVal = tmpInt; resLevel = i; resScale = ds.RasterXSize / tmpBand.XSize; quickShowWidth = tmpBand.XSize; quickShowHeight = tmpBand.YSize; } } } #endregion #region 读取各波段对应等级的金字塔,保存到一个列表中 List bands = new List(); //金字塔波段的列表 for (int i = 0; i < rasterCount; i++) { Band tmpBand = ds.GetRasterBand(i + 1).GetOverview(resLevel); bands.Add(tmpBand); } #endregion #region 新建快视图(JPG)对应的Dataset,并向其中写入数据 Dataset dout = drimen.Create(quickshowPath, quickShowWidth,quickShowHeight, rasterCount, DataType.GDT_Byte, null); //为避免因影像过大无法一次读取并写入完毕,这里按进行读取和写入 //以下为按行读取的一些参数 int rows = 1000000 / quickShowWidth; //一次读取的行数(正常情况下) int readCount = quickShowHeight / rows; //读取的次数 if (quickShowHeight % rows != 0) readCount++; //不能整除的话,还需要多读一次 byte[] raw = null; //读取和写入用到的数组 //开始读取并写入数据 for (int i = 0; i < bands.Count ; i++) { int tmpHeight = rows; //一次读取的行数 raw = new byte[rows * quickShowWidth]; Band tmpBand2 = dout.GetRasterBand(i + 1); for (int j = 0; j < readCount; j++) { //如果是最后一次读取,且行数不能整除一次读取的行数时,那要对剩余部分作一次单独的读取 if (j == readCount - 1 && quickShowHeight % rows != 0) { raw = null; tmpHeight = quickShowHeight % rows; raw = new byte[quickShowWidth * tmpHeight]; } bands[i].ReadRaster(0, j * rows, quickShowWidth, tmpHeight, raw, quickShowWidth, tmpHeight, 0, 0); tmpBand2.WriteRaster(0, j * rows, quickShowWidth, tmpHeight, raw, quickShowWidth, tmpHeight, 0, 0); } dout.FlushCache(); } #endregion drijpg.CreateCopy(quickshowPath, dout, 1, null, null, null); dout.Dispose(); return true; }

    推荐阅读