C#とDotSpatialでGeoTiff読み書き

DotSpatialを使ってGeoTiffの読み書きを行うサンプルを残しておきます。

DotSpatial版の他に、DotSpatialをインストールすると付いてくるgdal_csharp.dllを使った場合のソースも置いてます。


DotSpatial版

 [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
  static extern bool SetDllDirectory(string lpPathName);

  static void Main(string[] args)
  {
    SetDllDirectory(gdal_wrap.dllが置いてあるフォルダパス。例えば@"~\DotSpatial-master\Source\bin\x64\Release\gdal\x64"とか);

    string loadfilepath = 読み込むファイルパス;
    string savefilepath = 書き込みファイルパス;

    // GeoTiff読み込み
    GdalRasterProvider d = new GdalRasterProvider();
    IRaster src = d.Open(loadfilepath);
    int ncol = src.NumColumns; // 水平方向ピクセル数
    int nrow = src.NumRows; // 鉛直方向ピクセル数
    int band_num = src.NumBands; // バンド数
    string prj = src.ProjectionString;
    double nodata = src.NoDataValue;

    double[] pGT = src.Bounds.AffineCoefficients;
    double xllcenter = pGT[0];
    double cellsize_x = pGT[1];
    // pGT[2] # 回転 今回は使わない
    double yllcenter = pGT[3];
    // pGT[4] # 回転 今回は使わない
    double cellsize_y = pGT[5];

    IRaster dst = Raster.CreateRaster(savefilepath, src.DriverCode, ncol - 2, nrow - 2, 1, src.DataType, new[] { string.Empty });
    dst.NoDataValue = nodata;
    dst.ProjectionString = prj;
    dst.Bounds = new RasterBounds(nrow - 2, ncol - 2,
        new double[] { xllcenter + cellsize_x / 2, cellsize_x, 0, yllcenter + cellsize_y / 2, 0, cellsize_y });

    Hoi(src.Value, nodata, xllcenter, yllcenter, cellsize_x, nrow, ncol, dst.Value);

    dst.Save();
  }

1,2,6行目 「gdal_wrap.dll」を読み込むためにこの記述が必要です。『参照の追加』ではこのdllを読み込めないのです。

12,13行目 GeoTiffを読み込んでいます。

14~26行目 読み込んだGeoTiffの情報を取得しています。

28~32行目 書き込み用GeoTiffを作成しています。このサンプルでは、読み込んだGeoTiffより一回り小さいGeoTiffを作成するので、サイズを基画像の縦横-2(31行目)、原点を1ピクセル分内側(32行目)に設定しました。他にGeoTiffの原点、ピクセルのサイズを設定しています。

34行目 読み込んだGeoTiffを基に、斜面方位を計算して、書き込み用GeoTiffのピクセルデータを作成しています。(今回は説明を省きます)

36行目 書き込み用GeoTiffを保存しています。

 

ソースはこちらです。ソース見れない状態でした。すいませんでした。


gdal_csharp版

  [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
  static extern bool SetDllDirectory(string lpPathName);

  static void Main(string[] args)
  {
    SetDllDirectory(gdal_wrap.dllが置いてあるフォルダパス。例えば@"~\DotSpatial-master\Source\bin\x64\Release\gdal\x64"とか);

    string loadfilepath = 読み込むファイルパス;
    string savefilepath = 書き込みファイルパス;

    Gdal.AllRegister();

    // GeoTiff読み込み
    Dataset ds = Gdal.Open(loadfilepath, Access.GA_Update);
    int ncol = ds.RasterXSize; // 水平方向ピクセル数
    int nrow = ds.RasterYSize; // 鉛直方向ピクセル数
    int band_num = ds.RasterCount; // バンド数
    string prj = ds.GetProjection();

    double nodata;
    int hasval;
    ds.GetRasterBand(1).GetNoDataValue(out nodata, out hasval);

    double[] pGT = new double[6];
    ds.GetGeoTransform(pGT);
    double xllcorner = pGT[0];
    double cellsize_x = pGT[1];
    // pGT[2] # 回転 今回は使わない
    double yllcorner = pGT[3];
    // pGT[4] # 回転 今回は使わない
    double cellsize_y = pGT[5];

    double[][] dVals = new double[band_num][];
    for (int i = 1; i <= band_num; i++)
    {
        dVals[i - 1] = new double[ncol * nrow];
        ds.GetRasterBand(i).ReadRaster(0, 0, ncol, nrow, dVals[i - 1], ncol, nrow, 0, 0);
    }

    double xllcenter = xllcorner + cellsize_x / 2;
    double yllcenter = yllcorner + cellsize_y / 2;
    double[] output = Hoi(dVals[0], nodata, xllcenter, yllcenter, cellsize_x, nrow, ncol);

    // GeoTiff書き出し
    ds = null;
    Driver imgDriver = Gdal.GetDriverByName("GTiff");
    ds = imgDriver.Create(savefilepath, ncol - 2, nrow - 2, 1, DataType.GDT_Float32, new string[] { });
    ds.SetProjection(prj);
    ds.SetGeoTransform(new double[] { xllcorner + cellsize_x, cellsize_x, 0, yllcorner - cellsize_x, 0, -1 * cellsize_x });
    Band rband = ds.GetRasterBand(1);
    rband.WriteRaster(0, 0, ncol - 2, nrow - 2, output, ncol - 2, nrow - 2, 0, 0);
    rband.SetNoDataValue(nodata);
    ds.FlushCache();

    return;
  }

11行目 GDALのドライバを登録しています。アプリケーションの開始時に1回呼び出す必要があります。

14行目 GeoTiffを読み込んでいます。

15~38行目 読み込んだTiffの情報を取得しています。DotSpatialと違い、原点は画像の端っこの座標を取得します(26行目と29行目)。33行目で画像の各ピクセルデータをdoubleの配列に格納しています。

40~42行目 原点ピクセルの中心点を取得して、42行目で斜面方位を計算してdoubleの配列を取得しています。

46,47行目 書き込む空のGeoTiffを作成しています。サイズは今回も基画像より一回り小さいサイズです。

49行目 書き込むGeoTiffの原点やピクセルサイズを設定しています。

51,53行目 42行目で作成したピクセルデータをディスクに書き込んでいます。(52行目は上に移した方が見栄え良いと思います。)

 

ソースはこちらです。ソース見れない状態でした。すいませんでした。

最後までご覧頂き、ありがとうございました