2012-10-04 80 views
0

我遇到问题。我使用gdal_csharp.dll库(在gdal_retile.py脚本中重写为C#)在瓷砖上切割了一张地图。除了一种情况,一切正常。当我用nodata值(边界上的图块)剪切区域并将它们保存为JPEG文件时,nodata区域为黑色(我需要它们为白色) - 包含下面的示例图块。我试图用tBand.SetNoDataValue(0);但有时黑not-nodata值(例如城市名,路名等)含有白点......白色无数值而不是黑色

例瓦:Tile no1Tile no2

我不知道如何设置SetNoDataValue(/* what to write in here? */) ......也许有另一种方法可以解决这个问题?

这里是我的方法:

private void CreatePyramidTile(MosaicInfo levelMosaicInfo, int offsetX, int offsetY, int width, int height, string tileName, DataSource ogrds) 
{ 
    double sx = levelMosaicInfo.ScaleX * _scaleFactor; 
    double sy = levelMosaicInfo.ScaleY * _scaleFactor; 

    AffineTransformDecorator dec = 
     new AffineTransformDecorator(new[] 
             { 
              levelMosaicInfo.Ulx + offsetX*sx, sx, 0, 
              levelMosaicInfo.Uly + offsetY*sy, 0, sy 
             }); 

    Dataset sFh = levelMosaicInfo.GetDataSet((int) Math.Round(dec.Ulx), 
              (int) Math.Round((dec.Uly + height*dec.ScaleY)), 
              (int) Math.Round((dec.Ulx + width*dec.ScaleX)), 
              (int) Math.Round(dec.Uly)); 

    if (sFh == null) 
    { 
     return; 
    } 

    if (ogrds != null) 
    { 
     var points = dec.PointsFor(width, height); 
     AddFeature(ogrds, tileName, points); 
    } 

    DataType bt; 
    if (_bandType == DataType.GDT_Unknown) 
    { 
     bt = levelMosaicInfo.BandType; 
    } 
    else 
    { 
     bt = _bandType; 
    } 

    double[] geotransform = { dec.Ulx, dec.ScaleX, 0, dec.Uly, 0, dec.ScaleY }; 
    int bands = levelMosaicInfo.Bands; 

    Dataset tFh; 
    if (_memDriver == null) 
    { 
     tFh = _driver.Create(tileName, width, height, bands, bt, _createOptions.ToArray()); 
    } 
    else 
    { 
     tFh = _memDriver.Create(tileName, width, height, bands, bt, _createOptions.ToArray()); 
    } 

    if (tFh == null) 
    { 
     throw new Exception("Creation failed, terminating gdal_tile."); 
    } 

    tFh.SetGeoTransform(geotransform); 
    tFh.SetProjection(levelMosaicInfo.Projection); 
// I think, the problem occurs in this loop; I tried to set nodata values 
    for (int band = 1; band < bands + 1; band++) 
    { 
     Band tBand = tFh.GetRasterBand(band); 

     if (levelMosaicInfo.Ct != null) 
     { 
      tBand.SetRasterColorTable(levelMosaicInfo.Ct); 
     } 
     tBand.SetRasterColorInterpretation(levelMosaicInfo.Ci[band - 1]); 
//    tBand.SetNoDataValue(0); 
    } 

    var res = Gdal.ReprojectImage(sFh, tFh, null, null, _resamplingMethod, 0, 0, null, null); 

    if (res != 0) 
    { 
     throw new Exception("Reprojection failed for " + tileName + ", error " + res + "."); 
    } 

    levelMosaicInfo.CloseDataSet(ref sFh); 

    if (_memDriver != null) 
    { 
     Dataset ttFh = _driver.CreateCopy(tileName, tFh, 0, _createOptions.ToArray(), null, null); 
     ttFh.Dispose(); 
    } 

    tFh.Dispose(); 
} 

[编辑]
总还是有同样的问题...我改变了循环:

for (int band = 1; band < bands + 1; band++) 
{ 
    Band tBand = tFh.GetRasterBand(band); 
    tBand.Fill(255, 0); 
    tBand.SetNoDataValue(255); 

    if (levelMosaicInfo.Ct != null) 
    { 
     tBand.SetRasterColorTable(levelMosaicInfo.Ct); 
    } 
    tBand.SetRasterColorInterpretation(levelMosaicInfo.Ci[band - 1]); 
} 

现在我认为我的问题可能出现通过我的转换方法。我得到的数据是8-bit格式 - 重新投影后,黑色填充90%。因此,我首先使用pct2rgb.py脚本(将其重写为C#)将源数据转换为24-bit

下面的代码:

public Dataset Convert8To24Bit() 
{ 
    Gdal.AllRegister(); 

    string[] argv = Gdal.GeneralCmdLineProcessor(_args, 0); 

    int i = 1; 
    while (i < argv.Count()) 
    { 
     string arg = argv.ElementAt(i); 
     switch (arg) 
     { 
      case "-of": 
       i++; 
       _format = argv[i]; 
       break; 
      case "-b": 
       i++; 
       _bandNumber = int.Parse(argv[i]); 
       break; 
      case "-rgba": 
       _outBands = 4; 
       break; 
      default: 
       if (string.IsNullOrEmpty(_srcFileName)) 
       { 
        _srcFileName = argv[i]; 
       } 
       else 
       { 
        Usage(); 
       } 
       break; 
     } 
     i++; 
    } 

    string tmpFileName = _srcFileName + ".bak"; 

    // open source file 
    Dataset srcDS = Gdal.Open(_srcFileName, Access.GA_ReadOnly); 
    if (srcDS == null) 
    { 
     throw new Exception("Unable to open " + _srcFileName + "."); 
    } 

    Band srcBand = srcDS.GetRasterBand(_bandNumber); 

    // ensure we recognise the driver 
    Driver dstDriver = Gdal.GetDriverByName(_format); 
    if (dstDriver == null) 
    { 
     throw new Exception("\"" + _format + "\" not registered."); 
    } 

    // build color table 
    int[][] lookup = new int[4][]; 
    lookup[0] = Enumerable.Range(0, 256).ToArray(); 
    lookup[1] = Enumerable.Range(0, 256).ToArray(); 
    lookup[2] = Enumerable.Range(0, 256).ToArray(); 
    lookup[3] = new int[256]; 

    for (i = 0; i < 256; i++) 
    { 
     lookup[3][i] = 255; 
    } 

    ColorTable ct = srcBand.GetRasterColorTable(); 

    if (ct != null) 
    { 
     for (i = 0; i < Math.Min(256, ct.GetCount()); i++) 
     { 
      ColorEntry entry = ct.GetColorEntry(i); 
      for (int j = 0; j < 4; j++) 
      { 
       switch (j) 
       { 
        case 0: 
         lookup[j][i] = entry.c1; 
         break; 
        case 1: 
         lookup[j][i] = entry.c2; 
         break; 
        case 2: 
         lookup[j][i] = entry.c3; 
         break; 
        case 3: 
         lookup[j][i] = entry.c4; 
         break; 
       } 
      } 
     } 
    } 
    else 
    { 
     return srcDS; 
    } 

    // create the working file 
    string tifFileName = string.Empty; 
    if (_format.Equals("GTiff", StringComparison.OrdinalIgnoreCase)) 
    { 
     tifFileName = tmpFileName; 
    } 
    else 
    { 
     tifFileName = Path.Combine(Directory.GetParent(tmpFileName).Name, "temp.gif"); 
    } 

//   Driver gTiffDriver = Gdal.GetDriverByName("GTiff"); 
    Driver gTiffDriver = Gdal.GetDriverByName("MEM"); 

    Dataset tifDS = gTiffDriver.Create(tifFileName, srcDS.RasterXSize, srcDS.RasterYSize, _outBands, DataType.GDT_Byte, 
             new string[] {}); 

    // we should copy projection information and so forth at this point 
    tifDS.SetProjection(srcDS.GetProjection()); 
    double[] geotransform = new double[6]; 
    srcDS.GetGeoTransform(geotransform); 
    tifDS.SetGeoTransform(geotransform); 

    if (srcDS.GetGCPCount() > 0) 
    { 
     tifDS.SetGCPs(srcDS.GetGCPs(), srcDS.GetGCPProjection()); 
    } 

    // do the processing one scanline at a time 
    for (int iY = 0; iY < srcDS.RasterYSize; iY++) 
    { 
     byte[] srcData = new byte[srcDS.RasterXSize*1]; 
     srcBand.ReadRaster(0, iY, srcDS.RasterXSize, 1, srcData, srcDS.RasterXSize, 1, 0, 0); 

     for (int iBand = 0; iBand < _outBands; iBand++) 
     { 
      int[] bandLookup = lookup[iBand]; 

      int[] dstData = new int[srcData.Count()]; 
      for (int index = 0; index < srcData.Count(); index++) 
      { 
       byte b = srcData[index]; 
       dstData[index] = bandLookup[b]; 
      } 

      tifDS.GetRasterBand(iBand + 1).WriteRaster(0, iY, srcDS.RasterXSize, 1, dstData, 
                 srcDS.RasterXSize, 1, 0, 0); 
     } 
    } 

//   if (tifFileName != _srcFileName) 
//   { 
//    tifDS = Gdal.Open(tifFileName, Access.GA_ReadOnly); 
//    dstDriver.CreateCopy(_srcFileName, tifDS, 0, new string[] { }, null, null);; 
//   } 

    srcDS.Dispose(); 

    return tifDS; 
} 

全类:GdalRetile.csTiffConverter.cs

回答

0

好,我找到了一个解决方案!我只是用白色填充了我的TEMP图像,这是结果图块的背景。

GetDataSet()方法所做的更改:

Dataset resultDS = _tempDriver.Create("TEMP", resultSizeX, resultSizeY, _bands, _bandType, new string[] { });

线以上更改为:

Dataset resultDS = _tempDriver.Create("TEMP", resultSizeX, resultSizeY, _bands, _bandType, new string[] { }); 
for (int i = 1; i < _bands + 1; i++) 
{ 
    Band band = resultDS.GetRasterBand(i); 
    band.Fill(255, 0); 
} 
2

对于栅格,无数据并不总是尊重。 JPEG不尊重大多数软件的NoData元数据。所以如果你有NoData为'0',这可以被解释为黑色的像素值。默认情况下,光栅填充0或黑色。你只需要重新定义NoData是什么。如果你希望它是白色的,你的像素类型是字节,那么它应该是255

作为一个建议,创建数据集后加载数据前,试试这个:

... 
    Band tBand = tFh.GetRasterBand(band); 
    tBand.Fill(255); // otherwise it is filled with 0 
    tBand.SetNoDataValue(255); // set metadata 
... 
+0

它没有为我工作,但检查我的编辑,请。也许这是问题...... :( – Nickon

相关问题