1 : /******************************************************************************
2 : * $Id: vrtdriver.cpp 21945 2011-03-12 21:11:37Z warmerdam $
3 : *
4 : * Project: Virtual GDAL Datasets
5 : * Purpose: Implementation of VRTDriver
6 : * Author: Frank Warmerdam <warmerdam@pobox.com>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.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 "vrtdataset.h"
31 : #include "cpl_minixml.h"
32 : #include "cpl_string.h"
33 : #include "gdal_alg_priv.h"
34 :
35 : CPL_CVSID("$Id: vrtdriver.cpp 21945 2011-03-12 21:11:37Z warmerdam $");
36 :
37 : /************************************************************************/
38 : /* VRTDriver() */
39 : /************************************************************************/
40 :
41 561 : VRTDriver::VRTDriver()
42 :
43 : {
44 561 : papszSourceParsers = NULL;
45 : pDeserializerData = GDALRegisterTransformDeserializer("WarpedOverviewTransformer",
46 : VRTWarpedOverviewTransform,
47 561 : VRTDeserializeWarpedOverviewTransformer);
48 561 : }
49 :
50 : /************************************************************************/
51 : /* ~VRTDriver() */
52 : /************************************************************************/
53 :
54 542 : VRTDriver::~VRTDriver()
55 :
56 : {
57 542 : CSLDestroy( papszSourceParsers );
58 :
59 542 : if ( pDeserializerData )
60 : {
61 542 : GDALUnregisterTransformDeserializer( pDeserializerData );
62 : }
63 542 : }
64 :
65 : /************************************************************************/
66 : /* GetMetadata() */
67 : /************************************************************************/
68 :
69 18 : char **VRTDriver::GetMetadata( const char *pszDomain )
70 :
71 : {
72 18 : if( pszDomain && EQUAL(pszDomain,"SourceParsers") )
73 0 : return papszSourceParsers;
74 : else
75 18 : return GDALDriver::GetMetadata( pszDomain );
76 : }
77 :
78 : /************************************************************************/
79 : /* SetMetadata() */
80 : /************************************************************************/
81 :
82 0 : CPLErr VRTDriver::SetMetadata( char **papszMetadata, const char *pszDomain )
83 :
84 : {
85 0 : if( pszDomain && EQUAL(pszDomain,"SourceParsers") )
86 : {
87 0 : CSLDestroy( papszSourceParsers );
88 0 : papszSourceParsers = CSLDuplicate( papszMetadata );
89 0 : return CE_None;
90 : }
91 : else
92 0 : return GDALDriver::SetMetadata( papszMetadata, pszDomain );
93 : }
94 :
95 : /************************************************************************/
96 : /* AddSourceParser() */
97 : /************************************************************************/
98 :
99 2244 : void VRTDriver::AddSourceParser( const char *pszElementName,
100 : VRTSourceParser pfnParser )
101 :
102 : {
103 : char szPtrValue[128];
104 :
105 2244 : sprintf( szPtrValue, "%p", pfnParser );
106 : papszSourceParsers = CSLSetNameValue( papszSourceParsers,
107 2244 : pszElementName, szPtrValue );
108 2244 : }
109 :
110 : /************************************************************************/
111 : /* ParseSource() */
112 : /************************************************************************/
113 :
114 945 : VRTSource *VRTDriver::ParseSource( CPLXMLNode *psSrc, const char *pszVRTPath )
115 :
116 : {
117 : const char *pszParserFunc;
118 :
119 945 : if( psSrc == NULL || psSrc->eType != CXT_Element )
120 : {
121 : CPLError( CE_Failure, CPLE_AppDefined,
122 0 : "Corrupt or empty VRT source XML document." );
123 0 : return NULL;
124 : }
125 :
126 945 : pszParserFunc = CSLFetchNameValue( papszSourceParsers, psSrc->pszValue );
127 945 : if( pszParserFunc == NULL )
128 484 : return NULL;
129 :
130 461 : VRTSourceParser pfnParser = NULL;
131 :
132 461 : sscanf( pszParserFunc, "%p", &pfnParser );
133 :
134 461 : if( pfnParser == NULL )
135 0 : return NULL;
136 : else
137 461 : return pfnParser( psSrc, pszVRTPath );
138 : }
139 :
140 : /************************************************************************/
141 : /* VRTCreateCopy() */
142 : /************************************************************************/
143 :
144 : static GDALDataset *
145 102 : VRTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
146 : int bStrict, char ** papszOptions,
147 : GDALProgressFunc pfnProgress, void * pProgressData )
148 :
149 : {
150 102 : VRTDataset *poVRTDS = NULL;
151 :
152 : (void) bStrict;
153 : (void) papszOptions;
154 :
155 102 : CPLAssert( NULL != poSrcDS );
156 :
157 : /* -------------------------------------------------------------------- */
158 : /* If the source dataset is a virtual dataset then just write */
159 : /* it to disk as a special case to avoid extra layers of */
160 : /* indirection. */
161 : /* -------------------------------------------------------------------- */
162 306 : if( poSrcDS->GetDriver() != NULL &&
163 204 : EQUAL(poSrcDS->GetDriver()->GetDescription(),"VRT") )
164 : {
165 :
166 : /* -------------------------------------------------------------------- */
167 : /* Convert tree to a single block of XML text. */
168 : /* -------------------------------------------------------------------- */
169 8 : char *pszVRTPath = CPLStrdup(CPLGetPath(pszFilename));
170 8 : CPLXMLNode *psDSTree = ((VRTDataset *) poSrcDS)->SerializeToXML( pszVRTPath );
171 :
172 8 : char *pszXML = CPLSerializeXMLTree( psDSTree );
173 :
174 8 : CPLDestroyXMLNode( psDSTree );
175 :
176 8 : CPLFree( pszVRTPath );
177 :
178 : /* -------------------------------------------------------------------- */
179 : /* Write to disk. */
180 : /* -------------------------------------------------------------------- */
181 8 : GDALDataset* pCopyDS = NULL;
182 :
183 8 : if( 0 != strlen( pszFilename ) )
184 : {
185 8 : VSILFILE *fpVRT = NULL;
186 :
187 8 : fpVRT = VSIFOpenL( pszFilename, "wb" );
188 8 : if (fpVRT == NULL)
189 : {
190 : CPLError(CE_Failure, CPLE_AppDefined,
191 1 : "Cannot create %s", pszFilename);
192 1 : CPLFree( pszXML );
193 1 : return NULL;
194 : }
195 :
196 7 : VSIFWriteL( pszXML, 1, strlen(pszXML), fpVRT );
197 7 : VSIFCloseL( fpVRT );
198 :
199 7 : pCopyDS = (GDALDataset *) GDALOpen( pszFilename, GA_Update );
200 : }
201 : else
202 : {
203 : /* No destination file is given, so pass serialized XML directly. */
204 :
205 0 : pCopyDS = (GDALDataset *) GDALOpen( pszXML, GA_Update );
206 : }
207 :
208 7 : CPLFree( pszXML );
209 :
210 7 : return pCopyDS;
211 : }
212 :
213 : /* -------------------------------------------------------------------- */
214 : /* Create the virtual dataset. */
215 : /* -------------------------------------------------------------------- */
216 : poVRTDS = (VRTDataset *)
217 : VRTDataset::Create( pszFilename,
218 : poSrcDS->GetRasterXSize(),
219 : poSrcDS->GetRasterYSize(),
220 94 : 0, GDT_Byte, NULL );
221 94 : if (poVRTDS == NULL)
222 0 : return NULL;
223 :
224 : /* -------------------------------------------------------------------- */
225 : /* Do we have a geotransform? */
226 : /* -------------------------------------------------------------------- */
227 : double adfGeoTransform[6];
228 :
229 94 : if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
230 : {
231 94 : poVRTDS->SetGeoTransform( adfGeoTransform );
232 : }
233 :
234 : /* -------------------------------------------------------------------- */
235 : /* Copy projection */
236 : /* -------------------------------------------------------------------- */
237 94 : poVRTDS->SetProjection( poSrcDS->GetProjectionRef() );
238 :
239 : /* -------------------------------------------------------------------- */
240 : /* Emit dataset level metadata. */
241 : /* -------------------------------------------------------------------- */
242 94 : poVRTDS->SetMetadata( poSrcDS->GetMetadata() );
243 :
244 : /* -------------------------------------------------------------------- */
245 : /* Copy any special domains that should be transportable. */
246 : /* -------------------------------------------------------------------- */
247 : char **papszMD;
248 :
249 94 : papszMD = poSrcDS->GetMetadata( "RPC" );
250 94 : if( papszMD )
251 0 : poVRTDS->SetMetadata( papszMD, "RPC" );
252 :
253 94 : papszMD = poSrcDS->GetMetadata( "IMD" );
254 94 : if( papszMD )
255 0 : poVRTDS->SetMetadata( papszMD, "IMD" );
256 :
257 94 : papszMD = poSrcDS->GetMetadata( "GEOLOCATION" );
258 94 : if( papszMD )
259 0 : poVRTDS->SetMetadata( papszMD, "GEOLOCATION" );
260 :
261 : /* -------------------------------------------------------------------- */
262 : /* GCPs */
263 : /* -------------------------------------------------------------------- */
264 94 : if( poSrcDS->GetGCPCount() > 0 )
265 : {
266 1 : poVRTDS->SetGCPs( poSrcDS->GetGCPCount(),
267 1 : poSrcDS->GetGCPs(),
268 3 : poSrcDS->GetGCPProjection() );
269 : }
270 :
271 : /* -------------------------------------------------------------------- */
272 : /* Loop over all the bands. */
273 : /* -------------------------------------------------------------------- */
274 205 : for( int iBand = 0; iBand < poSrcDS->GetRasterCount(); iBand++ )
275 : {
276 111 : GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
277 :
278 : /* -------------------------------------------------------------------- */
279 : /* Create the band with the appropriate band type. */
280 : /* -------------------------------------------------------------------- */
281 111 : poVRTDS->AddBand( poSrcBand->GetRasterDataType(), NULL );
282 :
283 : VRTSourcedRasterBand *poVRTBand =
284 111 : (VRTSourcedRasterBand *) poVRTDS->GetRasterBand( iBand+1 );
285 :
286 : /* -------------------------------------------------------------------- */
287 : /* Setup source mapping. */
288 : /* -------------------------------------------------------------------- */
289 111 : poVRTBand->AddSimpleSource( poSrcBand );
290 :
291 : /* -------------------------------------------------------------------- */
292 : /* Emit various band level metadata. */
293 : /* -------------------------------------------------------------------- */
294 111 : poVRTBand->CopyCommonInfoFrom( poSrcBand );
295 :
296 : /* -------------------------------------------------------------------- */
297 : /* Add specific mask band. */
298 : /* -------------------------------------------------------------------- */
299 111 : if ( (poSrcBand->GetMaskFlags() & (GMF_PER_DATASET | GMF_ALL_VALID | GMF_NODATA)) == 0)
300 : {
301 : VRTSourcedRasterBand* poVRTMaskBand = new VRTSourcedRasterBand(poVRTDS, 0,
302 0 : poSrcBand->GetMaskBand()->GetRasterDataType(),
303 0 : poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize());
304 0 : poVRTMaskBand->AddMaskBandSource( poSrcBand );
305 0 : poVRTBand->SetMaskBand( poVRTMaskBand );
306 : }
307 : }
308 :
309 : /* -------------------------------------------------------------------- */
310 : /* Add dataset mask band */
311 : /* -------------------------------------------------------------------- */
312 187 : if (poSrcDS->GetRasterCount() != 0 &&
313 : poSrcDS->GetRasterBand(1) != NULL &&
314 93 : poSrcDS->GetRasterBand(1)->GetMaskFlags() == GMF_PER_DATASET)
315 : {
316 1 : GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand(1);
317 : VRTSourcedRasterBand* poVRTMaskBand = new VRTSourcedRasterBand(poVRTDS, 0,
318 1 : poSrcBand->GetMaskBand()->GetRasterDataType(),
319 1 : poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize());
320 1 : poVRTMaskBand->AddMaskBandSource( poSrcBand );
321 1 : poVRTDS->SetMaskBand( poVRTMaskBand );
322 : }
323 :
324 94 : poVRTDS->FlushCache();
325 :
326 94 : return poVRTDS;
327 : }
328 :
329 : /************************************************************************/
330 : /* GDALRegister_VRT() */
331 : /************************************************************************/
332 :
333 1594 : void GDALRegister_VRT()
334 :
335 : {
336 : VRTDriver *poDriver;
337 :
338 1594 : if( GDALGetDriverByName( "VRT" ) == NULL )
339 : {
340 561 : poDriver = new VRTDriver();
341 :
342 561 : poDriver->SetDescription( "VRT" );
343 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
344 561 : "Virtual Raster" );
345 561 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "vrt" );
346 561 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "gdal_vrttut.html" );
347 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
348 561 : "Byte Int16 UInt16 Int32 UInt32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64" );
349 :
350 561 : poDriver->pfnOpen = VRTDataset::Open;
351 561 : poDriver->pfnCreateCopy = VRTCreateCopy;
352 561 : poDriver->pfnCreate = VRTDataset::Create;
353 561 : poDriver->pfnIdentify = VRTDataset::Identify;
354 561 : poDriver->pfnDelete = VRTDataset::Delete;
355 :
356 561 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
357 :
358 : poDriver->AddSourceParser( "SimpleSource",
359 561 : VRTParseCoreSources );
360 : poDriver->AddSourceParser( "ComplexSource",
361 561 : VRTParseCoreSources );
362 : poDriver->AddSourceParser( "AveragedSource",
363 561 : VRTParseCoreSources );
364 :
365 : poDriver->AddSourceParser( "KernelFilteredSource",
366 561 : VRTParseFilterSources );
367 :
368 561 : GetGDALDriverManager()->RegisterDriver( poDriver );
369 : }
370 1594 : }
371 :
|