Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I have a C++ program that manipulates raster digital elevation models.

I have been using ArcGrid ASCII format for results. It is simple to code and gets the job done, but it necessitates a decimal output. This means a loss of precision in floating-point numbers.

Is there a simple binary raster format which I could write to and ArcGIS could read from?

share|improve this question
    
One way to answer this is to use ArcGIS to export into a binary format: in the process of doing this you will find all the options (it used to be just one, the ".flt" format) and you will have an example file to work with. –  whuber May 10 '13 at 22:05
add comment

3 Answers

The easiest format for external reading/writing would be a pure binary file (BSQ, BIL, or BIP). These have absolutely no header information contained within--only a stream of bits beginning with the first data point and ending with the last data point. The ordering of bits in n dimensions will vary on the interleave method: either band sequential (BSQ), band interleaved by line (BIL), band interleaved by pixel (BIP) as shown below.

Interleaves

Your software (e.g. ArcGIS, ENVI) will delimit the file automatically based on the image dimensions, interleave type, bit size, and other information described in the accompanying text file with the .hdr extension (for header).

The advantage of this format is simplicity: you could tell C++ (or any programming language with I/O support) to just write the binary data from arrays directly to disk and then write the header file after. The disadvantage is that you need to be extremely careful with your header file--any mistakes in the dimensions or bit type will cause serious issues, and since you are just reading raw binary data ArcMap will not be "smart" enough to realize that something has gone wrong.

share|improve this answer
add comment

The binary equivalent of ESRI's ASCII Grid is the (tataaa) ArcINFO Binary Grid. But I think it is not very simple to read or write (due to the fact that i t consists of a whole bunch of files) without a library that does this job for you, like GDAL.

If you use a library like GDAL, I think it would be better to write Filegeodatabase based Rasterdatasets in the first place.

share|improve this answer
1  
I do not believe that the ESRI Filegeodatabase API currently supports rasters. As such, rasters contained in filegoedatabase are not accessible via GDAL. If this has changed it would certainly be good to know! –  Jeffrey Evans May 11 '13 at 16:00
add comment
up vote 2 down vote accepted

I ended up using the ArcGIS floating-point raster format (extension .flt), as described here.

The C++ code I wrote to handle things follows. It will not compile without a grid class, but it should be easy enough to read and understand.

/**
  @brief  Writes a floating-point grid file

  @param[in]  &basename     Name, without extension, of output file
  @param[in]  &output_grid  DEM object to write

  @todo Does not check byte order (big-endian, little-endian)
  @todo Does not output only IEEE-754 32-bit floating-point,
        which is required by ArcGIS

  @returns 0 upon success
*/
template <class T>
int write_floating_data(const std::string basename,const array2d<T> &output_grid){
  std::string fn_header(basename), fn_data(basename);

  fn_header+=".hdr";
  fn_data+=".flt";

  {
    std::ofstream fout;
    fout.open(fn_header.c_str());
    if(!fout.is_open())
      exit(-1);

    diagnostic("Writing floating-point header file...");
    fout<<"ncols\t\t"<<output_grid.width()<<std::endl;
    fout<<"nrows\t\t"<<output_grid.height()<<std::endl;
    fout<<"xllcorner\t"<<std::fixed<<std::setprecision(10)<<output_grid.xllcorner<<std::endl;
    fout<<"yllcorner\t"<<std::fixed<<std::setprecision(10)<<output_grid.yllcorner<<std::endl;
    fout<<"cellsize\t"<<std::fixed<<std::setprecision(10)<<output_grid.cellsize<<std::endl;
    fout<<"NODATA_value\t"<<std::fixed<<std::setprecision(10)<<output_grid.no_data<<std::endl;
    fout<<"BYTEORDER\tLSBFIRST"<<std::endl; //TODO: Detect endian-ness
    fout.close();
  }

  {
    std::ofstream fout(fn_data.c_str(), std::ios::binary | std::ios::out);
    if(!fout.is_open())
      exit(-1);

    for(int y=0;y<output_grid.height();++y)
    for(int x=0;x<output_grid.width();++x)
      fout.write(reinterpret_cast<const char*>(&output_grid(x,y)), std::streamsize(sizeof(T)));
    fout.close();
  }

  return 0;
}






/**
  @brief  Reads in a floating-point grid file

  @param[in]  &basename     Name, without extension, of input file
  @param[in]  &grid         DEM object in which to store data

  @todo Does not check byte order (big-endian, little-endian)
  @todo Does not input only IEEE-754 32-bit floating-point,
        which is required by ArcGIS

  @returns 0 upon success
*/
template <class T>
int read_floating_data(const std::string basename,array2d<T> &grid){
  std::string fn_header(basename), fn_data(basename);

  fn_header+=".hdr";
  fn_data+=".flt";

  int columns, rows;
  char byteorder; //L=LSB first, M=MSB first

  {
    FILE *fin;
    fin=fopen(fn_header.c_str(),"r");
    if(fin==NULL)
      exit(-1);

    if(fscanf(fin,"ncols %d nrows %d xllcorner %lf yllcorner %lf cellsize %lf NODATA_value %f BYTEORDER %c",&columns, &rows, &grid.xllcorner, &grid.yllcorner, &grid.cellsize, &grid.no_data, &byteorder)!=7)
      exit(-1);
    fclose(fin);
  }

  grid.resize(columns,rows);

  {
    std::ifstream fin(fn_data.c_str(), std::ios::binary | std::ios::in);
    if(!fin.is_open())
      exit(-1);

    grid.data_cells=0;
    for(int y=0;y<rows;++y)
    for(int x=0;x<columns;++x){
      fin.read(reinterpret_cast<char*>(&grid(x,y)), std::streamsize(sizeof(T)));
      if(grid(x,y)!=grid.no_data)
        grid.data_cells++;
    }
  }

  return 0;
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.