Structure IODescription in read and write sub structs. Cleanup

This commit is contained in:
Erik Broberg
2016-06-30 18:38:54 -04:00
parent aa36e6da00
commit 2b938f095b
2 changed files with 82 additions and 74 deletions

View File

@@ -92,21 +92,25 @@ namespace openspace {
: _doPreprocessing(doPreprocessing)
, _maxLevel(-1)
{
// 1. First make sure GDAL has been initialized
if (!GdalHasBeenInitialized) {
GDALAllRegister();
CPLSetConfigOption("GDAL_DATA", absPath("${MODULE_GLOBEBROWSING}/gdal_data").c_str());
GdalHasBeenInitialized = true;
}
//2. Secondly, open the GDAL dataset. Other methods depends on this
_dataset = (GDALDataset *)GDALOpen(gdalDatasetDesc.c_str(), GA_ReadOnly);
if (!_dataset) {
throw ghoul::RuntimeError("Failed to load dataset:\n" + gdalDatasetDesc);
}
_dataLayout = TileDataLayout(_dataset, dataType);
//3. Do any other initialization needed for the TileDataset
_dataLayout = TileDataLayout(_dataset, dataType);
_depthTransform = calculateTileDepthTransform();
_tileLevelDifference = calculateTileLevelDifference(_dataset, minimumPixelSize);
_tileLevelDifference = calculateTileLevelDifference(minimumPixelSize);
LDEBUG(gdalDatasetDesc << " - " << _tileLevelDifference);
}
@@ -115,8 +119,8 @@ namespace openspace {
delete _dataset;
}
int TileDataset::calculateTileLevelDifference(GDALDataset* dataset, int minimumPixelSize) {
GDALRasterBand* firstBand = dataset->GetRasterBand(1);
int TileDataset::calculateTileLevelDifference(int minimumPixelSize) {
GDALRasterBand* firstBand = _dataset->GetRasterBand(1);
GDALRasterBand* maxOverview;
int numOverviews = firstBand->GetOverviewCount();
int sizeLevel0;
@@ -146,10 +150,10 @@ namespace openspace {
return transform;
}
PixelCoordinate TileDataset::geodeticToPixel(GDALDataset* dataSet, const Geodetic2& geo) {
PixelCoordinate TileDataset::geodeticToPixel(const Geodetic2& geo) const{
double padfTransform[6];
CPLErr err = dataSet->GetGeoTransform(padfTransform);
CPLErr err = _dataset->GetGeoTransform(padfTransform);
ghoul_assert(err != CE_Failure, "Failed to get transform");
@@ -187,8 +191,8 @@ namespace openspace {
PixelRegion TileDataset::gdalPixelRegion(const GeodeticPatch& geodeticPatch) const {
Geodetic2 nwCorner = geodeticPatch.getCorner(Quad::NORTH_WEST);
Geodetic2 swCorner = geodeticPatch.getCorner(Quad::SOUTH_EAST);
PixelCoordinate pixelStart = TileDataset::geodeticToPixel(_dataset, nwCorner);
PixelCoordinate pixelEnd = TileDataset::geodeticToPixel(_dataset, swCorner);
PixelCoordinate pixelStart = geodeticToPixel(nwCorner);
PixelCoordinate pixelEnd = geodeticToPixel(swCorner);
PixelRegion gdalRegion(pixelStart, pixelEnd- pixelStart);
return gdalRegion;
}
@@ -258,35 +262,36 @@ namespace openspace {
region.downscalePow2(overview + 1); // pixel region at suitable overview
// Create an IORegion based on that overview pixel region
IODescription ioRegion;
ioRegion.overview = overview;
ioRegion.readRegion = region;
ioRegion.writeRegion = { PixelCoordinate(0, 0), region.numPixels };
IODescription io;
io.read.overview = overview;
io.read.region = region;
io.write.region = { PixelCoordinate(0, 0), region.numPixels };
// Handle the case where the dataset does not have overviews
if (!gdalHasOverviews()) {
ioRegion.readRegion.upscalePow2(overview + 1);
ioRegion.overview = 0; // no overview
io.read.region.upscalePow2(overview + 1);
io.read.overview = 0; // no overview
}
// For correct sampling in height dataset, we need to pad the texture tile
ioRegion.readRegion.pad(padding);
io.read.region.pad(padding);
// Doing this may cause invalid regions, i.e. having negative pixel coordinates
// or being too large etc. For now, just clamp
PixelRegion overviewRegion = gdalPixelRegion(gdalRasterBand(overview));
ioRegion.readRegion.clampTo(overviewRegion);
io.read.region.clampTo(overviewRegion);
return ioRegion;
io.write.bytesPerLine = _dataLayout.bytesPerPixel * io.write.region.numPixels.x;
io.write.totalNumBytes = io.write.bytesPerLine * io.write.region.numPixels.y;
return io;
}
std::shared_ptr<TileIOResult> TileDataset::readTileData(ChunkIndex chunkIndex) {
IODescription io = getIODescription(chunkIndex);
size_t bytesPerLine = _dataLayout.bytesPerPixel * io.writeRegion.numPixels.x;
size_t totalNumBytes = bytesPerLine * io.writeRegion.numPixels.y;
char* imageData = new char[totalNumBytes];
char* imageData = new char[io.write.totalNumBytes];
CPLErr worstError = CPLErr::CE_None;
@@ -294,20 +299,20 @@ namespace openspace {
for (size_t i = 0; i < _dataLayout.numRasters; i++) {
char* dataDestination = imageData + (i * _dataLayout.bytesPerDatum);
GDALRasterBand* rasterBand = gdalRasterBand(io.overview, i+1);
GDALRasterBand* rasterBand = gdalRasterBand(io.read.overview, i+1);
CPLErr err = rasterBand->RasterIO(
GF_Read,
io.readRegion.start.x, // Begin read x
io.readRegion.start.y, // Begin read y
io.readRegion.numPixels.x, // width to read x
io.readRegion.numPixels.y, // width to read y
io.read.region.start.x, // Begin read x
io.read.region.start.y, // Begin read y
io.read.region.numPixels.x, // width to read x
io.read.region.numPixels.y, // width to read y
dataDestination, // Where to put data
io.writeRegion.numPixels.x, // width to write x in destination
io.writeRegion.numPixels.y, // width to write y in destination
io.write.region.numPixels.x, // width to write x in destination
io.write.region.numPixels.y, // width to write y in destination
_dataLayout.gdalType, // Type
_dataLayout.bytesPerPixel, // Pixel spacing
bytesPerLine); // Line spacing
io.write.bytesPerLine); // Line spacing
// CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4
worstError = std::max(worstError, err);
@@ -315,18 +320,19 @@ namespace openspace {
std::shared_ptr<TileIOResult> result(new TileIOResult);
result->chunkIndex = chunkIndex;
result->imageData = getImageDataFlippedY(io.writeRegion, _dataLayout, imageData);
result->dimensions = glm::uvec3(io.writeRegion.numPixels, 1);
result->nBytesImageData = _dataLayout.bytesPerPixel * io.writeRegion.numPixels.x * io.writeRegion.numPixels.y;
result->imageData = getImageDataFlippedY(io.write.region, imageData);
result->dimensions = glm::uvec3(io.write.region.numPixels, 1);
result->nBytesImageData = io.write.totalNumBytes;
result->error = worstError;
if (_doPreprocessing) {
result->preprocessData = preprocess(imageData, io.writeRegion, _dataLayout);
result->preprocessData = preprocess(imageData, io.write.region);
int success;
auto gdalOverview = _dataset->GetRasterBand(1)->GetOverview(io.overview);
double missingDataValue = gdalOverview->GetNoDataValue(&success);
double missingDataValue = gdalRasterBand(io.read.overview)->GetNoDataValue(&success);
if (!success) {
missingDataValue = 32767; // missing data value
missingDataValue = 32767; // missing data value for TERRAIN.wms. Should be specified in xml
}
bool hasMissingData = false;
for (size_t c = 0; c < _dataLayout.numRasters; c++) {
hasMissingData |= result->preprocessData->maxValues[c] == missingDataValue;
@@ -341,10 +347,8 @@ namespace openspace {
return result;
}
char* TileDataset::getImageDataFlippedY(const PixelRegion& region,
const TileDataLayout& dataLayout, const char* imageData)
{
size_t bytesPerLine = dataLayout.bytesPerPixel * region.numPixels.x;
char* TileDataset::getImageDataFlippedY(const PixelRegion& region, const char* imageData) {
size_t bytesPerLine = _dataLayout.bytesPerPixel * region.numPixels.x;
size_t totalNumBytes = bytesPerLine * region.numPixels.y;
// GDAL reads image data top to bottom. We want the opposite.
@@ -354,8 +358,8 @@ namespace openspace {
size_t yi = (region.numPixels.y - 1 - y) * bytesPerLine;
size_t i = 0;
for (size_t x = 0; x < region.numPixels.x; x++) {
for (size_t c = 0; c < dataLayout.numRasters; c++) {
for (size_t b = 0; b < dataLayout.bytesPerDatum; b++) {
for (size_t c = 0; c < _dataLayout.numRasters; c++) {
for (size_t b = 0; b < _dataLayout.bytesPerDatum; b++) {
imageDataYflipped[yi_flipped + i] = imageData[yi + i];
i++;
}
@@ -372,17 +376,16 @@ namespace openspace {
}
std::shared_ptr<TilePreprocessData> TileDataset::preprocess(const char* imageData,
const PixelRegion& region, const TileDataLayout& dataLayout)
std::shared_ptr<TilePreprocessData> TileDataset::preprocess(const char* imageData, const PixelRegion& region)
{
size_t bytesPerLine = dataLayout.bytesPerPixel * region.numPixels.x;
size_t bytesPerLine = _dataLayout.bytesPerPixel * region.numPixels.x;
size_t totalNumBytes = bytesPerLine * region.numPixels.y;
TilePreprocessData* preprocessData = new TilePreprocessData();
preprocessData->maxValues.resize(dataLayout.numRasters);
preprocessData->minValues.resize(dataLayout.numRasters);
preprocessData->maxValues.resize(_dataLayout.numRasters);
preprocessData->minValues.resize(_dataLayout.numRasters);
for (size_t c = 0; c < dataLayout.numRasters; c++) {
for (size_t c = 0; c < _dataLayout.numRasters; c++) {
preprocessData->maxValues[c] = -FLT_MAX;
preprocessData->minValues[c] = FLT_MAX;
}
@@ -392,17 +395,17 @@ namespace openspace {
size_t yi = (region.numPixels.y - 1 - y) * bytesPerLine;
size_t i = 0;
for (size_t x = 0; x < region.numPixels.x; x++) {
for (size_t c = 0; c < dataLayout.numRasters; c++) {
for (size_t c = 0; c < _dataLayout.numRasters; c++) {
float val = TileDataType::interpretFloat(dataLayout.gdalType, &(imageData[yi + i]));
float val = TileDataType::interpretFloat(_dataLayout.gdalType, &(imageData[yi + i]));
preprocessData->maxValues[c] = std::max(val, preprocessData->maxValues[c]);
preprocessData->minValues[c] = std::min(val, preprocessData->minValues[c]);
i += dataLayout.bytesPerDatum;
i += _dataLayout.bytesPerDatum;
}
}
}
for (size_t c = 0; c < dataLayout.numRasters; c++) {
for (size_t c = 0; c < _dataLayout.numRasters; c++) {
if (preprocessData->maxValues[c] > 8800.0f) {
//LDEBUG("Bad preprocess data: " << preprocessData->maxValues[c] << " at " << region.chunkIndex);
}

View File

@@ -113,17 +113,21 @@ namespace openspace {
struct IODescription {
int overview;
PixelRegion readRegion;
PixelRegion writeRegion;
struct ReadData {
int overview;
PixelRegion region;
} read;
struct WriteData {
PixelRegion region; // should always start at 0,0
size_t bytesPerLine;
size_t totalNumBytes;
} write;
};
class TileDataset {
public:
/**
* Opens a GDALDataset in readonly mode and calculates meta data required for
@@ -138,7 +142,6 @@ namespace openspace {
~TileDataset();
std::shared_ptr<TileIOResult> readTileData(ChunkIndex chunkIndex);
@@ -148,11 +151,8 @@ namespace openspace {
const static glm::ivec2 tilePixelStartOffset;
const static glm::ivec2 tilePixelSizeDifference;
const static PixelRegion padding;
static PixelCoordinate geodeticToPixel(GDALDataset* dataSet, const Geodetic2& geo);
const static PixelRegion padding; // same as the two above
private:
@@ -161,34 +161,36 @@ namespace openspace {
//////////////////////////////////////////////////////////////////////////////////
// HELPER FUNCTIONS //
// GDAL HELPER FUNCTIONS //
//////////////////////////////////////////////////////////////////////////////////
PixelRegion gdalPixelRegion(const GeodeticPatch& geodeticPatch) const;
int gdalOverview(const PixelCoordinate& baseRegionSize) const;
int gdalOverview(const ChunkIndex& chunkIndex) const;
bool gdalHasOverviews() const;
PixelRegion gdalPixelRegion(GDALRasterBand* rasterBand) const;
GDALRasterBand* gdalRasterBand(int overview, int raster = 1) const;
//////////////////////////////////////////////////////////////////////////////////
// Initialization //
//////////////////////////////////////////////////////////////////////////////////
TileDepthTransform calculateTileDepthTransform();
std::shared_ptr<TilePreprocessData> preprocess(const char* imageData,
const PixelRegion& region, const TileDataLayout& dataLayout);
int calculateTileLevelDifference(int minimumPixelSize);
static int calculateTileLevelDifference(GDALDataset* dataset, int minimumPixelSize);
static char* getImageDataFlippedY(const PixelRegion& region,
const TileDataLayout& dataLayout, const char* imageData);
//////////////////////////////////////////////////////////////////////////////////
// ReadTileData helper functions //
//////////////////////////////////////////////////////////////////////////////////
PixelCoordinate geodeticToPixel(const Geodetic2& geo) const;
char* getImageDataFlippedY(const PixelRegion& region, const char* imageData);
std::shared_ptr<TilePreprocessData> preprocess(const char* imageData, const PixelRegion& region);
//////////////////////////////////////////////////////////////////////////////////
// MEMBER VARIABLES //
//////////////////////////////////////////////////////////////////////////////////
static bool GdalHasBeenInitialized;
int _maxLevel;
double _tileLevelDifference;
@@ -199,6 +201,9 @@ namespace openspace {
TileDataLayout _dataLayout;
bool _doPreprocessing;
static bool GdalHasBeenInitialized;
};