OGS
VtkGeoImageSource.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4// ** INCLUDES **
5#include "VtkGeoImageSource.h"
6
7#include <vtkFloatArray.h>
8#include <vtkImageChangeInformation.h>
9#include <vtkImageData.h>
10#include <vtkImageImport.h>
11#include <vtkImageShiftScale.h>
12#include <vtkIntArray.h>
13#include <vtkObjectFactory.h>
14#include <vtkPointData.h>
15
16#include "VtkRaster.h"
17
19
20// This function is copied from the vtkSimpleImageFilterExample.cpp
21//
22// The switch statement in Execute will call this method with
23// the appropriate input type (IT). Note that this example assumes
24// that the output data type is the same as the input data type.
25// This is not always the case.
26template <class IT>
27void vtkSimpleImageFilterExampleExecute(vtkImageData* input,
28 vtkImageData* output, IT* inPtr,
29 IT* outPtr)
30{
31 int dims[3];
32 input->GetDimensions(dims);
33 if (input->GetScalarType() != output->GetScalarType())
34 {
35 vtkGenericWarningMacro(
36 << "Execute: input ScalarType, " << input->GetScalarType()
37 << ", must match out ScalarType " << output->GetScalarType());
38 return;
39 }
40 // HACK LB Multiply by number of scalar components due to RGBA values ?????
41 int size =
42 dims[0] * dims[1] * dims[2] * input->GetNumberOfScalarComponents();
43
44 for (int i = 0; i < size; i++)
45 {
46 outPtr[i] = inPtr[i];
47 }
48}
49
51
53{
54 if (_imageSource)
55 {
56 _imageSource->Delete();
57 }
58}
59
60void VtkGeoImageSource::PrintSelf(ostream& os, vtkIndent indent)
61{
62 this->Superclass::PrintSelf(os, indent);
63}
64
65bool VtkGeoImageSource::readImage(const QString& filename)
66{
67 vtkImageAlgorithm* img(VtkRaster::loadImage(filename.toStdString()));
68 if (img == nullptr)
69 {
70 return false;
71 }
72 this->setImage(img, filename);
73 return true;
74}
75
76void VtkGeoImageSource::setImage(vtkImageAlgorithm* image, const QString& name)
77{
78 this->_imageSource = image;
79 this->SetInputConnection(_imageSource->GetOutputPort());
80 this->SetName(name);
81}
82
84{
85 return this->_imageSource->GetImageDataInput(0);
86}
87
88void VtkGeoImageSource::SimpleExecute(vtkImageData* input, vtkImageData* output)
89{
90 vtkDebugMacro(<< "Executing VtkGeoImageSource");
91 void* inPtr = input->GetScalarPointer();
92 void* outPtr = output->GetScalarPointer();
93 switch (output->GetScalarType())
94 {
95 // This is simply a #define for a big case list.
96 // It handles all data types that VTK supports.
98 input, output, (VTK_TT*)(inPtr), (VTK_TT*)(outPtr)));
99 default:
100 vtkGenericWarningMacro("Execute: Unknown input ScalarType");
101 return;
102 }
103}
104
105void VtkGeoImageSource::SetUserProperty(QString name, QVariant value)
106{
107 Q_UNUSED(name);
108 Q_UNUSED(value);
109}
110
111std::optional<GeoLib::Raster> VtkGeoImageSource::convertToRaster(
112 VtkGeoImageSource* const source)
113{
114 int dims[3];
115 source->GetOutput()->GetDimensions(dims);
116 double origin[3];
117 source->GetOutput()->GetOrigin(origin);
118 double spacing[3];
119 source->GetOutput()->GetSpacing(spacing);
120 MathLib::Point3d const origin_pnt(
121 std::array<double, 3>{{origin[0] - 0.5 * spacing[0],
122 origin[1] - 0.5 * spacing[1], origin[2]}});
123 GeoLib::RasterHeader const header = {static_cast<std::size_t>(dims[0]),
124 static_cast<std::size_t>(dims[1]),
125 static_cast<std::size_t>(dims[2]),
126 origin_pnt,
127 spacing[0],
128 -9999};
129
130 vtkSmartPointer<vtkDataArray> const pixelData =
131 vtkSmartPointer<vtkDataArray>(
132 source->GetOutput()->GetPointData()->GetScalars());
133 int const nTuple = pixelData->GetNumberOfComponents();
134 if (nTuple < 1 || nTuple > 4)
135 {
136 ERR("VtkMeshConverter::convertImgToMesh(): Unsupported pixel "
137 "composition!");
138 return {};
139 }
140
141 std::vector<double> pix(header.n_cols * header.n_rows * header.n_depth, 0);
142 for (std::size_t k = 0; k < header.n_depth; k++)
143 {
144 std::size_t const layer_idx = (k * header.n_rows * header.n_cols);
145 for (std::size_t i = 0; i < header.n_rows; i++)
146 {
147 std::size_t const idx = i * header.n_cols + layer_idx;
148 for (std::size_t j = 0; j < header.n_cols; j++)
149 {
150 double const* const colour = pixelData->GetTuple(idx + j);
151 bool const visible = (nTuple == 2 || nTuple == 4)
152 ? (colour[nTuple - 1] != 0)
153 : true;
154 if (!visible)
155 {
156 pix[idx + j] = header.no_data;
157 }
158 else
159 {
160 pix[idx + j] = (nTuple < 3) ? colour[0] : // grey (+ alpha)
161 (0.3 * colour[0] + 0.6 * colour[1] +
162 0.1 * colour[2]); // rgb(a)
163 }
164 }
165 }
166 }
167
168 return std::make_optional<GeoLib::Raster>(header, pix.begin(), pix.end());
169}
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
vtkStandardNewMacro(VtkGeoImageSource)
void vtkSimpleImageFilterExampleExecute(vtkImageData *input, vtkImageData *output, IT *inPtr, IT *outPtr)
void SetName(QString name)
Sets the name.
The VtkVisPipeline source object of a geo-referenced image (file).
VtkGeoImageSource(const VtkGeoImageSource &)=delete
static std::optional< GeoLib::Raster > convertToRaster(VtkGeoImageSource *const source)
VtkGeoImageSource()
Constructor.
void setImage(vtkImageAlgorithm *image, const QString &name)
Imports an existing image object.
void SetUserProperty(QString name, QVariant value) override
Sets a user property. This should be implemented by subclasses.
vtkImageAlgorithm * _imageSource
~VtkGeoImageSource() override
Destructor.
vtkImageData * getImageData()
Returns the ImageData object.
void PrintSelf(ostream &os, vtkIndent indent) override
Prints information about itself.
void SimpleExecute(vtkImageData *input, vtkImageData *output) override
Filter execution.
bool readImage(const QString &filename)
Reads an image from file.
static vtkImageAlgorithm * loadImage(const std::string &fileName)
Loads an image- or raster-file into an vtkImageAlgorithm-Object.
Definition VtkRaster.cpp:32
Contains the relevant information when storing a geoscientific raster data.
Definition Raster.h:18