private void ReadyArgs(AbstractWarpDataset srcRaster, FilePrjSettings prjSettings, SpatialReference dstSpatialRef, Action <int, string> progressCallback) { float resolutionScale = 1f; _readyProgress = 0; if (progressCallback != null) { progressCallback(_readyProgress++, "准备相关参数"); } _prjSettings = ArgsCheck(srcRaster, prjSettings); _geoDataProvider = _prjSettings.GeoFile; CheckIs0250(srcRaster); _dstSpatialRef = dstSpatialRef; switch (_dataType) { case "1KM": //整轨投影时候去除左右锯齿,分块投影不需要 _left = 10; _right = 10; if (_prjSettings.OutEnvelope == null || _prjSettings.OutEnvelope == PrjEnvelope.Empty) //整轨投影时做限制 { MemoryHelper.MemoryNeed(500, 1536); } else { MemoryHelper.MemoryNeed(400, 1536); //剩余900MB,已使用1.2GB } //_angleDataProvider = srcRaster; TryCreateDefaultArgs(srcRaster, _prjSettings, ref _dstSpatialRef); TrySetLeftRightInvalidPixel(_prjSettings.ExtArgs); DoSession(srcRaster, _geoDataProvider, _dstSpatialRef, _prjSettings, progressCallback); break; case "QKM": resolutionScale = 4f; _left = 20; _right = 20; if (_prjSettings.OutEnvelope == null || _prjSettings.OutEnvelope == PrjEnvelope.Empty) { MemoryHelper.MemoryNeed(800, 1280); //整幅投影对内存做限制,系统剩余内存不低于A参数MB,应用程序已使用内存不超过B参数MB } else { MemoryHelper.MemoryNeed(600, 1280); //剩余900MB,最大已使用1.2GB } //_angleDataProvider = _prjSettings.SecondaryOrbitRaster; TryCreate0250DefaultArgs(srcRaster, _prjSettings, ref _dstSpatialRef); TrySetLeftRightInvalidPixel(_prjSettings.ExtArgs); DoSession(srcRaster, _geoDataProvider, _dstSpatialRef, _prjSettings, progressCallback); break; default: break; } if (_prjSettings.OutEnvelope == null || _prjSettings.OutEnvelope == PrjEnvelope.Empty) { _prjSettings.OutEnvelope = _maxPrjEnvelope; _orbitBlock = new Block { xBegin = 0, yBegin = 0, xEnd = _srcLocationSize.Width - 1, yEnd = _srcLocationSize.Height - 1 }; } else { if (_xs != null && _ys != null) { GetEnvelope(_xs, _ys, _srcLocationSize.Width, _srcLocationSize.Height, _prjSettings.OutEnvelope, out _orbitBlock); } else { int bC = 8; int tmpWidth = 0; int tmpHeight = 0; double[] tmpxs = null; double[] tmpys = null; //8024,8000 tmpWidth = _srcLocationSize.Width / bC; tmpHeight = _srcLocationSize.Height / bC; tmpxs = ReadSampleDatas(_longitudeBand, 0, 0, tmpWidth, tmpHeight); tmpys = ReadSampleDatas(_latitudeBand, 0, 0, tmpWidth, tmpHeight); _rasterProjector.Transform(wgs84, tmpxs, tmpys, _dstSpatialRef); //计算偏移 GetEnvelope(tmpxs, tmpys, tmpWidth, tmpHeight, _prjSettings.OutEnvelope, out _orbitBlock); _orbitBlock = _orbitBlock.Zoom(bC, bC); } if (_orbitBlock == null || _orbitBlock.Width <= 0 || _orbitBlock.Height <= 0) { throw new Exception("数据不在目标区间内"); } float invalidPresent = (_orbitBlock.Width * _orbitBlock.Height * resolutionScale) / (_srcLocationSize.Width * _srcLocationSize.Height); if (invalidPresent < 0.0001f) { throw new Exception("数据占轨道数据比例太小,有效率" + invalidPresent * 100 + "%"); } if (invalidPresent > 0.60) { _orbitBlock = new Block { xBegin = 0, yBegin = 0, xEnd = _srcLocationSize.Width - 1, yEnd = _srcLocationSize.Height - 1 } } ; } //以下参数用于投影 _dstEnvelope = _prjSettings.OutEnvelope; if (!_dstEnvelope.IntersectsWith(_maxPrjEnvelope)) { throw new Exception("数据不在目标区间内"); } _outResolutionX = _prjSettings.OutResolutionX; _outResolutionY = _prjSettings.OutResolutionY; _outFormat = _prjSettings.OutFormat; _outfilename = _prjSettings.OutPathAndFileName; _dstProj4 = _dstSpatialRef.ExportToProj4(); _dstBandCount = _prjBands.Length; _dstSize = _prjSettings.OutSize; _isRadRef = _prjSettings.IsRadRef; _isSolarZenith = _prjSettings.IsSolarZenith; _isSensorZenith = _prjSettings.IsSensorZenith; _isRad = _prjSettings.IsRad; }
private void ReadyArgs(AbstractWarpDataset srcRaster, FilePrjSettings prjSettings, SpatialReference dstSpatialRef, Action <int, string> progressCallback) { if (srcRaster == null) { throw new ArgumentNullException("srcRaster"); } if (prjSettings == null) { throw new ArgumentNullException("prjSettings"); } _readyProgress = 0; base._prjSettings = prjSettings; _prjSettings = prjSettings as NPP_PrjSetting; _geoDataProvider = iBandGeoDataset == null ? mBandGeoDataset : iBandGeoDataset; if (_geoDataProvider == null) { throw new ArgumentNullException("NPP数据投影,未加载到正确的GEO数据集"); } _dstSpatialRef = dstSpatialRef; MemoryHelper.MemoryNeed(200, 1536); //剩余200MB,已使用1.2GB progressCallback?.Invoke(_readyProgress++, "准备相关参数"); TryCreateDefaultArgs(srcRaster, _prjSettings, ref dstSpatialRef); //这里去除的是读取轨道数据时候的左右像元个数。 _left = 8; _right = 8; TrySetLeftRightInvalidPixel(_prjSettings.ExtArgs); DoSession(srcRaster, _geoDataProvider, dstSpatialRef, _prjSettings, progressCallback); if (prjSettings.OutEnvelope == null || prjSettings.OutEnvelope == PrjEnvelope.Empty) { prjSettings.OutEnvelope = _maxPrjEnvelope; _orbitBlock = new Block { xBegin = 0, yBegin = 0, xEnd = srcRaster.Width - 1, yEnd = srcRaster.Height - 1 }; } else { GetEnvelope(_xs, _ys, srcRaster.Width, srcRaster.Height, _prjSettings.OutEnvelope, out _orbitBlock); if (_orbitBlock == null || _orbitBlock.Width <= 0 || _orbitBlock.Height <= 0) { throw new Exception("数据不在目标区间内"); } float invalidPresent = (_orbitBlock.Width * _orbitBlock.Height * 1.0F) / (srcRaster.Width * srcRaster.Height); if (invalidPresent < 0.0001f) { throw new Exception("数据占轨道数据比例太小,有效率" + invalidPresent * 100 + "%"); } if (invalidPresent > 0.60) { _orbitBlock = new Block { xBegin = 0, yBegin = 0, xEnd = srcRaster.Width - 1, yEnd = srcRaster.Height - 1 } } ; } //if (dstSpatialRef.Type == SpatialReferenceType.GeographicCS && (prjSettings.OutEnvelope.MaxY > 80 || prjSettings.OutEnvelope.MaxY < -80)) // throw new Exception(string.Format("高纬度数据,不适合投影为等经纬度数据[{0}]", _maxPrjEnvelope)); _dstSpatialRef = dstSpatialRef; _dstEnvelope = _prjSettings.OutEnvelope; if (!_dstEnvelope.IntersectsWith(_maxPrjEnvelope)) { throw new Exception("数据不在目标区间内"); } _outResolutionX = _prjSettings.OutResolutionX; _outResolutionY = _prjSettings.OutResolutionY; _outFormat = _prjSettings.OutFormat; _outfilename = _prjSettings.OutPathAndFileName; _dstProj4 = _dstSpatialRef.ExportToProj4(); _dstBandCount = _prjBands.Length; _dstSize = _prjSettings.OutSize; _isRadRef = _prjSettings.IsRadRef; _isSolarZenith = _prjSettings.IsSolarZenith; _isSensorZenith = _prjSettings.IsSensorZenith; _isRad = _prjSettings.IsRad; }
private void ProjectRaster <T>(AbstractWarpDataset srcRaster, FilePrjSettings prjSettings, Action <int, string> progressCallback, AbstractWarpDataset prdWriter, T fillValue, double dataWeight, float zoom) { DataType dataType = prdWriter.DataType; PrjEnvelope outEnvelope = prjSettings.OutEnvelope; float outResolutionX = prjSettings.OutResolutionX; float outResolutionY = prjSettings.OutResolutionY; Size outSize = prjSettings.OutSize; int outWidth = outSize.Width; int outHeight = outSize.Height; int outBandCount = prjSettings.OutBandNos.Length; if (progressCallback != null) { progressCallback(_readyProgress++, "投影准备"); } int srcHeight = srcRaster.Height; int srcWidth = srcRaster.Width; PrjPoint outLeftTopPoint = outEnvelope.LeftTop; float srcResolutionX = srcRaster.ResolutionX; float srcResolutionY = srcRaster.ResolutionY; Size srcSize = new Size(srcWidth, srcHeight); double outLtPointX = outLeftTopPoint.X; double outLtPointY = outLeftTopPoint.Y; PrjEnvelope srcEnvelope = new PrjEnvelope(srcRaster.GetEnvelope().MinX, srcRaster.GetEnvelope().MaxX, srcRaster.GetEnvelope().MinY, srcRaster.GetEnvelope().MaxY, null); ulong mem = MemoryHelper.GetAvalidPhyMemory(); #if !WIN64 mem = mem < 800 * 1024 * 1024 ? mem : 800 * 1024 * 1024; #endif ulong maxLimit = mem / (6 * 8 * 2); int rowStep = (int)(maxLimit / (UInt32)outWidth); if (rowStep == 0) { rowStep = 1; } if (rowStep > outHeight) { rowStep = outHeight; } int stepCount = (int)(Math.Ceiling((double)outHeight / rowStep)); int percent = 0; int progress = 0; int progressCount = outBandCount * stepCount + stepCount * 2; for (int oRow = 0; oRow < outHeight; oRow += rowStep) { if (progressCallback != null) { percent++; progress = percent * 100 / progressCount; progressCallback(progress, string.Format("投影完成{0}%", progress)); } if (oRow + rowStep > outHeight) { rowStep = outHeight - oRow; } Size outStepSize = new Size(outWidth, rowStep); double[] xs = new double[outWidth * rowStep]; double[] ys = new double[outWidth * rowStep]; double oY = oRow * outResolutionY; Parallel.For(0, rowStep, j => { double x; double y; int index; y = outLtPointY - j * outResolutionY - oY; for (int i = 0; i < outWidth; i++) { x = outLtPointX + i * outResolutionX; index = i + j * outWidth; xs[index] = x; ys[index] = y; } }); _projectionTransform.InverTransform(xs, ys); PrjEnvelope tEnvelope = PrjEnvelope.GetEnvelope(xs, ys, null); tEnvelope.Extend(srcResolutionX, srcResolutionY * 4); tEnvelope = PrjEnvelope.Intersect(tEnvelope, srcEnvelope); if (tEnvelope == null || tEnvelope.IsEmpty) { continue; } Size tSize = tEnvelope.GetSize(srcResolutionX, srcResolutionY); int tBeginRow = -1, tEndRow = -1, tBeginCol = -1, tEndCol = -1; int oBeginRow = -1, oEndRow = -1, oBeginCol = -1, oEndCol = -1; PrjBlockHelper.ComputeBeginEndRowCol(srcEnvelope, srcSize, tEnvelope, tSize, ref oBeginRow, ref oBeginCol, ref oEndRow, ref oEndCol, ref tBeginRow, ref tBeginCol, ref tEndRow, ref tEndCol); int srcStepWidth = oEndCol - oBeginCol; int srcStepHeight = oEndRow - oBeginRow; Size srcStepSize = new Size(srcStepWidth, srcStepHeight); T[] srcBandData = new T[srcStepWidth * srcStepHeight]; T[] dstBandData = new T[outWidth * rowStep]; double srcStepLeftTopX = tEnvelope.MinX; double srcStepLeftTopY = tEnvelope.MaxY; double srcStepRightBottomX = tEnvelope.MaxX; double srcStepRightBottomY = tEnvelope.MinY; UInt16[] rows = new UInt16[outWidth * rowStep]; //正向查找表 UInt16[] cols = new UInt16[outWidth * rowStep]; //正向查找表 if (progressCallback != null) { percent++; progress = percent * 100 / progressCount; progressCallback(progress, string.Format("投影完成{0}%", progress)); } Parallel.For(0, rowStep, j => { double x; double y; int index; for (int i = 0; i < outWidth; i++) { index = i + j * outWidth; x = xs[index]; y = ys[index]; if (x >= srcStepLeftTopX && x <= srcStepRightBottomX && y <= srcStepLeftTopY && y >= srcStepRightBottomY) { cols[index] = (UInt16)((x - srcStepLeftTopX) / srcResolutionX + 0.5); rows[index] = (UInt16)((srcStepLeftTopY - y) / srcResolutionY + 0.5); } } }); xs = null; ys = null; for (int b = 0; b < outBandCount; b++) { if (progressCallback != null) { percent++; progress = percent * 100 / progressCount; progressCallback(progress, string.Format("投影完成{0}%", progress)); } ReadBandData <T>(srcBandData, b, oBeginCol, oBeginRow, srcStepWidth, srcStepHeight, dataType); //用于测试全图输出结果,用于查看插值的效果: #if DebugEaseGrid GCHandle hTe = GCHandle.Alloc(srcBandData, GCHandleType.Pinned); try { Random random = new Random(12); IntPtr bufferPtr = hTe.AddrOfPinnedObject(); Int16[] tmp = new Int16[srcBandData.Length]; for (int i = 0; i < srcBandData.Length; i++) { tmp[i] = (Int16)random.Next(200, 255); } Marshal.Copy(tmp, 0, bufferPtr, tmp.Length); } finally { hTe.Free(); } #endif _rasterProjector.Project <T>(srcBandData, srcStepSize, rows, cols, outStepSize, dstBandData, fillValue, 0, null); if (dataWeight == 1) { WriteDataToLDF <T>(prdWriter, dataType, outWidth, rowStep, oRow, dstBandData, b); } else { WriteDataToLDF <T>(prdWriter, dataType, outWidth, rowStep, oRow, dstBandData, b, dataWeight, zoom); } } rows = null; rows = null; srcBandData = null; dstBandData = null; } }
// 2 private void ProjectRaster(AbstractWarpDataset srcRaster, FilePrjSettings prjSettings, AbstractWarpDataset prdWriter, Action <int, string> progressCallback, UInt16 fillValue, int beginBandIndex, double dataWeight, float zoom) { var timer = System.Diagnostics.Stopwatch.StartNew(); //输出数据类型 float outResolutionX = prjSettings.OutResolutionX; float outResolutionY = prjSettings.OutResolutionY; Size outSize = prjSettings.OutSize; int outWidth = outSize.Width; int outHeight = outSize.Height; int outBandCount = prjSettings.OutBandNos.Length; if (progressCallback != null) { progressCallback(_readyProgress++, "投影准备"); } int srcHeight = srcRaster.Height; int srcWidth = srcRaster.Width; PrjPoint outLeftTopPoint = prjSettings.OutEnvelope.LeftTop; //源数据的分辨率 float srcResolutionX = Convert.ToSingle(_srcGeoTrans[1]); float srcResolutionY = Math.Abs(Convert.ToSingle(_srcGeoTrans[5])); //输入数据的大小 Size srcSize = new Size() { Width = srcWidth, Height = srcHeight }; //输出数据的左上角地理坐标 double outLtPointX = outLeftTopPoint.X; double outLtPointY = outLeftTopPoint.Y; //输入数据源的坐标范围 PrjEnvelope srcEnvelope = new PrjEnvelope(_srcGeoTrans[0], _srcGeoTrans[0] + srcWidth * _srcGeoTrans[1], _srcGeoTrans[3] + srcHeight * _srcGeoTrans[5], _srcGeoTrans[3], _srcSpatialRef); ulong mem = MemoryHelper.GetAvalidPhyMemory(); mem = mem > 10.0 * 1024 * 1024 * 1024 ? Convert.ToUInt64(10.0 * 1024 * 1024 * 1024) : mem; ulong maxLimit = mem / (6 * 8); int rowStep = (int)(maxLimit / (UInt32)outWidth); if (rowStep == 0) { rowStep = 1; } if (rowStep > outHeight) { rowStep = outHeight; } int stepCount = (int)(Math.Ceiling((double)outHeight / rowStep)); int percent = 0; int progress = 0; int progressCount = outBandCount * stepCount + stepCount * 2; long stepGeolocationTime = 0, stepReadDataTime = 0, stepRadiationTime = 0, stepProjectRasterTime = 0, stepWriteDataTime = 0; for (int oRow = 0; oRow < outHeight; oRow += rowStep) { if (progressCallback != null) { percent++; progress = percent * 100 / progressCount; progressCallback(progress, string.Format("投影完成{0}%", progress)); } if (oRow + rowStep > outHeight) { rowStep = outHeight - oRow; } //经纬度数据 double[] xs, ys; UInt16[] rows, cols; try { xs = new double[outWidth * rowStep]; ys = new double[outWidth * rowStep]; rows = new UInt16[outWidth * rowStep]; cols = new UInt16[outWidth * rowStep]; } catch (Exception ex) { throw; } Size srcStepSize = new Size(); Block oBlock, tBlock; timer.Restart(); #region 初始化查找表 { double oY = oRow * outResolutionY; Parallel.For(0, rowStep, j => { double x; double y; int index; y = outLtPointY - j * outResolutionY - oY; for (int i = 0; i < outWidth; i++) { x = outLtPointX + i * outResolutionX; index = i + j * outWidth; xs[index] = x; ys[index] = y; } }); GeosInverCorrection(_dstSpatialRef, xs, ys); _projectionTransform.InverTransform(xs, ys); PrjEnvelope tEnvelope = PrjEnvelope.GetEnvelope(xs, ys, null); tEnvelope.Extend(srcResolutionX, srcResolutionY * 4); tEnvelope = PrjEnvelope.Intersect(tEnvelope, srcEnvelope); if (tEnvelope == null || tEnvelope.IsEmpty) { continue; } Size tSize = tEnvelope.GetSize(srcResolutionX, srcResolutionY); PrjBlockHelper.ComputeBlock(srcEnvelope, srcSize, tEnvelope, tSize, out oBlock, out tBlock); int srcStepWidth = oBlock.xEnd - oBlock.xBegin; int srcStepHeight = oBlock.yEnd - oBlock.yBegin; srcStepSize = new Size(srcStepWidth, srcStepHeight); double srcStepLeftTopX = tEnvelope.MinX; double srcStepLeftTopY = tEnvelope.MaxY; double srcStepRightBottomX = tEnvelope.MaxX; double srcStepRightBottomY = tEnvelope.MinY; if (progressCallback != null) { percent++; progress = percent * 100 / progressCount; } Parallel.For(0, rowStep, j => { double x; double y; int index; for (int i = 0; i < outWidth; i++) { index = i + j * outWidth; x = xs[index]; y = ys[index]; if (x >= srcStepLeftTopX && x <= srcStepRightBottomX && y <= srcStepLeftTopY && y >= srcStepRightBottomY) { cols[index] = (UInt16)((x - srcStepLeftTopX) / srcResolutionX + 0.5); rows[index] = (UInt16)((srcStepLeftTopY - y) / srcResolutionY + 0.5); } } }); xs = null; ys = null; } #endregion stepGeolocationTime += timer.ElapsedMilliseconds; //输入波段数据缓冲区 UInt16[] srcBandData = new UInt16[srcStepSize.Width * srcStepSize.Height]; //输出波段数据缓冲区 UInt16[] dstBandData = new UInt16[outWidth * rowStep]; //逐波段写入数据 for (int b = beginBandIndex; b < outBandCount + beginBandIndex; b++) { if (progressCallback != null) { percent++; progress = percent * 100 / progressCount; } var bandNum = b - beginBandIndex; timer.Restart(); ReadBandData <UInt16>(srcBandData, bandNum, oBlock.xBegin, oBlock.yBegin, srcStepSize.Width, srcStepSize.Height, DataType.GDT_UInt16); stepReadDataTime += timer.ElapsedMilliseconds; Size srcBlockSize = new Size(srcStepSize.Width, srcStepSize.Height); //进行辐射定标 timer.Restart(); DoRadiation(srcRaster, bandNum, srcBandData, null, srcBlockSize, srcBlockSize); stepRadiationTime += timer.ElapsedMilliseconds; //用于测试全图输出结果,用于查看插值的效果: #if DebugEaseGrid GCHandle hTe = GCHandle.Alloc(srcBandData, GCHandleType.Pinned); try { Random random = new Random(12); IntPtr bufferPtr = hTe.AddrOfPinnedObject(); Int16[] tmp = new Int16[srcBandData.Length]; for (int i = 0; i < srcBandData.Length; i++) { tmp[i] = (Int16)random.Next(200, 255); } Marshal.Copy(tmp, 0, bufferPtr, tmp.Length); } finally { hTe.Free(); } #endif //Size outStepSize = new Size(outWidth, rowStep); timer.Restart(); _rasterProjector.Project <UInt16>(srcBandData, srcStepSize, rows, cols, new Size(outWidth, rowStep), dstBandData, fillValue, 0, null); stepProjectRasterTime += timer.ElapsedMilliseconds; timer.Restart(); if (dataWeight == 1) { WriteDataToLDF <UInt16>(prdWriter, DataType.GDT_UInt16, outWidth, rowStep, oRow, dstBandData, b); } else { WriteDataToLDF <UInt16>(prdWriter, DataType.GDT_UInt16, outWidth, rowStep, oRow, dstBandData, b, dataWeight, zoom); } stepWriteDataTime += timer.ElapsedMilliseconds; } rows = null; rows = null; srcBandData = null; dstBandData = null; } Console.WriteLine($"坐标投影转换:{stepGeolocationTime}ms"); Console.WriteLine($"读取波段数据:{stepReadDataTime}ms"); Console.WriteLine($"定标波段数据:{stepRadiationTime}ms"); Console.WriteLine($"投影波段数据:{stepProjectRasterTime}ms"); Console.WriteLine($"写入波段数据:{stepWriteDataTime}ms"); }