1 : /******************************************************************************
2 : * $Id: aaigriddataset.cpp 25032 2012-10-03 00:00:02Z rcoup $
3 : *
4 : * Project: GDAL
5 : * Purpose: Implements Arc/Info ASCII Grid Format.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2001, 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 "gdal_pam.h"
31 : #include <ctype.h>
32 : #include <limits.h>
33 : #include "cpl_string.h"
34 : #include "ogr_spatialref.h"
35 :
36 : CPL_CVSID("$Id: aaigriddataset.cpp 25032 2012-10-03 00:00:02Z rcoup $");
37 :
38 : CPL_C_START
39 : void GDALRegister_AAIGrid(void);
40 : void GDALRegister_GRASSASCIIGrid(void);
41 : CPL_C_END
42 :
43 : static CPLString OSR_GDS( char **papszNV, const char * pszField,
44 : const char *pszDefaultValue );
45 :
46 : typedef enum
47 : {
48 : FORMAT_AAIG,
49 : FORMAT_GRASSASCII
50 : } GridFormat;
51 :
52 : /************************************************************************/
53 : /* ==================================================================== */
54 : /* AAIGDataset */
55 : /* ==================================================================== */
56 : /************************************************************************/
57 :
58 : class AAIGRasterBand;
59 :
60 : class CPL_DLL AAIGDataset : public GDALPamDataset
61 : {
62 : friend class AAIGRasterBand;
63 :
64 : VSILFILE *fp;
65 :
66 : char **papszPrj;
67 : CPLString osPrjFilename;
68 : char *pszProjection;
69 :
70 :
71 : unsigned char achReadBuf[256];
72 : GUIntBig nBufferOffset;
73 : int nOffsetInBuffer;
74 :
75 : char Getc();
76 : GUIntBig Tell();
77 : int Seek( GUIntBig nOffset );
78 :
79 : protected:
80 : GDALDataType eDataType;
81 : double adfGeoTransform[6];
82 : int bNoDataSet;
83 : double dfNoDataValue;
84 :
85 :
86 : virtual int ParseHeader(const char* pszHeader, const char* pszDataType);
87 :
88 : public:
89 : AAIGDataset();
90 : ~AAIGDataset();
91 :
92 : virtual char **GetFileList(void);
93 :
94 : static GDALDataset *CommonOpen( GDALOpenInfo * poOpenInfo,
95 : GridFormat eFormat );
96 :
97 : static GDALDataset *Open( GDALOpenInfo * );
98 : static int Identify( GDALOpenInfo * );
99 : static CPLErr Delete( const char *pszFilename );
100 : static CPLErr Remove( const char *pszFilename, int bRepError );
101 : static GDALDataset *CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
102 : int bStrict, char ** papszOptions,
103 : GDALProgressFunc pfnProgress, void * pProgressData );
104 :
105 : virtual CPLErr GetGeoTransform( double * );
106 : virtual const char *GetProjectionRef(void);
107 : };
108 :
109 : /************************************************************************/
110 : /* ==================================================================== */
111 : /* GRASSASCIIDataset */
112 : /* ==================================================================== */
113 : /************************************************************************/
114 :
115 : class GRASSASCIIDataset : public AAIGDataset
116 1 : {
117 : virtual int ParseHeader(const char* pszHeader, const char* pszDataType);
118 :
119 : public:
120 1 : GRASSASCIIDataset() : AAIGDataset() {}
121 :
122 : static GDALDataset *Open( GDALOpenInfo * );
123 : static int Identify( GDALOpenInfo * );
124 : };
125 :
126 : /************************************************************************/
127 : /* ==================================================================== */
128 : /* AAIGRasterBand */
129 : /* ==================================================================== */
130 : /************************************************************************/
131 :
132 : class AAIGRasterBand : public GDALPamRasterBand
133 : {
134 : friend class AAIGDataset;
135 :
136 : GUIntBig *panLineOffset;
137 :
138 : public:
139 :
140 : AAIGRasterBand( AAIGDataset *, int );
141 : virtual ~AAIGRasterBand();
142 :
143 : virtual double GetNoDataValue( int * );
144 : virtual CPLErr SetNoDataValue( double );
145 : virtual CPLErr IReadBlock( int, int, void * );
146 : };
147 :
148 : /************************************************************************/
149 : /* AAIGRasterBand() */
150 : /************************************************************************/
151 :
152 66 : AAIGRasterBand::AAIGRasterBand( AAIGDataset *poDS, int nDataStart )
153 :
154 : {
155 66 : this->poDS = poDS;
156 :
157 66 : nBand = 1;
158 66 : eDataType = poDS->eDataType;
159 :
160 66 : nBlockXSize = poDS->nRasterXSize;
161 66 : nBlockYSize = 1;
162 :
163 : panLineOffset =
164 66 : (GUIntBig *) VSICalloc( poDS->nRasterYSize, sizeof(GUIntBig) );
165 66 : if (panLineOffset == NULL)
166 : {
167 : CPLError(CE_Failure, CPLE_OutOfMemory,
168 : "AAIGRasterBand::AAIGRasterBand : Out of memory (nRasterYSize = %d)",
169 0 : poDS->nRasterYSize);
170 0 : return;
171 : }
172 66 : panLineOffset[0] = nDataStart;
173 0 : }
174 :
175 : /************************************************************************/
176 : /* ~AAIGRasterBand() */
177 : /************************************************************************/
178 :
179 66 : AAIGRasterBand::~AAIGRasterBand()
180 :
181 : {
182 66 : CPLFree( panLineOffset );
183 66 : }
184 :
185 : /************************************************************************/
186 : /* IReadBlock() */
187 : /************************************************************************/
188 :
189 745 : CPLErr AAIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
190 : void * pImage )
191 :
192 : {
193 745 : AAIGDataset *poODS = (AAIGDataset *) poDS;
194 : int iPixel;
195 :
196 745 : if( nBlockYOff < 0 || nBlockYOff > poODS->nRasterYSize - 1
197 : || nBlockXOff != 0 || panLineOffset == NULL || poODS->fp == NULL )
198 0 : return CE_Failure;
199 :
200 745 : if( panLineOffset[nBlockYOff] == 0 )
201 : {
202 : int iPrevLine;
203 :
204 6 : for( iPrevLine = 1; iPrevLine <= nBlockYOff; iPrevLine++ )
205 5 : if( panLineOffset[iPrevLine] == 0 )
206 5 : IReadBlock( nBlockXOff, iPrevLine-1, NULL );
207 : }
208 :
209 745 : if( panLineOffset[nBlockYOff] == 0 )
210 0 : return CE_Failure;
211 :
212 :
213 745 : if( poODS->Seek( panLineOffset[nBlockYOff] ) != 0 )
214 : {
215 : CPLError( CE_Failure, CPLE_FileIO,
216 : "Can't seek to offset %lu in input file to read data.",
217 0 : (long unsigned int)panLineOffset[nBlockYOff] );
218 0 : return CE_Failure;
219 : }
220 :
221 32027 : for( iPixel = 0; iPixel < poODS->nRasterXSize; )
222 : {
223 : char szToken[500];
224 : char chNext;
225 30537 : int iTokenChar = 0;
226 :
227 : /* suck up any pre-white space. */
228 37457 : do {
229 37457 : chNext = poODS->Getc();
230 : } while( isspace( (unsigned char)chNext ) );
231 :
232 151824 : while( chNext != '\0' && !isspace((unsigned char)chNext) )
233 : {
234 90750 : if( iTokenChar == sizeof(szToken)-2 )
235 : {
236 : CPLError( CE_Failure, CPLE_FileIO,
237 : "Token too long at scanline %d.",
238 0 : nBlockYOff );
239 0 : return CE_Failure;
240 : }
241 :
242 90750 : szToken[iTokenChar++] = chNext;
243 90750 : chNext = poODS->Getc();
244 : }
245 :
246 30537 : if( chNext == '\0' &&
247 : (iPixel != poODS->nRasterXSize - 1 ||
248 : nBlockYOff != poODS->nRasterYSize - 1) )
249 : {
250 : CPLError( CE_Failure, CPLE_FileIO,
251 : "File short, can't read line %d.",
252 0 : nBlockYOff );
253 0 : return CE_Failure;
254 : }
255 :
256 30537 : szToken[iTokenChar] = '\0';
257 :
258 30537 : if( pImage != NULL )
259 : {
260 30462 : if( eDataType == GDT_Float64 )
261 25 : ((double *) pImage)[iPixel] = CPLAtofM(szToken);
262 30437 : else if( eDataType == GDT_Float32 )
263 1015 : ((float *) pImage)[iPixel] = (float) CPLAtofM(szToken);
264 : else
265 29422 : ((GInt32 *) pImage)[iPixel] = (GInt32) atoi(szToken);
266 : }
267 :
268 30537 : iPixel++;
269 : }
270 :
271 745 : if( nBlockYOff < poODS->nRasterYSize - 1 )
272 706 : panLineOffset[nBlockYOff + 1] = poODS->Tell();
273 :
274 745 : return CE_None;
275 : }
276 :
277 : /************************************************************************/
278 : /* GetNoDataValue() */
279 : /************************************************************************/
280 :
281 36 : double AAIGRasterBand::GetNoDataValue( int * pbSuccess )
282 :
283 : {
284 36 : AAIGDataset *poODS = (AAIGDataset *) poDS;
285 :
286 36 : if( pbSuccess )
287 33 : *pbSuccess = poODS->bNoDataSet;
288 :
289 36 : return poODS->dfNoDataValue;
290 : }
291 :
292 :
293 : /************************************************************************/
294 : /* SetNoDataValue() */
295 : /************************************************************************/
296 :
297 0 : CPLErr AAIGRasterBand::SetNoDataValue( double dfNoData )
298 :
299 : {
300 0 : AAIGDataset *poODS = (AAIGDataset *) poDS;
301 :
302 0 : poODS->bNoDataSet = TRUE;
303 0 : poODS->dfNoDataValue = dfNoData;
304 :
305 0 : return CE_None;
306 : }
307 :
308 : /************************************************************************/
309 : /* ==================================================================== */
310 : /* AAIGDataset */
311 : /* ==================================================================== */
312 : /************************************************************************/
313 :
314 :
315 : /************************************************************************/
316 : /* AAIGDataset() */
317 : /************************************************************************/
318 :
319 66 : AAIGDataset::AAIGDataset()
320 :
321 : {
322 66 : papszPrj = NULL;
323 66 : pszProjection = CPLStrdup("");
324 66 : fp = NULL;
325 66 : eDataType = GDT_Int32;
326 66 : bNoDataSet = FALSE;
327 66 : dfNoDataValue = -9999.0;
328 :
329 66 : adfGeoTransform[0] = 0.0;
330 66 : adfGeoTransform[1] = 1.0;
331 66 : adfGeoTransform[2] = 0.0;
332 66 : adfGeoTransform[3] = 0.0;
333 66 : adfGeoTransform[4] = 0.0;
334 66 : adfGeoTransform[5] = 1.0;
335 :
336 66 : nOffsetInBuffer = 256;
337 66 : nBufferOffset = 0;
338 66 : }
339 :
340 : /************************************************************************/
341 : /* ~AAIGDataset() */
342 : /************************************************************************/
343 :
344 66 : AAIGDataset::~AAIGDataset()
345 :
346 : {
347 66 : FlushCache();
348 :
349 66 : if( fp != NULL )
350 66 : VSIFCloseL( fp );
351 :
352 66 : CPLFree( pszProjection );
353 66 : CSLDestroy( papszPrj );
354 66 : }
355 :
356 : /************************************************************************/
357 : /* Tell() */
358 : /************************************************************************/
359 :
360 706 : GUIntBig AAIGDataset::Tell()
361 :
362 : {
363 706 : return nBufferOffset + nOffsetInBuffer;
364 : }
365 :
366 : /************************************************************************/
367 : /* Seek() */
368 : /************************************************************************/
369 :
370 745 : int AAIGDataset::Seek( GUIntBig nNewOffset )
371 :
372 : {
373 745 : nOffsetInBuffer = sizeof(achReadBuf);
374 745 : return VSIFSeekL( fp, nNewOffset, SEEK_SET );
375 : }
376 :
377 : /************************************************************************/
378 : /* Getc() */
379 : /* */
380 : /* Read a single character from the input file (efficiently we */
381 : /* hope). */
382 : /************************************************************************/
383 :
384 128207 : char AAIGDataset::Getc()
385 :
386 : {
387 128207 : if( nOffsetInBuffer < (int) sizeof(achReadBuf) )
388 127262 : return achReadBuf[nOffsetInBuffer++];
389 :
390 945 : nBufferOffset = VSIFTellL( fp );
391 945 : int nRead = VSIFReadL( achReadBuf, 1, sizeof(achReadBuf), fp );
392 : unsigned int i;
393 22983 : for(i=nRead;i<sizeof(achReadBuf);i++)
394 22038 : achReadBuf[i] = '\0';
395 :
396 945 : nOffsetInBuffer = 0;
397 :
398 945 : return achReadBuf[nOffsetInBuffer++];
399 : }
400 :
401 : /************************************************************************/
402 : /* GetFileList() */
403 : /************************************************************************/
404 :
405 9 : char **AAIGDataset::GetFileList()
406 :
407 : {
408 9 : char **papszFileList = GDALPamDataset::GetFileList();
409 :
410 9 : if( papszPrj != NULL )
411 8 : papszFileList = CSLAddString( papszFileList, osPrjFilename );
412 :
413 9 : return papszFileList;
414 : }
415 :
416 : /************************************************************************/
417 : /* Identify() */
418 : /************************************************************************/
419 :
420 14270 : int AAIGDataset::Identify( GDALOpenInfo * poOpenInfo )
421 :
422 : {
423 : /* -------------------------------------------------------------------- */
424 : /* Does this look like an AI grid file? */
425 : /* -------------------------------------------------------------------- */
426 14270 : if( poOpenInfo->nHeaderBytes < 40
427 : || !( EQUALN((const char *) poOpenInfo->pabyHeader,"ncols",5) ||
428 : EQUALN((const char *) poOpenInfo->pabyHeader,"nrows",5) ||
429 : EQUALN((const char *) poOpenInfo->pabyHeader,"xllcorner",9)||
430 : EQUALN((const char *) poOpenInfo->pabyHeader,"yllcorner",9)||
431 : EQUALN((const char *) poOpenInfo->pabyHeader,"xllcenter",9)||
432 : EQUALN((const char *) poOpenInfo->pabyHeader,"yllcenter",9)||
433 : EQUALN((const char *) poOpenInfo->pabyHeader,"dx",2)||
434 : EQUALN((const char *) poOpenInfo->pabyHeader,"dy",2)||
435 : EQUALN((const char *) poOpenInfo->pabyHeader,"cellsize",8)) )
436 14205 : return FALSE;
437 :
438 65 : return TRUE;
439 : }
440 :
441 : /************************************************************************/
442 : /* Identify() */
443 : /************************************************************************/
444 :
445 14205 : int GRASSASCIIDataset::Identify( GDALOpenInfo * poOpenInfo )
446 :
447 : {
448 : /* -------------------------------------------------------------------- */
449 : /* Does this look like a GRASS ASCII grid file? */
450 : /* -------------------------------------------------------------------- */
451 14205 : if( poOpenInfo->nHeaderBytes < 40
452 : || !( EQUALN((const char *) poOpenInfo->pabyHeader,"north:",6) ||
453 : EQUALN((const char *) poOpenInfo->pabyHeader,"south:",6) ||
454 : EQUALN((const char *) poOpenInfo->pabyHeader,"east:",5)||
455 : EQUALN((const char *) poOpenInfo->pabyHeader,"west:",5)||
456 : EQUALN((const char *) poOpenInfo->pabyHeader,"rows:",5)||
457 : EQUALN((const char *) poOpenInfo->pabyHeader,"cols:",5) ) )
458 14204 : return FALSE;
459 :
460 1 : return TRUE;
461 : }
462 :
463 : /************************************************************************/
464 : /* Open() */
465 : /************************************************************************/
466 :
467 4052 : GDALDataset *AAIGDataset::Open( GDALOpenInfo * poOpenInfo )
468 : {
469 4052 : if (!Identify(poOpenInfo))
470 3987 : return NULL;
471 :
472 65 : return CommonOpen(poOpenInfo, FORMAT_AAIG);
473 : }
474 :
475 : /************************************************************************/
476 : /* ParseHeader() */
477 : /************************************************************************/
478 :
479 65 : int AAIGDataset::ParseHeader(const char* pszHeader, const char* pszDataType)
480 : {
481 : int i, j;
482 : char** papszTokens =
483 65 : CSLTokenizeString2( pszHeader, " \n\r\t" , 0 );
484 65 : int nTokens = CSLCount(papszTokens);
485 65 : double dfCellDX = 0;
486 65 : double dfCellDY = 0;
487 :
488 65 : if ( (i = CSLFindString( papszTokens, "ncols" )) < 0 ||
489 : i + 1 >= nTokens)
490 : {
491 0 : CSLDestroy( papszTokens );
492 0 : return FALSE;
493 : }
494 65 : nRasterXSize = atoi(papszTokens[i + 1]);
495 65 : if ( (i = CSLFindString( papszTokens, "nrows" )) < 0 ||
496 : i + 1 >= nTokens)
497 : {
498 0 : CSLDestroy( papszTokens );
499 0 : return FALSE;
500 : }
501 65 : nRasterYSize = atoi(papszTokens[i + 1]);
502 :
503 65 : if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
504 : {
505 0 : CSLDestroy( papszTokens );
506 0 : return FALSE;
507 : }
508 :
509 65 : if ( (i = CSLFindString( papszTokens, "cellsize" )) < 0 )
510 : {
511 : int iDX, iDY;
512 3 : if( (iDX = CSLFindString(papszTokens,"dx")) < 0
513 : || (iDY = CSLFindString(papszTokens,"dy")) < 0
514 : || iDX+1 >= nTokens
515 : || iDY+1 >= nTokens)
516 : {
517 0 : CSLDestroy( papszTokens );
518 0 : return FALSE;
519 : }
520 :
521 3 : dfCellDX = CPLAtofM( papszTokens[iDX+1] );
522 3 : dfCellDY = CPLAtofM( papszTokens[iDY+1] );
523 : }
524 : else
525 : {
526 62 : if (i + 1 >= nTokens)
527 : {
528 0 : CSLDestroy( papszTokens );
529 0 : return FALSE;
530 : }
531 62 : dfCellDX = dfCellDY = CPLAtofM( papszTokens[i + 1] );
532 : }
533 :
534 65 : if ((i = CSLFindString( papszTokens, "xllcorner" )) >= 0 &&
535 : (j = CSLFindString( papszTokens, "yllcorner" )) >= 0 &&
536 : i + 1 < nTokens && j + 1 < nTokens)
537 : {
538 65 : adfGeoTransform[0] = CPLAtofM( papszTokens[i + 1] );
539 :
540 : /* Small hack to compensate from insufficient precision in cellsize */
541 : /* parameter in datasets of http://ccafs-climate.org/data/A2a_2020s/hccpr_hadcm3 */
542 65 : if ((nRasterXSize % 360) == 0 &&
543 0 : fabs(adfGeoTransform[0] - (-180.0)) < 1e-12 &&
544 : dfCellDX == dfCellDY &&
545 : fabs(dfCellDX - (360.0 / nRasterXSize)) < 1e-9)
546 : {
547 0 : dfCellDX = dfCellDY = 360.0 / nRasterXSize;
548 : }
549 :
550 65 : adfGeoTransform[1] = dfCellDX;
551 65 : adfGeoTransform[2] = 0.0;
552 65 : adfGeoTransform[3] = CPLAtofM( papszTokens[j + 1] )
553 130 : + nRasterYSize * dfCellDY;
554 65 : adfGeoTransform[4] = 0.0;
555 65 : adfGeoTransform[5] = - dfCellDY;
556 : }
557 0 : else if ((i = CSLFindString( papszTokens, "xllcenter" )) >= 0 &&
558 : (j = CSLFindString( papszTokens, "yllcenter" )) >= 0 &&
559 : i + 1 < nTokens && j + 1 < nTokens)
560 : {
561 0 : SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );
562 :
563 0 : adfGeoTransform[0] = CPLAtofM(papszTokens[i + 1]) - 0.5 * dfCellDX;
564 0 : adfGeoTransform[1] = dfCellDX;
565 0 : adfGeoTransform[2] = 0.0;
566 0 : adfGeoTransform[3] = CPLAtofM( papszTokens[j + 1] )
567 : - 0.5 * dfCellDY
568 0 : + nRasterYSize * dfCellDY;
569 0 : adfGeoTransform[4] = 0.0;
570 0 : adfGeoTransform[5] = - dfCellDY;
571 : }
572 : else
573 : {
574 0 : adfGeoTransform[0] = 0.0;
575 0 : adfGeoTransform[1] = dfCellDX;
576 0 : adfGeoTransform[2] = 0.0;
577 0 : adfGeoTransform[3] = 0.0;
578 0 : adfGeoTransform[4] = 0.0;
579 0 : adfGeoTransform[5] = - dfCellDY;
580 : }
581 :
582 65 : if( (i = CSLFindString( papszTokens, "NODATA_value" )) >= 0 &&
583 : i + 1 < nTokens)
584 : {
585 19 : const char* pszNoData = papszTokens[i + 1];
586 :
587 19 : bNoDataSet = TRUE;
588 19 : dfNoDataValue = CPLAtofM(pszNoData);
589 19 : if( pszDataType == NULL &&
590 : (strchr( pszNoData, '.' ) != NULL ||
591 : strchr( pszNoData, ',' ) != NULL ||
592 : INT_MIN > dfNoDataValue || dfNoDataValue > INT_MAX) )
593 : {
594 1 : eDataType = GDT_Float32;
595 : }
596 19 : if( eDataType == GDT_Float32 )
597 : {
598 1 : dfNoDataValue = (double) (float) dfNoDataValue;
599 : }
600 : }
601 :
602 65 : CSLDestroy( papszTokens );
603 :
604 65 : return TRUE;
605 : }
606 :
607 : /************************************************************************/
608 : /* Open() */
609 : /************************************************************************/
610 :
611 3987 : GDALDataset *GRASSASCIIDataset::Open( GDALOpenInfo * poOpenInfo )
612 : {
613 3987 : if (!Identify(poOpenInfo))
614 3986 : return NULL;
615 :
616 1 : return CommonOpen(poOpenInfo, FORMAT_GRASSASCII);
617 : }
618 :
619 :
620 : /************************************************************************/
621 : /* ParseHeader() */
622 : /************************************************************************/
623 :
624 1 : int GRASSASCIIDataset::ParseHeader(const char* pszHeader, const char* pszDataType)
625 : {
626 : int i;
627 : char** papszTokens =
628 1 : CSLTokenizeString2( pszHeader, " \n\r\t:" , 0 );
629 1 : int nTokens = CSLCount(papszTokens);
630 1 : if ( (i = CSLFindString( papszTokens, "cols" )) < 0 ||
631 : i + 1 >= nTokens)
632 : {
633 0 : CSLDestroy( papszTokens );
634 0 : return FALSE;
635 : }
636 1 : nRasterXSize = atoi(papszTokens[i + 1]);
637 1 : if ( (i = CSLFindString( papszTokens, "rows" )) < 0 ||
638 : i + 1 >= nTokens)
639 : {
640 0 : CSLDestroy( papszTokens );
641 0 : return FALSE;
642 : }
643 1 : nRasterYSize = atoi(papszTokens[i + 1]);
644 :
645 1 : if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
646 : {
647 0 : CSLDestroy( papszTokens );
648 0 : return FALSE;
649 : }
650 :
651 1 : int iNorth = CSLFindString( papszTokens, "north" );
652 1 : int iSouth = CSLFindString( papszTokens, "south" );
653 1 : int iEast = CSLFindString( papszTokens, "east" );
654 1 : int iWest = CSLFindString( papszTokens, "west" );
655 :
656 1 : if (iNorth == -1 || iSouth == -1 || iEast == -1 || iWest == -1 ||
657 : MAX(MAX(iNorth, iSouth), MAX(iEast, iWest)) + 1 >= nTokens)
658 : {
659 0 : CSLDestroy( papszTokens );
660 0 : return FALSE;
661 : }
662 :
663 1 : double dfNorth = CPLAtofM( papszTokens[iNorth + 1] );
664 1 : double dfSouth = CPLAtofM( papszTokens[iSouth + 1] );
665 1 : double dfEast = CPLAtofM( papszTokens[iEast + 1] );
666 1 : double dfWest = CPLAtofM( papszTokens[iWest + 1] );
667 1 : double dfPixelXSize = (dfEast - dfWest) / nRasterXSize;
668 1 : double dfPixelYSize = (dfNorth - dfSouth) / nRasterYSize;
669 :
670 1 : adfGeoTransform[0] = dfWest;
671 1 : adfGeoTransform[1] = dfPixelXSize;
672 1 : adfGeoTransform[2] = 0.0;
673 1 : adfGeoTransform[3] = dfNorth;
674 1 : adfGeoTransform[4] = 0.0;
675 1 : adfGeoTransform[5] = - dfPixelYSize;
676 :
677 1 : if( (i = CSLFindString( papszTokens, "null" )) >= 0 &&
678 : i + 1 < nTokens)
679 : {
680 0 : const char* pszNoData = papszTokens[i + 1];
681 :
682 0 : bNoDataSet = TRUE;
683 0 : dfNoDataValue = CPLAtofM(pszNoData);
684 0 : if( pszDataType == NULL &&
685 : (strchr( pszNoData, '.' ) != NULL ||
686 : strchr( pszNoData, ',' ) != NULL ||
687 : INT_MIN > dfNoDataValue || dfNoDataValue > INT_MAX) )
688 : {
689 0 : eDataType = GDT_Float32;
690 : }
691 0 : if( eDataType == GDT_Float32 )
692 : {
693 0 : dfNoDataValue = (double) (float) dfNoDataValue;
694 : }
695 : }
696 :
697 1 : if( (i = CSLFindString( papszTokens, "type" )) >= 0 &&
698 : i + 1 < nTokens)
699 : {
700 0 : const char* pszType = papszTokens[i + 1];
701 0 : if (EQUAL(pszType, "int"))
702 0 : eDataType = GDT_Int32;
703 0 : else if (EQUAL(pszType, "float"))
704 0 : eDataType = GDT_Float32;
705 0 : else if (EQUAL(pszType, "double"))
706 0 : eDataType = GDT_Float64;
707 : else
708 : {
709 : CPLError(CE_Warning, CPLE_AppDefined,
710 0 : "Invalid value for type parameter : %s", pszType);
711 : }
712 : }
713 :
714 1 : CSLDestroy(papszTokens);
715 :
716 1 : return TRUE;
717 : }
718 :
719 : /************************************************************************/
720 : /* CommonOpen() */
721 : /************************************************************************/
722 :
723 66 : GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo * poOpenInfo,
724 : GridFormat eFormat )
725 : {
726 66 : int i = 0;
727 :
728 : /* -------------------------------------------------------------------- */
729 : /* Create a corresponding GDALDataset. */
730 : /* -------------------------------------------------------------------- */
731 : AAIGDataset *poDS;
732 :
733 66 : if (eFormat == FORMAT_AAIG)
734 65 : poDS = new AAIGDataset();
735 : else
736 1 : poDS = new GRASSASCIIDataset();
737 :
738 :
739 : const char* pszDataTypeOption = (eFormat == FORMAT_AAIG) ? "AAIGRID_DATATYPE":
740 66 : "GRASSASCIIGRID_DATATYPE";
741 66 : const char* pszDataType = CPLGetConfigOption(pszDataTypeOption, NULL);
742 66 : if (pszDataType != NULL)
743 : {
744 1 : poDS->eDataType = GDALGetDataTypeByName(pszDataType);
745 1 : if (!(poDS->eDataType == GDT_Int32 || poDS->eDataType == GDT_Float32 ||
746 : poDS->eDataType == GDT_Float64))
747 : {
748 : CPLError(CE_Warning, CPLE_NotSupported,
749 0 : "Unsupported value for %s : %s", pszDataTypeOption, pszDataType);
750 0 : poDS->eDataType = GDT_Int32;
751 0 : pszDataType = NULL;
752 : }
753 : }
754 :
755 : /* -------------------------------------------------------------------- */
756 : /* Parse the header. */
757 : /* -------------------------------------------------------------------- */
758 66 : if (!poDS->ParseHeader((const char *) poOpenInfo->pabyHeader, pszDataType))
759 : {
760 0 : delete poDS;
761 0 : return NULL;
762 : }
763 :
764 : /* -------------------------------------------------------------------- */
765 : /* Open file with large file API. */
766 : /* -------------------------------------------------------------------- */
767 :
768 66 : poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
769 66 : if( poDS->fp == NULL )
770 : {
771 : CPLError( CE_Failure, CPLE_OpenFailed,
772 : "VSIFOpenL(%s) failed unexpectedly.",
773 0 : poOpenInfo->pszFilename );
774 0 : delete poDS;
775 0 : return NULL;
776 : }
777 :
778 : /* -------------------------------------------------------------------- */
779 : /* Find the start of real data. */
780 : /* -------------------------------------------------------------------- */
781 : int nStartOfData;
782 :
783 8414 : for( i = 2; TRUE ; i++ )
784 : {
785 8414 : if( poOpenInfo->pabyHeader[i] == '\0' )
786 : {
787 : CPLError( CE_Failure, CPLE_AppDefined,
788 0 : "Couldn't find data values in ASCII Grid file.\n" );
789 0 : delete poDS;
790 0 : return NULL;
791 : }
792 :
793 31993 : if( poOpenInfo->pabyHeader[i-1] == '\n'
794 8061 : || poOpenInfo->pabyHeader[i-2] == '\n'
795 7774 : || poOpenInfo->pabyHeader[i-1] == '\r'
796 7744 : || poOpenInfo->pabyHeader[i-2] == '\r' )
797 : {
798 832 : if( !isalpha(poOpenInfo->pabyHeader[i])
799 96 : && poOpenInfo->pabyHeader[i] != '\n'
800 66 : && poOpenInfo->pabyHeader[i] != '\r')
801 : {
802 66 : nStartOfData = i;
803 :
804 : /* Beginning of real data found. */
805 : break;
806 : }
807 : }
808 : }
809 :
810 : /* -------------------------------------------------------------------- */
811 : /* Recognize the type of data. */
812 : /* -------------------------------------------------------------------- */
813 66 : CPLAssert( NULL != poDS->fp );
814 :
815 66 : if( pszDataType == NULL && poDS->eDataType != GDT_Float32)
816 : {
817 : /* Allocate 100K chunk + 1 extra byte for NULL character. */
818 64 : const size_t nChunkSize = 1024 * 100;
819 64 : GByte* pabyChunk = (GByte *) VSICalloc( nChunkSize + 1, sizeof(GByte) );
820 64 : if (pabyChunk == NULL)
821 : {
822 0 : CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
823 0 : delete poDS;
824 0 : return NULL;
825 : }
826 64 : pabyChunk[nChunkSize] = '\0';
827 :
828 64 : VSIFSeekL( poDS->fp, nStartOfData, SEEK_SET );
829 :
830 : /* Scan for dot in subsequent chunks of data. */
831 192 : while( !VSIFEofL( poDS->fp) )
832 : {
833 64 : VSIFReadL( pabyChunk, sizeof(GByte), nChunkSize, poDS->fp );
834 64 : CPLAssert( pabyChunk[nChunkSize] == '\0' );
835 :
836 5836890 : for(i = 0; i < (int)nChunkSize; i++)
837 : {
838 5836833 : GByte ch = pabyChunk[i];
839 5836833 : if (ch == '.' || ch == ',' || ch == 'e' || ch == 'E')
840 : {
841 7 : poDS->eDataType = GDT_Float32;
842 7 : break;
843 : }
844 : }
845 : }
846 :
847 : /* Deallocate chunk. */
848 64 : VSIFree( pabyChunk );
849 : }
850 :
851 : /* -------------------------------------------------------------------- */
852 : /* Create band information objects. */
853 : /* -------------------------------------------------------------------- */
854 66 : AAIGRasterBand* band = new AAIGRasterBand( poDS, nStartOfData );
855 66 : poDS->SetBand( 1, band );
856 66 : if (band->panLineOffset == NULL)
857 : {
858 0 : delete poDS;
859 0 : return NULL;
860 : }
861 :
862 : /* -------------------------------------------------------------------- */
863 : /* Try to read projection file. */
864 : /* -------------------------------------------------------------------- */
865 : char *pszDirname, *pszBasename;
866 : VSIStatBufL sStatBuf;
867 :
868 66 : pszDirname = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
869 66 : pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
870 :
871 66 : poDS->osPrjFilename = CPLFormFilename( pszDirname, pszBasename, "prj" );
872 66 : int nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );
873 :
874 95 : if( nRet != 0 && VSIIsCaseSensitiveFS(poDS->osPrjFilename) )
875 : {
876 29 : poDS->osPrjFilename = CPLFormFilename( pszDirname, pszBasename, "PRJ" );
877 29 : nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );
878 : }
879 :
880 66 : if( nRet == 0 )
881 : {
882 38 : OGRSpatialReference oSRS;
883 :
884 38 : poDS->papszPrj = CSLLoad( poDS->osPrjFilename );
885 :
886 : CPLDebug( "AAIGrid", "Loaded SRS from %s",
887 38 : poDS->osPrjFilename.c_str() );
888 :
889 38 : if( oSRS.importFromESRI( poDS->papszPrj ) == OGRERR_NONE )
890 : {
891 : // If geographic values are in seconds, we must transform.
892 : // Is there a code for minutes too?
893 38 : if( oSRS.IsGeographic()
894 : && EQUAL(OSR_GDS( poDS->papszPrj, "Units", ""), "DS") )
895 : {
896 0 : poDS->adfGeoTransform[0] /= 3600.0;
897 0 : poDS->adfGeoTransform[1] /= 3600.0;
898 0 : poDS->adfGeoTransform[2] /= 3600.0;
899 0 : poDS->adfGeoTransform[3] /= 3600.0;
900 0 : poDS->adfGeoTransform[4] /= 3600.0;
901 0 : poDS->adfGeoTransform[5] /= 3600.0;
902 : }
903 :
904 38 : CPLFree( poDS->pszProjection );
905 38 : oSRS.exportToWkt( &(poDS->pszProjection) );
906 38 : }
907 : }
908 :
909 66 : CPLFree( pszDirname );
910 66 : CPLFree( pszBasename );
911 :
912 : /* -------------------------------------------------------------------- */
913 : /* Initialize any PAM information. */
914 : /* -------------------------------------------------------------------- */
915 66 : poDS->SetDescription( poOpenInfo->pszFilename );
916 66 : poDS->TryLoadXML();
917 :
918 : /* -------------------------------------------------------------------- */
919 : /* Check for external overviews. */
920 : /* -------------------------------------------------------------------- */
921 66 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
922 :
923 66 : return( poDS );
924 : }
925 :
926 : /************************************************************************/
927 : /* GetGeoTransform() */
928 : /************************************************************************/
929 :
930 38 : CPLErr AAIGDataset::GetGeoTransform( double * padfTransform )
931 :
932 : {
933 38 : memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
934 38 : return( CE_None );
935 : }
936 :
937 : /************************************************************************/
938 : /* GetProjectionRef() */
939 : /************************************************************************/
940 :
941 48 : const char *AAIGDataset::GetProjectionRef()
942 :
943 : {
944 48 : return pszProjection;
945 : }
946 :
947 : /************************************************************************/
948 : /* CreateCopy() */
949 : /************************************************************************/
950 :
951 39 : GDALDataset * AAIGDataset::CreateCopy(
952 : const char * pszFilename, GDALDataset *poSrcDS,
953 : int bStrict, char ** papszOptions,
954 : GDALProgressFunc pfnProgress, void * pProgressData )
955 :
956 : {
957 39 : int nBands = poSrcDS->GetRasterCount();
958 39 : int nXSize = poSrcDS->GetRasterXSize();
959 39 : int nYSize = poSrcDS->GetRasterYSize();
960 :
961 : /* -------------------------------------------------------------------- */
962 : /* Some rudimentary checks */
963 : /* -------------------------------------------------------------------- */
964 39 : if( nBands != 1 )
965 : {
966 : CPLError( CE_Failure, CPLE_NotSupported,
967 : "AAIG driver doesn't support %d bands. Must be 1 band.\n",
968 5 : nBands );
969 :
970 5 : return NULL;
971 : }
972 :
973 34 : if( !pfnProgress( 0.0, NULL, pProgressData ) )
974 0 : return NULL;
975 :
976 : /* -------------------------------------------------------------------- */
977 : /* Create the dataset. */
978 : /* -------------------------------------------------------------------- */
979 : VSILFILE *fpImage;
980 :
981 34 : fpImage = VSIFOpenL( pszFilename, "wt" );
982 34 : if( fpImage == NULL )
983 : {
984 : CPLError( CE_Failure, CPLE_OpenFailed,
985 : "Unable to create file %s.\n",
986 13 : pszFilename );
987 13 : return NULL;
988 : }
989 :
990 : /* -------------------------------------------------------------------- */
991 : /* Write ASCII Grid file header */
992 : /* -------------------------------------------------------------------- */
993 : double adfGeoTransform[6];
994 : char szHeader[2000];
995 : const char *pszForceCellsize =
996 21 : CSLFetchNameValue( papszOptions, "FORCE_CELLSIZE" );
997 :
998 21 : poSrcDS->GetGeoTransform( adfGeoTransform );
999 :
1000 23 : if( ABS(adfGeoTransform[1]+adfGeoTransform[5]) < 0.0000001
1001 2 : || ABS(adfGeoTransform[1]-adfGeoTransform[5]) < 0.0000001
1002 : || (pszForceCellsize && CSLTestBoolean(pszForceCellsize)) )
1003 : sprintf( szHeader,
1004 : "ncols %d\n"
1005 : "nrows %d\n"
1006 : "xllcorner %.12f\n"
1007 : "yllcorner %.12f\n"
1008 : "cellsize %.12f\n",
1009 : nXSize, nYSize,
1010 : adfGeoTransform[0],
1011 40 : adfGeoTransform[3] - nYSize * adfGeoTransform[1],
1012 60 : adfGeoTransform[1] );
1013 : else
1014 : {
1015 1 : if( pszForceCellsize == NULL )
1016 : CPLError( CE_Warning, CPLE_AppDefined,
1017 : "Producing a Golden Surfer style file with DX and DY instead\n"
1018 : "of CELLSIZE since the input pixels are non-square. Use the\n"
1019 : "FORCE_CELLSIZE=TRUE creation option to force use of DX for\n"
1020 : "even though this will be distorted. Most ASCII Grid readers\n"
1021 1 : "(ArcGIS included) do not support the DX and DY parameters.\n" );
1022 : sprintf( szHeader,
1023 : "ncols %d\n"
1024 : "nrows %d\n"
1025 : "xllcorner %.12f\n"
1026 : "yllcorner %.12f\n"
1027 : "dx %.12f\n"
1028 : "dy %.12f\n",
1029 : nXSize, nYSize,
1030 : adfGeoTransform[0],
1031 2 : adfGeoTransform[3] + nYSize * adfGeoTransform[5],
1032 : adfGeoTransform[1],
1033 3 : fabs(adfGeoTransform[5]) );
1034 : }
1035 :
1036 : /* -------------------------------------------------------------------- */
1037 : /* Handle nodata (optionally). */
1038 : /* -------------------------------------------------------------------- */
1039 21 : GDALRasterBand * poBand = poSrcDS->GetRasterBand( 1 );
1040 : double dfNoData;
1041 : int bSuccess;
1042 :
1043 : // Write `nodata' value to header if it is exists in source dataset
1044 21 : dfNoData = poBand->GetNoDataValue( &bSuccess );
1045 21 : if ( bSuccess )
1046 : sprintf( szHeader+strlen(szHeader), "NODATA_value %6.20g\n",
1047 0 : dfNoData );
1048 :
1049 21 : VSIFWriteL( szHeader, 1, strlen(szHeader), fpImage );
1050 :
1051 : /* -------------------------------------------------------------------- */
1052 : /* Builds the format string used for printing float values. */
1053 : /* -------------------------------------------------------------------- */
1054 : char szFormatFloat[32];
1055 21 : strcpy(szFormatFloat, " %.20g");
1056 : const char *pszDecimalPrecision =
1057 21 : CSLFetchNameValue( papszOptions, "DECIMAL_PRECISION" );
1058 21 : if (pszDecimalPrecision)
1059 : {
1060 1 : int nDecimal = atoi(pszDecimalPrecision);
1061 1 : if (nDecimal >= 0)
1062 1 : sprintf(szFormatFloat, " %%.%dg", nDecimal);
1063 : }
1064 :
1065 : /* -------------------------------------------------------------------- */
1066 : /* Loop over image, copying image data. */
1067 : /* -------------------------------------------------------------------- */
1068 21 : int *panScanline = NULL;
1069 21 : double *padfScanline = NULL;
1070 : int bReadAsInt;
1071 : int iLine, iPixel;
1072 21 : CPLErr eErr = CE_None;
1073 :
1074 : bReadAsInt = ( poBand->GetRasterDataType() == GDT_Byte
1075 : || poBand->GetRasterDataType() == GDT_Int16
1076 : || poBand->GetRasterDataType() == GDT_UInt16
1077 21 : || poBand->GetRasterDataType() == GDT_Int32 );
1078 :
1079 : // Write scanlines to output file
1080 21 : if (bReadAsInt)
1081 : panScanline = (int *) CPLMalloc( nXSize *
1082 12 : GDALGetDataTypeSize(GDT_Int32) / 8 );
1083 : else
1084 : padfScanline = (double *) CPLMalloc( nXSize *
1085 9 : GDALGetDataTypeSize(GDT_Float64) / 8 );
1086 :
1087 407 : for( iLine = 0; eErr == CE_None && iLine < nYSize; iLine++ )
1088 : {
1089 386 : CPLString osBuf;
1090 : eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
1091 : (bReadAsInt) ? (void*)panScanline : (void*)padfScanline,
1092 : nXSize, 1, (bReadAsInt) ? GDT_Int32 : GDT_Float64,
1093 386 : 0, 0 );
1094 :
1095 386 : if( bReadAsInt )
1096 : {
1097 13762 : for ( iPixel = 0; iPixel < nXSize; iPixel++ )
1098 : {
1099 13486 : sprintf( szHeader, " %d", panScanline[iPixel] );
1100 13486 : osBuf += szHeader;
1101 13486 : if( (iPixel & 1023) == 0 || iPixel == nXSize - 1 )
1102 : {
1103 551 : if ( VSIFWriteL( osBuf, (int)osBuf.size(), 1, fpImage ) != 1 )
1104 : {
1105 0 : eErr = CE_Failure;
1106 : CPLError( CE_Failure, CPLE_AppDefined,
1107 0 : "Write failed, disk full?\n" );
1108 0 : break;
1109 : }
1110 551 : osBuf = "";
1111 : }
1112 : }
1113 : }
1114 : else
1115 : {
1116 1610 : for ( iPixel = 0; iPixel < nXSize; iPixel++ )
1117 : {
1118 1500 : sprintf( szHeader, szFormatFloat, padfScanline[iPixel] );
1119 1500 : osBuf += szHeader;
1120 1500 : if( (iPixel & 1023) == 0 || iPixel == nXSize - 1 )
1121 : {
1122 220 : if ( VSIFWriteL( osBuf, (int)osBuf.size(), 1, fpImage ) != 1 )
1123 : {
1124 0 : eErr = CE_Failure;
1125 : CPLError( CE_Failure, CPLE_AppDefined,
1126 0 : "Write failed, disk full?\n" );
1127 0 : break;
1128 : }
1129 220 : osBuf = "";
1130 : }
1131 : }
1132 : }
1133 386 : VSIFWriteL( (void *) "\n", 1, 1, fpImage );
1134 :
1135 386 : if( eErr == CE_None &&
1136 : !pfnProgress((iLine + 1) / ((double) nYSize), NULL, pProgressData) )
1137 : {
1138 0 : eErr = CE_Failure;
1139 : CPLError( CE_Failure, CPLE_UserInterrupt,
1140 0 : "User terminated CreateCopy()" );
1141 : }
1142 : }
1143 :
1144 21 : CPLFree( panScanline );
1145 21 : CPLFree( padfScanline );
1146 21 : VSIFCloseL( fpImage );
1147 :
1148 21 : if( eErr != CE_None )
1149 0 : return NULL;
1150 :
1151 : /* -------------------------------------------------------------------- */
1152 : /* Try to write projection file. */
1153 : /* -------------------------------------------------------------------- */
1154 : const char *pszOriginalProjection;
1155 :
1156 21 : pszOriginalProjection = (char *)poSrcDS->GetProjectionRef();
1157 21 : if( !EQUAL( pszOriginalProjection, "" ) )
1158 : {
1159 : char *pszDirname, *pszBasename;
1160 : char *pszPrjFilename;
1161 19 : char *pszESRIProjection = NULL;
1162 : VSILFILE *fp;
1163 19 : OGRSpatialReference oSRS;
1164 :
1165 19 : pszDirname = CPLStrdup( CPLGetPath(pszFilename) );
1166 19 : pszBasename = CPLStrdup( CPLGetBasename(pszFilename) );
1167 :
1168 19 : pszPrjFilename = CPLStrdup( CPLFormFilename( pszDirname, pszBasename, "prj" ) );
1169 19 : fp = VSIFOpenL( pszPrjFilename, "wt" );
1170 19 : if (fp != NULL)
1171 : {
1172 19 : oSRS.importFromWkt( (char **) &pszOriginalProjection );
1173 19 : oSRS.morphToESRI();
1174 19 : oSRS.exportToWkt( &pszESRIProjection );
1175 19 : VSIFWriteL( pszESRIProjection, 1, strlen(pszESRIProjection), fp );
1176 :
1177 19 : VSIFCloseL( fp );
1178 19 : CPLFree( pszESRIProjection );
1179 : }
1180 : else
1181 : {
1182 : CPLError( CE_Failure, CPLE_FileIO,
1183 0 : "Unable to create file %s.\n", pszPrjFilename );
1184 : }
1185 19 : CPLFree( pszDirname );
1186 19 : CPLFree( pszBasename );
1187 19 : CPLFree( pszPrjFilename );
1188 : }
1189 :
1190 : /* -------------------------------------------------------------------- */
1191 : /* Re-open dataset, and copy any auxilary pam information. */
1192 : /* -------------------------------------------------------------------- */
1193 :
1194 : /* If outputing to stdout, we can't reopen it, so we'll return */
1195 : /* a fake dataset to make the caller happy */
1196 21 : CPLPushErrorHandler(CPLQuietErrorHandler);
1197 21 : GDALPamDataset* poDS = (GDALPamDataset*) GDALOpen(pszFilename, GA_ReadOnly);
1198 21 : CPLPopErrorHandler();
1199 21 : if (poDS)
1200 : {
1201 21 : poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
1202 21 : return poDS;
1203 : }
1204 :
1205 0 : CPLErrorReset();
1206 :
1207 0 : AAIGDataset* poAAIG_DS = new AAIGDataset();
1208 0 : poAAIG_DS->nRasterXSize = nXSize;
1209 0 : poAAIG_DS->nRasterYSize = nYSize;
1210 0 : poAAIG_DS->nBands = 1;
1211 0 : poAAIG_DS->SetBand( 1, new AAIGRasterBand( poAAIG_DS, 1 ) );
1212 0 : return poAAIG_DS;
1213 : }
1214 :
1215 : /************************************************************************/
1216 : /* OSR_GDS() */
1217 : /************************************************************************/
1218 :
1219 11 : static CPLString OSR_GDS( char **papszNV, const char * pszField,
1220 : const char *pszDefaultValue )
1221 :
1222 : {
1223 : int iLine;
1224 :
1225 11 : if( papszNV == NULL || papszNV[0] == NULL )
1226 0 : return pszDefaultValue;
1227 :
1228 44 : for( iLine = 0;
1229 22 : papszNV[iLine] != NULL &&
1230 11 : !EQUALN(papszNV[iLine],pszField,strlen(pszField));
1231 : iLine++ ) {}
1232 :
1233 11 : if( papszNV[iLine] == NULL )
1234 11 : return pszDefaultValue;
1235 : else
1236 : {
1237 0 : CPLString osResult;
1238 : char **papszTokens;
1239 :
1240 0 : papszTokens = CSLTokenizeString(papszNV[iLine]);
1241 :
1242 0 : if( CSLCount(papszTokens) > 1 )
1243 0 : osResult = papszTokens[1];
1244 : else
1245 0 : osResult = pszDefaultValue;
1246 :
1247 0 : CSLDestroy( papszTokens );
1248 0 : return osResult;
1249 : }
1250 : }
1251 :
1252 : /************************************************************************/
1253 : /* GDALRegister_AAIGrid() */
1254 : /************************************************************************/
1255 :
1256 582 : void GDALRegister_AAIGrid()
1257 :
1258 : {
1259 : GDALDriver *poDriver;
1260 :
1261 582 : if( GDALGetDriverByName( "AAIGrid" ) == NULL )
1262 : {
1263 561 : poDriver = new GDALDriver();
1264 :
1265 561 : poDriver->SetDescription( "AAIGrid" );
1266 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
1267 561 : "Arc/Info ASCII Grid" );
1268 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
1269 561 : "frmt_various.html#AAIGrid" );
1270 561 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "asc" );
1271 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
1272 561 : "Byte UInt16 Int16 Int32 Float32" );
1273 :
1274 561 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
1275 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
1276 : "<CreationOptionList>\n"
1277 : " <Option name='FORCE_CELLSIZE' type='boolean' description='Force use of CELLSIZE, default is FALSE.'/>\n"
1278 : " <Option name='DECIMAL_PRECISION' type='int' description='Number of decimal when writing floating-point numbers.'/>\n"
1279 561 : "</CreationOptionList>\n" );
1280 :
1281 561 : poDriver->pfnOpen = AAIGDataset::Open;
1282 561 : poDriver->pfnIdentify = AAIGDataset::Identify;
1283 561 : poDriver->pfnCreateCopy = AAIGDataset::CreateCopy;
1284 :
1285 561 : GetGDALDriverManager()->RegisterDriver( poDriver );
1286 : }
1287 582 : }
1288 :
1289 : /************************************************************************/
1290 : /* GDALRegister_GRASSASCIIGrid() */
1291 : /************************************************************************/
1292 :
1293 582 : void GDALRegister_GRASSASCIIGrid()
1294 :
1295 : {
1296 : GDALDriver *poDriver;
1297 :
1298 582 : if( GDALGetDriverByName( "GRASSASCIIGrid" ) == NULL )
1299 : {
1300 561 : poDriver = new GDALDriver();
1301 :
1302 561 : poDriver->SetDescription( "GRASSASCIIGrid" );
1303 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
1304 561 : "GRASS ASCII Grid" );
1305 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
1306 561 : "frmt_various.html#GRASSASCIIGrid" );
1307 :
1308 561 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
1309 :
1310 561 : poDriver->pfnOpen = GRASSASCIIDataset::Open;
1311 561 : poDriver->pfnIdentify = GRASSASCIIDataset::Identify;
1312 :
1313 561 : GetGDALDriverManager()->RegisterDriver( poDriver );
1314 : }
1315 582 : }
|