OGS
VtkRaster Class Reference

Detailed Description

Loading raster data such as images or ArcGIS-data into VTK image data structures.

The VtkRaster class enables loading of raster data such as images or ArcGIS-data. Supported image formats are ..... Georeferenced data can be imported via the GeoTIFF- or asc-format.

Definition at line 29 of file VtkRaster.h.

#include <VtkRaster.h>

Static Public Member Functions

static vtkImageImport * loadImageFromArray (double const *const data_array, GeoLib::RasterHeader header)
 Returns a VtkImageAlgorithm from an array of pixel values and some image meta data.
 
static vtkImageAlgorithm * loadImage (const std::string &fileName)
 Loads an image- or raster-file into an vtkImageAlgorithm-Object.
 

Static Private Member Functions

static vtkImageAlgorithm * loadImageFromTIFF (const std::string &fileName)
 
static vtkImageReader2 * loadImageFromFile (const std::string &fileName)
 
static std::string findWorldFile (const std::string &filename)
 
static bool readWorldFile (std::string const &filename, vtkImageReader2 *image)
 

Member Function Documentation

◆ findWorldFile()

std::string VtkRaster::findWorldFile ( const std::string & filename)
staticprivate

Tries to find a world file for the image given by the filename. World files can have a number of extensions depending on the programme used to write the image and this method just cycles through the possibilities, returning the first match it finds.

Definition at line 329 of file VtkRaster.cpp.

330{
331 std::string const no_ext = BaseLib::dropFileExtension(filename);
332
333 constexpr std::array supported_extensions = {
334 ".pgw", ".pngw", ".pgwx", ".jgw", ".jpgw", ".jgwx", ".tfw",
335 ".tifw", ".tfwx", ".bpw", ".bmpw", ".bpwx", ".wld"};
336
337 auto const res =
338 std::find_if(supported_extensions.begin(), supported_extensions.end(),
339 [&no_ext](auto const& ext) -> bool
340 { return BaseLib::IsFileExisting(no_ext + ext); });
341 if (res != supported_extensions.end())
342 {
343 return no_ext + *res;
344 }
345
346 // no world file found
347 return {};
348}
std::string dropFileExtension(std::string const &filename)

References BaseLib::dropFileExtension().

Referenced by readWorldFile().

◆ loadImage()

vtkImageAlgorithm * VtkRaster::loadImage ( const std::string & fileName)
static

Loads an image- or raster-file into an vtkImageAlgorithm-Object.

Public method for loading all data formats. Internally the method automatically differentiates between images and georeferenced files and then calls the appropriate method for reading the file.

Parameters
fileNameFilename of the file that should be loaded.
Returns
The ImageAlgorithm-object.

Definition at line 43 of file VtkRaster.cpp.

44{
45 QFileInfo fileInfo(QString::fromStdString(fileName));
46
47 std::unique_ptr<GeoLib::Raster> raster(nullptr);
48 if (fileInfo.suffix().toLower() == "asc")
49 {
50 raster.reset(
52 }
53 else if (fileInfo.suffix().toLower() == "grd")
54 {
55 raster.reset(
57 }
58 else if (fileInfo.suffix().toLower() == "xyz")
59 {
60 raster.reset(
62 }
63 if (raster)
64 {
65 return VtkRaster::loadImageFromArray(raster->data(),
66 raster->getHeader());
67 }
68 if ((fileInfo.suffix().toLower() == "tif") ||
69 (fileInfo.suffix().toLower() == "tiff"))
70 {
71#ifdef GEOTIFF_FOUND
72 return loadImageFromTIFF(fileName);
73#else
74 ERR("VtkRaster::loadImage(): GeoTiff file format not supported in this "
75 "version! Trying to parse as Tiff-file.");
76 return loadImageFromFile(fileName);
77#endif
78 }
79
80 return loadImageFromFile(fileName);
81}
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:45
static GeoLib::Raster * getRasterFromXyzFile(std::string const &fname)
Reads a XYZ raster file.
static GeoLib::Raster * getRasterFromSurferFile(std::string const &fname)
Reads a Surfer GRD raster file.
static GeoLib::Raster * getRasterFromASCFile(std::string const &fname)
Reads an ArcGis ASC raster file.
static vtkImageAlgorithm * loadImageFromTIFF(const std::string &fileName)
static vtkImageReader2 * loadImageFromFile(const std::string &fileName)
static vtkImageImport * loadImageFromArray(double const *const data_array, GeoLib::RasterHeader header)
Returns a VtkImageAlgorithm from an array of pixel values and some image meta data.
Definition VtkRaster.cpp:82

References ERR(), FileIO::AsciiRasterInterface::getRasterFromASCFile(), FileIO::AsciiRasterInterface::getRasterFromSurferFile(), FileIO::AsciiRasterInterface::getRasterFromXyzFile(), loadImageFromArray(), loadImageFromFile(), and loadImageFromTIFF().

Referenced by VtkCompositeTextureOnSurfaceFilter::init(), MainWindow::loadFile(), and VtkGeoImageSource::readImage().

◆ loadImageFromArray()

vtkImageImport * VtkRaster::loadImageFromArray ( double const *const data_array,
GeoLib::RasterHeader header )
static

Returns a VtkImageAlgorithm from an array of pixel values and some image meta data.

Definition at line 82 of file VtkRaster.cpp.

84{
85 const unsigned length = header.n_rows * header.n_cols * header.n_depth;
86 auto* data = new float[length * 2];
87 float max_val =
88 static_cast<float>(*std::max_element(data_array, data_array + length));
89 for (unsigned j = 0; j < length; ++j)
90 {
91 data[j * 2] = static_cast<float>(data_array[j]);
92 if (fabs(data[j * 2] - header.no_data) <
93 std::numeric_limits<double>::epsilon())
94 {
95 data[j * 2] = max_val;
96 data[j * 2 + 1] = 0;
97 }
98 else
99 {
100 data[j * 2 + 1] = max_val;
101 }
102 }
103
104 vtkImageImport* image = vtkImageImport::New();
105 image->SetDataSpacing(header.cell_size, header.cell_size, header.cell_size);
106 image->SetDataOrigin(header.origin[0] + (header.cell_size / 2.0),
107 header.origin[1] + (header.cell_size / 2.0),
108 0); // translate whole mesh by half a pixel in x and y
109 image->SetWholeExtent(0, header.n_cols - 1, 0, header.n_rows - 1, 0,
110 header.n_depth - 1);
111 image->SetDataExtent(0, header.n_cols - 1, 0, header.n_rows - 1, 0,
112 header.n_depth - 1);
113 image->SetDataExtentToWholeExtent();
114 image->SetDataScalarTypeToFloat();
115 image->SetNumberOfScalarComponents(2);
116 image->SetImportVoidPointer(data, 0);
117 image->Update();
118
119 return image;
120}
std::size_t n_depth
Definition Raster.h:31
MathLib::Point3d origin
Definition Raster.h:32
std::size_t n_cols
Definition Raster.h:29
std::size_t n_rows
Definition Raster.h:30

References GeoLib::RasterHeader::cell_size, GeoLib::RasterHeader::n_cols, GeoLib::RasterHeader::n_depth, GeoLib::RasterHeader::n_rows, GeoLib::RasterHeader::no_data, and GeoLib::RasterHeader::origin.

Referenced by NetCdfConfigureDialog::createDataObject(), and loadImage().

◆ loadImageFromFile()

vtkImageReader2 * VtkRaster::loadImageFromFile ( const std::string & fileName)
staticprivate

Loads image files into a QPixmap object. Since images are not geo-referenced no origin point will be returned.

Parameters
fileNameFilename of the file that should be loaded.
Returns
vtkImageReader2-object containing the image data.

Definition at line 291 of file VtkRaster.cpp.

292{
293 QString file_name(QString::fromStdString(fileName));
294 QFileInfo fi(file_name);
295 vtkImageReader2* image(nullptr);
296
297 if (fi.suffix().toLower() == "png")
298 {
299 image = vtkPNGReader::New();
300 }
301 else if ((fi.suffix().toLower() == "tif") ||
302 (fi.suffix().toLower() == "tiff"))
303 {
304 image = vtkTIFFReader::New();
305 }
306 else if ((fi.suffix().toLower() == "jpg") ||
307 (fi.suffix().toLower() == "jpeg"))
308 {
309 image = vtkJPEGReader::New();
310 }
311 else if (fi.suffix().toLower() == "bmp")
312 {
313 image = vtkBMPReader::New();
314 }
315 else
316 {
317 ERR("VtkRaster::readImageFromFile(): File format not supported, please "
318 "convert to BMP, JPG, PNG or TIFF.");
319 return nullptr;
320 }
321
322 image->SetFileName(fileName.c_str());
323 image->GetOutput()->AllocateScalars(VTK_FLOAT, 1);
324 image->Update();
325 readWorldFile(fileName, image);
326 return image;
327}
static bool readWorldFile(std::string const &filename, vtkImageReader2 *image)

References ERR(), and readWorldFile().

Referenced by loadImage().

◆ loadImageFromTIFF()

vtkImageAlgorithm * VtkRaster::loadImageFromTIFF ( const std::string & fileName)
staticprivate

Loads ArcGIS asc-files to a QPixmap object and automatically does a contrast stretching to adjust values to 8 bit greyscale images.

Parameters
fileNameFilename of the file that should be loaded.
Returns
A vtkImageImport-object (derived from vtkImageAlgorithm).

Definition at line 123 of file VtkRaster.cpp.

124{
125 TIFF* tiff = XTIFFOpen(fileName.c_str(), "r");
126
127 if (tiff)
128 {
129 GTIF* geoTiff = GTIFNew(tiff);
130
131 int version[3];
132 int count(0);
133 GTIFDirectoryInfo(geoTiff, version, &count);
134
135 if (count == 0)
136 WARN("VtkRaster::loadImageFromTIFF - file is not georeferenced.");
137
138 if (geoTiff)
139 {
140 double x0 = 0.0;
141 double y0 = 0.0;
142 double cellsize = 1.0;
143 int imgWidth = 0;
144 int imgHeight = 0;
145 int nImages = 0;
146 int pntCount = 0;
147 double* pnts = nullptr;
148
149 // get actual number of images in the tiff file
150 do
151 {
152 ++nImages;
153 } while (TIFFReadDirectory(tiff));
154 if (nImages > 1)
155 INFO(
156 "VtkRaster::loadImageFromTIFF() - File contains {:d} "
157 "images. This method is not tested for this case.",
158 nImages);
159
160 // get image size
161 TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &imgWidth);
162 TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &imgHeight);
163
164 // get cellsize
165 // Note: GeoTiff allows anisotropic pixels. This is not supported
166 // here and equilateral pixels are assumed.
167 if (TIFFGetField(tiff, GTIFF_PIXELSCALE, &pntCount, &pnts))
168 {
169 if (pnts[0] != pnts[1])
170 WARN(
171 "VtkRaster::loadImageFromTIFF(): Original raster data "
172 "has anisotrop pixel size!");
173 cellsize = pnts[0];
174 }
175
176 // get upper left point / origin
177 if (TIFFGetField(tiff, GTIFF_TIEPOINTS, &pntCount, &pnts))
178 {
179 x0 = pnts[3];
180 y0 = pnts[4] -
181 (imgHeight * cellsize); // the origin should be the lower
182 // left corner of the img
183 }
184
185 // read pixel values
186 auto* pixVal = static_cast<uint32*>(
187 _TIFFmalloc(imgWidth * imgHeight * sizeof(uint32)));
188 if ((imgWidth > 0) && (imgHeight > 0))
189 {
190 if (!TIFFReadRGBAImage(tiff, imgWidth, imgHeight, pixVal, 0))
191 {
192 ERR("VtkRaster::loadImageFromTIFF(): reading GeoTIFF "
193 "file.");
194 _TIFFfree(pixVal);
195 GTIFFree(geoTiff);
196 XTIFFClose(tiff);
197 return nullptr;
198 }
199 }
200
201 // check for colormap
202 uint16 photometric;
203 TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric);
204 // read colormap
205 uint16 *cmap_red = nullptr, *cmap_green = nullptr,
206 *cmap_blue = nullptr;
207 int colormap_used = TIFFGetField(tiff, TIFFTAG_COLORMAP, &cmap_red,
208 &cmap_green, &cmap_blue);
209
210 auto* data = new float[imgWidth * imgHeight * 4];
211 auto* pxl(new int[4]);
212 for (int j = 0; j < imgHeight; ++j)
213 {
214 int lineindex = j * imgWidth;
215 for (int i = 0; i < imgWidth; ++i)
216 { // scale intensities and set nodata values to white (i.e. the
217 // background colour)
218 unsigned pxl_idx(lineindex + i);
219 unsigned pos = 4 * (pxl_idx);
220 if (photometric == 1 && colormap_used == 1)
221 {
222 int idx = TIFFGetR(pixVal[pxl_idx]);
223 data[pos] = static_cast<float>(cmap_red[idx] >> 8);
224 data[pos + 1] =
225 static_cast<float>(cmap_green[idx] >> 8);
226 data[pos + 2] = static_cast<float>(cmap_blue[idx] >> 8);
227 data[pos + 3] = 1;
228 }
229 else
230 {
231 data[pos] =
232 static_cast<float>(TIFFGetR(pixVal[pxl_idx]));
233 data[pos + 1] =
234 static_cast<float>(TIFFGetG(pixVal[pxl_idx]));
235 data[pos + 2] =
236 static_cast<float>(TIFFGetB(pixVal[pxl_idx]));
237 data[pos + 3] =
238 static_cast<float>(TIFFGetA(pixVal[pxl_idx]));
239 }
240 }
241 }
242 delete[] pxl;
243
244 // set transparency values according to maximum pixel value
245 if (photometric == 1)
246 {
247 float max_val(0);
248 unsigned nPixels = 4 * imgWidth * imgHeight;
249 for (unsigned j = 0; j < nPixels; ++j)
250 {
251 if (data[j] > max_val)
252 {
253 max_val = data[j];
254 }
255 }
256
257 for (unsigned j = 0; j < nPixels; j += 4)
258 {
259 data[j + 3] = max_val;
260 }
261 }
262
263 vtkImageImport* image = vtkImageImport::New();
264 image->SetDataOrigin(x0, y0, 0);
265 image->SetDataSpacing(cellsize, cellsize, cellsize);
266 image->SetWholeExtent(0, imgWidth - 1, 0, imgHeight - 1, 0, 0);
267 image->SetDataExtent(0, imgWidth - 1, 0, imgHeight - 1, 0, 0);
268 image->SetDataExtentToWholeExtent();
269 image->SetDataScalarTypeToFloat();
270 image->SetNumberOfScalarComponents(4);
271 image->SetImportVoidPointer(data, 0);
272 image->Update();
273
274 _TIFFfree(pixVal);
275 GTIFFree(geoTiff);
276 XTIFFClose(tiff);
277 return image;
278 }
279
280 XTIFFClose(tiff);
281 ERR("VtkRaster::loadImageFromTIFF() - File not recognised as "
282 "GeoTIFF-Image.");
283 return nullptr;
284 }
285
286 ERR("VtkRaster::loadImageFromTIFF() - File not recognised as TIFF-Image.");
287 return nullptr;
288}
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:35
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40

References ERR(), INFO(), uint32, and WARN().

Referenced by loadImage().

◆ readWorldFile()

bool VtkRaster::readWorldFile ( std::string const & filename,
vtkImageReader2 * image )
staticprivate

Tries to find and load the world file associated with a BMP/JPG/PNG-file and create a RasterHeader for the image.

Definition at line 350 of file VtkRaster.cpp.

352{
353 std::string const world_file = findWorldFile(filename);
354 if (world_file.empty())
355 {
356 WARN("No world file found. Image is not georeferenced.");
357 return false;
358 }
359
360 std::ifstream in(world_file.c_str());
361 if (!in.is_open())
362 {
363 ERR("VtkRaster::readWorldFile(): Could not open file {:s}.", filename);
364 return false;
365 }
366
367 std::string line;
368 // x-scaling
369 if (!std::getline(in, line))
370 {
371 return false;
372 }
373 double const delta_x = BaseLib::str2number<double>(line);
374 // 2x rotation (ignored)
375 if (!(std::getline(in, line) && std::getline(in, line)))
376 {
377 return false;
378 }
379 // negative y-scaling
380 if (!std::getline(in, line))
381 {
382 return false;
383 }
384 double const delta_y = BaseLib::str2number<double>(line);
385 if (delta_x != -delta_y)
386 WARN(
387 "Anisotropic pixel size detected ({:f} vs {:f}). An isotropic "
388 "spacing of {:f} is assumed, be aware results may be wrong.",
389 delta_x, delta_y, delta_x);
390 // x-translation
391 if (!std::getline(in, line))
392 {
393 return false;
394 }
395 double const x0 = BaseLib::str2number<double>(line);
396 // y-translation
397 if (!std::getline(in, line))
398 {
399 return false;
400 }
401 double const y0 = BaseLib::str2number<double>(line);
402
403 int extent[3];
404 image->GetOutput()->GetDimensions(extent);
405 image->SetDataSpacing(delta_x, delta_x, delta_x);
406 // for GIS the origin is on the lower left, for VTK it is on the upper left
407 double const vtk_y0 = y0 + (extent[1] * delta_y);
408 image->SetDataOrigin(x0, vtk_y0, 0);
409 return true;
410}
static std::string findWorldFile(const std::string &filename)
T str2number(const std::string &str)
Definition StringTools.h:60

References ERR(), findWorldFile(), BaseLib::str2number(), and WARN().

Referenced by loadImageFromFile().


The documentation for this class was generated from the following files: