GDAL
gdalgeoloc_dataset_accessor.h
1/******************************************************************************
2 *
3 * Project: GDAL
4 * Purpose: Dataset 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
29#include "gdalcachedpixelaccessor.h"
30
33/************************************************************************/
34/* GDALGeoLocDatasetAccessors */
35/************************************************************************/
36
37class GDALGeoLocDatasetAccessors
38{
39 typedef class GDALGeoLocDatasetAccessors AccessorType;
40
41 GDALGeoLocTransformInfo *m_psTransform;
42
43 CPLStringList m_aosGTiffCreationOptions{};
44
45 GDALDataset *m_poGeolocTmpDataset = nullptr;
46 GDALDataset *m_poBackmapTmpDataset = nullptr;
47 GDALDataset *m_poBackmapWeightsTmpDataset = nullptr;
48
49 GDALGeoLocDatasetAccessors(const GDALGeoLocDatasetAccessors &) = delete;
50 GDALGeoLocDatasetAccessors &
51 operator=(const GDALGeoLocDatasetAccessors &) = delete;
52
53 bool LoadGeoloc(bool bIsRegularGrid);
54
55 public:
56 static constexpr int TILE_SIZE = 1024;
57
63
64 explicit GDALGeoLocDatasetAccessors(GDALGeoLocTransformInfo *psTransform)
65 : m_psTransform(psTransform), geolocXAccessor(nullptr),
66 geolocYAccessor(nullptr), backMapXAccessor(nullptr),
67 backMapYAccessor(nullptr), backMapWeightAccessor(nullptr)
68 {
69 m_aosGTiffCreationOptions.SetNameValue("TILED", "YES");
70 m_aosGTiffCreationOptions.SetNameValue("INTERLEAVE", "BAND");
71 m_aosGTiffCreationOptions.SetNameValue("BLOCKXSIZE",
72 CPLSPrintf("%d", TILE_SIZE));
73 m_aosGTiffCreationOptions.SetNameValue("BLOCKYSIZE",
74 CPLSPrintf("%d", TILE_SIZE));
75 }
76
77 ~GDALGeoLocDatasetAccessors();
78
79 bool Load(bool bIsRegularGrid, bool bUseQuadtree);
80
81 bool AllocateBackMap();
82
83 GDALDataset *GetBackmapDataset();
84 void FlushBackmapCaches();
85
86 static void ReleaseBackmapDataset(GDALDataset *)
87 {
88 }
89
90 void FreeWghtsBackMap();
91};
92
93/************************************************************************/
94/* ~GDALGeoLocDatasetAccessors() */
95/************************************************************************/
96
97GDALGeoLocDatasetAccessors::~GDALGeoLocDatasetAccessors()
98{
99 geolocXAccessor.ResetModifiedFlag();
100 geolocYAccessor.ResetModifiedFlag();
101 backMapXAccessor.ResetModifiedFlag();
102 backMapYAccessor.ResetModifiedFlag();
103
104 FreeWghtsBackMap();
105
106 delete m_poGeolocTmpDataset;
107 delete m_poBackmapTmpDataset;
108}
109
110/************************************************************************/
111/* AllocateBackMap() */
112/************************************************************************/
113
114bool GDALGeoLocDatasetAccessors::AllocateBackMap()
115{
116 auto poDriver = GDALDriver::FromHandle(GDALGetDriverByName("GTiff"));
117 if (poDriver == nullptr)
118 return false;
119
120 m_poBackmapTmpDataset = poDriver->Create(
122 m_psTransform->nBackMapWidth, m_psTransform->nBackMapHeight, 2,
123 GDT_Float32, m_aosGTiffCreationOptions.List());
124 if (m_poBackmapTmpDataset == nullptr)
125 {
126 return false;
127 }
128 m_poBackmapTmpDataset->MarkSuppressOnClose();
129 VSIUnlink(m_poBackmapTmpDataset->GetDescription());
130 auto poBandX = m_poBackmapTmpDataset->GetRasterBand(1);
131 auto poBandY = m_poBackmapTmpDataset->GetRasterBand(2);
132
133 backMapXAccessor.SetBand(poBandX);
134 backMapYAccessor.SetBand(poBandY);
135
136 m_poBackmapWeightsTmpDataset = poDriver->Create(
138 m_psTransform->nBackMapWidth, m_psTransform->nBackMapHeight, 1,
139 GDT_Float32, m_aosGTiffCreationOptions.List());
140 if (m_poBackmapWeightsTmpDataset == nullptr)
141 {
142 return false;
143 }
144 m_poBackmapWeightsTmpDataset->MarkSuppressOnClose();
145 VSIUnlink(m_poBackmapWeightsTmpDataset->GetDescription());
146 backMapWeightAccessor.SetBand(
147 m_poBackmapWeightsTmpDataset->GetRasterBand(1));
148
149 return true;
150}
151
152/************************************************************************/
153/* FreeWghtsBackMap() */
154/************************************************************************/
155
156void GDALGeoLocDatasetAccessors::FreeWghtsBackMap()
157{
158 if (m_poBackmapWeightsTmpDataset)
159 {
160 backMapWeightAccessor.ResetModifiedFlag();
161 delete m_poBackmapWeightsTmpDataset;
162 m_poBackmapWeightsTmpDataset = nullptr;
163 }
164}
165
166/************************************************************************/
167/* GetBackmapDataset() */
168/************************************************************************/
169
170GDALDataset *GDALGeoLocDatasetAccessors::GetBackmapDataset()
171{
172 auto poBandX = m_poBackmapTmpDataset->GetRasterBand(1);
173 auto poBandY = m_poBackmapTmpDataset->GetRasterBand(2);
174 poBandX->SetNoDataValue(INVALID_BMXY);
175 poBandY->SetNoDataValue(INVALID_BMXY);
176 return m_poBackmapTmpDataset;
177}
178
179/************************************************************************/
180/* FlushBackmapCaches() */
181/************************************************************************/
182
183void GDALGeoLocDatasetAccessors::FlushBackmapCaches()
184{
185 backMapXAccessor.FlushCache();
186 backMapYAccessor.FlushCache();
187}
188
189/************************************************************************/
190/* Load() */
191/************************************************************************/
192
193bool GDALGeoLocDatasetAccessors::Load(bool bIsRegularGrid, bool bUseQuadtree)
194{
195 return LoadGeoloc(bIsRegularGrid) &&
196 ((bUseQuadtree && GDALGeoLocBuildQuadTree(m_psTransform)) ||
197 (!bUseQuadtree &&
198 GDALGeoLoc<AccessorType>::GenerateBackMap(m_psTransform)));
199}
200
201/************************************************************************/
202/* LoadGeoloc() */
203/************************************************************************/
204
205bool GDALGeoLocDatasetAccessors::LoadGeoloc(bool bIsRegularGrid)
206
207{
208 if (bIsRegularGrid)
209 {
210 const int nXSize = m_psTransform->nGeoLocXSize;
211 const int nYSize = m_psTransform->nGeoLocYSize;
212
213 auto poDriver = GDALDriver::FromHandle(GDALGetDriverByName("GTiff"));
214 if (poDriver == nullptr)
215 return false;
216
217 m_poGeolocTmpDataset = poDriver->Create(
218 CPLResetExtension(CPLGenerateTempFilename(nullptr), "tif"), nXSize,
219 nYSize, 2, GDT_Float64, m_aosGTiffCreationOptions.List());
220 if (m_poGeolocTmpDataset == nullptr)
221 {
222 return false;
223 }
224 m_poGeolocTmpDataset->MarkSuppressOnClose();
225 VSIUnlink(m_poGeolocTmpDataset->GetDescription());
226
227 auto poXBand = m_poGeolocTmpDataset->GetRasterBand(1);
228 auto poYBand = m_poGeolocTmpDataset->GetRasterBand(2);
229
230 // Case of regular grid.
231 // The XBAND contains the x coordinates for all lines.
232 // The YBAND contains the y coordinates for all columns.
233
234 double *padfTempX =
235 static_cast<double *>(VSI_MALLOC2_VERBOSE(nXSize, sizeof(double)));
236 double *padfTempY =
237 static_cast<double *>(VSI_MALLOC2_VERBOSE(nYSize, sizeof(double)));
238 if (padfTempX == nullptr || padfTempY == nullptr)
239 {
240 CPLFree(padfTempX);
241 CPLFree(padfTempY);
242 return false;
243 }
244
245 CPLErr eErr =
246 GDALRasterIO(m_psTransform->hBand_X, GF_Read, 0, 0, nXSize, 1,
247 padfTempX, nXSize, 1, GDT_Float64, 0, 0);
248
249 for (int j = 0; j < nYSize; j++)
250 {
251 if (poXBand->RasterIO(GF_Write, 0, j, nXSize, 1, padfTempX, nXSize,
252 1, GDT_Float64, 0, 0, nullptr) != CE_None)
253 {
254 eErr = CE_Failure;
255 break;
256 }
257 }
258
259 if (eErr == CE_None)
260 {
261 eErr = GDALRasterIO(m_psTransform->hBand_Y, GF_Read, 0, 0, nYSize,
262 1, padfTempY, nYSize, 1, GDT_Float64, 0, 0);
263
264 for (int i = 0; i < nXSize; i++)
265 {
266 if (poYBand->RasterIO(GF_Write, i, 0, 1, nYSize, padfTempY, 1,
267 nYSize, GDT_Float64, 0, 0,
268 nullptr) != CE_None)
269 {
270 eErr = CE_Failure;
271 break;
272 }
273 }
274 }
275
276 CPLFree(padfTempX);
277 CPLFree(padfTempY);
278
279 if (eErr != CE_None)
280 return false;
281
282 geolocXAccessor.SetBand(poXBand);
283 geolocYAccessor.SetBand(poYBand);
284 }
285 else
286 {
287 geolocXAccessor.SetBand(
288 GDALRasterBand::FromHandle(m_psTransform->hBand_X));
289 geolocYAccessor.SetBand(
290 GDALRasterBand::FromHandle(m_psTransform->hBand_Y));
291 }
292
293 GDALGeoLoc<GDALGeoLocDatasetAccessors>::LoadGeolocFinish(m_psTransform);
294 return true;
295}
296
String list class designed around our use of C "char**" string lists.
Definition cpl_string.h:449
Class to have reasonably fast random pixel access to a raster band, when accessing multiple pixels th...
Definition gdalcachedpixelaccessor.h:53
bool FlushCache()
Flush content of modified tiles and drop caches.
Definition gdalcachedpixelaccessor.h:281
void SetBand(GDALRasterBand *poBand)
Assign the raster band if not known at construction time.
Definition gdalcachedpixelaccessor.h:84
void ResetModifiedFlag()
Reset the modified flag for cached tiles.
Definition gdalcachedpixelaccessor.h:302
A set of associated raster bands, usually from one file.
Definition gdal_priv.h:490
void MarkSuppressOnClose()
Set that the dataset must be deleted on close.
Definition gdaldataset.cpp:1723
GDALRasterBand * GetRasterBand(int)
Fetch a band object for a dataset.
Definition gdaldataset.cpp:1013
static GDALDriver * FromHandle(GDALDriverH hDriver)
Convert a GDALDriverH to a GDALDriver*.
Definition gdal_priv.h:2173
virtual const char * GetDescription() const
Fetch object description.
Definition gdalmajorobject.cpp:77
virtual CPLErr SetNoDataValue(double dfNoData)
Set the no data value for this band.
Definition gdalrasterband.cpp:1994
static GDALRasterBand * FromHandle(GDALRasterBandH hBand)
Convert a GDALRasterBandH to a GDALRasterBand*.
Definition gdal_priv.h:1764
#define CPLFree
Alias of VSIFree()
Definition cpl_conv.h:98
const char * CPLGenerateTempFilename(const char *pszStem)
Generate temporary file name.
Definition cpl_path.cpp:1056
const char * CPLResetExtension(const char *, const char *)
Replace the extension with the provided one.
Definition cpl_path.cpp:436
CPLErr
Error category.
Definition cpl_error.h:53
int VSIUnlink(const char *pszFilename)
Delete a file.
Definition cpl_vsil.cpp:450
#define VSI_MALLOC2_VERBOSE(nSize1, nSize2)
VSI_MALLOC2_VERBOSE.
Definition cpl_vsi.h:353
@ GDT_Float64
Definition gdal.h:75
@ GDT_Float32
Definition gdal.h:74
@ GF_Write
Definition gdal.h:134
@ GF_Read
Definition gdal.h:133
GDALDriverH GDALGetDriverByName(const char *)
Fetch a driver based on the short name.
Definition gdaldrivermanager.cpp:691
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