GDAL
gdalgeoloc_carray_accessor.h
1/******************************************************************************
2 *
3 * Project: GDAL
4 * Purpose: C-Array storage of geolocation array and backmap
5 * Author: Even Rouault, <even.rouault at spatialys.com>
6 *
7 ******************************************************************************
8 * Copyright (c) 2022, Planet Labs
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 ****************************************************************************/
28
31/************************************************************************/
32/* GDALGeoLocCArrayAccessors */
33/************************************************************************/
34
35class GDALGeoLocCArrayAccessors
36{
37 typedef class GDALGeoLocCArrayAccessors AccessorType;
38
39 GDALGeoLocTransformInfo *m_psTransform;
40 double *m_padfGeoLocX = nullptr;
41 double *m_padfGeoLocY = nullptr;
42 float *m_pafBackMapX = nullptr;
43 float *m_pafBackMapY = nullptr;
44 float *m_wgtsBackMap = nullptr;
45
46 bool LoadGeoloc(bool bIsRegularGrid);
47
48 public:
49 template <class Type> struct CArrayAccessor
50 {
51 Type *m_array;
52 size_t m_nXSize;
53
54 CArrayAccessor(Type *array, size_t nXSize)
55 : m_array(array), m_nXSize(nXSize)
56 {
57 }
58
59 inline Type Get(int nX, int nY, bool *pbSuccess = nullptr)
60 {
61 if (pbSuccess)
62 *pbSuccess = true;
63 return m_array[nY * m_nXSize + nX];
64 }
65
66 inline bool Set(int nX, int nY, Type val)
67 {
68 m_array[nY * m_nXSize + nX] = val;
69 return true;
70 }
71 };
72
73 CArrayAccessor<double> geolocXAccessor;
74 CArrayAccessor<double> geolocYAccessor;
75 CArrayAccessor<float> backMapXAccessor;
76 CArrayAccessor<float> backMapYAccessor;
77 CArrayAccessor<float> backMapWeightAccessor;
78
79 explicit GDALGeoLocCArrayAccessors(GDALGeoLocTransformInfo *psTransform)
80 : m_psTransform(psTransform), geolocXAccessor(nullptr, 0),
81 geolocYAccessor(nullptr, 0), backMapXAccessor(nullptr, 0),
82 backMapYAccessor(nullptr, 0), backMapWeightAccessor(nullptr, 0)
83 {
84 }
85
86 ~GDALGeoLocCArrayAccessors()
87 {
88 VSIFree(m_pafBackMapX);
89 VSIFree(m_pafBackMapY);
90 VSIFree(m_padfGeoLocX);
91 VSIFree(m_padfGeoLocY);
92 VSIFree(m_wgtsBackMap);
93 }
94
95 GDALGeoLocCArrayAccessors(const GDALGeoLocCArrayAccessors &) = delete;
96 GDALGeoLocCArrayAccessors &
97 operator=(const GDALGeoLocCArrayAccessors &) = delete;
98
99 bool Load(bool bIsRegularGrid, bool bUseQuadtree);
100
101 bool AllocateBackMap();
102
103 GDALDataset *GetBackmapDataset();
104
105 static void FlushBackmapCaches()
106 {
107 }
108
109 static void ReleaseBackmapDataset(GDALDataset *poDS)
110 {
111 delete poDS;
112 }
113
114 void FreeWghtsBackMap();
115};
116
117/************************************************************************/
118/* AllocateBackMap() */
119/************************************************************************/
120
121bool GDALGeoLocCArrayAccessors::AllocateBackMap()
122{
123 m_pafBackMapX = static_cast<float *>(
124 VSI_MALLOC3_VERBOSE(m_psTransform->nBackMapWidth,
125 m_psTransform->nBackMapHeight, sizeof(float)));
126 m_pafBackMapY = static_cast<float *>(
127 VSI_MALLOC3_VERBOSE(m_psTransform->nBackMapWidth,
128 m_psTransform->nBackMapHeight, sizeof(float)));
129
130 m_wgtsBackMap = static_cast<float *>(
131 VSI_MALLOC3_VERBOSE(m_psTransform->nBackMapWidth,
132 m_psTransform->nBackMapHeight, sizeof(float)));
133
134 if (m_pafBackMapX == nullptr || m_pafBackMapY == nullptr ||
135 m_wgtsBackMap == nullptr)
136 {
137 return false;
138 }
139
140 const size_t nBMXYCount =
141 static_cast<size_t>(m_psTransform->nBackMapWidth) *
142 m_psTransform->nBackMapHeight;
143 for (size_t i = 0; i < nBMXYCount; i++)
144 {
145 m_pafBackMapX[i] = 0;
146 m_pafBackMapY[i] = 0;
147 m_wgtsBackMap[i] = 0.0;
148 }
149
150 backMapXAccessor.m_array = m_pafBackMapX;
151 backMapXAccessor.m_nXSize = m_psTransform->nBackMapWidth;
152
153 backMapYAccessor.m_array = m_pafBackMapY;
154 backMapYAccessor.m_nXSize = m_psTransform->nBackMapWidth;
155
156 backMapWeightAccessor.m_array = m_wgtsBackMap;
157 backMapWeightAccessor.m_nXSize = m_psTransform->nBackMapWidth;
158
159 return true;
160}
161
162/************************************************************************/
163/* FreeWghtsBackMap() */
164/************************************************************************/
165
166void GDALGeoLocCArrayAccessors::FreeWghtsBackMap()
167{
168 VSIFree(m_wgtsBackMap);
169 m_wgtsBackMap = nullptr;
170 backMapWeightAccessor.m_array = nullptr;
171 backMapWeightAccessor.m_nXSize = 0;
172}
173
174/************************************************************************/
175/* GetBackmapDataset() */
176/************************************************************************/
177
178GDALDataset *GDALGeoLocCArrayAccessors::GetBackmapDataset()
179{
180 auto poMEMDS = MEMDataset::Create("", m_psTransform->nBackMapWidth,
181 m_psTransform->nBackMapHeight, 0,
182 GDT_Float32, nullptr);
183
184 for (int i = 1; i <= 2; i++)
185 {
186 void *ptr = (i == 1) ? m_pafBackMapX : m_pafBackMapY;
187 GDALRasterBandH hMEMBand = MEMCreateRasterBandEx(
188 poMEMDS, i, static_cast<GByte *>(ptr), GDT_Float32, 0, 0, false);
189 poMEMDS->AddMEMBand(hMEMBand);
190 poMEMDS->GetRasterBand(i)->SetNoDataValue(INVALID_BMXY);
191 }
192 return poMEMDS;
193}
194
195/************************************************************************/
196/* Load() */
197/************************************************************************/
198
199bool GDALGeoLocCArrayAccessors::Load(bool bIsRegularGrid, bool bUseQuadtree)
200{
201 return LoadGeoloc(bIsRegularGrid) &&
202 ((bUseQuadtree && GDALGeoLocBuildQuadTree(m_psTransform)) ||
203 (!bUseQuadtree &&
204 GDALGeoLoc<AccessorType>::GenerateBackMap(m_psTransform)));
205}
206
207/************************************************************************/
208/* LoadGeoloc() */
209/************************************************************************/
210
211bool GDALGeoLocCArrayAccessors::LoadGeoloc(bool bIsRegularGrid)
212
213{
214 const int nXSize = m_psTransform->nGeoLocXSize;
215 const int nYSize = m_psTransform->nGeoLocYSize;
216
217 m_padfGeoLocY = static_cast<double *>(
218 VSI_MALLOC3_VERBOSE(sizeof(double), nXSize, nYSize));
219 m_padfGeoLocX = static_cast<double *>(
220 VSI_MALLOC3_VERBOSE(sizeof(double), nXSize, nYSize));
221
222 if (m_padfGeoLocX == nullptr || m_padfGeoLocY == nullptr)
223 {
224 return false;
225 }
226
227 if (bIsRegularGrid)
228 {
229 // Case of regular grid.
230 // The XBAND contains the x coordinates for all lines.
231 // The YBAND contains the y coordinates for all columns.
232
233 double *padfTempX =
234 static_cast<double *>(VSI_MALLOC2_VERBOSE(nXSize, sizeof(double)));
235 double *padfTempY =
236 static_cast<double *>(VSI_MALLOC2_VERBOSE(nYSize, sizeof(double)));
237 if (padfTempX == nullptr || padfTempY == nullptr)
238 {
239 CPLFree(padfTempX);
240 CPLFree(padfTempY);
241 return false;
242 }
243
244 CPLErr eErr =
245 GDALRasterIO(m_psTransform->hBand_X, GF_Read, 0, 0, nXSize, 1,
246 padfTempX, nXSize, 1, GDT_Float64, 0, 0);
247
248 for (size_t j = 0; j < static_cast<size_t>(nYSize); j++)
249 {
250 memcpy(m_padfGeoLocX + j * nXSize, padfTempX,
251 nXSize * sizeof(double));
252 }
253
254 if (eErr == CE_None)
255 {
256 eErr = GDALRasterIO(m_psTransform->hBand_Y, GF_Read, 0, 0, nYSize,
257 1, padfTempY, nYSize, 1, GDT_Float64, 0, 0);
258
259 for (size_t j = 0; j < static_cast<size_t>(nYSize); j++)
260 {
261 for (size_t i = 0; i < static_cast<size_t>(nXSize); i++)
262 {
263 m_padfGeoLocY[j * nXSize + i] = padfTempY[j];
264 }
265 }
266 }
267
268 CPLFree(padfTempX);
269 CPLFree(padfTempY);
270
271 if (eErr != CE_None)
272 return false;
273 }
274 else
275 {
276 if (GDALRasterIO(m_psTransform->hBand_X, GF_Read, 0, 0, nXSize, nYSize,
277 m_padfGeoLocX, nXSize, nYSize, GDT_Float64, 0,
278 0) != CE_None ||
279 GDALRasterIO(m_psTransform->hBand_Y, GF_Read, 0, 0, nXSize, nYSize,
280 m_padfGeoLocY, nXSize, nYSize, GDT_Float64, 0,
281 0) != CE_None)
282 return false;
283 }
284
285 geolocXAccessor.m_array = m_padfGeoLocX;
286 geolocXAccessor.m_nXSize = m_psTransform->nGeoLocXSize;
287
288 geolocYAccessor.m_array = m_padfGeoLocY;
289 geolocYAccessor.m_nXSize = m_psTransform->nGeoLocXSize;
290
291 GDALGeoLoc<GDALGeoLocCArrayAccessors>::LoadGeolocFinish(m_psTransform);
292 return true;
293}
294
A set of associated raster bands, usually from one file.
Definition gdal_priv.h:490
#define CPLFree
Alias of VSIFree()
Definition cpl_conv.h:98
CPLErr
Error category.
Definition cpl_error.h:53
unsigned char GByte
Unsigned byte type.
Definition cpl_port.h:185
#define VSI_MALLOC3_VERBOSE(nSize1, nSize2, nSize3)
VSI_MALLOC3_VERBOSE.
Definition cpl_vsi.h:361
#define VSI_MALLOC2_VERBOSE(nSize1, nSize2)
VSI_MALLOC2_VERBOSE.
Definition cpl_vsi.h:353
void VSIFree(void *)
Analog of free() for data allocated with VSIMalloc(), VSICalloc(), VSIRealloc()
Definition cpl_vsisimple.cpp:843
@ GDT_Float64
Definition gdal.h:75
@ GDT_Float32
Definition gdal.h:74
@ GF_Read
Definition gdal.h:133
void * GDALRasterBandH
Opaque type used for the C bindings of the C++ GDALRasterBand class.
Definition gdal.h:294
CPLErr GDALRasterIO(GDALRasterBandH hRBand, GDALRWFlag eRWFlag, int nDSXOff, int nDSYOff, int nDSXSize, int nDSYSize, void *pBuffer, int nBXSize, int nBYSize, GDALDataType eBDataType, int nPixelSpace, int nLineSpace)
Read/write a region of image data for this band.
Definition gdalrasterband.cpp:447