From 2b938f095bc4cdec41b08f097d2cc7d3f18f4c98 Mon Sep 17 00:00:00 2001 From: Erik Broberg Date: Thu, 30 Jun 2016 18:38:54 -0400 Subject: [PATCH] Structure IODescription in read and write sub structs. Cleanup --- modules/globebrowsing/tile/tiledataset.cpp | 107 +++++++++++---------- modules/globebrowsing/tile/tiledataset.h | 49 +++++----- 2 files changed, 82 insertions(+), 74 deletions(-) diff --git a/modules/globebrowsing/tile/tiledataset.cpp b/modules/globebrowsing/tile/tiledataset.cpp index 7783661845..f4188aeac2 100644 --- a/modules/globebrowsing/tile/tiledataset.cpp +++ b/modules/globebrowsing/tile/tiledataset.cpp @@ -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 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 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 TileDataset::preprocess(const char* imageData, - const PixelRegion& region, const TileDataLayout& dataLayout) + std::shared_ptr 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); } diff --git a/modules/globebrowsing/tile/tiledataset.h b/modules/globebrowsing/tile/tiledataset.h index 60ce62e30a..d06fa641cc 100644 --- a/modules/globebrowsing/tile/tiledataset.h +++ b/modules/globebrowsing/tile/tiledataset.h @@ -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 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 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 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; + };