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 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "gdalgeorefpamdataset.h"
31 :
32 : #include <cstring>
33 :
34 : #include "cpl_conv.h"
35 : #include "cpl_error.h"
36 : #include "gdal.h"
37 :
38 : //! @cond Doxygen_Suppress
39 : /************************************************************************/
40 : /* GDALGeorefPamDataset() */
41 : /************************************************************************/
42 :
43 2231 : GDALGeorefPamDataset::GDALGeorefPamDataset()
44 : : bGeoTransformValid(false), nGCPCount(0), pasGCPList(nullptr),
45 : m_papszRPC(nullptr), m_bPixelIsPoint(false),
46 : m_nGeoTransformGeorefSrcIndex(-1), m_nGCPGeorefSrcIndex(-1),
47 : m_nProjectionGeorefSrcIndex(-1), m_nRPCGeorefSrcIndex(-1),
48 : m_nPixelIsPointGeorefSrcIndex(-1), m_bGotPAMGeorefSrcIndex(false),
49 2231 : m_nPAMGeorefSrcIndex(0), m_bPAMLoaded(false), m_papszMainMD(nullptr)
50 : {
51 2231 : adfGeoTransform[0] = 0.0;
52 2231 : adfGeoTransform[1] = 1.0;
53 2231 : adfGeoTransform[2] = 0.0;
54 2231 : adfGeoTransform[3] = 0.0;
55 2231 : adfGeoTransform[4] = 0.0;
56 2231 : adfGeoTransform[5] = 1.0;
57 2231 : }
58 :
59 : /************************************************************************/
60 : /* ~GDALGeorefPamDataset() */
61 : /************************************************************************/
62 :
63 2231 : GDALGeorefPamDataset::~GDALGeorefPamDataset()
64 : {
65 2231 : if (nGCPCount > 0)
66 : {
67 14 : GDALDeinitGCPs(nGCPCount, pasGCPList);
68 14 : CPLFree(pasGCPList);
69 : }
70 2231 : CSLDestroy(m_papszMainMD);
71 2231 : CSLDestroy(m_papszRPC);
72 2231 : }
73 :
74 : /************************************************************************/
75 : /* GetMetadata() */
76 : /************************************************************************/
77 :
78 826 : char **GDALGeorefPamDataset::GetMetadata(const char *pszDomain)
79 : {
80 826 : if (pszDomain != nullptr && EQUAL(pszDomain, "RPC"))
81 : {
82 24 : const int nPAMIndex = GetPAMGeorefSrcIndex();
83 24 : if (nPAMIndex >= 0 &&
84 24 : ((m_papszRPC != nullptr && nPAMIndex < m_nRPCGeorefSrcIndex) ||
85 23 : m_nRPCGeorefSrcIndex < 0 || m_papszRPC == nullptr))
86 : {
87 24 : char **papszMD = GDALPamDataset::GetMetadata(pszDomain);
88 24 : if (papszMD)
89 2 : return papszMD;
90 : }
91 22 : return m_papszRPC;
92 : }
93 :
94 802 : if (pszDomain == nullptr || EQUAL(pszDomain, ""))
95 : {
96 486 : if (m_papszMainMD)
97 59 : return m_papszMainMD;
98 427 : m_papszMainMD = CSLDuplicate(GDALPamDataset::GetMetadata(pszDomain));
99 427 : const int nPAMIndex = GetPAMGeorefSrcIndex();
100 427 : if (nPAMIndex >= 0 &&
101 427 : ((m_bPixelIsPoint && nPAMIndex < m_nPixelIsPointGeorefSrcIndex) ||
102 423 : m_nPixelIsPointGeorefSrcIndex < 0 || !m_bPixelIsPoint))
103 : {
104 427 : if (CSLFetchNameValue(m_papszMainMD, GDALMD_AREA_OR_POINT) !=
105 : nullptr)
106 0 : return m_papszMainMD;
107 : }
108 427 : if (m_bPixelIsPoint)
109 : {
110 4 : m_papszMainMD = CSLSetNameValue(m_papszMainMD, GDALMD_AREA_OR_POINT,
111 : GDALMD_AOP_POINT);
112 : }
113 : else
114 : {
115 423 : m_papszMainMD =
116 423 : CSLSetNameValue(m_papszMainMD, GDALMD_AREA_OR_POINT, nullptr);
117 : }
118 427 : return m_papszMainMD;
119 : }
120 :
121 316 : return GDALPamDataset::GetMetadata(pszDomain);
122 : }
123 :
124 : /************************************************************************/
125 : /* GetMetadataItem() */
126 : /************************************************************************/
127 :
128 433 : const char *GDALGeorefPamDataset::GetMetadataItem(const char *pszName,
129 : const char *pszDomain)
130 : {
131 433 : if (pszDomain == nullptr || EQUAL(pszDomain, "") || EQUAL(pszDomain, "RPC"))
132 : {
133 200 : return CSLFetchNameValue(GetMetadata(pszDomain), pszName);
134 : }
135 233 : return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
136 : }
137 :
138 : /************************************************************************/
139 : /* TryLoadXML() */
140 : /************************************************************************/
141 :
142 1067 : CPLErr GDALGeorefPamDataset::TryLoadXML(char **papszSiblingFiles)
143 : {
144 1067 : m_bPAMLoaded = true;
145 1067 : CPLErr eErr = GDALPamDataset::TryLoadXML(papszSiblingFiles);
146 1067 : CSLDestroy(m_papszMainMD);
147 1067 : m_papszMainMD = nullptr;
148 1067 : return eErr;
149 : }
150 :
151 : /************************************************************************/
152 : /* SetMetadata() */
153 : /************************************************************************/
154 :
155 17 : CPLErr GDALGeorefPamDataset::SetMetadata(char **papszMetadata,
156 : const char *pszDomain)
157 : {
158 17 : if (m_bPAMLoaded && (pszDomain == nullptr || EQUAL(pszDomain, "")))
159 : {
160 17 : CSLDestroy(m_papszMainMD);
161 17 : m_papszMainMD = CSLDuplicate(papszMetadata);
162 : }
163 17 : return GDALPamDataset::SetMetadata(papszMetadata, pszDomain);
164 : }
165 :
166 : /************************************************************************/
167 : /* SetMetadata() */
168 : /************************************************************************/
169 :
170 590 : CPLErr GDALGeorefPamDataset::SetMetadataItem(const char *pszName,
171 : const char *pszValue,
172 : const char *pszDomain)
173 : {
174 590 : if (m_bPAMLoaded && (pszDomain == nullptr || EQUAL(pszDomain, "")))
175 : {
176 57 : char **papszMD = GetMetadata();
177 57 : if (papszMD != m_papszMainMD)
178 : {
179 45 : CSLDestroy(m_papszMainMD);
180 45 : m_papszMainMD = CSLDuplicate(papszMD);
181 : }
182 57 : m_papszMainMD = CSLSetNameValue(m_papszMainMD, pszName, pszValue);
183 : }
184 590 : return GDALPamDataset::SetMetadataItem(pszName, pszValue, pszDomain);
185 : }
186 :
187 : /************************************************************************/
188 : /* GetGCPCount() */
189 : /* */
190 : /* By default, we let PAM override the value stored */
191 : /* inside our file, unless GDAL_GEOREF_SOURCES is defined. */
192 : /************************************************************************/
193 :
194 443 : int GDALGeorefPamDataset::GetGCPCount()
195 :
196 : {
197 443 : const int nPAMIndex = GetPAMGeorefSrcIndex();
198 443 : if (nPAMIndex >= 0 &&
199 426 : ((nGCPCount != 0 && nPAMIndex < m_nGCPGeorefSrcIndex) ||
200 410 : m_nGCPGeorefSrcIndex < 0 || nGCPCount == 0))
201 : {
202 426 : const int nPAMGCPCount = GDALPamDataset::GetGCPCount();
203 426 : if (nPAMGCPCount)
204 2 : return nPAMGCPCount;
205 : }
206 :
207 441 : return nGCPCount;
208 : }
209 :
210 : /************************************************************************/
211 : /* GetGCPSpatialRef() */
212 : /* */
213 : /* By default, we let PAM override the value stored */
214 : /* inside our file, unless GDAL_GEOREF_SOURCES is defined. */
215 : /************************************************************************/
216 :
217 6 : const OGRSpatialReference *GDALGeorefPamDataset::GetGCPSpatialRef() const
218 :
219 : {
220 6 : const int nPAMIndex = GetPAMGeorefSrcIndex();
221 12 : if (nPAMIndex >= 0 &&
222 6 : ((!m_oSRS.IsEmpty() && nPAMIndex < m_nProjectionGeorefSrcIndex) ||
223 1 : m_nProjectionGeorefSrcIndex < 0 || m_oSRS.IsEmpty()))
224 : {
225 : const OGRSpatialReference *pszPAMGCPSRS =
226 6 : GDALPamDataset::GetGCPSpatialRef();
227 6 : if (pszPAMGCPSRS != nullptr)
228 1 : return pszPAMGCPSRS;
229 : }
230 :
231 5 : if (!m_oSRS.IsEmpty())
232 5 : return &m_oSRS;
233 :
234 0 : return nullptr;
235 : }
236 :
237 : /************************************************************************/
238 : /* GetGCP() */
239 : /* */
240 : /* By default, we let PAM override the value stored */
241 : /* inside our file, unless GDAL_GEOREF_SOURCES is defined. */
242 : /************************************************************************/
243 :
244 9 : const GDAL_GCP *GDALGeorefPamDataset::GetGCPs()
245 :
246 : {
247 9 : const int nPAMIndex = GetPAMGeorefSrcIndex();
248 9 : if (nPAMIndex >= 0 &&
249 9 : ((nGCPCount != 0 && nPAMIndex < m_nGCPGeorefSrcIndex) ||
250 4 : m_nGCPGeorefSrcIndex < 0 || nGCPCount == 0))
251 : {
252 9 : const GDAL_GCP *pasPAMGCPList = GDALPamDataset::GetGCPs();
253 9 : if (pasPAMGCPList)
254 1 : return pasPAMGCPList;
255 : }
256 :
257 8 : return pasGCPList;
258 : }
259 :
260 : /************************************************************************/
261 : /* GetSpatialRef() */
262 : /* */
263 : /* By default, we let PAM override the value stored */
264 : /* inside our file, unless GDAL_GEOREF_SOURCES is defined. */
265 : /************************************************************************/
266 :
267 356 : const OGRSpatialReference *GDALGeorefPamDataset::GetSpatialRef() const
268 :
269 : {
270 356 : if (const_cast<GDALGeorefPamDataset *>(this)->GetGCPCount() > 0)
271 2 : return nullptr;
272 :
273 354 : const int nPAMIndex = GetPAMGeorefSrcIndex();
274 691 : if (nPAMIndex >= 0 &&
275 337 : ((!m_oSRS.IsEmpty() && nPAMIndex < m_nProjectionGeorefSrcIndex) ||
276 80 : m_nProjectionGeorefSrcIndex < 0 || m_oSRS.IsEmpty()))
277 : {
278 333 : const OGRSpatialReference *poPAMSRS = GDALPamDataset::GetSpatialRef();
279 333 : if (poPAMSRS != nullptr)
280 20 : return poPAMSRS;
281 : }
282 :
283 334 : if (!m_oSRS.IsEmpty())
284 272 : return &m_oSRS;
285 :
286 62 : return nullptr;
287 : }
288 :
289 : /************************************************************************/
290 : /* GetGeoTransform() */
291 : /* */
292 : /* By default, we let PAM override the value stored */
293 : /* inside our file, unless GDAL_GEOREF_SOURCES is defined. */
294 : /************************************************************************/
295 :
296 491 : CPLErr GDALGeorefPamDataset::GetGeoTransform(double *padfTransform)
297 :
298 : {
299 491 : const int nPAMIndex = GetPAMGeorefSrcIndex();
300 491 : if (nPAMIndex >= 0 &&
301 474 : ((bGeoTransformValid && nPAMIndex <= m_nGeoTransformGeorefSrcIndex) ||
302 100 : m_nGeoTransformGeorefSrcIndex < 0 || !bGeoTransformValid))
303 : {
304 463 : if (GDALPamDataset::GetGeoTransform(padfTransform) == CE_None)
305 : {
306 14 : m_nGeoTransformGeorefSrcIndex = nPAMIndex;
307 14 : return CE_None;
308 : }
309 : }
310 :
311 477 : if (bGeoTransformValid)
312 : {
313 408 : memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6);
314 408 : return (CE_None);
315 : }
316 :
317 69 : return CE_Failure;
318 : }
319 :
320 : /************************************************************************/
321 : /* GetPAMGeorefSrcIndex() */
322 : /* */
323 : /* Get priority index of PAM (the lower, the more prioritary) */
324 : /************************************************************************/
325 1754 : int GDALGeorefPamDataset::GetPAMGeorefSrcIndex() const
326 : {
327 1754 : if (!m_bGotPAMGeorefSrcIndex)
328 : {
329 22 : m_bGotPAMGeorefSrcIndex = true;
330 22 : const char *pszGeorefSources = CSLFetchNameValueDef(
331 22 : papszOpenOptions, "GEOREF_SOURCES",
332 : CPLGetConfigOption("GDAL_GEOREF_SOURCES", "PAM,OTHER"));
333 22 : char **papszTokens = CSLTokenizeString2(pszGeorefSources, ",", 0);
334 22 : m_nPAMGeorefSrcIndex = CSLFindString(papszTokens, "PAM");
335 22 : CSLDestroy(papszTokens);
336 : }
337 1754 : return m_nPAMGeorefSrcIndex;
338 : }
339 :
340 : //! @endcond
|