/// <summary> /// 0、先生成目标文件,以防止目标空间不足。 /// 1、计算查找表 /// 2、对所有波段执行投影 /// </summary> private void ProjectToLDF(IRasterDataProvider srcRaster, FY3_VIRR_PrjSettings prjSettings, ISpatialReference dstSpatialRef, Action <int, string> progressCallback) { string outFormat = prjSettings.OutFormat; string outfilename = prjSettings.OutPathAndFileName; string dstProj4 = dstSpatialRef.ToProj4String(); List <BandMap> bandMaps = prjSettings.BandMapTable; int dstBandCount = bandMaps.Count; Size srcSize = new Size(srcRaster.Width, srcRaster.Height); Size dstSize = prjSettings.OutSize; using (IRasterDataDriver drv = GeoDataDriver.GetDriverByName("LDF") as IRasterDataDriver) { PrjEnvelope dstEnvelope = prjSettings.OutEnvelope; string mapInfo = "MAPINFO={" + 1 + "," + 1 + "}:{" + dstEnvelope.MinX + "," + dstEnvelope.MaxY + "}:{" + prjSettings.OutResolutionX + "," + prjSettings.OutResolutionY + "}"; using (IRasterDataProvider prdWriter = drv.Create(outfilename, dstSize.Width, dstSize.Height, dstBandCount, enumDataType.UInt16, "INTERLEAVE=BSQ", "VERSION=LDF", "SPATIALREF=" + dstProj4, mapInfo, "WITHHDR=TRUE") as IRasterDataProvider) { //计算查找表 //ISpatialReference srcSpatialRef = srcRaster.SpatialRef; UInt16[] dstRowLookUpTable = new UInt16[dstSize.Width * dstSize.Height]; UInt16[] dstColLookUpTable = new UInt16[dstSize.Width * dstSize.Height]; _rasterProjector.ComputeIndexMapTable(_xs, _ys, srcSize, dstSize, dstEnvelope, _maxPrjEnvelope, out dstRowLookUpTable, out dstColLookUpTable, progressCallback); //执行投影 UInt16[] srcBandData = new UInt16[srcSize.Width * srcSize.Height]; UInt16[] dstBandData = new UInt16[dstSize.Width * dstSize.Height]; int progress = 0; for (int i = 0; i < dstBandCount; i++) //读取原始通道值,投影到目标区域 { if (progressCallback != null) { progress = (int)((i + 1) * 100 / dstBandCount); progressCallback(progress, string.Format("投影第{0}共{1}通道", i + 1, dstBandCount)); } BandMap bandMap = bandMaps[i]; ReadBandData(srcBandData, bandMap.File, bandMap.DatasetName, bandMap.BandIndex, srcSize); if (prjSettings.IsRadiation) { DoRadiation(srcBandData, srcSize, bandMap.DatasetName, bandMap.BandIndex, prjSettings.IsSolarZenith); } _rasterProjector.Project <UInt16>(srcBandData, srcSize, dstRowLookUpTable, dstColLookUpTable, dstSize, dstBandData, 0, progressCallback); using (IRasterBand band = prdWriter.GetRasterBand(i + 1)) { unsafe { fixed(UInt16 *ptr = dstBandData) { IntPtr bufferPtr = new IntPtr(ptr); band.Write(0, 0, band.Width, band.Height, bufferPtr, enumDataType.UInt16, band.Width, band.Height); } } } } } } }
/// <summary> /// 0、先生成目标文件,以防止目标空间不足。 /// 1、计算查找表 /// 2、读取通道数据 /// 3、计算通道数据亮温 /// 4、投影通道。 /// </summary> private void ProjectToLDF(IRasterDataProvider srcRaster, NOAA_PrjSettings prjSettings, ISpatialReference dstSpatialRef, Action <int, string> progressCallback) { string outFormat = prjSettings.OutFormat; string outfilename = prjSettings.OutPathAndFileName; string dstProj4 = dstSpatialRef.ToProj4String(); int[] outBandNos = prjSettings.OutBandNos; int dstBandCount = outBandNos.Length; Size srcSize = new Size(srcRaster.Width, srcRaster.Height); Size dstSize = prjSettings.OutSize; Size srcJdSize = srcSize; using (IRasterDataDriver drv = GeoDataDriver.GetDriverByName("LDF") as IRasterDataDriver) { PrjEnvelope dstEnvelope = prjSettings.OutEnvelope; string[] options = new string[] { "INTERLEAVE=BSQ", "VERSION=LDF", "WITHHDR=TRUE", "SPATIALREF=" + dstSpatialRef.ToProj4String(), "MAPINFO={" + 1 + "," + 1 + "}:{" + dstEnvelope.MinX + "," + dstEnvelope.MaxY + "}:{" + prjSettings.OutResolutionX + "," + prjSettings.OutResolutionY + "}" , "BANDNAMES=" + BandNameString(prjSettings.OutBandNos) }; if (progressCallback != null) { progressCallback(6, "生成输出文件"); } using (IRasterDataProvider prdWriter = drv.Create(outfilename, dstSize.Width, dstSize.Height, dstBandCount, enumDataType.UInt16, options) as IRasterDataProvider) { float outResolutionX = prjSettings.OutResolutionX; float outResolutionY = prjSettings.OutResolutionY; Size outSize = dstEnvelope.GetSize(outResolutionX, outResolutionY); int blockXNum = 0; int blockYNum = 0; int blockWidth = 0; int blockHeight = 0; GetBlockNumber(outSize, out blockXNum, out blockYNum, out blockWidth, out blockHeight); Size dstBlockSize = new Size(blockWidth, blockHeight); UInt16[] dstRowBlockLUT = new UInt16[blockWidth * blockHeight]; UInt16[] dstColBlockLUT = new UInt16[blockWidth * blockHeight]; int blockCount = blockYNum * blockXNum; int progress = 0; int percent = 0; int progressCount = blockCount * dstBandCount; for (int blockYIndex = 0; blockYIndex < blockYNum; blockYIndex++) { for (int blockXIndex = 0; blockXIndex < blockXNum; blockXIndex++) { PrjEnvelope blockEnvelope = null; Block orbitBlock = null; //经纬度数据集,计算轨道数据范围偏移 double[] blockOrbitXs = null; double[] blockOrbitYs = null; if (blockCount == 1) //没分块的情况 { orbitBlock = _orbitBlock; if (_orbitBlock.Width == srcJdSize.Width && _orbitBlock.Height == srcJdSize.Height) { blockOrbitXs = _xs; blockOrbitYs = _ys; } else //源 { GetBlockDatas(_xs, _ys, srcJdSize.Width, srcJdSize.Height, orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Width, orbitBlock.Height, out blockOrbitXs, out blockOrbitYs); } blockEnvelope = dstEnvelope; } else { //当前块的四角范围 double blockMinX = dstEnvelope.MinX + blockWidth * outResolutionX * blockXIndex; double blockMaxX = blockMinX + blockWidth * outResolutionX; double blockMaxY = dstEnvelope.MaxY - blockHeight * outResolutionY * blockYIndex; double blockMinY = blockMaxY - blockHeight * outResolutionY; blockEnvelope = new PrjEnvelope(blockMinX, blockMaxX, blockMinY, blockMaxY); //根据当前输出块,反推出对应的源数据块起始行列 GetEnvelope(_xs, _ys, srcJdSize.Width, srcJdSize.Height, blockEnvelope, out orbitBlock); if (orbitBlock.Width <= 0 || orbitBlock.Height <= 0) //当前分块不在图像内部 { progress += dstBandCount; continue; } GetBlockDatas(_xs, _ys, srcJdSize.Width, srcJdSize.Height, orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Width, orbitBlock.Height, out blockOrbitXs, out blockOrbitYs); } float[] solarZenithData = null; if (prjSettings.IsRadiation && prjSettings.IsSolarZenith) { if (File.Exists(_szDataFilename)) { ReadBandData(out solarZenithData, _solarZenithCacheRaster, 1, orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Width, orbitBlock.Height); } TryReadZenithData(orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Width, orbitBlock.Height); } Size orbitBlockSize = new Size(orbitBlock.Width, orbitBlock.Height); _rasterProjector.ComputeIndexMapTable(blockOrbitXs, blockOrbitYs, orbitBlockSize, dstBlockSize, blockEnvelope, _maxPrjEnvelope, out dstRowBlockLUT, out dstColBlockLUT, null); //执行投影 UInt16[] srcBandData = new UInt16[orbitBlock.Width * orbitBlock.Height]; UInt16[] dstBandData = new UInt16[blockWidth * blockHeight]; for (int i = 0; i < dstBandCount; i++) //读取原始通道值,投影到目标区域 { if (progressCallback != null) { progress++; percent = progress * 100 / progressCount; progressCallback(percent, string.Format("投影第{0}/{1}块,第{2}/{3}通道", blockXIndex + blockYIndex, blockCount, i + 1, dstBandCount)); } int bandNo = outBandNos[i]; ReadBandData(srcBandData, srcRaster, bandNo, orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Width, orbitBlock.Height); if (prjSettings.IsRadiation) { DoRadiation(srcBandData, orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Size, bandNo, prjSettings.IsRadiation, prjSettings.IsSolarZenith, solarZenithData); } _rasterProjector.Project <UInt16>(srcBandData, orbitBlock.Size, dstRowBlockLUT, dstColBlockLUT, dstBlockSize, dstBandData, 0, null); IRasterBand band = prdWriter.GetRasterBand(i + 1); { unsafe { fixed(UInt16 *ptr = dstBandData) { IntPtr bufferPtr = new IntPtr(ptr); int blockOffsetY = blockYIndex * dstBlockSize.Height; int blockOffsetX = blockXIndex * dstBlockSize.Width; band.Write(blockOffsetX, blockOffsetY, blockWidth, blockHeight, bufferPtr, enumDataType.UInt16, blockWidth, blockHeight); } } } } ReleaseZenithData(); srcBandData = null; dstBandData = null; blockOrbitXs = null; blockOrbitYs = null; } } dstRowBlockLUT = null; dstColBlockLUT = null; } } }