1 : /******************************************************************************
2 : * $Id: aigdataset.cpp 19496 2010-04-22 15:39:29Z warmerdam $
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 19496 2010-04-22 15:39:29Z warmerdam $");
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 7 : {
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 : CPLErr AIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
146 5898 : 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 7 : 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 7 : }
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 : || EQUAL(papszCoverFiles[i],"..") )
358 0 : continue;
359 :
360 : papszFileList =
361 : CSLAddString( papszFileList,
362 : CPLFormFilename( GetDescription(),
363 : 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 0 : 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 11341 : 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 11341 : CPLString osCoverName;
519 :
520 11341 : osCoverName = poOpenInfo->pszFilename;
521 11341 : 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 11338 : else if( !poOpenInfo->bIsDirectory )
533 : {
534 11292 : return NULL;
535 : }
536 :
537 : /* -------------------------------------------------------------------- */
538 : /* Verify that a few of the "standard" files are available. */
539 : /* -------------------------------------------------------------------- */
540 : VSIStatBufL sStatBuf;
541 49 : CPLString osTestName;
542 :
543 49 : osTestName.Printf( "%s/hdr.adf", osCoverName.c_str() );
544 49 : if( VSIStatL( osTestName, &sStatBuf ) != 0 )
545 :
546 : {
547 44 : osTestName.Printf( "%s/HDR.ADF", osCoverName.c_str() );
548 44 : if( VSIStatL( osTestName, &sStatBuf ) != 0 )
549 42 : return NULL;
550 : }
551 :
552 : /* -------------------------------------------------------------------- */
553 : /* Confirm we have at least one raster data file. These can be */
554 : /* sparse so we don't require particular ones to exists but if */
555 : /* there are none this is likely not a grid. */
556 : /* -------------------------------------------------------------------- */
557 7 : char **papszFileList = VSIReadDir( osCoverName );
558 : int iFile;
559 7 : int bGotOne = FALSE;
560 :
561 49 : for( iFile = 0;
562 : papszFileList != NULL && papszFileList[iFile] != NULL && !bGotOne;
563 : iFile++ )
564 : {
565 42 : if( strlen(papszFileList[iFile]) != 11 )
566 35 : continue;
567 :
568 : // looking for something like w001001.adf or z001013.adf
569 7 : if( papszFileList[iFile][0] != 'w'
570 : && papszFileList[iFile][0] != 'W'
571 : && papszFileList[iFile][0] != 'z'
572 : && papszFileList[iFile][0] != 'Z' )
573 0 : continue;
574 :
575 7 : if( strncmp(papszFileList[iFile] + 1, "0010", 4) != 0 )
576 0 : continue;
577 :
578 7 : if( !EQUAL(papszFileList[iFile] + 7, ".adf") )
579 0 : continue;
580 :
581 7 : bGotOne = TRUE;
582 : }
583 7 : CSLDestroy( papszFileList );
584 :
585 7 : if( !bGotOne )
586 0 : return NULL;
587 :
588 : /* -------------------------------------------------------------------- */
589 : /* Open the file. */
590 : /* -------------------------------------------------------------------- */
591 7 : psInfo = AIGOpen( osCoverName.c_str(), "r" );
592 :
593 7 : if( psInfo == NULL )
594 : {
595 0 : CPLErrorReset();
596 0 : return NULL;
597 : }
598 :
599 : /* -------------------------------------------------------------------- */
600 : /* Confirm the requested access is supported. */
601 : /* -------------------------------------------------------------------- */
602 7 : if( poOpenInfo->eAccess == GA_Update )
603 : {
604 0 : AIGClose(psInfo);
605 : CPLError( CE_Failure, CPLE_NotSupported,
606 : "The AIG driver does not support update access to existing"
607 0 : " datasets.\n" );
608 0 : return NULL;
609 : }
610 : /* -------------------------------------------------------------------- */
611 : /* Create a corresponding GDALDataset. */
612 : /* -------------------------------------------------------------------- */
613 : AIGDataset *poDS;
614 :
615 7 : poDS = new AIGDataset();
616 :
617 7 : poDS->psInfo = psInfo;
618 :
619 : /* -------------------------------------------------------------------- */
620 : /* Try to read a color table (.clr). It seems it is legal to */
621 : /* have more than one so we just use the first one found. */
622 : /* -------------------------------------------------------------------- */
623 14 : char **papszFiles = CPLReadDir( psInfo->pszCoverName );
624 7 : CPLString osClrFilename;
625 7 : CPLString osCleanPath = CPLCleanTrailingSlash( psInfo->pszCoverName );
626 :
627 : // first check for any .clr in coverage dir.
628 54 : for( iFile = 0; papszFiles != NULL && papszFiles[iFile] != NULL; iFile++ )
629 : {
630 50 : if( !EQUAL(CPLGetExtension(papszFiles[iFile]),"clr") && !EQUAL(CPLGetExtension(papszFiles[iFile]),"CLR"))
631 47 : continue;
632 :
633 : osClrFilename = CPLFormFilename( psInfo->pszCoverName,
634 3 : papszFiles[iFile], NULL );
635 3 : break;
636 : }
637 :
638 7 : CSLDestroy( papszFiles );
639 :
640 : // Look in parent if we don't find a .clr in the coverage dir.
641 7 : if( strlen(osClrFilename) == 0 )
642 : {
643 : osTestName.Printf( "%s/../%s.clr",
644 : psInfo->pszCoverName,
645 4 : CPLGetFilename( osCleanPath ) );
646 :
647 4 : if( VSIStatL( osTestName, &sStatBuf ) != 0 )
648 :
649 : {
650 : osTestName.Printf( "%s/../%s.CLR",
651 : psInfo->pszCoverName,
652 4 : CPLGetFilename( osCleanPath ) );
653 :
654 4 : if( !VSIStatL( osTestName, &sStatBuf ) )
655 2 : osClrFilename = osTestName;
656 : }
657 : else
658 0 : osClrFilename = osTestName;
659 : }
660 :
661 :
662 7 : if( strlen(osClrFilename) > 0 )
663 5 : poDS->TranslateColorTable( osClrFilename );
664 :
665 : /* -------------------------------------------------------------------- */
666 : /* Establish raster info. */
667 : /* -------------------------------------------------------------------- */
668 7 : poDS->nRasterXSize = psInfo->nPixels;
669 7 : poDS->nRasterYSize = psInfo->nLines;
670 7 : poDS->nBands = 1;
671 :
672 : /* -------------------------------------------------------------------- */
673 : /* Create band information objects. */
674 : /* -------------------------------------------------------------------- */
675 7 : poDS->SetBand( 1, new AIGRasterBand( poDS, 1 ) );
676 :
677 : /* -------------------------------------------------------------------- */
678 : /* Try to read projection file. */
679 : /* -------------------------------------------------------------------- */
680 : const char *pszPrjFilename;
681 :
682 7 : pszPrjFilename = CPLFormCIFilename( psInfo->pszCoverName, "prj", "adf" );
683 7 : if( VSIStatL( pszPrjFilename, &sStatBuf ) == 0 )
684 : {
685 5 : OGRSpatialReference oSRS;
686 :
687 5 : poDS->papszPrj = CSLLoad( pszPrjFilename );
688 :
689 5 : if( oSRS.importFromESRI( poDS->papszPrj ) == OGRERR_NONE )
690 : {
691 : // If geographic values are in seconds, we must transform.
692 : // Is there a code for minutes too?
693 5 : if( oSRS.IsGeographic()
694 : && EQUAL(OSR_GDS( poDS->papszPrj, "Units", ""), "DS") )
695 : {
696 0 : psInfo->dfLLX /= 3600.0;
697 0 : psInfo->dfURY /= 3600.0;
698 0 : psInfo->dfCellSizeX /= 3600.0;
699 0 : psInfo->dfCellSizeY /= 3600.0;
700 : }
701 :
702 5 : CPLFree( poDS->pszProjection );
703 5 : oSRS.exportToWkt( &(poDS->pszProjection) );
704 5 : }
705 : }
706 :
707 : /* -------------------------------------------------------------------- */
708 : /* Initialize any PAM information. */
709 : /* -------------------------------------------------------------------- */
710 7 : poDS->SetDescription( psInfo->pszCoverName );
711 7 : poDS->TryLoadXML();
712 :
713 : /* -------------------------------------------------------------------- */
714 : /* Open overviews. */
715 : /* -------------------------------------------------------------------- */
716 7 : poDS->oOvManager.Initialize( poDS, psInfo->pszCoverName );
717 :
718 7 : return( poDS );
719 : }
720 :
721 : /************************************************************************/
722 : /* GetGeoTransform() */
723 : /************************************************************************/
724 :
725 1 : CPLErr AIGDataset::GetGeoTransform( double * padfTransform )
726 :
727 : {
728 1 : padfTransform[0] = psInfo->dfLLX;
729 1 : padfTransform[1] = psInfo->dfCellSizeX;
730 1 : padfTransform[2] = 0;
731 :
732 1 : padfTransform[3] = psInfo->dfURY;
733 1 : padfTransform[4] = 0;
734 1 : padfTransform[5] = -psInfo->dfCellSizeY;
735 :
736 1 : return( CE_None );
737 : }
738 :
739 : /************************************************************************/
740 : /* GetProjectionRef() */
741 : /************************************************************************/
742 :
743 1 : const char *AIGDataset::GetProjectionRef()
744 :
745 : {
746 1 : return pszProjection;
747 : }
748 :
749 : /************************************************************************/
750 : /* TranslateColorTable() */
751 : /************************************************************************/
752 :
753 5 : void AIGDataset::TranslateColorTable( const char *pszClrFilename )
754 :
755 : {
756 : int iLine;
757 : char **papszClrLines;
758 :
759 5 : papszClrLines = CSLLoad( pszClrFilename );
760 5 : if( papszClrLines == NULL )
761 0 : return;
762 :
763 5 : poCT = new GDALColorTable();
764 :
765 1295 : for( iLine = 0; papszClrLines[iLine] != NULL; iLine++ )
766 : {
767 1290 : char **papszTokens = CSLTokenizeString( papszClrLines[iLine] );
768 :
769 1290 : if( CSLCount(papszTokens) >= 4 && papszTokens[0][0] != '#' )
770 : {
771 : int nIndex;
772 : GDALColorEntry sEntry;
773 :
774 1280 : nIndex = atoi(papszTokens[0]);
775 1280 : sEntry.c1 = (short) atoi(papszTokens[1]);
776 1280 : sEntry.c2 = (short) atoi(papszTokens[2]);
777 1280 : sEntry.c3 = (short) atoi(papszTokens[3]);
778 1280 : sEntry.c4 = 255;
779 :
780 1280 : if( (nIndex < 0 || nIndex > 33000)
781 : || (sEntry.c1 < 0 || sEntry.c1 > 255)
782 : || (sEntry.c2 < 0 || sEntry.c2 > 255)
783 : || (sEntry.c3 < 0 || sEntry.c3 > 255) )
784 : {
785 0 : CSLDestroy( papszTokens );
786 : CPLError( CE_Failure, CPLE_AppDefined,
787 0 : "Color table entry appears to be corrupt, skipping the rest. " );
788 0 : break;
789 : }
790 :
791 1280 : poCT->SetColorEntry( nIndex, &sEntry );
792 : }
793 :
794 1290 : CSLDestroy( papszTokens );
795 : }
796 :
797 5 : CSLDestroy( papszClrLines );
798 : }
799 :
800 : /************************************************************************/
801 : /* OSR_GDS() */
802 : /************************************************************************/
803 :
804 : static CPLString OSR_GDS( char **papszNV, const char * pszField,
805 0 : const char *pszDefaultValue )
806 :
807 : {
808 : int iLine;
809 :
810 0 : if( papszNV == NULL || papszNV[0] == NULL )
811 0 : return pszDefaultValue;
812 :
813 0 : for( iLine = 0;
814 : papszNV[iLine] != NULL &&
815 : !EQUALN(papszNV[iLine],pszField,strlen(pszField));
816 : iLine++ ) {}
817 :
818 0 : if( papszNV[iLine] == NULL )
819 0 : return pszDefaultValue;
820 : else
821 : {
822 0 : CPLString osResult;
823 : char **papszTokens;
824 :
825 0 : papszTokens = CSLTokenizeString(papszNV[iLine]);
826 :
827 0 : if( CSLCount(papszTokens) > 1 )
828 0 : osResult = papszTokens[1];
829 : else
830 0 : osResult = pszDefaultValue;
831 :
832 0 : CSLDestroy( papszTokens );
833 0 : return osResult;
834 : }
835 : }
836 :
837 : /************************************************************************/
838 : /* AIGRename() */
839 : /* */
840 : /* Custom renamer for AIG dataset. */
841 : /************************************************************************/
842 :
843 0 : static CPLErr AIGRename( const char *pszNewName, const char *pszOldName )
844 :
845 : {
846 : /* -------------------------------------------------------------------- */
847 : /* Make sure we are talking about paths to the coverage */
848 : /* directory. */
849 : /* -------------------------------------------------------------------- */
850 0 : CPLString osOldPath, osNewPath;
851 :
852 0 : if( strlen(CPLGetExtension(pszNewName)) > 0 )
853 0 : osNewPath = CPLGetPath(pszNewName);
854 : else
855 0 : osNewPath = pszNewName;
856 :
857 0 : if( strlen(CPLGetExtension(pszOldName)) > 0 )
858 0 : osOldPath = CPLGetPath(pszOldName);
859 : else
860 0 : osOldPath = pszOldName;
861 :
862 : /* -------------------------------------------------------------------- */
863 : /* Get file list. */
864 : /* -------------------------------------------------------------------- */
865 :
866 0 : GDALDatasetH hDS = GDALOpen( osOldPath, GA_ReadOnly );
867 0 : if( hDS == NULL )
868 0 : return CE_Failure;
869 :
870 0 : char **papszFileList = GDALGetFileList( hDS );
871 0 : GDALClose( hDS );
872 :
873 0 : if( papszFileList == NULL )
874 0 : return CE_Failure;
875 :
876 : /* -------------------------------------------------------------------- */
877 : /* Work out the corresponding new names. */
878 : /* -------------------------------------------------------------------- */
879 0 : char **papszNewFileList = NULL;
880 : int i;
881 :
882 0 : for( i = 0; papszFileList[i] != NULL; i++ )
883 : {
884 0 : CPLString osNewFilename;
885 :
886 0 : if( !EQUALN(papszFileList[i],osOldPath,strlen(osOldPath)) )
887 : {
888 0 : CPLAssert( FALSE );
889 0 : return CE_Failure;
890 : }
891 :
892 0 : osNewFilename = osNewPath + (papszFileList[i] + strlen(osOldPath));
893 :
894 0 : papszNewFileList = CSLAddString( papszNewFileList, osNewFilename );
895 : }
896 :
897 : /* -------------------------------------------------------------------- */
898 : /* Try renaming the directory. */
899 : /* -------------------------------------------------------------------- */
900 0 : if( VSIRename( osNewPath, osOldPath ) != 0 )
901 : {
902 0 : if( VSIMkdir( osNewPath, 0777 ) != 0 )
903 : {
904 : CPLError( CE_Failure, CPLE_AppDefined,
905 : "Unable to create directory %s:\n%s",
906 : osNewPath.c_str(),
907 0 : VSIStrerror(errno) );
908 0 : return CE_Failure;
909 : }
910 : }
911 :
912 : /* -------------------------------------------------------------------- */
913 : /* Copy/rename any remaining files. */
914 : /* -------------------------------------------------------------------- */
915 : VSIStatBufL sStatBuf;
916 :
917 0 : for( i = 0; papszFileList[i] != NULL; i++ )
918 : {
919 0 : if( VSIStatL( papszFileList[i], &sStatBuf ) == 0
920 : && VSI_ISREG( sStatBuf.st_mode ) )
921 : {
922 0 : if( CPLMoveFile( papszNewFileList[i], papszFileList[i] ) != 0 )
923 : {
924 : CPLError( CE_Failure, CPLE_AppDefined,
925 : "Unable to move %s to %s:\n%s",
926 : papszFileList[i],
927 : papszNewFileList[i],
928 0 : VSIStrerror(errno) );
929 0 : return CE_Failure;
930 : }
931 : }
932 : }
933 :
934 0 : if( VSIStatL( osOldPath, &sStatBuf ) == 0 )
935 0 : CPLUnlinkTree( osOldPath );
936 :
937 0 : return CE_None;
938 : }
939 :
940 : /************************************************************************/
941 : /* AIGDelete() */
942 : /* */
943 : /* Custom dataset deleter for AIG dataset. */
944 : /************************************************************************/
945 :
946 0 : static CPLErr AIGDelete( const char *pszDatasetname )
947 :
948 : {
949 : /* -------------------------------------------------------------------- */
950 : /* Get file list. */
951 : /* -------------------------------------------------------------------- */
952 0 : GDALDatasetH hDS = GDALOpen( pszDatasetname, GA_ReadOnly );
953 0 : if( hDS == NULL )
954 0 : return CE_Failure;
955 :
956 0 : char **papszFileList = GDALGetFileList( hDS );
957 0 : GDALClose( hDS );
958 :
959 0 : if( papszFileList == NULL )
960 0 : return CE_Failure;
961 :
962 : /* -------------------------------------------------------------------- */
963 : /* Delete all regular files. */
964 : /* -------------------------------------------------------------------- */
965 : int i;
966 0 : for( i = 0; papszFileList[i] != NULL; i++ )
967 : {
968 : VSIStatBufL sStatBuf;
969 0 : if( VSIStatL( papszFileList[i], &sStatBuf ) == 0
970 : && VSI_ISREG( sStatBuf.st_mode ) )
971 : {
972 0 : if( VSIUnlink( papszFileList[i] ) != 0 )
973 : {
974 : CPLError( CE_Failure, CPLE_AppDefined,
975 : "Unable to delete '%s':\n%s",
976 0 : papszFileList[i], VSIStrerror( errno ) );
977 0 : return CE_Failure;
978 : }
979 : }
980 : }
981 :
982 : /* -------------------------------------------------------------------- */
983 : /* Delete directories. */
984 : /* -------------------------------------------------------------------- */
985 0 : for( i = 0; papszFileList[i] != NULL; i++ )
986 : {
987 : VSIStatBufL sStatBuf;
988 0 : if( VSIStatL( papszFileList[i], &sStatBuf ) == 0
989 : && VSI_ISDIR( sStatBuf.st_mode ) )
990 : {
991 0 : if( CPLUnlinkTree( papszFileList[i] ) != 0 )
992 0 : return CE_Failure;
993 : }
994 : }
995 :
996 0 : return CE_None;
997 : }
998 :
999 : /************************************************************************/
1000 : /* GDALRegister_AIG() */
1001 : /************************************************************************/
1002 :
1003 409 : void GDALRegister_AIGrid()
1004 :
1005 : {
1006 : GDALDriver *poDriver;
1007 :
1008 409 : if( GDALGetDriverByName( "AIG" ) == NULL )
1009 : {
1010 392 : poDriver = new GDALDriver();
1011 :
1012 392 : poDriver->SetDescription( "AIG" );
1013 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
1014 392 : "Arc/Info Binary Grid" );
1015 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
1016 392 : "frmt_various.html#AIG" );
1017 :
1018 392 : poDriver->pfnOpen = AIGDataset::Open;
1019 :
1020 392 : poDriver->pfnRename = AIGRename;
1021 392 : poDriver->pfnDelete = AIGDelete;
1022 :
1023 392 : GetGDALDriverManager()->RegisterDriver( poDriver );
1024 : }
1025 409 : }
|