1 : /******************************************************************************
2 : * $Id: aigdataset.cpp 17664 2009-09-21 21:16:45Z rouault $
3 : *
4 : * Project: Arc/Info Binary Grid Driver
5 : * Purpose: Implements GDAL interface to underlying library.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, 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 "cpl_string.h"
32 : #include "ogr_spatialref.h"
33 : #include "gdal_rat.h"
34 : #include "aigrid.h"
35 : #include "avc.h"
36 :
37 : CPL_CVSID("$Id: aigdataset.cpp 17664 2009-09-21 21:16:45Z rouault $");
38 :
39 : CPL_C_START
40 : void GDALRegister_AIGrid(void);
41 : CPL_C_END
42 :
43 : static CPLString OSR_GDS( char **papszNV, const char * pszField,
44 : const char *pszDefaultValue );
45 :
46 :
47 : /************************************************************************/
48 : /* ==================================================================== */
49 : /* AIGDataset */
50 : /* ==================================================================== */
51 : /************************************************************************/
52 :
53 : class AIGRasterBand;
54 :
55 : class CPL_DLL AIGDataset : public GDALPamDataset
56 : {
57 : friend class AIGRasterBand;
58 :
59 : AIGInfo_t *psInfo;
60 :
61 : char **papszPrj;
62 : char *pszProjection;
63 :
64 : GDALColorTable *poCT;
65 : int bHasReadRat;
66 :
67 : void TranslateColorTable( const char * );
68 :
69 : void ReadRAT();
70 : GDALRasterAttributeTable *poRAT;
71 :
72 : public:
73 : AIGDataset();
74 : ~AIGDataset();
75 :
76 : static GDALDataset *Open( GDALOpenInfo * );
77 :
78 : virtual CPLErr GetGeoTransform( double * );
79 : virtual const char *GetProjectionRef(void);
80 : virtual char **GetFileList(void);
81 : };
82 :
83 : /************************************************************************/
84 : /* ==================================================================== */
85 : /* AIGRasterBand */
86 : /* ==================================================================== */
87 : /************************************************************************/
88 :
89 : class AIGRasterBand : public GDALPamRasterBand
90 :
91 14 : {
92 : friend class AIGDataset;
93 :
94 : public:
95 :
96 : AIGRasterBand( AIGDataset *, int );
97 :
98 : virtual CPLErr IReadBlock( int, int, void * );
99 : virtual double GetMinimum( int *pbSuccess );
100 : virtual double GetMaximum( int *pbSuccess );
101 : virtual double GetNoDataValue( int *pbSuccess );
102 :
103 : virtual GDALColorInterp GetColorInterpretation();
104 : virtual GDALColorTable *GetColorTable();
105 : virtual const GDALRasterAttributeTable *GetDefaultRAT();
106 : };
107 :
108 : /************************************************************************/
109 : /* AIGRasterBand() */
110 : /************************************************************************/
111 :
112 7 : AIGRasterBand::AIGRasterBand( AIGDataset *poDS, int nBand )
113 :
114 : {
115 7 : this->poDS = poDS;
116 7 : this->nBand = nBand;
117 :
118 7 : nBlockXSize = poDS->psInfo->nBlockXSize;
119 7 : nBlockYSize = poDS->psInfo->nBlockYSize;
120 :
121 12 : if( poDS->psInfo->nCellType == AIG_CELLTYPE_INT
122 : && poDS->psInfo->dfMin >= 0.0 && poDS->psInfo->dfMax <= 254.0 )
123 : {
124 5 : eDataType = GDT_Byte;
125 : }
126 4 : else if( poDS->psInfo->nCellType == AIG_CELLTYPE_INT
127 : && poDS->psInfo->dfMin >= -32767 && poDS->psInfo->dfMax <= 32767 )
128 : {
129 2 : eDataType = GDT_Int16;
130 : }
131 0 : else if( poDS->psInfo->nCellType == AIG_CELLTYPE_INT )
132 : {
133 0 : eDataType = GDT_Int32;
134 : }
135 : else
136 : {
137 0 : eDataType = GDT_Float32;
138 : }
139 7 : }
140 :
141 : /************************************************************************/
142 : /* IReadBlock() */
143 : /************************************************************************/
144 :
145 5898 : CPLErr AIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
146 : void * pImage )
147 :
148 : {
149 5898 : AIGDataset *poODS = (AIGDataset *) poDS;
150 : GInt32 *panGridRaster;
151 : int i;
152 :
153 5898 : if( poODS->psInfo->nCellType == AIG_CELLTYPE_INT )
154 : {
155 5898 : panGridRaster = (GInt32 *) VSIMalloc3(4,nBlockXSize,nBlockYSize);
156 5898 : if( panGridRaster == NULL ||
157 : AIGReadTile( poODS->psInfo, nBlockXOff, nBlockYOff, panGridRaster )
158 : != CE_None )
159 : {
160 0 : CPLFree( panGridRaster );
161 0 : return CE_Failure;
162 : }
163 :
164 5898 : if( eDataType == GDT_Byte )
165 : {
166 2050 : for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
167 : {
168 2048 : if( panGridRaster[i] == ESRI_GRID_NO_DATA )
169 2042 : ((GByte *) pImage)[i] = 255;
170 : else
171 6 : ((GByte *) pImage)[i] = (GByte) panGridRaster[i];
172 : }
173 : }
174 5896 : else if( eDataType == GDT_Int16 )
175 : {
176 6043400 : for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
177 : {
178 6037504 : if( panGridRaster[i] == ESRI_GRID_NO_DATA )
179 4967529 : ((GInt16 *) pImage)[i] = -32768;
180 : else
181 1069975 : ((GInt16 *) pImage)[i] = (GInt16) panGridRaster[i];
182 : }
183 : }
184 : else
185 : {
186 0 : for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
187 0 : ((GInt32 *) pImage)[i] = panGridRaster[i];
188 : }
189 :
190 5898 : CPLFree( panGridRaster );
191 :
192 5898 : return CE_None;
193 : }
194 : else
195 : {
196 : return AIGReadFloatTile( poODS->psInfo, nBlockXOff, nBlockYOff,
197 0 : (float *) pImage );
198 : }
199 : }
200 :
201 : /************************************************************************/
202 : /* GetDefaultRAT() */
203 : /************************************************************************/
204 :
205 1 : const GDALRasterAttributeTable *AIGRasterBand::GetDefaultRAT()
206 :
207 : {
208 1 : AIGDataset *poODS = (AIGDataset *) poDS;
209 :
210 : /* -------------------------------------------------------------------- */
211 : /* Read info raster attribute table, if present. */
212 : /* -------------------------------------------------------------------- */
213 1 : if (!poODS->bHasReadRat)
214 : {
215 1 : poODS->ReadRAT();
216 1 : poODS->bHasReadRat = TRUE;
217 : }
218 :
219 1 : return poODS->poRAT;
220 : }
221 :
222 : /************************************************************************/
223 : /* GetMinimum() */
224 : /************************************************************************/
225 :
226 1 : double AIGRasterBand::GetMinimum( int *pbSuccess )
227 :
228 : {
229 1 : AIGDataset *poODS = (AIGDataset *) poDS;
230 :
231 1 : if( pbSuccess != NULL )
232 1 : *pbSuccess = TRUE;
233 :
234 1 : return poODS->psInfo->dfMin;
235 : }
236 :
237 : /************************************************************************/
238 : /* GetMaximum() */
239 : /************************************************************************/
240 :
241 1 : double AIGRasterBand::GetMaximum( int *pbSuccess )
242 :
243 : {
244 1 : AIGDataset *poODS = (AIGDataset *) poDS;
245 :
246 1 : if( pbSuccess != NULL )
247 1 : *pbSuccess = TRUE;
248 :
249 1 : return poODS->psInfo->dfMax;
250 : }
251 :
252 : /************************************************************************/
253 : /* GetNoDataValue() */
254 : /************************************************************************/
255 :
256 3 : double AIGRasterBand::GetNoDataValue( int *pbSuccess )
257 :
258 : {
259 3 : if( pbSuccess != NULL )
260 3 : *pbSuccess = TRUE;
261 :
262 3 : if( eDataType == GDT_Float32 )
263 0 : return ESRI_GRID_FLOAT_NO_DATA;
264 3 : else if( eDataType == GDT_Int16 )
265 0 : return -32768;
266 3 : else if( eDataType == GDT_Byte )
267 3 : return 255;
268 : else
269 0 : return ESRI_GRID_NO_DATA;
270 : }
271 :
272 : /************************************************************************/
273 : /* GetColorInterpretation() */
274 : /************************************************************************/
275 :
276 0 : GDALColorInterp AIGRasterBand::GetColorInterpretation()
277 :
278 : {
279 0 : AIGDataset *poODS = (AIGDataset *) poDS;
280 :
281 0 : if( poODS->poCT != NULL )
282 0 : return GCI_PaletteIndex;
283 : else
284 0 : return GCI_Undefined;
285 : }
286 :
287 : /************************************************************************/
288 : /* GetColorTable() */
289 : /************************************************************************/
290 :
291 2 : GDALColorTable *AIGRasterBand::GetColorTable()
292 :
293 : {
294 2 : AIGDataset *poODS = (AIGDataset *) poDS;
295 :
296 2 : return poODS->poCT;
297 : }
298 :
299 : /************************************************************************/
300 : /* ==================================================================== */
301 : /* AIGDataset */
302 : /* ==================================================================== */
303 : /************************************************************************/
304 :
305 :
306 : /************************************************************************/
307 : /* AIGDataset() */
308 : /************************************************************************/
309 :
310 7 : AIGDataset::AIGDataset()
311 :
312 : {
313 7 : psInfo = NULL;
314 7 : papszPrj = NULL;
315 7 : pszProjection = CPLStrdup("");
316 7 : poCT = NULL;
317 7 : poRAT = NULL;
318 7 : bHasReadRat = FALSE;
319 7 : }
320 :
321 : /************************************************************************/
322 : /* ~AIGDataset() */
323 : /************************************************************************/
324 :
325 14 : AIGDataset::~AIGDataset()
326 :
327 : {
328 7 : FlushCache();
329 7 : CPLFree( pszProjection );
330 7 : CSLDestroy( papszPrj );
331 7 : if( psInfo != NULL )
332 7 : AIGClose( psInfo );
333 :
334 7 : if( poCT != NULL )
335 5 : delete poCT;
336 :
337 7 : if( poRAT != NULL )
338 1 : delete poRAT;
339 14 : }
340 :
341 : /************************************************************************/
342 : /* GetFileList() */
343 : /************************************************************************/
344 :
345 0 : char **AIGDataset::GetFileList()
346 :
347 : {
348 0 : char **papszFileList = GDALPamDataset::GetFileList();
349 :
350 : // Add in all files in the cover directory.
351 0 : char **papszCoverFiles = VSIReadDir( GetDescription() );
352 : int i;
353 :
354 0 : for( i = 0; papszCoverFiles != NULL && papszCoverFiles[i] != NULL; i++ )
355 : {
356 0 : if( EQUAL(papszCoverFiles[i],".")
357 0 : || EQUAL(papszCoverFiles[i],"..") )
358 0 : continue;
359 :
360 : papszFileList =
361 : CSLAddString( papszFileList,
362 0 : CPLFormFilename( GetDescription(),
363 0 : papszCoverFiles[i],
364 0 : NULL ) );
365 : }
366 0 : CSLDestroy(papszCoverFiles);
367 :
368 0 : return papszFileList;
369 : }
370 :
371 : /************************************************************************/
372 : /* ReadRAT() */
373 : /************************************************************************/
374 :
375 1 : void AIGDataset::ReadRAT()
376 :
377 : {
378 : #ifndef OGR_ENABLED
379 : #else
380 : /* -------------------------------------------------------------------- */
381 : /* Check if we have an associated info directory. If not */
382 : /* return quietly. */
383 : /* -------------------------------------------------------------------- */
384 1 : CPLString osInfoPath, osTableName;
385 : VSIStatBufL sStatBuf;
386 :
387 1 : osInfoPath = psInfo->pszCoverName;
388 1 : osInfoPath += "/../info";
389 :
390 1 : if( VSIStatL( osInfoPath, &sStatBuf ) != 0 )
391 : {
392 : CPLDebug( "AIG", "No associated info directory at: %s, skip RAT.",
393 0 : osInfoPath.c_str() );
394 : return;
395 : }
396 :
397 1 : osInfoPath += "/";
398 :
399 : /* -------------------------------------------------------------------- */
400 : /* Attempt to open the VAT table associated with this coverage. */
401 : /* -------------------------------------------------------------------- */
402 1 : osTableName = CPLGetFilename(psInfo->pszCoverName);
403 1 : osTableName += ".VAT";
404 :
405 : AVCBinFile *psFile =
406 : AVCBinReadOpen( osInfoPath, osTableName,
407 1 : AVCCoverTypeUnknown, AVCFileTABLE, NULL );
408 :
409 1 : CPLErrorReset();
410 1 : if( psFile == NULL )
411 : return;
412 :
413 1 : AVCTableDef *psTableDef = psFile->hdr.psTableDef;
414 :
415 : /* -------------------------------------------------------------------- */
416 : /* Setup columns in corresponding RAT. */
417 : /* -------------------------------------------------------------------- */
418 : int iField;
419 :
420 1 : poRAT = new GDALRasterAttributeTable();
421 :
422 3 : for( iField = 0; iField < psTableDef->numFields; iField++ )
423 : {
424 2 : AVCFieldInfo *psFDef = psTableDef->pasFieldDef + iField;
425 2 : GDALRATFieldUsage eFUsage = GFU_Generic;
426 2 : GDALRATFieldType eFType = GFT_String;
427 :
428 2 : CPLString osFName = psFDef->szName;
429 2 : osFName.Trim();
430 :
431 2 : if( EQUAL(osFName,"VALUE") )
432 1 : eFUsage = GFU_MinMax;
433 1 : else if( EQUAL(osFName,"COUNT") )
434 1 : eFUsage = GFU_PixelCount;
435 :
436 2 : if( psFDef->nType1 * 10 == AVC_FT_BININT )
437 2 : eFType = GFT_Integer;
438 0 : else if( psFDef->nType1 * 10 == AVC_FT_BINFLOAT )
439 0 : eFType = GFT_Real;
440 :
441 2 : poRAT->CreateColumn( osFName, eFType, eFUsage );
442 : }
443 :
444 : /* -------------------------------------------------------------------- */
445 : /* Process all records into RAT. */
446 : /* -------------------------------------------------------------------- */
447 : AVCField *pasFields;
448 1 : int iRecord = 0;
449 :
450 2644 : while( (pasFields = AVCBinReadNextTableRec(psFile)) != NULL )
451 : {
452 2642 : iRecord++;
453 :
454 7926 : for( iField = 0; iField < psTableDef->numFields; iField++ )
455 : {
456 5284 : switch( psTableDef->pasFieldDef[iField].nType1 * 10 )
457 : {
458 : case AVC_FT_DATE:
459 : case AVC_FT_FIXINT:
460 : case AVC_FT_CHAR:
461 : case AVC_FT_FIXNUM:
462 : {
463 : // XXX - I bet mloskot would like to see const_cast + static_cast :-)
464 0 : const char* pszTmp = (const char*)(pasFields[iField].pszStr);
465 0 : CPLString osStrValue( pszTmp );
466 0 : poRAT->SetValue( iRecord-1, iField, osStrValue.Trim() );
467 : }
468 0 : break;
469 :
470 : case AVC_FT_BININT:
471 5284 : if( psTableDef->pasFieldDef[iField].nSize == 4 )
472 : poRAT->SetValue( iRecord-1, iField,
473 5284 : pasFields[iField].nInt32 );
474 : else
475 : poRAT->SetValue( iRecord-1, iField,
476 0 : pasFields[iField].nInt16 );
477 5284 : break;
478 :
479 : case AVC_FT_BINFLOAT:
480 0 : if( psTableDef->pasFieldDef[iField].nSize == 4 )
481 : poRAT->SetValue( iRecord-1, iField,
482 0 : pasFields[iField].fFloat );
483 : else
484 : poRAT->SetValue( iRecord-1, iField,
485 0 : pasFields[iField].dDouble );
486 : break;
487 : }
488 : }
489 : }
490 :
491 : /* -------------------------------------------------------------------- */
492 : /* Cleanup */
493 : /* -------------------------------------------------------------------- */
494 :
495 1 : AVCBinReadClose( psFile );
496 :
497 : /* Workaround against #2447 and #3031, to avoid binding languages */
498 : /* not being able to open the dataset */
499 1 : CPLErrorReset();
500 :
501 : #endif /* OGR_ENABLED */
502 : }
503 :
504 : /************************************************************************/
505 : /* Open() */
506 : /************************************************************************/
507 :
508 9922 : GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
509 :
510 : {
511 : AIGInfo_t *psInfo;
512 :
513 : /* -------------------------------------------------------------------- */
514 : /* If the pass name ends in .adf assume a file within the */
515 : /* coverage has been selected, and strip that off the coverage */
516 : /* name. */
517 : /* -------------------------------------------------------------------- */
518 9922 : CPLString osCoverName;
519 :
520 9922 : osCoverName = poOpenInfo->pszFilename;
521 9922 : if( osCoverName.size() > 4
522 : && EQUAL(osCoverName.c_str()+osCoverName.size()-4,".adf") )
523 : {
524 3 : osCoverName = CPLGetDirname( poOpenInfo->pszFilename );
525 3 : if( osCoverName == "" )
526 0 : osCoverName = ".";
527 : }
528 :
529 : /* -------------------------------------------------------------------- */
530 : /* Otherwise verify we were already given a directory. */
531 : /* -------------------------------------------------------------------- */
532 9919 : else if( !poOpenInfo->bIsDirectory )
533 : {
534 9893 : return NULL;
535 : }
536 :
537 : /* -------------------------------------------------------------------- */
538 : /* Verify that a few of the "standard" files are available. */
539 : /* -------------------------------------------------------------------- */
540 : VSIStatBufL sStatBuf;
541 29 : CPLString osTestName;
542 :
543 29 : osTestName.Printf( "%s/hdr.adf", osCoverName.c_str() );
544 29 : if( VSIStatL( osTestName, &sStatBuf ) != 0 )
545 :
546 : {
547 24 : osTestName.Printf( "%s/HDR.ADF", osCoverName.c_str() );
548 24 : if( VSIStatL( osTestName, &sStatBuf ) != 0 )
549 22 : return NULL;
550 : }
551 :
552 7 : osTestName.Printf( "%s/w001001x.adf", osCoverName.c_str() );
553 7 : if( VSIStatL( osTestName, &sStatBuf ) != 0 )
554 :
555 : {
556 2 : osTestName.Printf( "%s/W001001X.ADF", osCoverName.c_str() );
557 2 : if( VSIStatL( osTestName, &sStatBuf ) != 0 )
558 0 : return NULL;
559 : }
560 :
561 7 : osTestName.Printf( "%s/w001001.adf", osCoverName.c_str() );
562 7 : if( VSIStatL( osTestName, &sStatBuf ) != 0 )
563 :
564 : {
565 2 : osTestName.Printf( "%s/W001001.ADF", osCoverName.c_str() );
566 2 : if( VSIStatL( osTestName, &sStatBuf ) != 0 )
567 0 : return NULL;
568 : }
569 :
570 : /* -------------------------------------------------------------------- */
571 : /* Open the file. */
572 : /* -------------------------------------------------------------------- */
573 7 : psInfo = AIGOpen( osCoverName.c_str(), "r" );
574 :
575 7 : if( psInfo == NULL )
576 : {
577 0 : CPLErrorReset();
578 0 : return NULL;
579 : }
580 :
581 : /* -------------------------------------------------------------------- */
582 : /* Confirm the requested access is supported. */
583 : /* -------------------------------------------------------------------- */
584 7 : if( poOpenInfo->eAccess == GA_Update )
585 : {
586 0 : AIGClose(psInfo);
587 : CPLError( CE_Failure, CPLE_NotSupported,
588 : "The AIG driver does not support update access to existing"
589 0 : " datasets.\n" );
590 0 : return NULL;
591 : }
592 : /* -------------------------------------------------------------------- */
593 : /* Create a corresponding GDALDataset. */
594 : /* -------------------------------------------------------------------- */
595 : AIGDataset *poDS;
596 :
597 7 : poDS = new AIGDataset();
598 :
599 7 : poDS->psInfo = psInfo;
600 :
601 : /* -------------------------------------------------------------------- */
602 : /* Try to read a color table (.clr). It seems it is legal to */
603 : /* have more than one so we just use the first one found. */
604 : /* -------------------------------------------------------------------- */
605 : int iFile;
606 14 : char **papszFiles = CPLReadDir( psInfo->pszCoverName );
607 7 : CPLString osClrFilename;
608 7 : CPLString osCleanPath = CPLCleanTrailingSlash( psInfo->pszCoverName );
609 :
610 : // first check for any .clr in coverage dir.
611 96 : for( iFile = 0; papszFiles != NULL && papszFiles[iFile] != NULL; iFile++ )
612 : {
613 44 : if( !EQUAL(CPLGetExtension(papszFiles[iFile]),"clr") && !EQUAL(CPLGetExtension(papszFiles[iFile]),"CLR"))
614 41 : continue;
615 :
616 : osClrFilename = CPLFormFilename( psInfo->pszCoverName,
617 3 : papszFiles[iFile], NULL );
618 3 : break;
619 : }
620 :
621 7 : CSLDestroy( papszFiles );
622 :
623 : // Look in parent if we don't find a .clr in the coverage dir.
624 7 : if( strlen(osClrFilename) == 0 )
625 : {
626 : osTestName.Printf( "%s/../%s.clr",
627 : psInfo->pszCoverName,
628 4 : CPLGetFilename( osCleanPath ) );
629 :
630 4 : if( VSIStatL( osTestName, &sStatBuf ) != 0 )
631 :
632 : {
633 : osTestName.Printf( "%s/../%s.CLR",
634 : psInfo->pszCoverName,
635 4 : CPLGetFilename( osCleanPath ) );
636 :
637 4 : if( !VSIStatL( osTestName, &sStatBuf ) )
638 2 : osClrFilename = osTestName;
639 : }
640 : else
641 0 : osClrFilename = osTestName;
642 : }
643 :
644 :
645 7 : if( strlen(osClrFilename) > 0 )
646 5 : poDS->TranslateColorTable( osClrFilename );
647 :
648 : /* -------------------------------------------------------------------- */
649 : /* Establish raster info. */
650 : /* -------------------------------------------------------------------- */
651 7 : poDS->nRasterXSize = psInfo->nPixels;
652 7 : poDS->nRasterYSize = psInfo->nLines;
653 7 : poDS->nBands = 1;
654 :
655 : /* -------------------------------------------------------------------- */
656 : /* Create band information objects. */
657 : /* -------------------------------------------------------------------- */
658 7 : poDS->SetBand( 1, new AIGRasterBand( poDS, 1 ) );
659 :
660 : /* -------------------------------------------------------------------- */
661 : /* Try to read projection file. */
662 : /* -------------------------------------------------------------------- */
663 : const char *pszPrjFilename;
664 :
665 7 : pszPrjFilename = CPLFormCIFilename( psInfo->pszCoverName, "prj", "adf" );
666 7 : if( VSIStatL( pszPrjFilename, &sStatBuf ) == 0 )
667 : {
668 5 : OGRSpatialReference oSRS;
669 :
670 5 : poDS->papszPrj = CSLLoad( pszPrjFilename );
671 :
672 5 : if( oSRS.importFromESRI( poDS->papszPrj ) == OGRERR_NONE )
673 : {
674 : // If geographic values are in seconds, we must transform.
675 : // Is there a code for minutes too?
676 5 : if( oSRS.IsGeographic()
677 : && EQUAL(OSR_GDS( poDS->papszPrj, "Units", ""), "DS") )
678 : {
679 0 : psInfo->dfLLX /= 3600.0;
680 0 : psInfo->dfURY /= 3600.0;
681 0 : psInfo->dfCellSizeX /= 3600.0;
682 0 : psInfo->dfCellSizeY /= 3600.0;
683 : }
684 :
685 5 : CPLFree( poDS->pszProjection );
686 5 : oSRS.exportToWkt( &(poDS->pszProjection) );
687 5 : }
688 : }
689 :
690 : /* -------------------------------------------------------------------- */
691 : /* Initialize any PAM information. */
692 : /* -------------------------------------------------------------------- */
693 7 : poDS->SetDescription( psInfo->pszCoverName );
694 7 : poDS->TryLoadXML();
695 :
696 : /* -------------------------------------------------------------------- */
697 : /* Open overviews. */
698 : /* -------------------------------------------------------------------- */
699 7 : poDS->oOvManager.Initialize( poDS, psInfo->pszCoverName );
700 :
701 7 : return( poDS );
702 : }
703 :
704 : /************************************************************************/
705 : /* GetGeoTransform() */
706 : /************************************************************************/
707 :
708 1 : CPLErr AIGDataset::GetGeoTransform( double * padfTransform )
709 :
710 : {
711 1 : padfTransform[0] = psInfo->dfLLX;
712 1 : padfTransform[1] = psInfo->dfCellSizeX;
713 1 : padfTransform[2] = 0;
714 :
715 1 : padfTransform[3] = psInfo->dfURY;
716 1 : padfTransform[4] = 0;
717 1 : padfTransform[5] = -psInfo->dfCellSizeY;
718 :
719 1 : return( CE_None );
720 : }
721 :
722 : /************************************************************************/
723 : /* GetProjectionRef() */
724 : /************************************************************************/
725 :
726 1 : const char *AIGDataset::GetProjectionRef()
727 :
728 : {
729 1 : return pszProjection;
730 : }
731 :
732 : /************************************************************************/
733 : /* TranslateColorTable() */
734 : /************************************************************************/
735 :
736 5 : void AIGDataset::TranslateColorTable( const char *pszClrFilename )
737 :
738 : {
739 : int iLine;
740 : char **papszClrLines;
741 :
742 5 : papszClrLines = CSLLoad( pszClrFilename );
743 5 : if( papszClrLines == NULL )
744 0 : return;
745 :
746 5 : poCT = new GDALColorTable();
747 :
748 1295 : for( iLine = 0; papszClrLines[iLine] != NULL; iLine++ )
749 : {
750 1290 : char **papszTokens = CSLTokenizeString( papszClrLines[iLine] );
751 :
752 1290 : if( CSLCount(papszTokens) >= 4 && papszTokens[0][0] != '#' )
753 : {
754 : int nIndex;
755 : GDALColorEntry sEntry;
756 :
757 1280 : nIndex = atoi(papszTokens[0]);
758 1280 : sEntry.c1 = (short) atoi(papszTokens[1]);
759 1280 : sEntry.c2 = (short) atoi(papszTokens[2]);
760 1280 : sEntry.c3 = (short) atoi(papszTokens[3]);
761 1280 : sEntry.c4 = 255;
762 :
763 1280 : if( (nIndex < 0 || nIndex > 33000)
764 : || (sEntry.c1 < 0 || sEntry.c1 > 255)
765 : || (sEntry.c2 < 0 || sEntry.c2 > 255)
766 : || (sEntry.c3 < 0 || sEntry.c3 > 255) )
767 : {
768 0 : CSLDestroy( papszTokens );
769 : CPLError( CE_Failure, CPLE_AppDefined,
770 0 : "Color table entry appears to be corrupt, skipping the rest. " );
771 0 : break;
772 : }
773 :
774 1280 : poCT->SetColorEntry( nIndex, &sEntry );
775 : }
776 :
777 1290 : CSLDestroy( papszTokens );
778 : }
779 :
780 5 : CSLDestroy( papszClrLines );
781 : }
782 :
783 : /************************************************************************/
784 : /* OSR_GDS() */
785 : /************************************************************************/
786 :
787 0 : static CPLString OSR_GDS( char **papszNV, const char * pszField,
788 : const char *pszDefaultValue )
789 :
790 : {
791 : int iLine;
792 :
793 0 : if( papszNV == NULL || papszNV[0] == NULL )
794 0 : return pszDefaultValue;
795 :
796 0 : for( iLine = 0;
797 0 : papszNV[iLine] != NULL &&
798 0 : !EQUALN(papszNV[iLine],pszField,strlen(pszField));
799 : iLine++ ) {}
800 :
801 0 : if( papszNV[iLine] == NULL )
802 0 : return pszDefaultValue;
803 : else
804 : {
805 0 : CPLString osResult;
806 : char **papszTokens;
807 :
808 0 : papszTokens = CSLTokenizeString(papszNV[iLine]);
809 :
810 0 : if( CSLCount(papszTokens) > 1 )
811 0 : osResult = papszTokens[1];
812 : else
813 0 : osResult = pszDefaultValue;
814 :
815 0 : CSLDestroy( papszTokens );
816 0 : return osResult;
817 : }
818 : }
819 :
820 : /************************************************************************/
821 : /* AIGRename() */
822 : /* */
823 : /* Custom renamer for AIG dataset. */
824 : /************************************************************************/
825 :
826 0 : static CPLErr AIGRename( const char *pszNewName, const char *pszOldName )
827 :
828 : {
829 : /* -------------------------------------------------------------------- */
830 : /* Make sure we are talking about paths to the coverage */
831 : /* directory. */
832 : /* -------------------------------------------------------------------- */
833 0 : CPLString osOldPath, osNewPath;
834 :
835 0 : if( strlen(CPLGetExtension(pszNewName)) > 0 )
836 0 : osNewPath = CPLGetPath(pszNewName);
837 : else
838 0 : osNewPath = pszNewName;
839 :
840 0 : if( strlen(CPLGetExtension(pszOldName)) > 0 )
841 0 : osOldPath = CPLGetPath(pszOldName);
842 : else
843 0 : osOldPath = pszOldName;
844 :
845 : /* -------------------------------------------------------------------- */
846 : /* Get file list. */
847 : /* -------------------------------------------------------------------- */
848 :
849 0 : GDALDatasetH hDS = GDALOpen( osOldPath, GA_ReadOnly );
850 0 : if( hDS == NULL )
851 0 : return CE_Failure;
852 :
853 0 : char **papszFileList = GDALGetFileList( hDS );
854 0 : GDALClose( hDS );
855 :
856 0 : if( papszFileList == NULL )
857 0 : return CE_Failure;
858 :
859 : /* -------------------------------------------------------------------- */
860 : /* Work out the corresponding new names. */
861 : /* -------------------------------------------------------------------- */
862 0 : char **papszNewFileList = NULL;
863 : int i;
864 :
865 0 : for( i = 0; papszFileList[i] != NULL; i++ )
866 : {
867 0 : CPLString osNewFilename;
868 :
869 0 : if( !EQUALN(papszFileList[i],osOldPath,strlen(osOldPath)) )
870 : {
871 : CPLAssert( FALSE );
872 0 : return CE_Failure;
873 : }
874 :
875 0 : osNewFilename = osNewPath + (papszFileList[i] + strlen(osOldPath));
876 :
877 0 : papszNewFileList = CSLAddString( papszNewFileList, osNewFilename );
878 : }
879 :
880 : /* -------------------------------------------------------------------- */
881 : /* Try renaming the directory. */
882 : /* -------------------------------------------------------------------- */
883 0 : if( VSIRename( osNewPath, osOldPath ) != 0 )
884 : {
885 0 : if( VSIMkdir( osNewPath, 0777 ) != 0 )
886 : {
887 : CPLError( CE_Failure, CPLE_AppDefined,
888 : "Unable to create directory %s:\n%s",
889 : osNewPath.c_str(),
890 0 : VSIStrerror(errno) );
891 0 : return CE_Failure;
892 : }
893 : }
894 :
895 : /* -------------------------------------------------------------------- */
896 : /* Copy/rename any remaining files. */
897 : /* -------------------------------------------------------------------- */
898 : VSIStatBufL sStatBuf;
899 :
900 0 : for( i = 0; papszFileList[i] != NULL; i++ )
901 : {
902 0 : if( VSIStatL( papszFileList[i], &sStatBuf ) == 0
903 : && VSI_ISREG( sStatBuf.st_mode ) )
904 : {
905 0 : if( CPLMoveFile( papszNewFileList[i], papszFileList[i] ) != 0 )
906 : {
907 : CPLError( CE_Failure, CPLE_AppDefined,
908 : "Unable to move %s to %s:\n%s",
909 : papszFileList[i],
910 : papszNewFileList[i],
911 0 : VSIStrerror(errno) );
912 0 : return CE_Failure;
913 : }
914 : }
915 : }
916 :
917 0 : if( VSIStatL( osOldPath, &sStatBuf ) == 0 )
918 0 : CPLUnlinkTree( osOldPath );
919 :
920 0 : return CE_None;
921 : }
922 :
923 : /************************************************************************/
924 : /* AIGDelete() */
925 : /* */
926 : /* Custom dataset deleter for AIG dataset. */
927 : /************************************************************************/
928 :
929 0 : static CPLErr AIGDelete( const char *pszDatasetname )
930 :
931 : {
932 : /* -------------------------------------------------------------------- */
933 : /* Get file list. */
934 : /* -------------------------------------------------------------------- */
935 0 : GDALDatasetH hDS = GDALOpen( pszDatasetname, GA_ReadOnly );
936 0 : if( hDS == NULL )
937 0 : return CE_Failure;
938 :
939 0 : char **papszFileList = GDALGetFileList( hDS );
940 0 : GDALClose( hDS );
941 :
942 0 : if( papszFileList == NULL )
943 0 : return CE_Failure;
944 :
945 : /* -------------------------------------------------------------------- */
946 : /* Delete all regular files. */
947 : /* -------------------------------------------------------------------- */
948 : int i;
949 0 : for( i = 0; papszFileList[i] != NULL; i++ )
950 : {
951 : VSIStatBufL sStatBuf;
952 0 : if( VSIStatL( papszFileList[i], &sStatBuf ) == 0
953 : && VSI_ISREG( sStatBuf.st_mode ) )
954 : {
955 0 : if( VSIUnlink( papszFileList[i] ) != 0 )
956 : {
957 : CPLError( CE_Failure, CPLE_AppDefined,
958 : "Unable to delete '%s':\n%s",
959 0 : papszFileList[i], VSIStrerror( errno ) );
960 0 : return CE_Failure;
961 : }
962 : }
963 : }
964 :
965 : /* -------------------------------------------------------------------- */
966 : /* Delete directories. */
967 : /* -------------------------------------------------------------------- */
968 0 : for( i = 0; papszFileList[i] != NULL; i++ )
969 : {
970 : VSIStatBufL sStatBuf;
971 0 : if( VSIStatL( papszFileList[i], &sStatBuf ) == 0
972 : && VSI_ISDIR( sStatBuf.st_mode ) )
973 : {
974 0 : if( CPLUnlinkTree( papszFileList[i] ) != 0 )
975 0 : return CE_Failure;
976 : }
977 : }
978 :
979 0 : return CE_None;
980 : }
981 :
982 : /************************************************************************/
983 : /* GDALRegister_AIG() */
984 : /************************************************************************/
985 :
986 338 : void GDALRegister_AIGrid()
987 :
988 : {
989 : GDALDriver *poDriver;
990 :
991 338 : if( GDALGetDriverByName( "AIG" ) == NULL )
992 : {
993 336 : poDriver = new GDALDriver();
994 :
995 336 : poDriver->SetDescription( "AIG" );
996 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
997 336 : "Arc/Info Binary Grid" );
998 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
999 336 : "frmt_various.html#AIG" );
1000 :
1001 336 : poDriver->pfnOpen = AIGDataset::Open;
1002 :
1003 336 : poDriver->pfnRename = AIGRename;
1004 336 : poDriver->pfnDelete = AIGDelete;
1005 :
1006 336 : GetGDALDriverManager()->RegisterDriver( poDriver );
1007 : }
1008 338 : }
|