Beispiel #1
0
    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);
                }
            }
        }