1 : /******************************************************************************
2 : * $Id: tildataset.cpp 17664 2009-09-21 21:16:45Z rouault $
3 : *
4 : * Project: EarthWatch .TIL Driver
5 : * Purpose: Implementation of the TILDataset class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2009, Frank Warmerdam
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 "gdal_pam.h"
31 : #include "gdal_proxy.h"
32 : #include "ogr_spatialref.h"
33 : #include "cpl_string.h"
34 : #include "vrtdataset.h"
35 : #include "cpl_multiproc.h"
36 : #include "cplkeywordparser.h"
37 :
38 : CPL_CVSID("$Id: tildataset.cpp 17664 2009-09-21 21:16:45Z rouault $");
39 :
40 : /************************************************************************/
41 : /* ==================================================================== */
42 : /* TILDataset */
43 : /* ==================================================================== */
44 : /************************************************************************/
45 :
46 : class CPL_DLL TILDataset : public GDALPamDataset
47 : {
48 : VRTDataset *poVRTDS;
49 : std::vector<GDALDataset *> apoTileDS;
50 :
51 : public:
52 : TILDataset();
53 : ~TILDataset();
54 :
55 : static GDALDataset *Open( GDALOpenInfo * );
56 : static int Identify( GDALOpenInfo *poOpenInfo );
57 : };
58 :
59 : /************************************************************************/
60 : /* ==================================================================== */
61 : /* TILRasterBand */
62 : /* ==================================================================== */
63 : /************************************************************************/
64 :
65 : class TILRasterBand : public GDALPamRasterBand
66 : {
67 : friend class TILDataset;
68 :
69 : VRTRasterBand *poVRTBand;
70 :
71 : public:
72 : TILRasterBand( TILDataset *, int, VRTRasterBand * );
73 0 : virtual ~TILRasterBand() {};
74 :
75 : virtual CPLErr IReadBlock( int, int, void * );
76 : };
77 :
78 : /************************************************************************/
79 : /* TILRasterBand() */
80 : /************************************************************************/
81 :
82 0 : TILRasterBand::TILRasterBand( TILDataset *poTILDS, int nBand,
83 0 : VRTRasterBand *poVRTBand )
84 :
85 : {
86 0 : this->poDS = poTILDS;
87 0 : this->poVRTBand = poVRTBand;
88 0 : this->nBand = nBand;
89 0 : this->eDataType = poVRTBand->GetRasterDataType();
90 :
91 0 : poVRTBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
92 0 : }
93 :
94 : /************************************************************************/
95 : /* IReadBlock() */
96 : /************************************************************************/
97 :
98 0 : CPLErr TILRasterBand::IReadBlock( int iBlockX, int iBlockY, void *pBuffer )
99 :
100 : {
101 0 : return poVRTBand->ReadBlock( iBlockX, iBlockY, pBuffer );
102 : }
103 :
104 : /************************************************************************/
105 : /* ==================================================================== */
106 : /* TILDataset */
107 : /* ==================================================================== */
108 : /************************************************************************/
109 :
110 : /************************************************************************/
111 : /* TILDataset() */
112 : /************************************************************************/
113 :
114 0 : TILDataset::TILDataset()
115 :
116 : {
117 0 : poVRTDS = NULL;
118 0 : }
119 :
120 : /************************************************************************/
121 : /* ~TILDataset() */
122 : /************************************************************************/
123 :
124 0 : TILDataset::~TILDataset()
125 :
126 : {
127 0 : if( poVRTDS )
128 0 : delete poVRTDS;
129 :
130 0 : while( !apoTileDS.empty() )
131 : {
132 0 : GDALClose( (GDALDatasetH) apoTileDS.back() );
133 0 : apoTileDS.pop_back();
134 : }
135 0 : }
136 :
137 : /************************************************************************/
138 : /* Identify() */
139 : /************************************************************************/
140 :
141 9020 : int TILDataset::Identify( GDALOpenInfo *poOpenInfo )
142 :
143 : {
144 9020 : if( poOpenInfo->nHeaderBytes < 200
145 : || !EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"TIL") )
146 9020 : return FALSE;
147 :
148 0 : if( strstr((const char *) poOpenInfo->pabyHeader,"numTiles") == NULL )
149 0 : return FALSE;
150 : else
151 0 : return TRUE;
152 : }
153 :
154 : /************************************************************************/
155 : /* Open() */
156 : /************************************************************************/
157 :
158 1291 : GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
159 :
160 : {
161 1291 : if( !Identify( poOpenInfo ) )
162 1291 : return NULL;
163 :
164 : /* -------------------------------------------------------------------- */
165 : /* Confirm the requested access is supported. */
166 : /* -------------------------------------------------------------------- */
167 0 : if( poOpenInfo->eAccess == GA_Update )
168 : {
169 : CPLError( CE_Failure, CPLE_NotSupported,
170 : "The TIL driver does not support update access to existing"
171 0 : " datasets.\n" );
172 0 : return NULL;
173 : }
174 :
175 0 : CPLString osDirname = CPLGetDirname(poOpenInfo->pszFilename);
176 :
177 : /* -------------------------------------------------------------------- */
178 : /* Try to find the corresponding .IMD file. */
179 : /* -------------------------------------------------------------------- */
180 : char **papszIMD = GDALLoadIMDFile( poOpenInfo->pszFilename,
181 0 : poOpenInfo->papszSiblingFiles );
182 :
183 0 : if( papszIMD == NULL )
184 : {
185 : CPLError( CE_Failure, CPLE_OpenFailed,
186 0 : "Unable to open .TIL dataset due to missing .IMD file." );
187 0 : return NULL;
188 : }
189 :
190 0 : if( CSLFetchNameValue( papszIMD, "numRows" ) == NULL
191 : || CSLFetchNameValue( papszIMD, "numColumns" ) == NULL
192 : || CSLFetchNameValue( papszIMD, "bitsPerPixel" ) == NULL )
193 : {
194 : CPLError( CE_Failure, CPLE_OpenFailed,
195 0 : "Missing a required field in the .IMD file." );
196 0 : CSLDestroy( papszIMD );
197 0 : return NULL;
198 : }
199 :
200 : /* -------------------------------------------------------------------- */
201 : /* Try to load and parse the .TIL file. */
202 : /* -------------------------------------------------------------------- */
203 0 : FILE *fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
204 :
205 0 : if( fp == NULL )
206 : {
207 0 : CSLDestroy( papszIMD );
208 0 : return NULL;
209 : }
210 :
211 0 : CPLKeywordParser oParser;
212 :
213 0 : if( !oParser.Ingest( fp ) )
214 : {
215 0 : VSIFCloseL( fp );
216 0 : CSLDestroy( papszIMD );
217 0 : return NULL;
218 : }
219 :
220 0 : VSIFCloseL( fp );
221 :
222 0 : char **papszTIL = oParser.GetAllKeywords();
223 :
224 : /* -------------------------------------------------------------------- */
225 : /* Create a corresponding GDALDataset. */
226 : /* -------------------------------------------------------------------- */
227 : TILDataset *poDS;
228 :
229 0 : poDS = new TILDataset();
230 :
231 0 : poDS->nRasterXSize = atoi(CSLFetchNameValueDef(papszIMD,"numColumns","0"));
232 0 : poDS->nRasterYSize = atoi(CSLFetchNameValueDef(papszIMD,"numRows","0"));
233 0 : if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
234 : {
235 0 : delete poDS;
236 0 : CSLDestroy( papszIMD );
237 0 : return NULL;
238 : }
239 :
240 : /* -------------------------------------------------------------------- */
241 : /* We need to open one of the images in order to establish */
242 : /* details like the band count and types. */
243 : /* -------------------------------------------------------------------- */
244 : GDALDataset *poTemplateDS;
245 0 : const char *pszFilename = CSLFetchNameValue( papszTIL, "TILE_1.filename" );
246 0 : if( pszFilename == NULL )
247 : {
248 : CPLError( CE_Failure, CPLE_AppDefined,
249 0 : "Missing TILE_1.filename in .TIL file." );
250 0 : delete poDS;
251 0 : CSLDestroy( papszIMD );
252 0 : return NULL;
253 : }
254 :
255 : // trim double quotes.
256 0 : if( pszFilename[0] == '"' )
257 0 : pszFilename++;
258 0 : if( pszFilename[strlen(pszFilename)-1] == '"' )
259 0 : ((char *) pszFilename)[strlen(pszFilename)-1] = '\0';
260 :
261 0 : CPLString osFilename = CPLFormFilename(osDirname, pszFilename, NULL);
262 0 : poTemplateDS = (GDALDataset *) GDALOpen( osFilename, GA_ReadOnly );
263 0 : if( poTemplateDS == NULL || poTemplateDS->GetRasterCount() == 0)
264 : {
265 0 : delete poDS;
266 0 : CSLDestroy( papszIMD );
267 0 : if (poTemplateDS != NULL)
268 0 : GDALClose( poTemplateDS );
269 0 : return NULL;
270 : }
271 :
272 0 : GDALRasterBand *poTemplateBand = poTemplateDS->GetRasterBand(1);
273 0 : GDALDataType eDT = poTemplateBand->GetRasterDataType();
274 0 : int nBandCount = poTemplateDS->GetRasterCount();
275 :
276 0 : poTemplateBand = NULL;
277 0 : GDALClose( poTemplateDS );
278 :
279 : /* -------------------------------------------------------------------- */
280 : /* Create and initialize the corresponding VRT dataset used to */
281 : /* manage the tiled data access. */
282 : /* -------------------------------------------------------------------- */
283 : int iBand;
284 :
285 0 : poDS->poVRTDS = new VRTDataset(poDS->nRasterXSize,poDS->nRasterYSize);
286 :
287 0 : for( iBand = 0; iBand < nBandCount; iBand++ )
288 0 : poDS->poVRTDS->AddBand( eDT, NULL );
289 :
290 : /* Don't try to write a VRT file */
291 0 : poDS->poVRTDS->SetWritable(FALSE);
292 :
293 : /* -------------------------------------------------------------------- */
294 : /* Create band information objects. */
295 : /* -------------------------------------------------------------------- */
296 0 : for( iBand = 1; iBand <= nBandCount; iBand++ )
297 : poDS->SetBand( iBand,
298 : new TILRasterBand( poDS, iBand,
299 0 : (VRTRasterBand *) poDS->poVRTDS->GetRasterBand(iBand)));
300 :
301 : /* -------------------------------------------------------------------- */
302 : /* Add tiles as sources for each band. */
303 : /* -------------------------------------------------------------------- */
304 0 : int nTileCount = atoi(CSLFetchNameValueDef(papszTIL,"numTiles","0"));
305 0 : int iTile = 0;
306 :
307 0 : for( iTile = 1; iTile <= nTileCount; iTile++ )
308 : {
309 0 : CPLString osKey;
310 :
311 0 : osKey.Printf( "TILE_%d.filename", iTile );
312 0 : pszFilename = CSLFetchNameValue( papszTIL, osKey );
313 0 : if( pszFilename == NULL )
314 : {
315 : CPLError( CE_Failure, CPLE_AppDefined,
316 0 : "Missing TILE_%d.filename in .TIL file.", iTile );
317 0 : delete poDS;
318 0 : CSLDestroy( papszIMD );
319 0 : return NULL;
320 : }
321 :
322 : // trim double quotes.
323 0 : if( pszFilename[0] == '"' )
324 0 : pszFilename++;
325 0 : if( pszFilename[strlen(pszFilename)-1] == '"' )
326 0 : ((char *) pszFilename)[strlen(pszFilename)-1] = '\0';
327 0 : osFilename = CPLFormFilename(osDirname, pszFilename, NULL);
328 :
329 0 : osKey.Printf( "TILE_%d.ULColOffset", iTile );
330 0 : int nULX = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
331 :
332 0 : osKey.Printf( "TILE_%d.ULRowOffset", iTile );
333 0 : int nULY = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
334 :
335 0 : osKey.Printf( "TILE_%d.LRColOffset", iTile );
336 0 : int nLRX = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
337 :
338 0 : osKey.Printf( "TILE_%d.LRRowOffset", iTile );
339 0 : int nLRY = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
340 :
341 : #ifdef notdef
342 : GDALDataset *poTileDS = (GDALDataset *)
343 : GDALOpen(osFilename,GA_ReadOnly);
344 : #else
345 : GDALDataset *poTileDS =
346 : new GDALProxyPoolDataset( osFilename,
347 0 : nLRX - nULX + 1, nLRY - nULY + 1 );
348 : #endif
349 0 : if( poTileDS == NULL )
350 0 : continue;
351 :
352 0 : poDS->apoTileDS.push_back( poTileDS );
353 :
354 0 : for( iBand = 1; iBand <= nBandCount; iBand++ )
355 : {
356 : #ifndef notdef
357 : ((GDALProxyPoolDataset *) poTileDS)->
358 0 : AddSrcBandDescription( eDT, nLRX - nULX + 1, 1 );
359 : #endif
360 0 : GDALRasterBand *poSrcBand = poTileDS->GetRasterBand(iBand);
361 :
362 : VRTSourcedRasterBand *poVRTBand =
363 0 : (VRTSourcedRasterBand *) poDS->poVRTDS->GetRasterBand(iBand);
364 :
365 : poVRTBand->AddSimpleSource( poSrcBand,
366 : 0, 0,
367 : nLRX - nULX + 1, nLRY - nULY + 1,
368 : nULX, nULY,
369 0 : nLRX - nULX + 1, nLRY - nULY + 1 );
370 : }
371 : }
372 :
373 : /* -------------------------------------------------------------------- */
374 : /* Set RPC and IMD metadata. */
375 : /* -------------------------------------------------------------------- */
376 : char **papszRPCMD = GDALLoadRPBFile( poOpenInfo->pszFilename,
377 0 : poOpenInfo->papszSiblingFiles );
378 :
379 0 : if( papszRPCMD != NULL )
380 : {
381 0 : poDS->SetMetadata( papszRPCMD, "RPC" );
382 0 : CSLDestroy( papszRPCMD );
383 : }
384 :
385 0 : if( papszIMD != NULL )
386 0 : poDS->SetMetadata( papszIMD, "IMD" );
387 :
388 : /* -------------------------------------------------------------------- */
389 : /* Cleanup */
390 : /* -------------------------------------------------------------------- */
391 0 : CSLDestroy( papszIMD );
392 :
393 : /* -------------------------------------------------------------------- */
394 : /* Initialize any PAM information. */
395 : /* -------------------------------------------------------------------- */
396 0 : poDS->SetDescription( poOpenInfo->pszFilename );
397 0 : poDS->TryLoadXML();
398 :
399 : /* -------------------------------------------------------------------- */
400 : /* Check for overviews. */
401 : /* -------------------------------------------------------------------- */
402 0 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
403 :
404 0 : return( poDS );
405 : }
406 :
407 : /************************************************************************/
408 : /* GDALRegister_TIL() */
409 : /************************************************************************/
410 :
411 338 : void GDALRegister_TIL()
412 :
413 : {
414 : GDALDriver *poDriver;
415 :
416 338 : if( GDALGetDriverByName( "TIL" ) == NULL )
417 : {
418 336 : poDriver = new GDALDriver();
419 :
420 336 : poDriver->SetDescription( "TIL" );
421 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
422 336 : "EarthWatch .TIL" );
423 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
424 336 : "frmt_til.html" );
425 :
426 336 : poDriver->pfnOpen = TILDataset::Open;
427 336 : poDriver->pfnIdentify = TILDataset::Identify;
428 :
429 336 : GetGDALDriverManager()->RegisterDriver( poDriver );
430 : }
431 338 : }
432 :
433 :
|