172 std::function<T(V, V)> convert)
174 logging::info(
"Reading file %s", filename.c_str());
178 auto min_value = std::numeric_limits<V>::max();
179 auto max_value = std::numeric_limits<V>::min();
181 logging::debug(
"Reading a raster where T = %s, V = %s",
184 logging::debug(
"Raster type V has limits %ld, %ld",
185 std::numeric_limits<V>::min(),
186 std::numeric_limits<V>::max());
187 const GridBase grid_info = read_header(tif, gtif);
189 uint32_t tile_length;
190 TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width);
191 TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_length);
194 TIFFGetField(tif, TIFFTAG_GDAL_NODATA, &count, &
data);
195 logging::check_fatal(0 == count,
"NODATA value is not set in input");
196 logging::debug(
"NODATA value is '%s'",
static_cast<char*
>(
data));
197 const auto nodata_orig = stoi(
string(
static_cast<char*
>(
data)));
198 logging::debug(
"NODATA value is originally parsed as %d", nodata_orig);
199 const auto nodata_input =
static_cast<V
>(stoi(
string(
static_cast<char*
>(
data))));
200 logging::debug(
"NODATA value is parsed as %d", nodata_input);
204 logging::note(
"Coordinates before reading are (%d, %d => %f, %f)",
205 std::get<0>(*coordinates),
206 std::get<1>(*coordinates),
207 std::get<0>(*coordinates) + std::get<2>(*coordinates) / 1000.0,
208 std::get<1>(*coordinates) + std::get<3>(*coordinates) / 1000.0);
209 auto min_column = max(
static_cast<FullIdx
>(0),
210 static_cast<FullIdx
>(std::get<1>(*coordinates) -
static_cast<FullIdx
>(MAX_COLUMNS) /
static_cast<FullIdx
>(2)));
211 if (min_column + MAX_COLUMNS >= actual_columns)
213 min_column = max(
static_cast<FullIdx
>(0), actual_columns - MAX_COLUMNS);
216 const auto tile_column = tile_width *
static_cast<FullIdx
>(min_column / tile_width);
217 const auto max_column =
static_cast<FullIdx
>(min(min_column + MAX_COLUMNS - 1, actual_columns));
219 logging::check_fatal(min_column < 0,
"Column can't be less than 0");
220 logging::check_fatal(max_column - min_column > MAX_COLUMNS,
"Can't have more than %d columns", MAX_COLUMNS);
221 logging::check_fatal(max_column > actual_columns,
"Can't have more than actual %d columns", actual_columns);
223 auto min_row = max(
static_cast<FullIdx
>(0),
224 static_cast<FullIdx
>(std::get<0>(*coordinates) -
static_cast<FullIdx
>(MAX_ROWS) /
static_cast<FullIdx
>(2)));
225 if (min_row + MAX_COLUMNS >= actual_rows)
227 min_row = max(
static_cast<FullIdx
>(0), actual_rows - MAX_ROWS);
229 const auto tile_row = tile_width *
static_cast<FullIdx
>(min_row / tile_width);
230 const auto max_row =
static_cast<FullIdx
>(min(min_row + MAX_ROWS - 1, actual_rows));
232 logging::check_fatal(min_row < 0,
"Row can't be less than 0 but is %d", min_row);
233 logging::check_fatal(max_row - min_row > MAX_ROWS,
"Can't have more than %d rows but have %d", MAX_ROWS, max_row - min_row);
234 logging::check_fatal(max_row > actual_rows,
"Can't have more than actual %d rows", actual_rows);
236 T nodata_value = convert(nodata_input, nodata_input);
237 logging::check_fatal(
238 convert(nodata_input, nodata_input) != nodata_value,
239 "Expected nodata value to be returned from convert()");
240 vector<T> values(
static_cast<size_t>(MAX_ROWS) * MAX_COLUMNS, nodata_value);
241 logging::verbose(
"%s: malloc start", filename.c_str());
242 int bps = std::numeric_limits<V>::digits + (1 * std::numeric_limits<V>::is_signed);
244 TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bps_file);
245 logging::check_fatal(bps != bps_file,
246 "Raster %s type is not expected type (%d bits instead of %d)",
251 int bps_int16_t = std::numeric_limits<int16_t>::digits + (1 * std::numeric_limits<int16_t>::is_signed);
252 logging::debug(
"Size of pointer to int is %ld vs %ld",
sizeof(int16_t*),
sizeof(V*));
253 logging::debug(
"Raster %s calculated bps for type V is %ld; tif says bps is %ld; int16_t is %ld",
259 const auto tile_size = TIFFTileSize(tif);
260 logging::debug(
"Tile size for reading %s is %ld", filename.c_str(), tile_size);
261 const auto buf = _TIFFmalloc(tile_size);
262 logging::verbose(
"%s: read start", filename.c_str());
263 const tsample_t smp{};
264 logging::debug(
"Want to clip grid to (%d, %d) => (%d, %d) for a %dx%d raster",
271 for (
auto h = tile_row; h <= max_row; h += tile_length)
273 for (
auto w = tile_column; w <= max_column; w += tile_width)
275 TIFFReadTile(tif, buf,
static_cast<uint32_t
>(w),
static_cast<uint32_t
>(h), 0, smp);
278 (y < static_cast<FullIdx>(tile_length)) && (y + h <= max_row);
282 const auto y_row =
static_cast<HashSize
>((h - min_row) + y);
283 const auto actual_row = (max_row - min_row) - y_row;
284 if (actual_row >= 0 && actual_row < MAX_ROWS)
288 (x < static_cast<FullIdx>(tile_width)) && (x + w <= max_column);
291 const auto offset = y * tile_width + x;
292 const auto actual_column = ((w - min_column) + x);
293 if (actual_column >= 0 && actual_column < MAX_ROWS)
295 const auto cur_hash = actual_row * MAX_COLUMNS + actual_column;
296 auto cur = *(
static_cast<V*
>(buf) + offset);
298 min_value = min(cur, min_value);
299 max_value = max(cur, max_value);
303 values.at(cur_hash) = convert(cur, nodata_input);
331 logging::verbose(
"%s: read end", filename.c_str());
333 logging::verbose(
"%s: free end", filename.c_str());
334 const auto new_xll = grid_info.
xllcorner() + (
static_cast<MathSize
>(min_column) * grid_info.
cellSize());
335 const auto new_yll = grid_info.
yllcorner()
336 + (
static_cast<MathSize
>(actual_rows) -
static_cast<MathSize
>(max_row))
339 logging::check_fatal(new_yll < grid_info.
yllcorner(),
340 "New yllcorner is outside original grid");
342 logging::verbose(
"Translated lower left is (%f, %f) from (%f, %f)",
347 const auto num_rows = max_row - min_row + 1;
348 const auto num_columns = max_column - min_column + 1;
356 new_xll + (
static_cast<MathSize
>(num_columns) + 1) * grid_info.
cellSize(),
357 new_yll + (
static_cast<MathSize
>(num_rows) + 1) * grid_info.
cellSize(),
358 string(grid_info.
proj4()),
360 auto new_location = result->findCoordinates(point,
false);
362 logging::check_fatal(
nullptr == new_location,
"Invalid location after reading");
364 logging::note(
"Coordinates are (%d, %d => %f, %f)",
365 std::get<0>(*new_location),
366 std::get<1>(*new_location),
367 std::get<0>(*new_location) + std::get<2>(*new_location) / 1000.0,
368 std::get<1>(*new_location) + std::get<3>(*new_location) / 1000.0);
370 logging::note(
"Values for %s range from %d to %d",