internal void SetArgs(ISpatialReference spatialRef, PrjEnvelope prjEnvelope, float resolutionX, float resolutionY) { _spatialRef = spatialRef; _prjEnvelope = prjEnvelope; _resolutionX = resolutionX; _resolutionY = resolutionY; _piexlSize = _prjEnvelope.GetSize(resolutionX, resolutionY); txtX.Text = _prjEnvelope.CenterX.ToString(); txtY.Text = _prjEnvelope.CenterY.ToString(); txtPixelSizeX.Text = _piexlSize.Width.ToString(); txtPixelSizeY.Text = _piexlSize.Height.ToString(); txtResolutionX.Text = resolutionX.ToString(); txtResolutionY.Text = resolutionY.ToString(); }
private IRasterDataProvider CreateMosaicFile(IRasterDataProvider copyRaster, PrjEnvelope env, string filename) { ISpatialReference spatialRef = copyRaster.SpatialRef; string bandNames = BandNameString(copyRaster as ILdfDataProvider); Size outSize = env.GetSize(copyRaster.ResolutionX, copyRaster.ResolutionY); string[] options = new string[] { "INTERLEAVE=BSQ", "VERSION=LDF", "WITHHDR=TRUE", "SPATIALREF=" + spatialRef.ToProj4String(), "MAPINFO={" + 1 + "," + 1 + "}:{" + env.MinX + "," + env.MaxY + "}:{" + copyRaster.ResolutionX + "," + copyRaster.ResolutionY + "}", "BANDNAMES=" + bandNames }; return(IdentifyOutFile(filename, copyRaster.BandCount, outSize, copyRaster.DataType, options)); }
public void SetGeoEnvelope(PrjEnvelope geoEnvelope) { try { BeginChangedValue(); txtCenterLongitude.Text = geoEnvelope.CenterX.ToString(); txtCenterLatitude.Text = geoEnvelope.CenterY.ToString(); Size size = geoEnvelope.GetSize(_resolutionX, _resolutionY); cmbSizeX.Text = size.Width.ToString(); cmbSizeY.Text = size.Height.ToString(); } finally { EndChangedValue(); } }
private AbstractWarpDataset CreateMosaicFile(string mosaicFilename, InputArg inArg) { SpatialReference spatialRef = fileRaster.SpatialRef; PrjEnvelope env = inArg.MosaicInputArg.Envelope.PrjEnvelope; //string bandNames = BandNameString(fileRaster as ILdfDataProvider); Size outSize = env.GetSize(fileRaster.ResolutionX, fileRaster.ResolutionY); string[] options = new string[] { "INTERLEAVE=BSQ", "VERSION=LDF", "WITHHDR=TRUE", "SPATIALREF=" + spatialRef.ExportToProj4(), "MAPINFO={" + 1 + "," + 1 + "}:{" + env.MinX + "," + env.MaxY + "}:{" + fileRaster.ResolutionX + "," + fileRaster.ResolutionY + "}", //"BANDNAMES="+ bandNames }; return(CreateOutFile(mosaicFilename, fileRaster.BandCount, outSize, DataType.GDT_UInt16, env, spatialRef, options)); }
private void UpdatePrjenvelopeSet(float resolution) { if (resolution == 0f) { if (_dstSpatialRef == null || _dstSpatialRef.ProjectionCoordSystem == null) { resolution = 0.01f; } else { resolution = 1000f; } } if (_mosaicProjectionFileProvider.FileItems != null && _mosaicProjectionFileProvider.FileItems.Length != 0) { PrjEnvelope env = _mosaicProjectionFileProvider.FileItems[0].Envelope; Size size = env.GetSize(resolution, resolution); ucPrjEnvelopes1.SetValue(_dstSpatialRef, new PrjPoint(env.CenterX, env.CenterY), resolution, resolution, size); } else { ucPrjEnvelopes1.SetValue(_dstSpatialRef, null, resolution, resolution, new Size((int)resolution, (int)resolution)); } }
public void RastAndProject <T>(Size outSize, H5T.H5Type ht5type, H5FileId fileId, string dataset, Action <int, string> progressCallback, int outWidth, int outHeight, int rowStep, IRasterDataProvider srcRaster, FilePrjSettings prjSettings, int bandnum, T fillValue, HDF5.Hdf5Operator ope) { T[,] data = new T[outSize.Height, outSize.Width]; // 定义数据集操作部分 long[] dims = new long[2]; dims[0] = Convert.ToInt64(outSize.Height); dims[1] = Convert.ToInt64(outSize.Width); H5DataSpaceId dspaceId = H5S.create_simple(2, dims); // Define datatype for the data in the file. H5DataTypeId dtypeId = H5T.copy(ht5type); // Create the data set DATASETNAME. H5DataSetId dsetId = H5D.create(fileId, dataset, dtypeId, dspaceId); for (int oRow = 0; oRow < outHeight; oRow += rowStep) { #region 分块读取数据集 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 * prjSettings.OutResolutionY; Parallel.For(0, rowStep, j => { double x; double y; int index; y = prjSettings.OutEnvelope.LeftTop.Y - j * prjSettings.OutResolutionY - oY; for (int i = 0; i < outWidth; i++) { x = prjSettings.OutEnvelope.LeftTop.Y + i * prjSettings.OutResolutionX; index = i + j * outWidth; xs[index] = x; ys[index] = y; } }); _projectionTransform.InverTransform(xs, ys); PrjEnvelope tEnvelope = PrjEnvelope.GetEnvelope(xs, ys, null); tEnvelope.Extend(srcRaster.ResolutionX, srcRaster.ResolutionY * 4); PrjEnvelope srcEnvelope = new PrjEnvelope(srcRaster.CoordEnvelope.MinX, srcRaster.CoordEnvelope.MaxX, srcRaster.CoordEnvelope.MinY, srcRaster.CoordEnvelope.MaxY); tEnvelope = PrjEnvelope.Intersect(tEnvelope, srcEnvelope); if (tEnvelope == null || tEnvelope.IsEmpty) { continue; } Size tSize = tEnvelope.GetSize(srcRaster.ResolutionX, srcRaster.ResolutionY); int tBeginRow = -1, tEndRow = -1, tBeginCol = -1, tEndCol = -1; int oBeginRow = -1, oEndRow = -1, oBeginCol = -1, oEndCol = -1; PrjBlockHelper.ComputeBeginEndRowCol(srcEnvelope, new Size(srcRaster.Width, srcRaster.Height), 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) / srcRaster.ResolutionX + 0.5); rows[index] = (UInt16)((srcStepLeftTopY - y) / srcRaster.ResolutionY + 0.5); } } }); xs = null; ys = null; #endregion //分块读取不同波段数据 ReadBandData <T>(srcBandData, bandnum, oBeginCol, oBeginRow, srcStepWidth, srcStepHeight, GetSysDataType(ht5type)); //投影不同分块的数据集 _rasterProjector.Project <T>(srcBandData, srcStepSize, rows, cols, outStepSize, dstBandData, fillValue, 0, null); for (int i = 0; i < outStepSize.Width; i++) { for (int j = 0; j < outStepSize.Height; j++) { int index = j * outStepSize.Width + i; data[j + oRow, i] = dstBandData[index]; } } rows = null; rows = null; srcBandData = null; dstBandData = null; } H5D.write(dsetId, dtypeId, new H5Array <T>(data)); //写数据集属性 //Dictionary<string, string> dsetkeyvalue = ope.GetAttributes(dataset); //foreach (string key in dsetkeyvalue.Keys) //{ // string value = dsetkeyvalue[key]; // HDFAttributeDef attrdef = new HDFAttributeDef(key, typeof(string), dsetkeyvalue[key].Length, value); // WriteHdfAttributes.WriteHdfAttribute(dsetId, attrdef); //} H5D.close(dsetId); }
private void ProjectRaster <T>(IRasterDataProvider srcRaster, FilePrjSettings prjSettings, Action <int, string> progressCallback, IRasterDataProvider prdWriter, T fillValue, double dataWeight, float zoom) { enumDataType 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.CoordEnvelope.MinX, srcRaster.CoordEnvelope.MaxX, srcRaster.CoordEnvelope.MinY, srcRaster.CoordEnvelope.MaxY); long mem = MemoryHelper.GetAvalidPhyMemory(); #if !WIN64 mem = mem < 800 * 1024 * 1024 ? mem : 800 * 1024 * 1024; #endif long maxLimit = mem / (6 * 8 * 2); int rowStep = (int)(maxLimit / 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; } }
/// <summary> ///数据集投影 /// </summary> /// <typeparam name="T">数据集类型</typeparam> /// <param name="sourcedata">原始数据集</param> /// <param name="srcEnvelope">原始数据集坐标范围(正弦坐标系)</param> /// <param name="dstEnvelope">目标数据集坐标范围(品面坐标系)</param> /// <param name="outSize">输出范围</param> /// <param name="dstResoultion">输出分辨率</param> /// <param name="srcResoultionX">原始数据集分辨率X</param> /// <param name="srcResoultionY">原始数据集分辨率Y</param> /// <returns></returns> private static SDataByProject <T> GetDataByProject <T>(T[,] sourcedata, PrjEnvelope srcEnvelope, PrjEnvelope dstEnvelope, Size inSize, Size outSize, float dstResoultion, float srcResoultionX, float srcResoultionY, T fillValue, ISpatialReference dstSpatialRef, out UInt16[] rows, out UInt16[] cols, out Size srcStepSize) { rows = null; cols = null; srcStepSize = Size.Empty; IProjectionTransform _projectionTransform; //初始化原始坐标系转化对象 //ISpatialReference dstSpatialRef = SpatialReference.GetDefault(); string proj4str = "proj4 = +proj=sinu +lon_0=0 +x_0=0 +y_0=0 +a=6371007.181 +b=6371007.181 +units=m +no_defs"; ISpatialReference srcSpatialRef = SpatialReference.FromProj4(proj4str); _projectionTransform = ProjectionTransformFactory.GetProjectionTransform(srcSpatialRef, dstSpatialRef); //坐标系转换 int rowStep = outSize.Height; for (int oRow = 0; oRow < outSize.Height; oRow += rowStep) { if (oRow + rowStep > outSize.Height) { rowStep = outSize.Height - oRow; } Size outStepSize = new Size(outSize.Width, rowStep); double[] xs = new double[outSize.Width * rowStep]; double[] ys = new double[outSize.Width * rowStep]; double oY = oRow * dstResoultion; Parallel.For(0, rowStep, j => { double x; double y; int index; y = dstEnvelope.LeftTop.Y - j * dstResoultion - oY; for (int i = 0; i < outSize.Width; i++) { x = dstEnvelope.LeftTop.X + i * dstResoultion; index = i + j * outSize.Width; xs[index] = x; ys[index] = y; } }); _projectionTransform.InverTransform(xs, ys); PrjEnvelope tEnvelope = PrjEnvelope.GetEnvelope(xs, ys, null); tEnvelope.Extend(srcResoultionX, srcResoultionY * 4); tEnvelope = PrjEnvelope.Intersect(tEnvelope, srcEnvelope); if (tEnvelope == null || tEnvelope.IsEmpty) { continue; } Size tSize = tEnvelope.GetSize(srcResoultionX, srcResoultionY); int tBeginRow = -1, tEndRow = -1, tBeginCol = -1, tEndCol = -1; int oBeginRow = -1, oEndRow = -1, oBeginCol = -1, oEndCol = -1; PrjBlockHelper.ComputeBeginEndRowCol(srcEnvelope, new Size(inSize.Width, inSize.Height), 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; srcStepSize = new Size(srcStepWidth, srcStepHeight); T[,] dstData = new T[outSize.Height, outSize.Width]; //double srcStepLeftTopX = tEnvelope.MinX; //double srcStepLeftTopY = tEnvelope.MaxY; //double srcStepRightBottomX = tEnvelope.MaxX; //double srcStepRightBottomY = tEnvelope.MinY; double srcStepLeftTopX = srcEnvelope.MinX; double srcStepLeftTopY = srcEnvelope.MaxY; double srcStepRightBottomX = srcEnvelope.MaxX; double srcStepRightBottomY = srcEnvelope.MinY; UInt16[] rowTemps = new UInt16[outSize.Width * rowStep]; //正向查找表 UInt16[] colTemps = new UInt16[outSize.Width * rowStep]; //正向查找表 Parallel.For(0, rowStep, j => { double x; double y; int index; for (int i = 0; i < outSize.Width; i++) { index = i + j * outSize.Width; x = xs[index]; y = ys[index]; if (x >= srcStepLeftTopX && x <= srcStepRightBottomX && y <= srcStepLeftTopY && y >= srcStepRightBottomY) { colTemps[index] = (UInt16)((x - srcStepLeftTopX) / srcResoultionX + 0.5); rowTemps[index] = (UInt16)((srcStepLeftTopY - y) / srcResoultionY + 0.5); } } }); rows = rowTemps; cols = colTemps; return(DoProject <T>(sourcedata, fillValue, ref outStepSize, ref srcStepSize, dstData, rows, cols)); } return(null); }
protected void ProjectToLDF(Band[] srcBands, Band[] dstBands, int beginBandIndex, Action <int, string> progressCallback) { //progressCallback = progressCallback; if (srcBands == null || srcBands[0].XSize == 0 || srcBands[0].YSize == 0) { throw new Exception("投影数据失败:无法读取源数据,或者源数据高或宽为0。"); } Size srcImgSize = new Size(srcBands[0].XSize, srcBands[0].YSize); Size outSize = _dstEnvelope.GetSize(_outResolutionX, _outResolutionY); float bufferResolutionX = 0f; float bufferResolutionY = 0f; float outXScale = _srcImgResolution / _outResolutionX; float outYScale = _srcImgResolution / _outResolutionY; if (outXScale > 1.5f || outYScale > 1.5f) { bufferResolutionX = _srcImgResolution; bufferResolutionY = _srcImgResolution; } else { bufferResolutionX = _outResolutionX; bufferResolutionY = _outResolutionY; } int blockXCount; int blockYCount; int blockWidth; int blockHeight; //后面投影需要的内存:(double)经纬度数据、(int16)原始通道数据、(int16)投影后通道、(int16)其他(如角度数据等) GetBlockNumber(outSize, _srcLocationSize, outXScale, outYScale, out blockXCount, out blockYCount, out blockWidth, out blockHeight); int imgLocationRatioX = srcImgSize.Width / _srcLocationSize.Width; int imgLocationRatioY = srcImgSize.Height / _srcLocationSize.Height; progressCount = blockYCount * blockXCount * (_dstBandCount + (_angleBands == null ? 0 : _angleBands.Length) + (_extSrcBands == null ? 0 : _extSrcBands.Length)); progress = 0; percent = 0; Size bufferSize; #region 在需要分块的情况下,采样经纬度数据集 int bC = 1; int tmpWidth = 0; int tmpHeight = 0; double[] tmpxs = null; double[] tmpys = null; if (blockYCount * blockXCount > 1 && (_xs == null || _ys == null)) { bC = (int)Math.Sqrt(blockXCount * blockYCount) + 1; tmpWidth = _srcLocationSize.Width / bC; tmpHeight = _srcLocationSize.Height / bC; tmpxs = ReadSampleDatas(_longitudeBand, 0, 0, tmpWidth, tmpHeight); tmpys = ReadSampleDatas(_latitudeBand, 0, 0, tmpWidth, tmpHeight); TryApplyGeoInterceptSlope(tmpxs, tmpys); _rasterProjector.Transform(SpatialReferenceFactory.CreateSpatialReference(4326), tmpxs, tmpys, _dstSpatialRef); } #endregion for (int blockXNo = 0; blockXNo < blockXCount; blockXNo++) { for (int blockYNo = 0; blockYNo < blockYCount; blockYNo++) { //起始偏移,结束偏移 int beginX = blockWidth * blockXNo; int beginY = blockHeight * blockYNo; if (beginX >= outSize.Width || beginY >= outSize.Height) { continue; } if (beginX + blockWidth > outSize.Width) { blockWidth = outSize.Width - beginX; } if (beginY + blockHeight > outSize.Height) { blockHeight = outSize.Height - beginY; } //当前块的四角范围 double blockMinX = _dstEnvelope.MinX + beginX * _outResolutionX; double blockMaxX = blockMinX + blockWidth * _outResolutionX; double blockMaxY = _dstEnvelope.MaxY - beginY * _outResolutionY; double blockMinY = blockMaxY - blockHeight * _outResolutionY; PrjEnvelope blockEnvelope = new PrjEnvelope(blockMinX, blockMaxX, blockMinY, blockMaxY, _dstSpatialRef); bufferSize = blockEnvelope.GetSize(bufferResolutionX, bufferResolutionY); //根据当前输出块,反算出对应的源数据块(轨道)起始行列,为了减小后面需要读取的源数据大小 Block curOrbitblock = null; //开始获取当前分块的经纬度数据集,计算轨道数据范围偏移 double[] srcBlockXs; double[] srcBlockYs; if (blockYCount == 1 && blockXCount == 1) //没分块的情况 { curOrbitblock = _orbitBlock.Clone() as Block; if (curOrbitblock.xBegin < _left) { curOrbitblock.xBegin = _left; } if (curOrbitblock.xEnd > _srcLocationSize.Width - 1 - _right) { curOrbitblock.xEnd = _srcLocationSize.Width - 1 - _right; } if (curOrbitblock.Width == _srcLocationSize.Width && curOrbitblock.Height == _srcLocationSize.Height) { if (_xs != null && _ys != null) { srcBlockXs = _xs; srcBlockYs = _ys; } else { srcBlockXs = ReadBlockDatas(_longitudeBand, curOrbitblock.xBegin, curOrbitblock.yBegin, curOrbitblock.Width, curOrbitblock.Height); srcBlockYs = ReadBlockDatas(_latitudeBand, curOrbitblock.xBegin, curOrbitblock.yBegin, curOrbitblock.Width, curOrbitblock.Height); TryApplyGeoInterceptSlope(srcBlockXs, srcBlockYs); _rasterProjector.Transform(SpatialReferenceFactory.CreateSpatialReference(4326), srcBlockXs, srcBlockYs, _dstSpatialRef); } } else { if (_xs != null && _ys != null) { GetBlockDatas(_xs, _ys, _srcLocationSize.Width, _srcLocationSize.Height, curOrbitblock.xBegin, curOrbitblock.yBegin, curOrbitblock.Width, curOrbitblock.Height, out srcBlockXs, out srcBlockYs); } else { srcBlockXs = ReadBlockDatas(_longitudeBand, curOrbitblock.xBegin, curOrbitblock.yBegin, curOrbitblock.Width, curOrbitblock.Height); srcBlockYs = ReadBlockDatas(_latitudeBand, curOrbitblock.xBegin, curOrbitblock.yBegin, curOrbitblock.Width, curOrbitblock.Height); TryApplyGeoInterceptSlope(srcBlockXs, srcBlockYs); _rasterProjector.Transform(SpatialReferenceFactory.CreateSpatialReference(4326), srcBlockXs, srcBlockYs, _dstSpatialRef); } } } else { if (_xs != null && _ys != null) { GetEnvelope(_xs, _ys, _srcLocationSize.Width, _srcLocationSize.Height, blockEnvelope, out curOrbitblock); } else { //计算偏移。 GetEnvelope(tmpxs, tmpys, tmpWidth, tmpHeight, blockEnvelope, out curOrbitblock); curOrbitblock = curOrbitblock.Zoom(bC, bC); } if (curOrbitblock.Width <= 0 || curOrbitblock.Height <= 0) //当前分块不在图像内部 { progress += _dstBandCount; continue; } if (curOrbitblock.xBegin < _left) { curOrbitblock.xBegin = _left; } if (curOrbitblock.xEnd > _srcLocationSize.Width - 1 - _right) { curOrbitblock.xEnd = _srcLocationSize.Width - 1 - _right; } if (_xs != null && _ys != null) { GetBlockDatas(_xs, _ys, _srcLocationSize.Width, _srcLocationSize.Height, curOrbitblock.xBegin, curOrbitblock.yBegin, curOrbitblock.Width, curOrbitblock.Height, out srcBlockXs, out srcBlockYs); } else { srcBlockXs = ReadBlockDatas(_longitudeBand, curOrbitblock.xBegin, curOrbitblock.yBegin, curOrbitblock.Width, curOrbitblock.Height); srcBlockYs = ReadBlockDatas(_latitudeBand, curOrbitblock.xBegin, curOrbitblock.yBegin, curOrbitblock.Width, curOrbitblock.Height); TryApplyGeoInterceptSlope(srcBlockXs, srcBlockYs); _rasterProjector.Transform(SpatialReferenceFactory.CreateSpatialReference(4326), srcBlockXs, srcBlockYs, _dstSpatialRef); } } int srcBlockJdWidth = curOrbitblock.Width; int srcBlockJdHeight = curOrbitblock.Height; int srcBlockImgWidth = curOrbitblock.Width * imgLocationRatioX; int srcBlockImgHeight = curOrbitblock.Height * imgLocationRatioY; Size srcBlockLocationSize = new Size(srcBlockJdWidth, srcBlockJdHeight); Size srcBlockImgSize = new Size(srcBlockImgWidth, srcBlockImgHeight); //亮温订正,天顶角修正:下面获取用到的部分经纬度和太阳高度角修正系数数据,下面修改为从临时文件直接读取。 float[] solarZenithData = null; if (_isRadRef && _isSolarZenith) { if (_solarZenithCacheRaster != null) //太阳天顶角数据 { ReadBandData(out solarZenithData, _solarZenithCacheRaster, 1, curOrbitblock.xBegin, curOrbitblock.yBegin, srcBlockJdWidth, srcBlockJdHeight); } //亮温临边变暗订正,读取卫星天顶角数据。 //if (_isSensorZenith) // ReadBandData(out _sensorZenithData, _sensorSenithBand, curOrbitblock.xOffset, curOrbitblock.yBegin, curOrbitblock.Width, curOrbitblock.Height); TryReadZenithData(curOrbitblock.xBegin, curOrbitblock.yBegin, curOrbitblock.Width, curOrbitblock.Height); } //计算当前分块的投影查算表 UInt16[] dstRowLookUpTable = new UInt16[bufferSize.Width * bufferSize.Height]; UInt16[] dstColLookUpTable = new UInt16[bufferSize.Width * bufferSize.Height]; if (imgLocationRatioX == 1) { _rasterProjector.ComputeIndexMapTable(srcBlockXs, srcBlockYs, srcBlockImgSize, bufferSize, blockEnvelope, _maxPrjEnvelope, out dstRowLookUpTable, out dstColLookUpTable, null); } else { _rasterProjector.ComputeIndexMapTable(srcBlockXs, srcBlockYs, srcBlockLocationSize, srcBlockImgSize, bufferSize, blockEnvelope, //_maxPrjEnvelope, out dstRowLookUpTable, out dstColLookUpTable, null, 0); } //执行投影 UInt16[] srcBandData = null; UInt16[] dstBandData = new UInt16[bufferSize.Width * bufferSize.Height]; for (int i = 0; i < srcBands.Length; i++) //读取原始通道值,投影到目标区域 { if (progressCallback != null) { progress++; percent = (int)(progress * 100 / progressCount); progressCallback(percent, string.Format("投影完成{0}%", percent)); } ReadImgBand(srcBands[i], curOrbitblock.xBegin * imgLocationRatioX, curOrbitblock.yBegin * imgLocationRatioY, srcBlockImgWidth, srcBlockImgHeight, new Size(srcBlockImgWidth, srcBlockImgHeight), out srcBandData); //ReadImgBand(out srcBandData, i, curOrbitblock.xOffset * imgLocationRatioX, curOrbitblock.yBegin * imgLocationRatioY, srcBlockImgWidth, srcBlockImgHeight); Size angleSize = new Size(srcBlockJdWidth, srcBlockJdHeight); DoRadiation(srcBands[i], srcBandData, solarZenithData, srcBlockImgSize, angleSize); _rasterProjector.Project <UInt16>(srcBandData, srcBlockImgSize, dstRowLookUpTable, dstColLookUpTable, bufferSize, dstBandData, 0, null); srcBandData = null; Band band = dstBands[i]; unsafe { fixed(UInt16 *ptr = dstBandData) { IntPtr bufferPtr = new IntPtr(ptr); int blockOffsetY = blockHeight * blockYNo; int blockOffsetX = blockWidth * blockXNo; band.WriteRaster(blockOffsetX, blockOffsetY, blockWidth, blockHeight, bufferPtr, bufferSize.Width, bufferSize.Height, DataType.GDT_UInt16, 0, 0); } } } srcBandData = null; dstBandData = null; GC.Collect(); ReleaseZenithData(); Size srcBufferSize = new Size(srcBlockImgWidth, srcBlockImgHeight); ProjectAngle(bufferSize, srcBufferSize, blockWidth, blockHeight, blockYNo, blockXNo, curOrbitblock, dstRowLookUpTable, dstColLookUpTable, progressCallback); ProjectExtBands(bufferSize, srcBufferSize, blockWidth, blockHeight, blockYNo, blockXNo, curOrbitblock, dstRowLookUpTable, dstColLookUpTable, progressCallback); dstRowLookUpTable = null; dstColLookUpTable = null; } } }
/// <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; } } }
private void ProjectToLDF0500(IRasterDataProvider srcRaster, Size srcLocationSize, EOS_MODIS_PrjSettings prjSettings, ISpatialReference dstSpatialRef, Action <int, string> progressCallback) { if (srcRaster == null || srcRaster.Width == 0 || srcRaster.Height == 0) { throw new Exception("投影250米MERSI数据失败:无法读取源数据,或者源数据高或宽为0。"); } Size srcDataSize = new Size(srcRaster.Width, srcRaster.Height); string outFormat = prjSettings.OutFormat; string outfilename = prjSettings.OutPathAndFileName; string dstProj4 = dstSpatialRef.ToProj4String(); List <BandMap> bandMaps = prjSettings.BandMapTable; int dstBandCount = bandMaps.Count; 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) { //考虑分块 float outResolutionX = prjSettings.OutResolutionX; float outResolutionY = prjSettings.OutResolutionY; Size outSize = dstEnvelope.GetSize(outResolutionX, outResolutionY); #region 计算分块个数、分块高宽 int blockXNum; int blockYNum; int blockWidth; int blockHeight; GetBlockNumber(outSize, out blockXNum, out blockYNum, out blockWidth, out blockHeight); #endregion Size blockSize = new Size(blockWidth, blockHeight); for (int blockYIndex = 0; blockYIndex < blockYNum; blockYIndex++) { for (int blockXIndex = 0; blockXIndex < blockXNum; blockXIndex++) { //当前块的四角范围 double blockMinX = dstEnvelope.MinX + blockWidth * outResolutionX * blockXIndex; double blockMaxX = blockMinX + blockWidth * outResolutionX; double blockMaxY = dstEnvelope.MaxY - blockHeight * outResolutionY * blockYIndex; double blockMinY = blockMaxY - blockHeight * outResolutionY; PrjEnvelope blockEnvelope = new PrjEnvelope(blockMinX, blockMaxX, blockMinY, blockMaxY); UInt16[] dstRowLookUpTable = new UInt16[blockWidth * blockHeight]; UInt16[] dstColLookUpTable = new UInt16[blockWidth * blockHeight]; _rasterProjector.ComputeIndexMapTable(_xs, _ys, srcLocationSize, srcDataSize, blockSize, blockEnvelope, out dstRowLookUpTable, out dstColLookUpTable, progressCallback); //执行投影 UInt16[] srcBandData = null; UInt16[] dstBandData = new UInt16[blockWidth * blockHeight]; for (int i = 0; i < dstBandCount; i++) //读取原始通道值,投影到目标区域 { BandMap bandMap = bandMaps[i]; ReadBandData(out srcBandData, bandMap.File, bandMap.DatasetName, bandMap.BandIndex, srcDataSize); if (prjSettings.IsRadiation) //亮温转换,这里处理的不好,如果是做了一个小块的分幅,这里花的代价太高, { DoRadiation(srcBandData, srcDataSize, srcLocationSize, bandMap.DatasetName, bandMap.BandIndex, srcRaster, prjSettings.IsRadiation, prjSettings.IsSolarZenith); } _rasterProjector.Project <UInt16>(srcBandData, srcDataSize, dstRowLookUpTable, dstColLookUpTable, blockSize, dstBandData, 0, progressCallback); using (IRasterBand band = prdWriter.GetRasterBand(i + 1)) { unsafe { fixed(UInt16 *ptr = dstBandData) { IntPtr bufferPtr = new IntPtr(ptr); int blockOffsetY = blockYIndex * blockSize.Height; int blockOffsetX = blockWidth * blockXIndex; band.Write(blockOffsetX, blockOffsetY, blockWidth, blockHeight, bufferPtr, enumDataType.UInt16, blockWidth, blockHeight); } } } } } } } } }
// 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"); }
/// <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; List <string> opts = new List <string>(); opts.AddRange(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), "SENSOR=AVHRR" }); if (srcRaster.DataIdentify != null) { string satellite = srcRaster.DataIdentify.Satellite; DateTime dt = srcRaster.DataIdentify.OrbitDateTime; bool asc = srcRaster.DataIdentify.IsAscOrbitDirection; if (!string.IsNullOrWhiteSpace(satellite)) { opts.Add("SATELLITE=" + satellite); } if (dt != DateTime.MinValue && dt != DateTime.MaxValue) { opts.Add("DATETIME=" + dt.ToString("yyyy/MM/dd HH:mm")); } opts.Add("ORBITDIRECTION=" + (asc ? "ASC" : "DESC")); } if (progressCallback != null) { progressCallback(6, "生成输出文件"); } using (IRasterDataProvider prdWriter = drv.Create(outfilename, dstSize.Width, dstSize.Height, dstBandCount, enumDataType.UInt16, opts.ToArray()) 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; progress = 0; progressCount = blockCount * (dstBandCount + (_angleBands == null ? 0 : _angleBands.Length)); percent = 0; 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}%", percent)); } 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; Size srcBufferSize = new Size(orbitBlock.Width, orbitBlock.Height); ProjectAngle(dstBlockSize, srcBufferSize, blockWidth, blockHeight, blockYIndex, blockXIndex, orbitBlock, dstRowBlockLUT, dstColBlockLUT, progressCallback); } } dstRowBlockLUT = null; dstColBlockLUT = null; } } }