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"); }