1 : /******************************************************************************
2 : * $Id: gxfdataset.cpp 17664 2009-09-21 21:16:45Z rouault $
3 : *
4 : * Project: GXF Reader
5 : * Purpose: GDAL binding for GXF reader.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1998, 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 "gxfopen.h"
31 : #include "gdal_pam.h"
32 :
33 : CPL_CVSID("$Id: gxfdataset.cpp 17664 2009-09-21 21:16:45Z rouault $");
34 :
35 : #ifndef PI
36 : # define PI 3.14159265358979323846
37 : #endif
38 :
39 : CPL_C_START
40 : void GDALRegister_GXF(void);
41 : CPL_C_END
42 :
43 : /************************************************************************/
44 : /* ==================================================================== */
45 : /* GXFDataset */
46 : /* ==================================================================== */
47 : /************************************************************************/
48 :
49 : class GXFRasterBand;
50 :
51 : class GXFDataset : public GDALPamDataset
52 : {
53 : friend class GXFRasterBand;
54 :
55 : GXFHandle hGXF;
56 :
57 : char *pszProjection;
58 : double dfNoDataValue;
59 :
60 : public:
61 : GXFDataset();
62 : ~GXFDataset();
63 :
64 : static GDALDataset *Open( GDALOpenInfo * );
65 :
66 : CPLErr GetGeoTransform( double * padfTransform );
67 : const char *GetProjectionRef();
68 : };
69 :
70 : /************************************************************************/
71 : /* ==================================================================== */
72 : /* GXFRasterBand */
73 : /* ==================================================================== */
74 : /************************************************************************/
75 :
76 : class GXFRasterBand : public GDALPamRasterBand
77 14 : {
78 : friend class GXFDataset;
79 :
80 : public:
81 :
82 : GXFRasterBand( GXFDataset *, int );
83 : double GetNoDataValue(int* bGotNoDataValue);
84 :
85 : virtual CPLErr IReadBlock( int, int, void * );
86 : };
87 :
88 :
89 : /************************************************************************/
90 : /* GXFRasterBand() */
91 : /************************************************************************/
92 :
93 7 : GXFRasterBand::GXFRasterBand( GXFDataset *poDS, int nBand )
94 :
95 : {
96 7 : this->poDS = poDS;
97 7 : this->nBand = nBand;
98 :
99 7 : eDataType = GDT_Float32;
100 :
101 7 : nBlockXSize = poDS->GetRasterXSize();
102 7 : nBlockYSize = 1;
103 7 : }
104 :
105 : /************************************************************************/
106 : /* GetNoDataValue() */
107 : /************************************************************************/
108 :
109 0 : double GXFRasterBand::GetNoDataValue(int* bGotNoDataValue)
110 :
111 : {
112 0 : GXFDataset *poGXF_DS = (GXFDataset *) poDS;
113 0 : if (bGotNoDataValue)
114 0 : *bGotNoDataValue = (fabs(poGXF_DS->dfNoDataValue - -1e12) > .1);
115 0 : return poGXF_DS->dfNoDataValue;
116 : }
117 :
118 : /************************************************************************/
119 : /* IReadBlock() */
120 : /************************************************************************/
121 :
122 1530 : CPLErr GXFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
123 : void * pImage )
124 :
125 : {
126 1530 : GXFDataset *poGXF_DS = (GXFDataset *) poDS;
127 : double *padfBuffer;
128 1530 : float *pafBuffer = (float *) pImage;
129 : int i;
130 : CPLErr eErr;
131 :
132 : CPLAssert( nBlockXOff == 0 );
133 :
134 1530 : padfBuffer = (double *) CPLMalloc(sizeof(double) * nBlockXSize);
135 1530 : eErr = GXFGetRawScanline( poGXF_DS->hGXF, nBlockYOff, padfBuffer );
136 :
137 613917 : for( i = 0; i < nBlockXSize; i++ )
138 612387 : pafBuffer[i] = (float) padfBuffer[i];
139 :
140 1530 : CPLFree( padfBuffer );
141 :
142 1530 : return eErr;
143 : }
144 :
145 : /************************************************************************/
146 : /* ==================================================================== */
147 : /* GXFDataset */
148 : /* ==================================================================== */
149 : /************************************************************************/
150 :
151 : /************************************************************************/
152 : /* GXFDataset() */
153 : /************************************************************************/
154 :
155 7 : GXFDataset::GXFDataset()
156 :
157 : {
158 7 : pszProjection = NULL;
159 7 : hGXF = NULL;
160 7 : dfNoDataValue = 0;
161 7 : }
162 :
163 : /************************************************************************/
164 : /* ~GXFDataset() */
165 : /************************************************************************/
166 :
167 14 : GXFDataset::~GXFDataset()
168 :
169 : {
170 7 : FlushCache();
171 7 : if( hGXF != NULL )
172 7 : GXFClose( hGXF );
173 7 : CPLFree( pszProjection );
174 14 : }
175 :
176 :
177 : /************************************************************************/
178 : /* GetGeoTransform() */
179 : /************************************************************************/
180 :
181 0 : CPLErr GXFDataset::GetGeoTransform( double * padfTransform )
182 :
183 : {
184 : CPLErr eErr;
185 : double dfXOrigin, dfYOrigin, dfXSize, dfYSize, dfRotation;
186 :
187 : eErr = GXFGetPosition( hGXF, &dfXOrigin, &dfYOrigin,
188 0 : &dfXSize, &dfYSize, &dfRotation );
189 :
190 0 : if( eErr != CE_None )
191 0 : return eErr;
192 :
193 : // Transform to radians.
194 0 : dfRotation = (dfRotation / 360.0) * 2 * PI;
195 :
196 0 : padfTransform[1] = dfXSize * cos(dfRotation);
197 0 : padfTransform[2] = dfYSize * sin(dfRotation);
198 0 : padfTransform[4] = dfXSize * sin(dfRotation);
199 0 : padfTransform[5] = -1 * dfYSize * cos(dfRotation);
200 :
201 : // take into account that GXF is point or center of pixel oriented.
202 0 : padfTransform[0] = dfXOrigin - 0.5*padfTransform[1] - 0.5*padfTransform[2];
203 0 : padfTransform[3] = dfYOrigin - 0.5*padfTransform[4] - 0.5*padfTransform[5];
204 :
205 0 : return CE_None;
206 : }
207 :
208 : /************************************************************************/
209 : /* GetProjectionRef() */
210 : /************************************************************************/
211 :
212 0 : const char *GXFDataset::GetProjectionRef()
213 :
214 : {
215 0 : return( pszProjection );
216 : }
217 :
218 : /************************************************************************/
219 : /* Open() */
220 : /************************************************************************/
221 :
222 8466 : GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )
223 :
224 : {
225 : GXFHandle hGXF;
226 : int i, bFoundKeyword, bFoundIllegal;
227 :
228 : /* -------------------------------------------------------------------- */
229 : /* Before trying GXFOpen() we first verify that there is at */
230 : /* least one "\n#keyword" type signature in the first chunk of */
231 : /* the file. */
232 : /* -------------------------------------------------------------------- */
233 8466 : if( poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 50 )
234 8325 : return NULL;
235 :
236 141 : bFoundKeyword = FALSE;
237 141 : bFoundIllegal = FALSE;
238 25833 : for( i = 0; i < poOpenInfo->nHeaderBytes-1; i++ )
239 : {
240 51705 : if( (poOpenInfo->pabyHeader[i] == 10
241 25669 : || poOpenInfo->pabyHeader[i] == 13)
242 234 : && poOpenInfo->pabyHeader[i+1] == '#' )
243 : {
244 44 : bFoundKeyword = TRUE;
245 : }
246 25802 : if( poOpenInfo->pabyHeader[i] == 0 )
247 : {
248 110 : bFoundIllegal = TRUE;
249 110 : break;
250 : }
251 : }
252 :
253 141 : if( !bFoundKeyword || bFoundIllegal )
254 134 : return NULL;
255 :
256 :
257 : /* -------------------------------------------------------------------- */
258 : /* At this point it is plausible that this is a GXF file, but */
259 : /* we also now verify that there is a #GRID keyword before */
260 : /* passing it off to GXFOpen(). We check in the first 50K. */
261 : /* -------------------------------------------------------------------- */
262 7 : int nBytesRead, bGotGrid = FALSE;
263 : char szBigBuf[50000];
264 : FILE *fp;
265 :
266 7 : fp = VSIFOpen( poOpenInfo->pszFilename, "rb" );
267 7 : if( fp == NULL )
268 0 : return NULL;
269 :
270 7 : nBytesRead = VSIFRead( szBigBuf, 1, sizeof(szBigBuf), fp );
271 7 : VSIFClose( fp );
272 :
273 14659 : for( i = 0; i < nBytesRead - 5 && !bGotGrid; i++ )
274 : {
275 14652 : if( szBigBuf[i] == '#' && EQUALN(szBigBuf+i+1,"GRID",4) )
276 7 : bGotGrid = TRUE;
277 : }
278 :
279 7 : if( !bGotGrid )
280 0 : return NULL;
281 :
282 : /* -------------------------------------------------------------------- */
283 : /* Try opening the dataset. */
284 : /* -------------------------------------------------------------------- */
285 :
286 7 : hGXF = GXFOpen( poOpenInfo->pszFilename );
287 :
288 7 : if( hGXF == NULL )
289 0 : return( NULL );
290 :
291 : /* -------------------------------------------------------------------- */
292 : /* Confirm the requested access is supported. */
293 : /* -------------------------------------------------------------------- */
294 7 : if( poOpenInfo->eAccess == GA_Update )
295 : {
296 0 : GXFClose(hGXF);
297 : CPLError( CE_Failure, CPLE_NotSupported,
298 : "The GXF driver does not support update access to existing"
299 0 : " datasets.\n" );
300 0 : return NULL;
301 : }
302 :
303 : /* -------------------------------------------------------------------- */
304 : /* Create a corresponding GDALDataset. */
305 : /* -------------------------------------------------------------------- */
306 : GXFDataset *poDS;
307 :
308 7 : poDS = new GXFDataset();
309 :
310 7 : poDS->hGXF = hGXF;
311 :
312 : /* -------------------------------------------------------------------- */
313 : /* Establish the projection. */
314 : /* -------------------------------------------------------------------- */
315 7 : poDS->pszProjection = GXFGetMapProjectionAsOGCWKT( hGXF );
316 :
317 : /* -------------------------------------------------------------------- */
318 : /* Capture some information from the file that is of interest. */
319 : /* -------------------------------------------------------------------- */
320 : GXFGetRawInfo( hGXF, &(poDS->nRasterXSize), &(poDS->nRasterYSize), NULL,
321 7 : NULL, NULL, &(poDS->dfNoDataValue) );
322 :
323 14 : if (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0)
324 : {
325 : CPLError( CE_Failure, CPLE_AppDefined,
326 : "Invalid dimensions : %d x %d",
327 0 : poDS->nRasterXSize, poDS->nRasterYSize);
328 0 : delete poDS;
329 0 : return NULL;
330 : }
331 :
332 : /* -------------------------------------------------------------------- */
333 : /* Create band information objects. */
334 : /* -------------------------------------------------------------------- */
335 7 : poDS->nBands = 1;
336 7 : poDS->SetBand( 1, new GXFRasterBand( poDS, 1 ));
337 :
338 : /* -------------------------------------------------------------------- */
339 : /* Initialize any PAM information. */
340 : /* -------------------------------------------------------------------- */
341 7 : poDS->SetDescription( poOpenInfo->pszFilename );
342 7 : poDS->TryLoadXML();
343 :
344 7 : return( poDS );
345 : }
346 :
347 : /************************************************************************/
348 : /* GDALRegister_GXF() */
349 : /************************************************************************/
350 :
351 338 : void GDALRegister_GXF()
352 :
353 : {
354 : GDALDriver *poDriver;
355 :
356 338 : if( GDALGetDriverByName( "GXF" ) == NULL )
357 : {
358 336 : poDriver = new GDALDriver();
359 :
360 336 : poDriver->SetDescription( "GXF" );
361 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
362 336 : "GeoSoft Grid Exchange Format" );
363 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
364 336 : "frmt_various.html#GXF" );
365 336 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gxf" );
366 :
367 336 : poDriver->pfnOpen = GXFDataset::Open;
368 :
369 336 : GetGDALDriverManager()->RegisterDriver( poDriver );
370 : }
371 338 : }
|