Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL
4 : * Purpose: GDALPamDataset with internal storage for georeferencing, with
5 : * priority for PAM over internal georeferencing
6 : * Author: Even Rouault <even dot rouault at spatialys.com>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2013, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "gdalgeorefpamdataset.h"
15 :
16 : #include <cstring>
17 :
18 : #include "cpl_conv.h"
19 : #include "cpl_error.h"
20 : #include "gdal.h"
21 :
22 : //! @cond Doxygen_Suppress
23 : /************************************************************************/
24 : /* GDALGeorefPamDataset() */
25 : /************************************************************************/
26 :
27 2282 : GDALGeorefPamDataset::GDALGeorefPamDataset()
28 : : bGeoTransformValid(false), nGCPCount(0), pasGCPList(nullptr),
29 : m_papszRPC(nullptr), m_bPixelIsPoint(false),
30 : m_nGeoTransformGeorefSrcIndex(-1), m_nGCPGeorefSrcIndex(-1),
31 : m_nProjectionGeorefSrcIndex(-1), m_nRPCGeorefSrcIndex(-1),
32 : m_nPixelIsPointGeorefSrcIndex(-1), m_bGotPAMGeorefSrcIndex(false),
33 2282 : m_nPAMGeorefSrcIndex(0), m_bPAMLoaded(false), m_papszMainMD(nullptr)
34 : {
35 2282 : adfGeoTransform[0] = 0.0;
36 2282 : adfGeoTransform[1] = 1.0;
37 2282 : adfGeoTransform[2] = 0.0;
38 2282 : adfGeoTransform[3] = 0.0;
39 2282 : adfGeoTransform[4] = 0.0;
40 2282 : adfGeoTransform[5] = 1.0;
41 2282 : }
42 :
43 : /************************************************************************/
44 : /* ~GDALGeorefPamDataset() */
45 : /************************************************************************/
46 :
47 2282 : GDALGeorefPamDataset::~GDALGeorefPamDataset()
48 : {
49 2282 : if (nGCPCount > 0)
50 : {
51 14 : GDALDeinitGCPs(nGCPCount, pasGCPList);
52 14 : CPLFree(pasGCPList);
53 : }
54 2282 : CSLDestroy(m_papszMainMD);
55 2282 : CSLDestroy(m_papszRPC);
56 2282 : }
57 :
58 : /************************************************************************/
59 : /* GetMetadata() */
60 : /************************************************************************/
61 :
62 837 : char **GDALGeorefPamDataset::GetMetadata(const char *pszDomain)
63 : {
64 837 : if (pszDomain != nullptr && EQUAL(pszDomain, "RPC"))
65 : {
66 25 : const int nPAMIndex = GetPAMGeorefSrcIndex();
67 25 : if (nPAMIndex >= 0 &&
68 25 : ((m_papszRPC != nullptr && nPAMIndex < m_nRPCGeorefSrcIndex) ||
69 24 : m_nRPCGeorefSrcIndex < 0 || m_papszRPC == nullptr))
70 : {
71 25 : char **papszMD = GDALPamDataset::GetMetadata(pszDomain);
72 25 : if (papszMD)
73 2 : return papszMD;
74 : }
75 23 : return m_papszRPC;
76 : }
77 :
78 812 : if (pszDomain == nullptr || EQUAL(pszDomain, ""))
79 : {
80 495 : if (m_papszMainMD)
81 59 : return m_papszMainMD;
82 436 : m_papszMainMD = CSLDuplicate(GDALPamDataset::GetMetadata(pszDomain));
83 436 : const int nPAMIndex = GetPAMGeorefSrcIndex();
84 436 : if (nPAMIndex >= 0 &&
85 436 : ((m_bPixelIsPoint && nPAMIndex < m_nPixelIsPointGeorefSrcIndex) ||
86 432 : m_nPixelIsPointGeorefSrcIndex < 0 || !m_bPixelIsPoint))
87 : {
88 436 : if (CSLFetchNameValue(m_papszMainMD, GDALMD_AREA_OR_POINT) !=
89 : nullptr)
90 0 : return m_papszMainMD;
91 : }
92 436 : if (m_bPixelIsPoint)
93 : {
94 4 : m_papszMainMD = CSLSetNameValue(m_papszMainMD, GDALMD_AREA_OR_POINT,
95 : GDALMD_AOP_POINT);
96 : }
97 : else
98 : {
99 432 : m_papszMainMD =
100 432 : CSLSetNameValue(m_papszMainMD, GDALMD_AREA_OR_POINT, nullptr);
101 : }
102 436 : return m_papszMainMD;
103 : }
104 :
105 317 : return GDALPamDataset::GetMetadata(pszDomain);
106 : }
107 :
108 : /************************************************************************/
109 : /* GetMetadataItem() */
110 : /************************************************************************/
111 :
112 438 : const char *GDALGeorefPamDataset::GetMetadataItem(const char *pszName,
113 : const char *pszDomain)
114 : {
115 438 : if (pszDomain == nullptr || EQUAL(pszDomain, "") || EQUAL(pszDomain, "RPC"))
116 : {
117 204 : return CSLFetchNameValue(GetMetadata(pszDomain), pszName);
118 : }
119 234 : return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
120 : }
121 :
122 : /************************************************************************/
123 : /* TryLoadXML() */
124 : /************************************************************************/
125 :
126 1085 : CPLErr GDALGeorefPamDataset::TryLoadXML(CSLConstList papszSiblingFiles)
127 : {
128 1085 : m_bPAMLoaded = true;
129 1085 : CPLErr eErr = GDALPamDataset::TryLoadXML(papszSiblingFiles);
130 1085 : CSLDestroy(m_papszMainMD);
131 1085 : m_papszMainMD = nullptr;
132 1085 : return eErr;
133 : }
134 :
135 : /************************************************************************/
136 : /* SetMetadata() */
137 : /************************************************************************/
138 :
139 18 : CPLErr GDALGeorefPamDataset::SetMetadata(char **papszMetadata,
140 : const char *pszDomain)
141 : {
142 18 : if (m_bPAMLoaded && (pszDomain == nullptr || EQUAL(pszDomain, "")))
143 : {
144 18 : CSLDestroy(m_papszMainMD);
145 18 : m_papszMainMD = CSLDuplicate(papszMetadata);
146 : }
147 18 : return GDALPamDataset::SetMetadata(papszMetadata, pszDomain);
148 : }
149 :
150 : /************************************************************************/
151 : /* SetMetadata() */
152 : /************************************************************************/
153 :
154 589 : CPLErr GDALGeorefPamDataset::SetMetadataItem(const char *pszName,
155 : const char *pszValue,
156 : const char *pszDomain)
157 : {
158 589 : if (m_bPAMLoaded && (pszDomain == nullptr || EQUAL(pszDomain, "")))
159 : {
160 57 : char **papszMD = GetMetadata();
161 57 : if (papszMD != m_papszMainMD)
162 : {
163 45 : CSLDestroy(m_papszMainMD);
164 45 : m_papszMainMD = CSLDuplicate(papszMD);
165 : }
166 57 : m_papszMainMD = CSLSetNameValue(m_papszMainMD, pszName, pszValue);
167 : }
168 589 : return GDALPamDataset::SetMetadataItem(pszName, pszValue, pszDomain);
169 : }
170 :
171 : /************************************************************************/
172 : /* GetGCPCount() */
173 : /* */
174 : /* By default, we let PAM override the value stored */
175 : /* inside our file, unless GDAL_GEOREF_SOURCES is defined. */
176 : /************************************************************************/
177 :
178 452 : int GDALGeorefPamDataset::GetGCPCount()
179 :
180 : {
181 452 : const int nPAMIndex = GetPAMGeorefSrcIndex();
182 452 : if (nPAMIndex >= 0 &&
183 435 : ((nGCPCount != 0 && nPAMIndex < m_nGCPGeorefSrcIndex) ||
184 419 : m_nGCPGeorefSrcIndex < 0 || nGCPCount == 0))
185 : {
186 435 : const int nPAMGCPCount = GDALPamDataset::GetGCPCount();
187 435 : if (nPAMGCPCount)
188 2 : return nPAMGCPCount;
189 : }
190 :
191 450 : return nGCPCount;
192 : }
193 :
194 : /************************************************************************/
195 : /* GetGCPSpatialRef() */
196 : /* */
197 : /* By default, we let PAM override the value stored */
198 : /* inside our file, unless GDAL_GEOREF_SOURCES is defined. */
199 : /************************************************************************/
200 :
201 6 : const OGRSpatialReference *GDALGeorefPamDataset::GetGCPSpatialRef() const
202 :
203 : {
204 6 : const int nPAMIndex = GetPAMGeorefSrcIndex();
205 12 : if (nPAMIndex >= 0 &&
206 6 : ((!m_oSRS.IsEmpty() && nPAMIndex < m_nProjectionGeorefSrcIndex) ||
207 1 : m_nProjectionGeorefSrcIndex < 0 || m_oSRS.IsEmpty()))
208 : {
209 : const OGRSpatialReference *pszPAMGCPSRS =
210 6 : GDALPamDataset::GetGCPSpatialRef();
211 6 : if (pszPAMGCPSRS != nullptr)
212 1 : return pszPAMGCPSRS;
213 : }
214 :
215 5 : if (!m_oSRS.IsEmpty())
216 5 : return &m_oSRS;
217 :
218 0 : return nullptr;
219 : }
220 :
221 : /************************************************************************/
222 : /* GetGCP() */
223 : /* */
224 : /* By default, we let PAM override the value stored */
225 : /* inside our file, unless GDAL_GEOREF_SOURCES is defined. */
226 : /************************************************************************/
227 :
228 9 : const GDAL_GCP *GDALGeorefPamDataset::GetGCPs()
229 :
230 : {
231 9 : const int nPAMIndex = GetPAMGeorefSrcIndex();
232 9 : if (nPAMIndex >= 0 &&
233 9 : ((nGCPCount != 0 && nPAMIndex < m_nGCPGeorefSrcIndex) ||
234 4 : m_nGCPGeorefSrcIndex < 0 || nGCPCount == 0))
235 : {
236 9 : const GDAL_GCP *pasPAMGCPList = GDALPamDataset::GetGCPs();
237 9 : if (pasPAMGCPList)
238 1 : return pasPAMGCPList;
239 : }
240 :
241 8 : return pasGCPList;
242 : }
243 :
244 : /************************************************************************/
245 : /* GetSpatialRef() */
246 : /* */
247 : /* By default, we let PAM override the value stored */
248 : /* inside our file, unless GDAL_GEOREF_SOURCES is defined. */
249 : /************************************************************************/
250 :
251 362 : const OGRSpatialReference *GDALGeorefPamDataset::GetSpatialRef() const
252 :
253 : {
254 362 : if (const_cast<GDALGeorefPamDataset *>(this)->GetGCPCount() > 0)
255 2 : return nullptr;
256 :
257 360 : const int nPAMIndex = GetPAMGeorefSrcIndex();
258 703 : if (nPAMIndex >= 0 &&
259 343 : ((!m_oSRS.IsEmpty() && nPAMIndex < m_nProjectionGeorefSrcIndex) ||
260 81 : m_nProjectionGeorefSrcIndex < 0 || m_oSRS.IsEmpty()))
261 : {
262 339 : const OGRSpatialReference *poPAMSRS = GDALPamDataset::GetSpatialRef();
263 339 : if (poPAMSRS != nullptr)
264 20 : return poPAMSRS;
265 : }
266 :
267 340 : if (!m_oSRS.IsEmpty())
268 277 : return &m_oSRS;
269 :
270 63 : return nullptr;
271 : }
272 :
273 : /************************************************************************/
274 : /* GetGeoTransform() */
275 : /* */
276 : /* By default, we let PAM override the value stored */
277 : /* inside our file, unless GDAL_GEOREF_SOURCES is defined. */
278 : /************************************************************************/
279 :
280 499 : CPLErr GDALGeorefPamDataset::GetGeoTransform(double *padfTransform)
281 :
282 : {
283 499 : const int nPAMIndex = GetPAMGeorefSrcIndex();
284 499 : if (nPAMIndex >= 0 &&
285 482 : ((bGeoTransformValid && nPAMIndex <= m_nGeoTransformGeorefSrcIndex) ||
286 103 : m_nGeoTransformGeorefSrcIndex < 0 || !bGeoTransformValid))
287 : {
288 471 : if (GDALPamDataset::GetGeoTransform(padfTransform) == CE_None)
289 : {
290 14 : m_nGeoTransformGeorefSrcIndex = nPAMIndex;
291 14 : return CE_None;
292 : }
293 : }
294 :
295 485 : if (bGeoTransformValid)
296 : {
297 413 : memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6);
298 413 : return (CE_None);
299 : }
300 :
301 72 : return CE_Failure;
302 : }
303 :
304 : /************************************************************************/
305 : /* GetPAMGeorefSrcIndex() */
306 : /* */
307 : /* Get priority index of PAM (the lower, the more prioritary) */
308 : /************************************************************************/
309 1787 : int GDALGeorefPamDataset::GetPAMGeorefSrcIndex() const
310 : {
311 1787 : if (!m_bGotPAMGeorefSrcIndex)
312 : {
313 22 : m_bGotPAMGeorefSrcIndex = true;
314 22 : const char *pszGeorefSources = CSLFetchNameValueDef(
315 22 : papszOpenOptions, "GEOREF_SOURCES",
316 : CPLGetConfigOption("GDAL_GEOREF_SOURCES", "PAM,OTHER"));
317 22 : char **papszTokens = CSLTokenizeString2(pszGeorefSources, ",", 0);
318 22 : m_nPAMGeorefSrcIndex = CSLFindString(papszTokens, "PAM");
319 22 : CSLDestroy(papszTokens);
320 : }
321 1787 : return m_nPAMGeorefSrcIndex;
322 : }
323 :
324 : //! @endcond
|