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 GDALGeorefPamDataset::GDALGeorefPamDataset() : 44 bGeoTransformValid(false), 45 pszProjection(nullptr), 46 nGCPCount(0), 47 pasGCPList(nullptr), 48 m_papszRPC(nullptr), 49 m_bPixelIsPoint(false), 50 m_nGeoTransformGeorefSrcIndex(-1), 51 m_nGCPGeorefSrcIndex(-1), 52 m_nProjectionGeorefSrcIndex(-1), 53 m_nRPCGeorefSrcIndex(-1), 54 m_nPixelIsPointGeorefSrcIndex(-1), 55 m_bGotPAMGeorefSrcIndex(false), 56 m_nPAMGeorefSrcIndex(0), 57 m_bPAMLoaded(false), 58 m_papszMainMD(nullptr) 59 { 60 adfGeoTransform[0] = 0.0; 61 adfGeoTransform[1] = 1.0; 62 adfGeoTransform[2] = 0.0; 63 adfGeoTransform[3] = 0.0; 64 adfGeoTransform[4] = 0.0; 65 adfGeoTransform[5] = 1.0; 66 } 67 68 /************************************************************************/ 69 /* ~GDALGeorefPamDataset() */ 70 /************************************************************************/ 71 72 GDALGeorefPamDataset::~GDALGeorefPamDataset() 73 { 74 CPLFree( pszProjection ); 75 76 if( nGCPCount > 0 ) 77 { 78 GDALDeinitGCPs( nGCPCount, pasGCPList ); 79 CPLFree( pasGCPList ); 80 } 81 CSLDestroy(m_papszMainMD); 82 CSLDestroy(m_papszRPC); 83 } 84 85 /************************************************************************/ 86 /* GetMetadata() */ 87 /************************************************************************/ 88 89 char **GDALGeorefPamDataset::GetMetadata( const char * pszDomain ) 90 { 91 if( pszDomain != nullptr && EQUAL(pszDomain, "RPC") ) 92 { 93 const int nPAMIndex = GetPAMGeorefSrcIndex(); 94 if( nPAMIndex >= 0 && 95 ((m_papszRPC != nullptr && nPAMIndex < m_nRPCGeorefSrcIndex) || 96 m_nRPCGeorefSrcIndex < 0 || m_papszRPC == nullptr)) 97 { 98 char** papszMD = GDALPamDataset::GetMetadata(pszDomain); 99 if( papszMD ) 100 return papszMD; 101 } 102 return m_papszRPC; 103 } 104 105 if( pszDomain == nullptr || EQUAL(pszDomain, "") ) 106 { 107 if( m_papszMainMD ) 108 return m_papszMainMD; 109 m_papszMainMD = CSLDuplicate(GDALPamDataset::GetMetadata(pszDomain)); 110 const int nPAMIndex = GetPAMGeorefSrcIndex(); 111 if( nPAMIndex >= 0 && 112 ((m_bPixelIsPoint && nPAMIndex < m_nPixelIsPointGeorefSrcIndex) || 113 m_nPixelIsPointGeorefSrcIndex < 0 || !m_bPixelIsPoint)) 114 { 115 if( CSLFetchNameValue(m_papszMainMD, GDALMD_AREA_OR_POINT) != nullptr ) 116 return m_papszMainMD; 117 } 118 if( m_bPixelIsPoint ) 119 { 120 m_papszMainMD = CSLSetNameValue(m_papszMainMD, 121 GDALMD_AREA_OR_POINT, 122 GDALMD_AOP_POINT); 123 } 124 else 125 { 126 m_papszMainMD = CSLSetNameValue(m_papszMainMD, 127 GDALMD_AREA_OR_POINT, nullptr); 128 } 129 return m_papszMainMD; 130 } 131 132 return GDALPamDataset::GetMetadata(pszDomain); 133 } 134 135 /************************************************************************/ 136 /* GetMetadataItem() */ 137 /************************************************************************/ 138 139 const char *GDALGeorefPamDataset::GetMetadataItem( const char * pszName, 140 const char * pszDomain ) 141 { 142 if( pszDomain == nullptr || EQUAL(pszDomain, "") || EQUAL(pszDomain, "RPC") ) 143 { 144 return CSLFetchNameValue( GetMetadata(pszDomain), pszName ); 145 } 146 return GDALPamDataset::GetMetadataItem(pszName, pszDomain); 147 } 148 149 /************************************************************************/ 150 /* TryLoadXML() */ 151 /************************************************************************/ 152 153 CPLErr GDALGeorefPamDataset::TryLoadXML(char **papszSiblingFiles) 154 { 155 m_bPAMLoaded = true; 156 CPLErr eErr = GDALPamDataset::TryLoadXML(papszSiblingFiles); 157 CSLDestroy(m_papszMainMD); 158 m_papszMainMD = nullptr; 159 return eErr; 160 } 161 162 /************************************************************************/ 163 /* SetMetadata() */ 164 /************************************************************************/ 165 166 CPLErr GDALGeorefPamDataset::SetMetadata( char ** papszMetadata, 167 const char * pszDomain ) 168 { 169 if( m_bPAMLoaded && (pszDomain == nullptr || EQUAL(pszDomain, "")) ) 170 { 171 CSLDestroy(m_papszMainMD); 172 m_papszMainMD = CSLDuplicate(papszMetadata); 173 } 174 return GDALPamDataset::SetMetadata(papszMetadata, pszDomain); 175 } 176 177 /************************************************************************/ 178 /* SetMetadata() */ 179 /************************************************************************/ 180 181 CPLErr GDALGeorefPamDataset::SetMetadataItem( const char * pszName, 182 const char * pszValue, 183 const char * pszDomain ) 184 { 185 if( m_bPAMLoaded && (pszDomain == nullptr || EQUAL(pszDomain, "")) ) 186 { 187 m_papszMainMD = CSLSetNameValue( GetMetadata(), pszName, pszValue ); 188 } 189 return GDALPamDataset::SetMetadataItem(pszName, pszValue, pszDomain); 190 } 191 192 /************************************************************************/ 193 /* GetGCPCount() */ 194 /* */ 195 /* By default, we let PAM override the value stored */ 196 /* inside our file, unless GDAL_GEOREF_SOURCES is defined. */ 197 /************************************************************************/ 198 199 int GDALGeorefPamDataset::GetGCPCount() 200 201 { 202 const int nPAMIndex = GetPAMGeorefSrcIndex(); 203 if( nPAMIndex >= 0 && 204 ((nGCPCount != 0 && nPAMIndex < m_nGCPGeorefSrcIndex) || 205 m_nGCPGeorefSrcIndex < 0 || nGCPCount == 0)) 206 { 207 const int nPAMGCPCount = GDALPamDataset::GetGCPCount(); 208 if( nPAMGCPCount ) 209 return nPAMGCPCount; 210 } 211 212 return nGCPCount; 213 } 214 215 /************************************************************************/ 216 /* GetGCPProjection() */ 217 /* */ 218 /* By default, we let PAM override the value stored */ 219 /* inside our file, unless GDAL_GEOREF_SOURCES is defined. */ 220 /************************************************************************/ 221 222 const char *GDALGeorefPamDataset::_GetGCPProjection() 223 224 { 225 const int nPAMIndex = GetPAMGeorefSrcIndex(); 226 if( nPAMIndex >= 0 && 227 ((pszProjection != nullptr && nPAMIndex < m_nProjectionGeorefSrcIndex) || 228 m_nProjectionGeorefSrcIndex < 0 || pszProjection == nullptr) ) 229 { 230 const char* pszPAMGCPProjection = GDALPamDataset::_GetGCPProjection(); 231 if( pszPAMGCPProjection != nullptr && strlen(pszPAMGCPProjection) > 0 ) 232 return pszPAMGCPProjection; 233 } 234 235 if( pszProjection != nullptr ) 236 return pszProjection; 237 238 return ""; 239 } 240 241 /************************************************************************/ 242 /* GetGCP() */ 243 /* */ 244 /* By default, we let PAM override the value stored */ 245 /* inside our file, unless GDAL_GEOREF_SOURCES is defined. */ 246 /************************************************************************/ 247 248 const GDAL_GCP *GDALGeorefPamDataset::GetGCPs() 249 250 { 251 const int nPAMIndex = GetPAMGeorefSrcIndex(); 252 if( nPAMIndex >= 0 && 253 ((nGCPCount != 0 && nPAMIndex < m_nGCPGeorefSrcIndex) || 254 m_nGCPGeorefSrcIndex < 0 || nGCPCount == 0)) 255 { 256 const GDAL_GCP* pasPAMGCPList = GDALPamDataset::GetGCPs(); 257 if( pasPAMGCPList ) 258 return pasPAMGCPList; 259 } 260 261 return pasGCPList; 262 } 263 264 /************************************************************************/ 265 /* GetProjectionRef() */ 266 /* */ 267 /* By default, we let PAM override the value stored */ 268 /* inside our file, unless GDAL_GEOREF_SOURCES is defined. */ 269 /************************************************************************/ 270 271 const char *GDALGeorefPamDataset::_GetProjectionRef() 272 273 { 274 if( GetGCPCount() > 0 ) 275 return ""; 276 277 const int nPAMIndex = GetPAMGeorefSrcIndex(); 278 if( nPAMIndex >= 0 && 279 ((pszProjection != nullptr && nPAMIndex < m_nProjectionGeorefSrcIndex) || 280 m_nProjectionGeorefSrcIndex < 0 || pszProjection == nullptr) ) 281 { 282 const char* pszPAMProjection = GDALPamDataset::_GetProjectionRef(); 283 if( pszPAMProjection != nullptr && strlen(pszPAMProjection) > 0 ) 284 return pszPAMProjection; 285 } 286 287 if( pszProjection != nullptr ) 288 return pszProjection; 289 290 return ""; 291 } 292 293 /************************************************************************/ 294 /* GetGeoTransform() */ 295 /* */ 296 /* By default, we let PAM override the value stored */ 297 /* inside our file, unless GDAL_GEOREF_SOURCES is defined. */ 298 /************************************************************************/ 299 300 CPLErr GDALGeorefPamDataset::GetGeoTransform( double * padfTransform ) 301 302 { 303 const int nPAMIndex = GetPAMGeorefSrcIndex(); 304 if( nPAMIndex >= 0 && 305 ((bGeoTransformValid && nPAMIndex <= m_nGeoTransformGeorefSrcIndex) || 306 m_nGeoTransformGeorefSrcIndex < 0 || !bGeoTransformValid) ) 307 { 308 if( GDALPamDataset::GetGeoTransform( padfTransform ) == CE_None ) 309 { 310 m_nGeoTransformGeorefSrcIndex = nPAMIndex; 311 return CE_None; 312 } 313 } 314 315 if( bGeoTransformValid ) 316 { 317 memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 ); 318 return( CE_None ); 319 } 320 321 return CE_Failure; 322 } 323 324 /************************************************************************/ 325 /* GetPAMGeorefSrcIndex() */ 326 /* */ 327 /* Get priority index of PAM (the lower, the more prioritary) */ 328 /************************************************************************/ 329 int GDALGeorefPamDataset::GetPAMGeorefSrcIndex() 330 { 331 if( !m_bGotPAMGeorefSrcIndex ) 332 { 333 m_bGotPAMGeorefSrcIndex = true; 334 const char* pszGeorefSources = CSLFetchNameValueDef( papszOpenOptions, 335 "GEOREF_SOURCES", 336 CPLGetConfigOption("GDAL_GEOREF_SOURCES", "PAM,OTHER") ); 337 char** papszTokens = CSLTokenizeString2(pszGeorefSources, ",", 0); 338 m_nPAMGeorefSrcIndex = CSLFindString(papszTokens, "PAM"); 339 CSLDestroy(papszTokens); 340 } 341 return m_nPAMGeorefSrcIndex; 342 } 343 //! @endcond 344