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 
37 class 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 
62  GDALCachedPixelAccessor<float, TILE_SIZE> backMapWeightAccessor;
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 
97 GDALGeoLocDatasetAccessors::~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 
114 bool 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 
156 void 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 
170 GDALDataset *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 
183 void GDALGeoLocDatasetAccessors::FlushBackmapCaches()
184 {
185  backMapXAccessor.FlushCache();
186  backMapYAccessor.FlushCache();
187 }
188 
189 /************************************************************************/
190 /* Load() */
191 /************************************************************************/
192 
193 bool 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 
205 bool 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:503
void MarkSuppressOnClose()
Set that the dataset must be deleted on close.
Definition: gdaldataset.cpp:1726
GDALRasterBand * GetRasterBand(int)
Fetch a band object for a dataset.
Definition: gdaldataset.cpp:1016
static GDALDriver * FromHandle(GDALDriverH hDriver)
Convert a GDALDriverH to a GDALDriver*.
Definition: gdal_priv.h:2225
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:1996
static GDALRasterBand * FromHandle(GDALRasterBandH hBand)
Convert a GDALRasterBandH to a GDALRasterBand*.
Definition: gdal_priv.h:1816
#define CPLFree
Alias of VSIFree()
Definition: cpl_conv.h:98
const char * CPLResetExtension(const char *, const char *)
Replace the extension with the provided one.
Definition: cpl_path.cpp:436
const char * CPLGenerateTempFilename(const char *pszStem)
Generate temporary file name.
Definition: cpl_path.cpp:1056
CPLErr
Error category.
Definition: cpl_error.h:53
const char * CPLSPrintf(const char *fmt,...)
CPLSPrintf() that works with 10 static buffer.
Definition: cpl_string.cpp:982
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:355
@ 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:449