Perhaps this tutorial I made some times ago can help you :
Is write it at a time I was working on a terrain importer project :
For geotiff to raw16 convertion I used GDAl library like this :
#include “Convert.h”
#include
#include
#include
#include <gdal_priv.h>
void ConvertGeoTiffToRaw16(ign::Download const & height_download, double no_data_value, ign::DVec2 const& position_m)
{
std::cout << “Converting heightmap to raw” << std::endl;
std::string dataSetPath = height_download.compute_path();
std::string headerPath = height_download.folder_path + "/" + height_download.name + ".json";
std::string rawDataPath = height_download.folder_path + "/" + height_download.name + ".raw";
//Open dataset
GDALAllRegister();
auto poDataset = GDALDataset::FromHandle(GDALOpen(dataSetPath.c_str(), GA_ReadOnly));
if (poDataset == nullptr)
{
std::cerr << "Can load dataset : " << dataSetPath << std::endl;
return;
}
//Get infos
double adfGeoTransform[6];
//Get raster band
GDALRasterBand* poBand;
int nBlockXSize, nBlockYSize;
int bGotMin, bGotMax;
double adfMinMax[2];
poBand = poDataset->GetRasterBand(1);
poBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
GDALSetRasterNoDataValue((GDALRasterBandH)poBand, -99999.0);
adfMinMax[0] = poBand->GetMinimum(&bGotMin);
adfMinMax[1] = poBand->GetMaximum(&bGotMax);
if (!(bGotMin && bGotMax))
GDALComputeRasterMinMax((GDALRasterBandH)poBand, FALSE, adfMinMax);
//printf("Min=%.3fd, Max=%.3f\n", adfMinMax[0], adfMinMax[1]);
/*if (poBand->GetOverviewCount() > 0)
printf("Band has %d overviews.\n", poBand->GetOverviewCount());
if (poBand->GetColorTable() != NULL)
printf("Band has a color table with %d entries.\n",
poBand->GetColorTable()->GetColorEntryCount());*/
//Reading
float* pafScanline;
int nXSize = poBand->GetXSize();
int nYSize = poBand->GetYSize();
pafScanline = (float*)CPLMalloc(sizeof(float) * nXSize);
//Compute distance
double lon0 = adfGeoTransform[0];
double lat0 = adfGeoTransform[3];
double lon1 = lon0 + nXSize * adfGeoTransform[1];
double lat1 = lat0 + nYSize * adfGeoTransform[5];
double midLat = (lat0 + lat1) / 2.0;
double midLon = (lon0 + lon1) / 2.0;
double minHeight_m = adfMinMax[0];
double height_m = adfMinMax[1] - minHeight_m;
double midHeight_m = minHeight_m + height_m / 2.0;
//Write header
ign::DVec2 tile_resolution_m_px = height_download.bbox.size_m / ign::DVec2(height_download.size_px);
ign::DVec2 tile_size_m = tile_resolution_m_px * (ign::DVec2(height_download.size_px) - ign::DVec2(1, 1));
std::ofstream header(headerPath);
header << std::setprecision(3) << std::fixed;
header << "{ " << std::endl;
header << "\t\"resolutionX_px\" : " << nXSize << ", " << std::endl;
header << "\t\"resolutionY_px\" : " << nYSize << ", " << std::endl;
header << "\t\"sizeX_m\" : " << tile_size_m.x << ", " << std::endl;
header << "\t\"sizeY_m\" : " << tile_size_m.y << ", " << std::endl;
header << "\t\"sizeZ_m\" : " << height_m << ", " << std::endl;
header << "\t\"minZ_m\" : " << minHeight_m << ", " << std::endl;
header << "\t\"maxZ_m\" : " << minHeight_m + height_m << ", " << std::endl;
header << "\t\"midZ_m\" : " << midHeight_m << ", " << std::endl;
header << "\t\"UEImport\" : { " << std::endl;
header << "\t\t\"LocationX\" : " << position_m.x * 100 << ", " << std::endl;
header << "\t\t\"LocationY\" : " << position_m.y * -100 << ", " << std::endl;
header << "\t\t\"LocationZ\" : " << midHeight_m * 100 << ", " << std::endl;
header << "\t\t\"ScaleX\" : " << 100.0 * tile_resolution_m_px.x << ", " << std::endl;
header << "\t\t\"ScaleY\" : " << 100.0 * tile_resolution_m_px.y << ", " << std::endl;
header << "\t\t\"ScaleZ\" : " << 100.0 * height_m / 511.992 << std::endl;
header << "}" << std::endl;
header << "}" << std::endl;
header.close();
//Write data
std::ofstream rawData(rawDataPath, std::ios::binary);
std::vector<uint16_t> rawLine = std::vector<uint16_t>(nXSize);
for (int y = 0; y < nYSize; ++y)
{
poBand->RasterIO(GF_Read, 0, y, nXSize, 1,
pafScanline, nXSize, 1, GDT_Float32,
0, 0);
for (int x = 0; x < nXSize; ++x)
{
rawLine[x] = (std::uint16_t)std::round(
std::numeric_limits<uint16_t>::max() * (pafScanline[x] - minHeight_m) / height_m
);
}
rawData.write((const char*)&rawLine.front(), nXSize * sizeof(std::uint16_t));
}
rawData.close();
//Close
CPLFree(pafScanline);
GDALClose(poDataset);
}