private static void SaveBitmapDirect(string filename, Dataset ds, int xOff, int yOff, int width, int height, int imageWidth, int imageHeight) { if (ds.RasterCount == 0) { return; } int[] bandMap = new int[4] { 1, 1, 1, 1 }; int channelCount = 1; bool hasAlpha = false; bool isIndexed = false; int channelSize = 8; ColorTable ct = null; // Evaluate the bands and find out a proper image transfer format for (int i = 0; i < ds.RasterCount; i++) { Band band = ds.GetRasterBand(i + 1); if (Gdal.GetDataTypeSize(band.DataType) > 8) { channelSize = 16; } switch (band.GetRasterColorInterpretation()) { case ColorInterp.GCI_AlphaBand: channelCount = 4; hasAlpha = true; bandMap[3] = i + 1; break; case ColorInterp.GCI_BlueBand: if (channelCount < 3) { channelCount = 3; } bandMap[0] = i + 1; break; case ColorInterp.GCI_RedBand: if (channelCount < 3) { channelCount = 3; } bandMap[2] = i + 1; break; case ColorInterp.GCI_GreenBand: if (channelCount < 3) { channelCount = 3; } bandMap[1] = i + 1; break; case ColorInterp.GCI_PaletteIndex: ct = band.GetRasterColorTable(); isIndexed = true; bandMap[0] = i + 1; break; case ColorInterp.GCI_GrayIndex: isIndexed = true; bandMap[0] = i + 1; break; default: // we create the bandmap using the dataset ordering by default if (i < 4 && bandMap[i] == 0) { if (channelCount < i) { channelCount = i; } bandMap[i] = i + 1; } break; } } // find out the pixel format based on the gathered information PixelFormat pixelFormat; DataType dataType; int pixelSpace; if (isIndexed) { pixelFormat = PixelFormat.Format8bppIndexed; dataType = DataType.GDT_Byte; pixelSpace = 1; } else { if (channelCount == 1) { if (channelSize > 8) { pixelFormat = PixelFormat.Format16bppGrayScale; dataType = DataType.GDT_Int16; pixelSpace = 2; } else { pixelFormat = PixelFormat.Format24bppRgb; channelCount = 3; dataType = DataType.GDT_Byte; pixelSpace = 3; } } else { if (hasAlpha) { if (channelSize > 8) { pixelFormat = PixelFormat.Format64bppArgb; dataType = DataType.GDT_UInt16; pixelSpace = 8; } else { pixelFormat = PixelFormat.Format32bppArgb; dataType = DataType.GDT_Byte; pixelSpace = 4; } channelCount = 4; } else { if (channelSize > 8) { pixelFormat = PixelFormat.Format48bppRgb; dataType = DataType.GDT_UInt16; pixelSpace = 6; } else { pixelFormat = PixelFormat.Format24bppRgb; dataType = DataType.GDT_Byte; pixelSpace = 3; } channelCount = 3; } } } // Create a Bitmap to store the GDAL image in Bitmap bitmap = new Bitmap(imageWidth, imageHeight, pixelFormat); if (isIndexed) { // setting up the color table if (ct != null) { int iCol = ct.GetCount(); ColorPalette pal = bitmap.Palette; for (int i = 0; i < iCol; i++) { ColorEntry ce = ct.GetColorEntry(i); pal.Entries[i] = Color.FromArgb(ce.c4, ce.c1, ce.c2, ce.c3); } bitmap.Palette = pal; } else { // grayscale ColorPalette pal = bitmap.Palette; for (int i = 0; i < 256; i++) { pal.Entries[i] = Color.FromArgb(255, i, i, i); } bitmap.Palette = pal; } } // Use GDAL raster reading methods to read the image data directly into the Bitmap BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, imageWidth, imageHeight), ImageLockMode.ReadWrite, pixelFormat); try { int stride = bitmapData.Stride; System.IntPtr buf = bitmapData.Scan0; using (RasterIOExtraArg arg = new RasterIOExtraArg()) { GCHandle handle = GCHandle.Alloc("Test data", GCHandleType.Pinned); try { arg.nVersion = argVersion; arg.eResampleAlg = resampleAlg; arg.pfnProgress = new Gdal.GDALProgressFuncDelegate(ProgressFunc); arg.pProgressData = handle.AddrOfPinnedObject(); // or System.IntPtr.Zero if not data to be added; arg.bFloatingPointWindowValidity = 0; ds.ReadRaster(xOff, yOff, width, height, buf, imageWidth, imageHeight, dataType, channelCount, bandMap, pixelSpace, stride, 1, arg); } finally { handle.Free(); } } } finally { bitmap.UnlockBits(bitmapData); } bitmap.Save(filename); }
/// <summary> /// Npp卫星数据读取 /// </summary> /// <param name="bandData"></param> /// <param name="dstBandIndex"></param> /// <param name="xOffset"></param> /// <param name="yOffset"></param> /// <param name="blockWidth"></param> /// <param name="blockHeight"></param> /// <param name="srcImgSize"></param> protected override void ReadImgBand(out ushort[] bandData, int dstBandIndex, int xOffset, int yOffset, int blockWidth, int blockHeight, Size?srcImgSize = default(Size?)) { //Npp的波段数据含有多种无效值,并且Radiance与Temperature数据集可能为Uint16也可能为Float //65535 65534 65533 65532 65531 65530 65529 65528 //-999.9 -999.8 -999.7 -999.6 -999.5 -999.4 -999.3 -999.2 //如果需要判断读取的是反射率还是亮温,可以通过_prjSettings.IsRadRef||_prjSettings.IsRad //_prjBands为待投影波段信息 //以下代码为假设对NPP数据进行亮温与反射率的读取 Band rasterBand = _rasterDataBands[dstBandIndex]; // bandData = new ushort[blockWidth * blockHeight]; bool ok = false; try { double ratioX = 1, ratioY = 1; if (srcImgSize.HasValue) { ratioX = rasterBand.GetXSize() * 1.0 / srcImgSize.Value.Width; ratioY = rasterBand.GetYSize() * 1.0 / srcImgSize.Value.Height; } Func <double, int> ToInt = t => Convert.ToInt32(t); if (rasterBand.DataType == DataType.GDT_UInt16) { RasterIOExtraArg exArg = new RasterIOExtraArg() { eResampleAlg = RIOResampleAlg.GRIORA_NearestNeighbour, dfXOff = xOffset * ratioX, dfYOff = yOffset * ratioY, dfXSize = blockWidth * ratioX, dfYSize = blockHeight * ratioY, nVersion = 1 }; ok = rasterBand.ReadRaster(ToInt(xOffset * ratioX), ToInt(yOffset * ratioY), ToInt(blockWidth * ratioX), ToInt(blockHeight * ratioY), bandData, blockWidth, blockHeight, 0, 0, exArg) == CPLErr.CE_None; //无效值剔除 for (int i = 0; i < blockWidth * blockHeight; i++) { if (bandData[i] > 65527) { bandData[i] = 0; } } } else if (rasterBand.DataType == DataType.GDT_Float32) { RasterIOExtraArg exArg = new RasterIOExtraArg() { eResampleAlg = RIOResampleAlg.GRIORA_NearestNeighbour, dfXOff = xOffset * ratioX, dfYOff = yOffset * ratioY, dfXSize = blockWidth * ratioX, dfYSize = blockHeight * ratioY, nVersion = 1 }; float[] tempBuf = new float[blockWidth * blockHeight]; ok = rasterBand.ReadRaster(ToInt(xOffset * ratioX), ToInt(yOffset * ratioY), ToInt(blockWidth * ratioX), ToInt(blockHeight * ratioY), tempBuf, blockWidth, blockHeight, 0, 0, exArg) == CPLErr.CE_None; for (int i = 0; i < blockWidth * blockHeight; i++) { //过滤无效值为0 bandData[i] = tempBuf[i] < 0 ? (UInt16)0 : (UInt16)(tempBuf[i] * 10); } tempBuf = null; } if (!ok) { throw new Exception($"波段数据读取失败"); } } finally { if (!ok) { System.Diagnostics.Debug.WriteLine("ReadImgBand Index:{0}失败", dstBandIndex); } } }