1433 lines
49 KiB
C++
1433 lines
49 KiB
C++
/*
|
||
This file is part of SECONDO.
|
||
|
||
Copyright (C) 2011, University in Hagen, Department of Computer Science,
|
||
Database Systems for New Applications.
|
||
|
||
SECONDO is free software; you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation; either version 2 of the License, or
|
||
(at your option) any later version.
|
||
|
||
SECONDO is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with SECONDO; if not, write to the Free Software
|
||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
||
*/
|
||
|
||
#include "importEsriGrid.h"
|
||
|
||
using namespace std;
|
||
|
||
namespace raster2
|
||
{
|
||
/*
|
||
Reads a a file for a filename into a given buffer.
|
||
|
||
*/
|
||
bool readFileIntoBuffer(char* buffer, const string& fname,
|
||
const uint32_t len)
|
||
{
|
||
ifstream f(fname.c_str(), ios::in|ios::binary|ios::ate);
|
||
if(!f.is_open()){
|
||
cerr << "could not open " + fname << endl;
|
||
return false;
|
||
}
|
||
f.seekg(0,ios::beg);
|
||
f.read(buffer,len);
|
||
if(!f.good()) {
|
||
f.close();
|
||
cerr << "error in reading " << fname << endl;
|
||
return false;
|
||
}
|
||
f.close();
|
||
return true;
|
||
}
|
||
|
||
void readEsriGridBounds(RasterData *EsriRasterData,
|
||
const string boundingFileName) {
|
||
char buffer[32];
|
||
if(!readFileIntoBuffer(buffer, boundingFileName, 32)) {
|
||
return;
|
||
}
|
||
|
||
EsriRasterData->esriGridConfigData.llxCoord =
|
||
EsriRasterData->getDouble(buffer,0);;
|
||
EsriRasterData->esriGridConfigData.llyCoord =
|
||
EsriRasterData->getDouble(buffer,8);
|
||
EsriRasterData->esriGridConfigData.urxCoord =
|
||
EsriRasterData->getDouble(buffer,16);
|
||
EsriRasterData->esriGridConfigData.uryCoord =
|
||
EsriRasterData->getDouble(buffer,24);
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << "bbox : ( (";
|
||
cout << EsriRasterData->esriGridConfigData.llxCoord;
|
||
cout << ", ";
|
||
cout << EsriRasterData->esriGridConfigData.llyCoord;
|
||
cout << ") -> (";
|
||
cout << EsriRasterData->esriGridConfigData.urxCoord;
|
||
cout << ", ";
|
||
cout << EsriRasterData->esriGridConfigData.uryCoord;
|
||
cout << "))" << endl;
|
||
}
|
||
}
|
||
|
||
void readEsriGridIndexConfig(RasterData *EsriRasterData,
|
||
ifstream *indexFile) {
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << endl << endl << "Reading EsriGrid Index File:" << endl;
|
||
cout << "============================" << endl << endl;
|
||
}
|
||
|
||
indexFile->seekg(24,ios::beg);
|
||
char buffer[4];
|
||
indexFile->read(buffer,4);
|
||
|
||
// filesize in bytes
|
||
EsriRasterData->esriGridConfigData.fileSize =
|
||
EsriRasterData->getUInt32(buffer,0) * 2;
|
||
const uint32_t indexFileSize =
|
||
EsriRasterData->esriGridConfigData.fileSize;
|
||
|
||
// detail information for tiles start at byte 100
|
||
// (8 bytes for every tile)
|
||
EsriRasterData->esriGridConfigData.numTiles =
|
||
(indexFileSize - 100) / INDEX_BUFFER_SIZE;
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << "filesize = " << indexFileSize << endl;
|
||
cout << "numTiles = ";
|
||
cout << EsriRasterData->esriGridConfigData.numTiles;
|
||
cout << endl << endl;
|
||
}
|
||
}
|
||
|
||
void readStatisticData(RasterData *EsriRasterData,
|
||
const string statisticsFileName) {
|
||
char buffer[32];
|
||
if (!readFileIntoBuffer(buffer, statisticsFileName, 32))
|
||
{
|
||
return;
|
||
}
|
||
const double minValue =
|
||
EsriRasterData->getDouble(buffer,0);
|
||
const double maxValue =
|
||
EsriRasterData->getDouble(buffer,8);
|
||
EsriRasterData->esriGridConfigData.esriGridMinimum = minValue;
|
||
EsriRasterData->esriGridConfigData.esriGridMaxmimum = maxValue;
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << endl << endl << "Reading Esri Statistics" << endl;
|
||
cout << "============================" << endl << endl;
|
||
cout << "SMin : " << minValue << endl;
|
||
cout << "SMax : " << maxValue << endl;
|
||
cout << "SMean : " <<
|
||
EsriRasterData->getDouble(buffer,16) << endl;
|
||
cout << "SStdDev : ";
|
||
cout << EsriRasterData->getDouble(buffer,24);
|
||
cout << endl << endl;
|
||
}
|
||
}
|
||
|
||
/*
|
||
Determines the actual number of rows and columns.
|
||
|
||
*/
|
||
void evaluateActualTilesRowAndColumnCount(RasterData *EsriRasterData) {
|
||
|
||
// actual number of columns
|
||
EsriRasterData->esriGridConfigData.actualNumberOfColumns =
|
||
EsriRasterData->currentGridHDR.HTilesPerRow;
|
||
|
||
// actual number of rows
|
||
const double numberOfRows =
|
||
EsriRasterData->esriGridConfigData.actualNumberOfRows =
|
||
EsriRasterData->esriGridConfigData.numTiles /
|
||
EsriRasterData->esriGridConfigData.actualNumberOfColumns;
|
||
EsriRasterData->esriGridConfigData.actualNumberOfRows =
|
||
ceil(numberOfRows);
|
||
}
|
||
|
||
template <typename T, typename Helper>
|
||
void stype<T, Helper>::processConstantBlockData(
|
||
ifstream *dataFile,
|
||
RasterData *esriRasterData,
|
||
const uint32_t tileColIdx,
|
||
const uint32_t tileRowIdx,
|
||
const size_t maxRasterIdxY,
|
||
const uint32_t cellColCount,
|
||
const uint32_t cellRowCount,
|
||
const uint8_t minSize) {
|
||
|
||
const int undefValue = esriRasterData->getEsriGridUndef();
|
||
size_t tilePixelCounter = 0;
|
||
const uint32_t tileLimitCount = cellColCount * cellRowCount;
|
||
storage_type& rasterStorage = this->getStorage();
|
||
|
||
int minValue =
|
||
esriRasterData->getIntFromFileStream(dataFile, minSize);
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << "Min value: " << minValue << endl;
|
||
}
|
||
|
||
// Iterate over cell rows (y-direction)
|
||
for (uint32_t cellRowIdx=0; cellRowIdx<cellRowCount;
|
||
cellRowIdx++) {
|
||
|
||
// Iterate over cell columns (x-direction)
|
||
for (uint32_t cellColIdx=0; cellColIdx<cellColCount;
|
||
cellColIdx++) {
|
||
++tilePixelCounter;
|
||
if (tilePixelCounter > tileLimitCount) {
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << endl << "Leaving processing of tile, ";
|
||
cout << "tilePixelCounter: " << tilePixelCounter;
|
||
}
|
||
return;
|
||
}
|
||
|
||
// the stype raster definition goes from bottom to top, so
|
||
// the y-rasterIndex cell row values have to be turned over
|
||
size_t rasterIndexX =
|
||
(tileColIdx*cellColCount + cellColIdx);
|
||
size_t rasterIndexY = maxRasterIdxY -
|
||
(tileRowIdx*cellRowCount + cellRowIdx);
|
||
|
||
// initialize raster index for current cell
|
||
RasterIndex<2> rasterIndex = (int[2]) {
|
||
(int)rasterIndexX, (int)rasterIndexY
|
||
};
|
||
if (undefValue != minValue) {
|
||
rasterStorage[rasterIndex] = minValue;
|
||
}
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << " " << minValue;
|
||
}
|
||
} // cell columns
|
||
} // cell rows
|
||
}
|
||
|
||
template <typename T, typename Helper>
|
||
void stype<T, Helper>::processEsriTilePixelValueData(
|
||
ifstream *dataFile,
|
||
const uint8_t *rTileType,
|
||
RasterData *esriRasterData,
|
||
const uint32_t tileColIdx,
|
||
const uint32_t tileRowIdx,
|
||
const size_t maxRasterIdxY,
|
||
const uint32_t cellColCount,
|
||
const uint32_t cellRowCount,
|
||
const uint32_t nextTileOffset,
|
||
const uint8_t rMinSize) {
|
||
|
||
const int undefValue = esriRasterData->getEsriGridUndef();
|
||
int tilePixelCounter = 0;
|
||
storage_type& rasterStorage = this->getStorage();
|
||
uint32_t currentTilePosition = 0;
|
||
|
||
int minValue =
|
||
esriRasterData->getIntFromFileStream(dataFile, rMinSize);
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << "Min value: " << minValue << endl;
|
||
}
|
||
|
||
// Iterate over cell rows (y-direction)
|
||
for (uint32_t cellRowIdx=0; cellRowIdx<cellRowCount;
|
||
cellRowIdx++) {
|
||
|
||
// Iterate over cell columns (x-direction)
|
||
for (uint32_t cellColIdx=0; cellColIdx<cellColCount;
|
||
cellColIdx++) {
|
||
currentTilePosition = dataFile->tellg();
|
||
if ((currentTilePosition) > nextTileOffset) {
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << endl << "Leaving processing of tile, ";
|
||
cout << "tilePixelCounter: ";
|
||
cout << tilePixelCounter + 1;
|
||
}
|
||
return;
|
||
}
|
||
|
||
// the stype raster definition goes from bottom to top, so
|
||
// the y-rasterIndex cell row values have to be turned over
|
||
size_t rasterIndexX =
|
||
(tileColIdx*cellColCount + cellColIdx);
|
||
size_t rasterIndexY = maxRasterIdxY -
|
||
(tileRowIdx*cellRowCount + cellRowIdx);
|
||
|
||
// initialize raster index for current cell
|
||
RasterIndex<2> rasterIndex = (int[2]) {
|
||
(int)rasterIndexX, (int)rasterIndexY
|
||
};
|
||
|
||
// read pixel data memory block
|
||
const int pixelValue =
|
||
esriRasterData->getIntValueByRTileType(
|
||
dataFile, rTileType,
|
||
tilePixelCounter);
|
||
|
||
// write it to the raster storage cell
|
||
int resultValue = pixelValue + minValue;
|
||
if (undefValue != resultValue) {
|
||
rasterStorage[rasterIndex] = resultValue;
|
||
}
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << resultValue << " ";
|
||
}
|
||
++tilePixelCounter;
|
||
} // cell columns
|
||
} // cell rows
|
||
}
|
||
|
||
/*
|
||
RTileType 0xCF
|
||
|
||
*/
|
||
template <typename T, typename Helper>
|
||
void stype<T, Helper>::processEsriTile16BitLiteralRunsData(
|
||
ifstream *dataFile,
|
||
RasterData *esriRasterData,
|
||
const uint32_t tileColIdx,
|
||
const uint32_t tileRowIdx,
|
||
const size_t maxRasterIdxY,
|
||
const uint32_t cellColCount,
|
||
const uint32_t cellRowCount,
|
||
const uint32_t nextTileOffset,
|
||
const uint8_t rMinSize) {
|
||
|
||
size_t tilePixelCounter = 0;
|
||
storage_type& rasterStorage = this->getStorage();
|
||
uint32_t currentTilePosition = 0;
|
||
bool isNoDataType = false;
|
||
uint8_t noDataRunPixelCount = 0;
|
||
uint8_t dataRunPixelCount = 0;
|
||
const int undefValue = esriRasterData->getEsriGridUndef();
|
||
|
||
int minValue =
|
||
esriRasterData->getIntFromFileStream(dataFile, rMinSize);
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << "Min value: " << minValue << endl;
|
||
}
|
||
|
||
// Iterate over cell rows (y-direction)
|
||
for (uint32_t cellRowIdx=0; cellRowIdx<cellRowCount;
|
||
cellRowIdx++) {
|
||
|
||
// Iterate over cell columns (x-direction)
|
||
for (uint32_t cellColIdx=0; cellColIdx<cellColCount;
|
||
cellColIdx++) {
|
||
++tilePixelCounter;
|
||
currentTilePosition = dataFile->tellg();
|
||
if (currentTilePosition > nextTileOffset) {
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << endl << "Leaving processing of tile, ";
|
||
cout << "tilePixelCounter: ";
|
||
cout << tilePixelCounter;
|
||
}
|
||
return;
|
||
}
|
||
|
||
// read next byte and it's marker value
|
||
// for the next run of bytes
|
||
if ((dataRunPixelCount == 0) &&
|
||
(noDataRunPixelCount == 0)) {
|
||
// the first byte is a marker for a series of bytes´
|
||
const uint8_t markerByteValue =
|
||
esriRasterData->getUInt8FromFileStream(dataFile);
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << " marker:" << (int)markerByteValue;
|
||
cout << " ";
|
||
}
|
||
|
||
// check if the following run will be of NoData pixels
|
||
isNoDataType = (markerByteValue > 127);
|
||
if (isNoDataType)
|
||
{
|
||
noDataRunPixelCount = 256 - markerByteValue;
|
||
}
|
||
else
|
||
{
|
||
dataRunPixelCount = markerByteValue;
|
||
}
|
||
}
|
||
|
||
// the stype raster definition goes from bottom to top, so
|
||
// the y-rasterIndex cell row values have to be turned over
|
||
size_t rasterIndexX =
|
||
(tileColIdx*cellColCount + cellColIdx);
|
||
size_t rasterIndexY = maxRasterIdxY -
|
||
(tileRowIdx*cellRowCount + cellRowIdx);
|
||
|
||
// initialize raster index for current cell
|
||
RasterIndex<2> rasterIndex = (int[2]) {
|
||
(int)rasterIndexX, (int)rasterIndexY
|
||
};
|
||
|
||
// write NoData values into storage
|
||
if (isNoDataType) {
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << " " << undefValue;
|
||
}
|
||
noDataRunPixelCount--;
|
||
}
|
||
// write 16Bit data integers into storage
|
||
else {
|
||
// read data memory block
|
||
int16_t pixelValue =
|
||
esriRasterData->getInt16FromFileStream(dataFile);
|
||
if (esriRasterData->getEndianTypeLittle()) {
|
||
pixelValue =
|
||
esriRasterData->convert16BitEndian(pixelValue);
|
||
}
|
||
|
||
// write it to the raster storage cell
|
||
int resultValue = (int)pixelValue + minValue;
|
||
if (undefValue != resultValue) {
|
||
rasterStorage[rasterIndex] = resultValue;
|
||
}
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << " " << resultValue;
|
||
}
|
||
dataRunPixelCount--;
|
||
}
|
||
} // cell columns
|
||
} // cell rows
|
||
}
|
||
|
||
/*
|
||
RTileType 0xD7
|
||
|
||
*/
|
||
template <typename T, typename Helper>
|
||
void stype<T, Helper>::processEsriTileLiteralRunsData(
|
||
ifstream *dataFile,
|
||
RasterData *esriRasterData,
|
||
const uint32_t tileColIdx,
|
||
const uint32_t tileRowIdx,
|
||
const size_t maxRasterIdxY,
|
||
const uint32_t cellColCount,
|
||
const uint32_t cellRowCount,
|
||
const uint32_t nextTileOffset,
|
||
const uint8_t minSize) {
|
||
|
||
size_t tilePixelCounter = 0;
|
||
storage_type& rasterStorage = this->getStorage();
|
||
uint32_t currentTilePosition = 0;
|
||
bool isNoDataType = false;
|
||
uint8_t noDataRunPixelCount = 0;
|
||
uint8_t dataRunPixelCount = 0;
|
||
const int undefValue = esriRasterData->getEsriGridUndef();
|
||
|
||
int minValue =
|
||
esriRasterData->getIntFromFileStream(dataFile, minSize);
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << "Min value: " << minValue << endl;
|
||
}
|
||
|
||
// Iterate over cell rows (y-direction)
|
||
for (uint32_t cellRowIdx=0; cellRowIdx<cellRowCount;
|
||
cellRowIdx++) {
|
||
|
||
// Iterate over cell columns (x-direction)
|
||
for (uint32_t cellColIdx=0; cellColIdx<cellColCount;
|
||
cellColIdx++) {
|
||
++tilePixelCounter;
|
||
currentTilePosition = dataFile->tellg();
|
||
if (currentTilePosition > nextTileOffset) {
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << endl << "Leaving processing of tile, ";
|
||
cout << "currentTilePosition: ";
|
||
cout << currentTilePosition;
|
||
cout << ", nextTileOffset: " << nextTileOffset;
|
||
cout << ", tilePixelCounter: ";
|
||
cout << tilePixelCounter;
|
||
}
|
||
return;
|
||
}
|
||
|
||
// read next byte and it's marker value
|
||
// for the next run of bytes
|
||
if ((dataRunPixelCount == 0) &&
|
||
(noDataRunPixelCount == 0)) {
|
||
// the first byte is a marker for a series of bytes´
|
||
const uint8_t markerByteValue =
|
||
esriRasterData->getUInt8FromFileStream(dataFile);
|
||
//cout << " marker:" << (int)markerByteValue << " ";
|
||
|
||
// check if the following run will be of NoData pixels
|
||
isNoDataType = (markerByteValue > 127);
|
||
if (isNoDataType)
|
||
{
|
||
noDataRunPixelCount = 256 - markerByteValue;
|
||
}
|
||
else
|
||
{
|
||
dataRunPixelCount = markerByteValue;
|
||
}
|
||
}
|
||
|
||
// the stype raster definition goes from bottom to top, so
|
||
// the y-rasterIndex cell row values have to be turned over
|
||
size_t rasterIndexX =
|
||
(tileColIdx*cellColCount + cellColIdx);
|
||
size_t rasterIndexY = maxRasterIdxY -
|
||
(tileRowIdx*cellRowCount + cellRowIdx);
|
||
|
||
// initialize raster index for current cell
|
||
RasterIndex<2> rasterIndex = (int[2]) {
|
||
(int)rasterIndexX, (int)rasterIndexY
|
||
};
|
||
|
||
// write NoData values into storage
|
||
if (isNoDataType) {
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << " " << undefValue;
|
||
}
|
||
noDataRunPixelCount--;
|
||
}
|
||
// write 8Bit data integers into storage
|
||
else {
|
||
// read unsigned integer data memory block
|
||
const uint8_t pixelValue =
|
||
esriRasterData->getUInt8FromFileStream(dataFile);
|
||
|
||
// write it to the raster storage cell
|
||
int resultValue = (int)pixelValue + minValue;
|
||
if (undefValue != resultValue) {
|
||
rasterStorage[rasterIndex] = resultValue;
|
||
}
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << " " << resultValue;
|
||
}
|
||
dataRunPixelCount--;
|
||
}
|
||
} // cell columns
|
||
} // cell rows
|
||
}
|
||
|
||
/*
|
||
RTileType 0xDF
|
||
|
||
*/
|
||
template <typename T, typename Helper>
|
||
void stype<T, Helper>::processEsriTileRMinRunsData(
|
||
ifstream *dataFile,
|
||
RasterData *esriRasterData,
|
||
const uint32_t tileColIdx,
|
||
const uint32_t tileRowIdx,
|
||
const size_t maxRasterIdxY,
|
||
const uint32_t cellColCount,
|
||
const uint32_t cellRowCount,
|
||
const uint32_t nextTileOffset,
|
||
const uint8_t rMinSize) {
|
||
|
||
size_t tilePixelCounter = 0;
|
||
storage_type& rasterStorage = this->getStorage();
|
||
uint32_t currentTilePosition = 0;
|
||
bool isNoDataType = false;
|
||
uint8_t noDataRunPixelCount = 0;
|
||
uint8_t dataRunPixelCount = 0;
|
||
const int undefValue = esriRasterData->getEsriGridUndef();
|
||
|
||
int minValue =
|
||
esriRasterData->getIntFromFileStream(dataFile, rMinSize);
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << "Min value: " << minValue << endl;
|
||
}
|
||
|
||
// Iterate over cell rows (y-direction)
|
||
for (uint32_t cellRowIdx=0; cellRowIdx<cellRowCount;
|
||
cellRowIdx++) {
|
||
|
||
// Iterate over cell columns (x-direction)
|
||
for (uint32_t cellColIdx=0; cellColIdx<cellColCount;
|
||
cellColIdx++) {
|
||
++tilePixelCounter;
|
||
currentTilePosition = dataFile->tellg();
|
||
if (currentTilePosition > nextTileOffset) {
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << endl << "Leaving processing of tile, ";
|
||
cout << "tilePixelCounter: " << tilePixelCounter;
|
||
}
|
||
return;
|
||
}
|
||
|
||
// read next byte and it's marker value
|
||
// for the next run of bytes
|
||
if ((dataRunPixelCount == 0) &&
|
||
(noDataRunPixelCount == 0)) {
|
||
// the first byte is a marker for a series of bytes´
|
||
const uint8_t markerByteValue =
|
||
esriRasterData->getUInt8FromFileStream(dataFile);
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << " marker:" << (int)markerByteValue << " ";
|
||
}
|
||
|
||
// check if the following run will be of NoData pixels
|
||
isNoDataType = (markerByteValue > 127);
|
||
if (isNoDataType)
|
||
{
|
||
noDataRunPixelCount = 256 - markerByteValue;
|
||
}
|
||
else
|
||
{
|
||
dataRunPixelCount = markerByteValue;
|
||
}
|
||
}
|
||
|
||
// the stype raster definition goes from bottom to top, so
|
||
// the y-rasterIndex cell row values have to be turned over
|
||
size_t rasterIndexX =
|
||
(tileColIdx*cellColCount + cellColIdx);
|
||
size_t rasterIndexY = maxRasterIdxY -
|
||
(tileRowIdx*cellRowCount + cellRowIdx);
|
||
|
||
// initialize raster index for current cell
|
||
RasterIndex<2> rasterIndex = (int[2]) {
|
||
(int)rasterIndexX, (int)rasterIndexY
|
||
};
|
||
|
||
// write NoData values into storage
|
||
if (isNoDataType) {
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << " " << undefValue;
|
||
}
|
||
noDataRunPixelCount--;
|
||
}
|
||
// write minValue integers into storage
|
||
else {
|
||
// write minValue to the raster storage
|
||
if (undefValue != minValue) {
|
||
rasterStorage[rasterIndex] = minValue;
|
||
}
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << " " << minValue;
|
||
}
|
||
dataRunPixelCount--;
|
||
}
|
||
} // cell columns
|
||
} // cell rows
|
||
}
|
||
|
||
template <typename T, typename Helper>
|
||
void stype<T, Helper>::processEsriTileCountLengthData(
|
||
ifstream *dataFile,
|
||
const uint8_t *rTileType,
|
||
RasterData *esriRasterData,
|
||
const uint32_t tileColIdx,
|
||
const uint32_t tileRowIdx,
|
||
const size_t maxRasterIdxY,
|
||
const uint32_t cellColCount,
|
||
const uint32_t cellRowCount,
|
||
const uint32_t nextTileOffset,
|
||
const uint8_t rMinSize) {
|
||
|
||
size_t tilePixelCounter = 0;
|
||
storage_type& rasterStorage = this->getStorage();
|
||
uint32_t currentTilePosition = 0;
|
||
const int undefValue = esriRasterData->getEsriGridUndef();
|
||
|
||
uint8_t countByteValue = 0;
|
||
int intValue = 0;
|
||
int minValue =
|
||
esriRasterData->getIntFromFileStream(dataFile, rMinSize);
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << "Min value: " << minValue << endl;
|
||
}
|
||
|
||
// Iterate over cell rows (y-direction)
|
||
for (uint32_t cellRowIdx=0; cellRowIdx<cellRowCount;
|
||
cellRowIdx++) {
|
||
|
||
// Iterate over cell columns (x-direction)
|
||
for (uint32_t cellColIdx=0; cellColIdx<cellColCount;
|
||
cellColIdx++) {
|
||
++tilePixelCounter;
|
||
currentTilePosition = dataFile->tellg();
|
||
if (currentTilePosition > nextTileOffset) {
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << endl << "Leaving processing of tile, ";
|
||
cout << "tilePixelCounter: " << tilePixelCounter;
|
||
cout << endl;
|
||
}
|
||
return;
|
||
}
|
||
|
||
// read next byte and it's count marker value
|
||
// for the next run of bytes
|
||
if (countByteValue == 0)
|
||
{
|
||
countByteValue =
|
||
esriRasterData->getUInt8FromFileStream(dataFile);
|
||
|
||
intValue = esriRasterData->getIntValueByRTileType(
|
||
dataFile, rTileType, tilePixelCounter);
|
||
}
|
||
|
||
// the stype raster definition goes from bottom to top, so
|
||
// the y-rasterIndex cell row values have to be turned over
|
||
size_t rasterIndexX =
|
||
(tileColIdx*cellColCount + cellColIdx);
|
||
size_t rasterIndexY = maxRasterIdxY -
|
||
(tileRowIdx*cellRowCount + cellRowIdx);
|
||
|
||
// initialize raster index for current cell
|
||
RasterIndex<2> rasterIndex = (int[2]) {
|
||
(int)rasterIndexX, (int)rasterIndexY
|
||
};
|
||
int result = esriRasterData->getEsriGridUndef();
|
||
int tempResult = (int)intValue + minValue;
|
||
if ((countByteValue > 0) && (tempResult > result))
|
||
{
|
||
result = tempResult;
|
||
}
|
||
|
||
if (undefValue != result) {
|
||
rasterStorage[rasterIndex] = result;
|
||
}
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << result << " ";
|
||
}
|
||
--countByteValue;
|
||
} // cell columns
|
||
} // cell rows
|
||
}
|
||
|
||
template <typename T, typename Helper>
|
||
void stype<T, Helper>::processEsriTileRMinCCITTRLEData(
|
||
ifstream *dataFile,
|
||
RasterData *esriRasterData,
|
||
const uint32_t tileColIdx,
|
||
const uint32_t tileRowIdx,
|
||
const size_t maxRasterIdxY,
|
||
const uint32_t cellColCount,
|
||
const uint32_t cellRowCount,
|
||
const uint32_t nextTileOffset,
|
||
const uint16_t rTileSize,
|
||
const uint8_t rMinSize) {
|
||
|
||
int tilePixelCounter = 0;
|
||
|
||
storage_type& rasterStorage = this->getStorage();
|
||
uint32_t currentTilePosition = 0;
|
||
const int undefValue = esriRasterData->getEsriGridUndef();
|
||
|
||
int minValue =
|
||
esriRasterData->getIntFromFileStream(dataFile, rMinSize);
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << "Min value: " << minValue << endl;
|
||
}
|
||
|
||
// rTileType algorithm taken from gdal library
|
||
// frmts/aigrid/gridlib.c, line 287-317
|
||
int numPixelBytes = rTileSize - 4 - rMinSize;
|
||
int nDstBytes = (numPixelBytes + 7) / 8;
|
||
unsigned char *byteIntermediate;
|
||
byteIntermediate = (unsigned char *) malloc(nDstBytes);
|
||
|
||
// Iterate over cell rows (y-direction)
|
||
for (uint32_t cellRowIdx=0; cellRowIdx<cellRowCount;
|
||
cellRowIdx++) {
|
||
|
||
// Iterate over cell columns (x-direction)
|
||
for (uint32_t cellColIdx=0; cellColIdx<cellColCount;
|
||
cellColIdx++) {
|
||
++tilePixelCounter;
|
||
currentTilePosition = dataFile->tellg();
|
||
if (currentTilePosition > nextTileOffset) {
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << endl << "Leaving processing of tile, ";
|
||
cout << "tilePixelCounter: " << tilePixelCounter;
|
||
}
|
||
return;
|
||
}
|
||
|
||
int intValue = 0;
|
||
if (byteIntermediate != NULL)
|
||
{
|
||
if(byteIntermediate[tilePixelCounter>>3] &
|
||
(0x80 >> (tilePixelCounter & 0x7)))
|
||
{
|
||
intValue = 1;
|
||
}
|
||
else
|
||
{
|
||
intValue = 0;
|
||
}
|
||
}
|
||
|
||
// the stype raster definition goes from bottom to top, so
|
||
// the y-rasterIndex cell row values have to be turned over
|
||
size_t rasterIndexX =
|
||
(tileColIdx*cellColCount + cellColIdx);
|
||
size_t rasterIndexY = maxRasterIdxY -
|
||
(tileRowIdx*cellRowCount + cellRowIdx);
|
||
|
||
// initialize raster index for current cell
|
||
RasterIndex<2> rasterIndex = (int[2]) {
|
||
(int)rasterIndexX, (int)rasterIndexY
|
||
};
|
||
|
||
int resultValue = intValue + minValue;
|
||
if (undefValue != resultValue) {
|
||
rasterStorage[rasterIndex] = resultValue;
|
||
}
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << resultValue << " ";
|
||
}
|
||
} // cell columns
|
||
} // cell rows
|
||
}
|
||
|
||
/*
|
||
Processes an Esri Grid data file by the RTileType.
|
||
|
||
*/
|
||
template <typename T, typename Helper>
|
||
void stype<T, Helper>::processEsriGridByRTileType(
|
||
ifstream *dataFile,
|
||
RasterData *esriRasterData,
|
||
const uint32_t tileColIdx,
|
||
const uint32_t tileRowIdx,
|
||
const size_t maxRasterIdxY,
|
||
const uint32_t cellColCount,
|
||
const uint32_t cellRowCount,
|
||
const uint32_t nextTileOffset) {
|
||
|
||
size_t pos = dataFile->tellg();
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << endl << "Tile Offset: " << pos;
|
||
}
|
||
|
||
char tileInfoBuffer[4];
|
||
dataFile->read(tileInfoBuffer, 4);
|
||
|
||
uint16_t rTileSize = tileInfoBuffer[0];
|
||
unsigned char rTileType = tileInfoBuffer[2];
|
||
uint8_t rMinSize = tileInfoBuffer[3];
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << endl << "MinSize: " << (int)rMinSize;
|
||
|
||
// print cell index
|
||
cout << endl << "Raster storage cell coordinates start: (";
|
||
cout << (int)(tileColIdx * cellColCount) << ", ";
|
||
cout << (int)(maxRasterIdxY - (tileRowIdx * cellRowCount));
|
||
cout << ")";
|
||
|
||
cout << endl << "Esri Grid data for RTileType 0x";
|
||
cout << std::hex << setw(2) << setfill('0');
|
||
cout << int(rTileType) << ":" << std::dec << endl;
|
||
cout << "======================================================";
|
||
cout << endl;
|
||
}
|
||
|
||
/*
|
||
Choose the RTileType handler implementation
|
||
for compressed integer data.
|
||
|
||
*/
|
||
switch(rTileType) {
|
||
case 0x00 :
|
||
processConstantBlockData(
|
||
dataFile,
|
||
esriRasterData,
|
||
tileColIdx,
|
||
tileRowIdx,
|
||
maxRasterIdxY,
|
||
cellColCount,
|
||
cellRowCount,
|
||
rMinSize);
|
||
break;
|
||
|
||
case 0x01 :
|
||
case 0x04 :
|
||
case 0x08 :
|
||
case 0x10 :
|
||
case 0x20 :
|
||
processEsriTilePixelValueData(
|
||
dataFile,
|
||
&rTileType,
|
||
esriRasterData,
|
||
tileColIdx,
|
||
tileRowIdx,
|
||
maxRasterIdxY,
|
||
cellColCount,
|
||
cellRowCount,
|
||
nextTileOffset,
|
||
rMinSize);
|
||
break;
|
||
|
||
case 0xCF :
|
||
processEsriTile16BitLiteralRunsData(
|
||
dataFile,
|
||
esriRasterData,
|
||
tileColIdx,
|
||
tileRowIdx,
|
||
maxRasterIdxY,
|
||
cellColCount,
|
||
cellRowCount,
|
||
nextTileOffset,
|
||
rMinSize);
|
||
break;
|
||
|
||
case 0xD7 :
|
||
processEsriTileLiteralRunsData(
|
||
dataFile,
|
||
esriRasterData,
|
||
tileColIdx,
|
||
tileRowIdx,
|
||
maxRasterIdxY,
|
||
cellColCount,
|
||
cellRowCount,
|
||
nextTileOffset,
|
||
rMinSize);
|
||
break;
|
||
|
||
case 0xDF :
|
||
processEsriTileRMinRunsData(
|
||
dataFile,
|
||
esriRasterData,
|
||
tileColIdx,
|
||
tileRowIdx,
|
||
maxRasterIdxY,
|
||
cellColCount,
|
||
cellRowCount,
|
||
nextTileOffset,
|
||
rMinSize);
|
||
break;
|
||
|
||
case 0xE0 :
|
||
case 0xF0 :
|
||
case 0xFC :
|
||
case 0xF8 :
|
||
processEsriTileCountLengthData(
|
||
dataFile,
|
||
&rTileType,
|
||
esriRasterData,
|
||
tileColIdx,
|
||
tileRowIdx,
|
||
maxRasterIdxY,
|
||
cellColCount,
|
||
cellRowCount,
|
||
nextTileOffset,
|
||
rMinSize);
|
||
break;
|
||
|
||
case 0xFF :
|
||
processEsriTileRMinCCITTRLEData(
|
||
dataFile,
|
||
esriRasterData,
|
||
tileColIdx,
|
||
tileRowIdx,
|
||
maxRasterIdxY,
|
||
cellColCount,
|
||
cellRowCount,
|
||
nextTileOffset,
|
||
rTileSize,
|
||
rMinSize);
|
||
break;
|
||
|
||
default :
|
||
// Handle ERROR
|
||
break;
|
||
}
|
||
}
|
||
|
||
ListExpr importEsriGridTypeMap(ListExpr args)
|
||
{
|
||
const std::string error_message =
|
||
"expected single argument {text|string}";
|
||
|
||
if(!nl->HasLength(args, 1))
|
||
return listutils::typeError(error_message);
|
||
|
||
ListExpr arg = nl->First(args);
|
||
if(nl->ListLength(arg) !=2)
|
||
return listutils::typeError(
|
||
"Error, argument has to consists of 2 parts");
|
||
|
||
ListExpr type = nl->First(arg);
|
||
ListExpr value = nl->Second(arg);
|
||
|
||
if(!listutils::isSymbol(type,CcString::BasicType())
|
||
&& !listutils::isSymbol(type,FText::BasicType()))
|
||
return listutils::typeError(
|
||
"expected argument of type {text|string}");
|
||
|
||
//retrieve the value from the argument list
|
||
Word res;
|
||
bool success =
|
||
QueryProcessor::ExecuteQuery(nl->ToString(value),res);
|
||
|
||
if(!success)
|
||
return listutils::typeError("could not evaluate the value of " +
|
||
nl->ToString(value) );
|
||
|
||
string path;
|
||
if(listutils::isSymbol(type,CcString::BasicType())){
|
||
CcString* resText = static_cast<CcString*>(res.addr);
|
||
if(!resText->IsDefined()){
|
||
resText->DeleteIfAllowed();
|
||
return listutils::typeError(
|
||
"filename evaluated to be undefined");
|
||
}
|
||
|
||
path = resText->GetValue();
|
||
resText->DeleteIfAllowed();
|
||
} else {
|
||
FText* resText = static_cast<FText*>(res.addr);
|
||
if(!resText->IsDefined()){
|
||
resText->DeleteIfAllowed();
|
||
return listutils::typeError(
|
||
"filename evaluated to be undefined");
|
||
}
|
||
|
||
path = resText->GetValue();
|
||
resText->DeleteIfAllowed();
|
||
}
|
||
|
||
RasterData *EsriRasterData = new RasterData(false);
|
||
int32_t celltype = EsriRasterData->getCellTypeFromFile(path);
|
||
if(celltype == -1){
|
||
delete EsriRasterData;
|
||
EsriRasterData = 0;
|
||
return listutils::typeError(
|
||
"error while file operation");
|
||
}
|
||
|
||
ListExpr returnObject;
|
||
if(celltype == 2)
|
||
returnObject = nl->SymbolAtom(sreal::BasicType());
|
||
else if(celltype == 1)
|
||
returnObject = nl->SymbolAtom(sint::BasicType());
|
||
else {
|
||
delete EsriRasterData;
|
||
EsriRasterData = 0;
|
||
return listutils::typeError(
|
||
"wrong cell type in HDR File");
|
||
}
|
||
|
||
delete EsriRasterData;
|
||
EsriRasterData = 0;
|
||
|
||
//Return correct object along with additional bool parameter
|
||
return returnObject;
|
||
}
|
||
|
||
int importEsriGridSelectFun(ListExpr args) {
|
||
NList type(args);
|
||
|
||
if(type.first().isSymbol(CcString::BasicType()))
|
||
return 0;
|
||
|
||
if(type.first().isSymbol(FText::BasicType()))
|
||
return 1;
|
||
|
||
return 2;
|
||
}
|
||
|
||
ValueMapping importEsriGridFuns[] = {
|
||
importEsriGridFun<CcString>,
|
||
importEsriGridFun<FText>,
|
||
0
|
||
};
|
||
|
||
/*
|
||
The Esri Grid Import ValueMapping.
|
||
|
||
*/
|
||
template<class inClass>
|
||
int importEsriGridFun
|
||
(Word* args, Word& result, int message, Word& local, Supplier s)
|
||
{
|
||
cout << endl << endl;
|
||
cout << "Starting EsriGrid import..." << endl << endl;
|
||
|
||
string importPath =
|
||
static_cast<inClass*>( args[0].addr )->GetValue();
|
||
|
||
RasterData *EsriRasterData = new RasterData(false);
|
||
|
||
if(EsriRasterData->getEsriGridHDR(importPath) == 0){
|
||
//retrieve handle to result object
|
||
result = qp->ResultStorage(s);
|
||
|
||
if(EsriRasterData->CellTypeReal()) {
|
||
sreal* esriObject = static_cast<sreal*>(result.addr);
|
||
esriObject->clear();
|
||
//only testdata, will later be filled with real data
|
||
esriObject->importEsriGridFile(EsriRasterData);
|
||
}
|
||
else {
|
||
sint* esriObject = static_cast<sint*>(result.addr);
|
||
esriObject->clear();
|
||
//only testdata, will later be filled with real data
|
||
esriObject->importEsriGridFile(EsriRasterData);
|
||
}
|
||
}
|
||
delete EsriRasterData;
|
||
EsriRasterData = 0;
|
||
|
||
return 0;
|
||
}
|
||
|
||
template <typename T, typename Helper>
|
||
int stype<T, Helper>::importEsriGridFile(RasterData *EsriRasterData)
|
||
{
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << "Magic_number : " <<
|
||
EsriRasterData->currentGridHDR.HMagic << endl;
|
||
cout << "CellType : " <<
|
||
EsriRasterData->currentGridHDR.HCellType << endl;
|
||
cout << "Compressed : " <<
|
||
EsriRasterData->currentGridHDR.CompFlag << endl;
|
||
cout << "HPixelSizeX : " <<
|
||
EsriRasterData->currentGridHDR.HPixelSizeX << endl;
|
||
cout << "HPixelSizeY : " <<
|
||
EsriRasterData->currentGridHDR.HPixelSizeY << endl;
|
||
cout << "XRef : " <<
|
||
EsriRasterData->currentGridHDR.XRef << endl;
|
||
cout << "YRef : " <<
|
||
EsriRasterData->currentGridHDR.YRef << endl;
|
||
cout << "HTilesPerRow : " <<
|
||
EsriRasterData->currentGridHDR.HTilesPerRow << endl;
|
||
cout << "HTilesPerColumn : " <<
|
||
EsriRasterData->currentGridHDR.HTilesPerColumn << endl;
|
||
cout << "HTileXSize : " <<
|
||
EsriRasterData->currentGridHDR.HTileXSize << endl;
|
||
cout << "HTileYSize : " <<
|
||
EsriRasterData->currentGridHDR.HTileYSize << endl;
|
||
}
|
||
|
||
/*
|
||
Processing of Esri grid files:
|
||
|
||
- read global information about tiles etc. from index file
|
||
- iterate over tiles in index file
|
||
- read data of every tile in index file
|
||
- jump to every tile in data file from address given in index file
|
||
- read esri tile data from data file
|
||
|
||
*/
|
||
|
||
const string dirname =
|
||
EsriRasterData->esriGridConfigData.filePath;
|
||
const string boundingFileName =
|
||
dirname + FILE_SEPARATOR + BOUNDING_FILE_NAME;
|
||
const string indexFileName =
|
||
dirname + FILE_SEPARATOR + INDEX_FILE_NAME;
|
||
const string dataFileName =
|
||
dirname + FILE_SEPARATOR + DATA_FILE_NAME;
|
||
const string statisticsFileName =
|
||
dirname + FILE_SEPARATOR + STATISTICS_FILE_NAME;
|
||
|
||
readEsriGridBounds(EsriRasterData, boundingFileName);
|
||
|
||
// initialize the index file
|
||
ifstream indexFile(indexFileName.c_str(), ios::in|ios::binary);
|
||
if(!indexFile.is_open())
|
||
{
|
||
cerr << "problem in opening Esri index file" << endl;
|
||
return 0;
|
||
}
|
||
readEsriGridIndexConfig(EsriRasterData, &indexFile);
|
||
|
||
// evaluate actual tiles per row and column
|
||
evaluateActualTilesRowAndColumnCount(EsriRasterData);
|
||
|
||
// read statistic data from Esri statistics file
|
||
readStatisticData(EsriRasterData, statisticsFileName);
|
||
|
||
// evaluate number of rows and columns that will be filled with tiles
|
||
const uint32_t tileRowCount =
|
||
EsriRasterData->esriGridConfigData.actualNumberOfRows;
|
||
const uint32_t tileColCount =
|
||
EsriRasterData->esriGridConfigData.actualNumberOfColumns;
|
||
|
||
// evaluate cell(pixel) count for each tile
|
||
const uint32_t cellRowCount =
|
||
EsriRasterData->currentGridHDR.HTileYSize;
|
||
const uint32_t cellColCount =
|
||
EsriRasterData->currentGridHDR.HTileXSize;
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << "Number of cell columns (x-direction): ";
|
||
cout << (EsriRasterData->esriGridConfigData.actualNumberOfColumns
|
||
* EsriRasterData->currentGridHDR.HTileXSize) << endl;
|
||
cout << "Number of cell rows (y-direction): ";
|
||
cout << EsriRasterData->esriGridConfigData.actualNumberOfRows
|
||
* EsriRasterData->currentGridHDR.HTileYSize << endl;
|
||
}
|
||
|
||
indexFile.seekg(100,ios::beg);
|
||
|
||
// initialize the Esri data file
|
||
ifstream dataFile(dataFileName.c_str(), ios::in|ios::binary);
|
||
if(!dataFile.is_open())
|
||
{
|
||
cerr << "Problem in opening EsriGrid data file." << endl;
|
||
|
||
indexFile.close();
|
||
dataFile.close();
|
||
return 0;
|
||
}
|
||
|
||
//get storage of current sint/sreal
|
||
storage_type& rasterStorage = this->getStorage();
|
||
|
||
// cell length
|
||
double cellLength = 1.0;
|
||
if (EsriRasterData->currentGridHDR.HPixelSizeX ==
|
||
EsriRasterData->currentGridHDR.HPixelSizeY) {
|
||
cellLength = EsriRasterData->currentGridHDR.HPixelSizeX;
|
||
}
|
||
|
||
// initialize grid
|
||
// coordinates of lower left geographic corner
|
||
grid = grid2(
|
||
EsriRasterData->esriGridConfigData.llxCoord,
|
||
EsriRasterData->esriGridConfigData.llyCoord,
|
||
cellLength);
|
||
|
||
// biggest and smallest defined values from all data cells
|
||
minimum = EsriRasterData->esriGridConfigData.esriGridMinimum;
|
||
maximum = EsriRasterData->esriGridConfigData.esriGridMaxmimum;
|
||
|
||
const int undefValue = EsriRasterData->getEsriGridUndef();
|
||
|
||
/*
|
||
The data file w001001.adf contains data ordered by tiles.
|
||
All data will be read tile by tile.
|
||
So we do not have to iterate mainly over cell rows but
|
||
over tiles. Therefore all cells of a tile will be read
|
||
completely for a tile. Then all cells of the next tile
|
||
will be read.
|
||
|
||
*/
|
||
|
||
// the upper limit of cells in y-direction (count of cell rows)
|
||
const size_t maxRasterIdxY = tileRowCount * cellRowCount;
|
||
|
||
// cell count for debugging
|
||
int debugTileCount = 0;
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << endl << endl;
|
||
cout << "Storing Esri Grid Data to Raster Storage...";
|
||
cout << endl << endl;
|
||
}
|
||
|
||
// Iterate over tile rows (y-direction)
|
||
for (uint32_t tileRowIdx=0; tileRowIdx<tileRowCount;
|
||
tileRowIdx++) {
|
||
|
||
// Iterate over tile columns (x-direction)
|
||
for (uint32_t tileColIdx=0; tileColIdx<tileColCount;
|
||
tileColIdx++) {
|
||
|
||
++debugTileCount;
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << endl << endl << std::dec;
|
||
cout << "Tile No: " << debugTileCount;
|
||
}
|
||
|
||
char indexBuffer[INDEX_BUFFER_SIZE];
|
||
|
||
// read next position in index file
|
||
indexFile.read(indexBuffer, INDEX_BUFFER_SIZE);
|
||
|
||
// read next tile offset (next tile position)
|
||
uint32_t offset =
|
||
EsriRasterData->getUInt32(indexBuffer, 0) * 2;
|
||
|
||
uint32_t tileSize =
|
||
EsriRasterData->getUInt32(indexBuffer, 4) * 2;
|
||
uint32_t nextTileOffset = offset + tileSize + 2;
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << endl << "Tile Size (bytes): " << tileSize;
|
||
cout << endl << "Tile coordinates (x,y): ";
|
||
cout << "(" << tileColIdx << ",";
|
||
cout << (tileRowCount-tileRowIdx) << ")";
|
||
}
|
||
|
||
/*
|
||
Process the tiles.
|
||
|
||
*/
|
||
|
||
// read next tile
|
||
dataFile.seekg(offset,ios::beg);
|
||
|
||
/*
|
||
For floating point and uncompressed integer files
|
||
the data is just the tile size (RTileSize)
|
||
in two bytes beginning from 'offset' followed
|
||
by the pixel data as 4 byte words.
|
||
|
||
Every compressed tile on the other hand contains
|
||
the following information at the beginning:
|
||
- byte 0-1: RTileSize
|
||
- byte 2 : RTileType
|
||
- byte 3 : RMinSize
|
||
For compressed integer tiles it is necessary
|
||
to interpret the RTileType to establish the
|
||
details of the tile organization
|
||
|
||
*/
|
||
|
||
// Read compressed data dependent on the RTileType.
|
||
if (EsriRasterData->currentGridHDR.CompFlag == 0) {
|
||
processEsriGridByRTileType(
|
||
&dataFile, EsriRasterData,
|
||
tileColIdx, tileRowIdx, maxRasterIdxY,
|
||
cellColCount, cellRowCount,
|
||
nextTileOffset);
|
||
/*
|
||
Not compressed data:
|
||
Only read the first 2 bytes (RTileSize),
|
||
then read the data (integer or float) in
|
||
4 byte portions.
|
||
|
||
*/
|
||
} else if (tileSize > 0) {
|
||
|
||
float undefValueFloat =
|
||
EsriRasterData->getEsriGridFloatUndef();
|
||
|
||
size_t pos = dataFile.tellg();
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << endl << "Tile Offset: " << pos << endl;
|
||
}
|
||
|
||
// Iterate over cell rows (y-direction)
|
||
for (uint32_t cellRowIdx=0; cellRowIdx<cellRowCount;
|
||
cellRowIdx++) {
|
||
|
||
// Iterate over cell columns (x-direction)
|
||
for (uint32_t cellColIdx=0; cellColIdx<cellColCount;
|
||
cellColIdx++) {
|
||
|
||
/*
|
||
Process one cell/pixel value.
|
||
|
||
*/
|
||
|
||
// the stype raster definition goes from bottom
|
||
// to top, so the y-rasterIndex values (of the
|
||
// cell rows) have to be turned over
|
||
size_t rasterIdxY = maxRasterIdxY -
|
||
(cellRowIdx*cellRowCount + cellRowIdx);
|
||
size_t rasterIdxX =
|
||
(tileColIdx*cellColCount + cellColIdx);
|
||
|
||
// initialize raster index for current cell
|
||
RasterIndex<2> rasterIndex = (int[2]) {
|
||
(int)rasterIdxY,(int) rasterIdxX
|
||
};
|
||
|
||
// read data memory block
|
||
char* dataMemoryBlock = new char[4];
|
||
dataFile.read(dataMemoryBlock, 4);
|
||
|
||
// distinguish between integer and real values
|
||
if (EsriRasterData->CellTypeReal()) {
|
||
|
||
// floating points in single precision (32 bits)
|
||
float floatValue =
|
||
*((float*) dataMemoryBlock);
|
||
float f_nan = numeric_limits<float>::quiet_NaN();
|
||
if (floatValue != f_nan)
|
||
{
|
||
if (EsriRasterData->getEndianTypeLittle())
|
||
{
|
||
floatValue =
|
||
EsriRasterData->convertFloat(floatValue);
|
||
}
|
||
int intTemp = floatValue * 100;
|
||
floatValue = intTemp/100.0;
|
||
|
||
// write it to the raster storage
|
||
// TODO correct limits
|
||
if ((floatValue > undefValueFloat)
|
||
&& (floatValue < 1000)
|
||
&& (floatValue > -1000))
|
||
{
|
||
rasterStorage[rasterIndex] = floatValue;
|
||
}
|
||
}
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << " " << floatValue;
|
||
}
|
||
}
|
||
else {
|
||
int32_t intValue = *((int32_t*) dataMemoryBlock);
|
||
if (EsriRasterData->getEndianTypeLittle())
|
||
{
|
||
intValue =
|
||
EsriRasterData->convertEndian(intValue);
|
||
}
|
||
|
||
// write it to the raster storage
|
||
if (undefValue != intValue)
|
||
{
|
||
rasterStorage[rasterIndex] = intValue;
|
||
}
|
||
|
||
if (DEBUG_OUTPUT_ENABLED) {
|
||
cout << " " << intValue;
|
||
}
|
||
} // cell type integer
|
||
} // cell columns
|
||
} // cell rows
|
||
} // else not compressed data
|
||
else {
|
||
cout << endl << "Tile will not be processed";
|
||
}
|
||
} // tile columns
|
||
} // tile rows
|
||
indexFile.close();
|
||
dataFile.close();
|
||
cout << endl << endl << "Done." << endl;
|
||
cout << "Successfully imported EsriGrid Data" << endl << endl;
|
||
|
||
return 0;
|
||
}
|
||
}
|