1 : /******************************************************************************
2 : * $Id: cpgdataset.cpp 18073 2009-11-22 01:01:14Z rouault $
3 : *
4 : * Project: Polarimetric Workstation
5 : * Purpose: Convair PolGASP data (.img/.hdr format).
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2004, 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 "rawdataset.h"
31 : #include "ogr_spatialref.h"
32 : #include "cpl_string.h"
33 :
34 : CPL_CVSID("$Id: cpgdataset.cpp 18073 2009-11-22 01:01:14Z rouault $");
35 :
36 : CPL_C_START
37 : void GDALRegister_CPG(void);
38 : CPL_C_END
39 :
40 :
41 : enum Interleave {BSQ, BIL, BIP};
42 :
43 : /************************************************************************/
44 : /* ==================================================================== */
45 : /* CPGDataset */
46 : /* ==================================================================== */
47 : /************************************************************************/
48 :
49 : class SIRC_QSLCRasterBand;
50 : class CPG_STOKESRasterBand;
51 :
52 : class CPGDataset : public RawDataset
53 : {
54 : friend class SIRC_QSLCRasterBand;
55 : friend class CPG_STOKESRasterBand;
56 :
57 : FILE *afpImage[4];
58 :
59 : int nGCPCount;
60 : GDAL_GCP *pasGCPList;
61 : char *pszGCPProjection;
62 :
63 : double adfGeoTransform[6];
64 : char *pszProjection;
65 :
66 : int nLoadedStokesLine;
67 : float *padfStokesMatrix;
68 :
69 : int nInterleave;
70 : static int AdjustFilename( char **, const char *, const char * );
71 : static int FindType1( const char *pszWorkname );
72 : static int FindType2( const char *pszWorkname );
73 : static int FindType3( const char *pszWorkname );
74 : static GDALDataset *InitializeType1Or2Dataset( const char *pszWorkname );
75 : static GDALDataset *InitializeType3Dataset( const char *pszWorkname );
76 : CPLErr LoadStokesLine( int iLine, int bNativeOrder );
77 :
78 : public:
79 : CPGDataset();
80 : ~CPGDataset();
81 :
82 : virtual int GetGCPCount();
83 : virtual const char *GetGCPProjection();
84 : virtual const GDAL_GCP *GetGCPs();
85 :
86 : virtual const char *GetProjectionRef(void);
87 : virtual CPLErr GetGeoTransform( double * );
88 :
89 : static GDALDataset *Open( GDALOpenInfo * );
90 : };
91 :
92 : /************************************************************************/
93 : /* CPGDataset() */
94 : /************************************************************************/
95 :
96 1 : CPGDataset::CPGDataset()
97 : {
98 : int iBand;
99 :
100 1 : nGCPCount = 0;
101 1 : pasGCPList = NULL;
102 1 : pszProjection = CPLStrdup("");
103 1 : pszGCPProjection = CPLStrdup("");
104 1 : adfGeoTransform[0] = 0.0;
105 1 : adfGeoTransform[1] = 1.0;
106 1 : adfGeoTransform[2] = 0.0;
107 1 : adfGeoTransform[3] = 0.0;
108 1 : adfGeoTransform[4] = 0.0;
109 1 : adfGeoTransform[5] = 1.0;
110 :
111 1 : nLoadedStokesLine = -1;
112 1 : padfStokesMatrix = NULL;
113 :
114 5 : for( iBand = 0; iBand < 4; iBand++ )
115 4 : afpImage[iBand] = NULL;
116 1 : }
117 :
118 : /************************************************************************/
119 : /* ~CPGDataset() */
120 : /************************************************************************/
121 :
122 1 : CPGDataset::~CPGDataset()
123 :
124 : {
125 : int iBand;
126 :
127 1 : FlushCache();
128 :
129 5 : for( iBand = 0; iBand < 4; iBand++ )
130 : {
131 4 : if( afpImage[iBand] != NULL )
132 1 : VSIFClose( afpImage[iBand] );
133 : }
134 :
135 1 : if( nGCPCount > 0 )
136 : {
137 1 : GDALDeinitGCPs( nGCPCount, pasGCPList );
138 1 : CPLFree( pasGCPList );
139 : }
140 :
141 1 : CPLFree( pszProjection );
142 1 : CPLFree( pszGCPProjection );
143 :
144 1 : if (padfStokesMatrix != NULL)
145 0 : CPLFree( padfStokesMatrix );
146 :
147 1 : }
148 :
149 : /************************************************************************/
150 : /* ==================================================================== */
151 : /* SIRC_QSLCPRasterBand */
152 : /* ==================================================================== */
153 : /************************************************************************/
154 :
155 : class SIRC_QSLCRasterBand : public GDALRasterBand
156 4 : {
157 : friend class CPGDataset;
158 :
159 : public:
160 : SIRC_QSLCRasterBand( CPGDataset *, int, GDALDataType );
161 :
162 : virtual CPLErr IReadBlock( int, int, void * );
163 : };
164 :
165 : #define M11 0
166 : #define M12 1
167 : #define M13 2
168 : #define M14 3
169 : #define M21 4
170 : #define M22 5
171 : #define M23 6
172 : #define M24 7
173 : #define M31 8
174 : #define M32 9
175 : #define M33 10
176 : #define M34 11
177 : #define M41 12
178 : #define M42 13
179 : #define M43 14
180 : #define M44 15
181 :
182 : /************************************************************************/
183 : /* ==================================================================== */
184 : /* CPG_STOKESRasterBand */
185 : /* ==================================================================== */
186 : /************************************************************************/
187 :
188 : class CPG_STOKESRasterBand : public GDALRasterBand
189 : {
190 : friend class CPGDataset;
191 :
192 : int nBand;
193 : int bNativeOrder;
194 :
195 : public:
196 : CPG_STOKESRasterBand( GDALDataset *poDS, int nBand,
197 : GDALDataType eType,
198 : int bNativeOrder );
199 : virtual ~CPG_STOKESRasterBand();
200 :
201 : virtual CPLErr IReadBlock( int, int, void * );
202 : };
203 :
204 : /************************************************************************/
205 : /* AdjustFilename() */
206 : /* */
207 : /* Try to find the file with the request polarization and */
208 : /* extention and update the passed filename accordingly. */
209 : /* */
210 : /* Return TRUE if file found otherwise FALSE. */
211 : /************************************************************************/
212 :
213 4 : int CPGDataset::AdjustFilename( char **pszFilename,
214 : const char *pszPolarization,
215 : const char *pszExtension )
216 :
217 : {
218 : VSIStatBuf sStatBuf;
219 : const char *pszNewName;
220 : char *subptr;
221 :
222 : /* eventually we should handle upper/lower case ... */
223 :
224 4 : if ( EQUAL(pszPolarization,"stokes") )
225 : {
226 : pszNewName = CPLResetExtension((const char *) *pszFilename,
227 0 : (const char *) pszExtension);
228 0 : CPLFree(*pszFilename);
229 0 : *pszFilename = CPLStrdup(pszNewName);
230 : }
231 4 : else if (strlen(pszPolarization) == 2)
232 : {
233 1 : subptr = strstr(*pszFilename,"hh");
234 1 : if (subptr == NULL)
235 1 : subptr = strstr(*pszFilename,"hv");
236 1 : if (subptr == NULL)
237 1 : subptr = strstr(*pszFilename,"vv");
238 1 : if (subptr == NULL)
239 1 : subptr = strstr(*pszFilename,"vh");
240 1 : if (subptr == NULL)
241 1 : return FALSE;
242 :
243 0 : strncpy( subptr, pszPolarization, 2);
244 : pszNewName = CPLResetExtension((const char *) *pszFilename,
245 0 : (const char *) pszExtension);
246 0 : CPLFree(*pszFilename);
247 0 : *pszFilename = CPLStrdup(pszNewName);
248 :
249 : }
250 : else
251 : {
252 : pszNewName = CPLResetExtension((const char *) *pszFilename,
253 3 : (const char *) pszExtension);
254 3 : CPLFree(*pszFilename);
255 3 : *pszFilename = CPLStrdup(pszNewName);
256 : }
257 3 : return VSIStat( *pszFilename, &sStatBuf ) == 0;
258 : }
259 :
260 : /************************************************************************/
261 : /* Search for the various types of Convair filesets */
262 : /* Return TRUE for a match, FALSE for no match */
263 : /************************************************************************/
264 11982 : int CPGDataset::FindType1( const char *pszFilename )
265 : {
266 : int nNameLen;
267 :
268 11982 : nNameLen = strlen(pszFilename);
269 :
270 11982 : if ((strstr(pszFilename,"sso") == NULL) &&
271 : (strstr(pszFilename,"polgasp") == NULL))
272 11982 : return FALSE;
273 :
274 0 : if (( strlen(pszFilename) < 5) ||
275 : (!EQUAL(pszFilename+nNameLen-4,".hdr")
276 : && !EQUAL(pszFilename+nNameLen-4,".img")))
277 0 : return FALSE;
278 :
279 : /* Expect all bands and headers to be present */
280 0 : char* pszTemp = CPLStrdup(pszFilename);
281 :
282 : int bNotFound = !AdjustFilename( &pszTemp, "hh", "img" )
283 : || !AdjustFilename( &pszTemp, "hh", "hdr" )
284 : || !AdjustFilename( &pszTemp, "hv", "img" )
285 : || !AdjustFilename( &pszTemp, "hv", "hdr" )
286 : || !AdjustFilename( &pszTemp, "vh", "img" )
287 : || !AdjustFilename( &pszTemp, "vh", "hdr" )
288 : || !AdjustFilename( &pszTemp, "vv", "img" )
289 0 : || !AdjustFilename( &pszTemp, "vv", "hdr" );
290 :
291 0 : CPLFree(pszTemp);
292 :
293 0 : if (bNotFound)
294 0 : return FALSE;
295 :
296 0 : return TRUE;
297 : }
298 :
299 11982 : int CPGDataset::FindType2( const char *pszFilename )
300 : {
301 : int nNameLen;
302 :
303 11982 : nNameLen = strlen( pszFilename );
304 :
305 11982 : if (( strlen(pszFilename) < 9) ||
306 : (!EQUAL(pszFilename+nNameLen-8,"SIRC.hdr")
307 : && !EQUAL(pszFilename+nNameLen-8,"SIRC.img")))
308 11981 : return FALSE;
309 :
310 1 : char* pszTemp = CPLStrdup(pszFilename);
311 : int bNotFound = !AdjustFilename( &pszTemp, "", "img" )
312 1 : || !AdjustFilename( &pszTemp, "", "hdr" );
313 1 : CPLFree(pszTemp);
314 :
315 1 : if (bNotFound)
316 0 : return FALSE;
317 :
318 1 : return TRUE;
319 : }
320 :
321 0 : int CPGDataset::FindType3( const char *pszFilename )
322 : {
323 : int nNameLen;
324 :
325 0 : nNameLen = strlen( pszFilename );
326 :
327 0 : if ((strstr(pszFilename,"sso") == NULL) &&
328 : (strstr(pszFilename,"polgasp") == NULL))
329 0 : return FALSE;
330 :
331 0 : if (( strlen(pszFilename) < 9) ||
332 : (!EQUAL(pszFilename+nNameLen-4,".img")
333 : && !EQUAL(pszFilename+nNameLen-8,".img_def")))
334 0 : return FALSE;
335 :
336 0 : char* pszTemp = CPLStrdup(pszFilename);
337 : int bNotFound = !AdjustFilename( &pszTemp, "stokes", "img" )
338 0 : || !AdjustFilename( &pszTemp, "stokes", "img_def" );
339 0 : CPLFree(pszTemp);
340 :
341 0 : if (bNotFound)
342 0 : return FALSE;
343 :
344 0 : return TRUE;
345 : }
346 :
347 : /************************************************************************/
348 : /* LoadStokesLine() */
349 : /************************************************************************/
350 :
351 0 : CPLErr CPGDataset::LoadStokesLine( int iLine, int bNativeOrder )
352 :
353 : {
354 : int offset, nBytesToRead, band_index;
355 0 : int nDataSize = GDALGetDataTypeSize(GDT_Float32)/8;
356 :
357 0 : if( iLine == nLoadedStokesLine )
358 0 : return CE_None;
359 :
360 : /* -------------------------------------------------------------------- */
361 : /* allocate working buffers if we don't have them already. */
362 : /* -------------------------------------------------------------------- */
363 0 : if( padfStokesMatrix == NULL )
364 : {
365 0 : padfStokesMatrix = (float *) CPLMalloc(sizeof(float) * nRasterXSize*16);
366 : }
367 :
368 : /* -------------------------------------------------------------------- */
369 : /* Load all the pixel data associated with this scanline. */
370 : /* Retains same interleaving as original dataset. */
371 : /* -------------------------------------------------------------------- */
372 0 : if ( nInterleave == BIP )
373 : {
374 0 : offset = nRasterXSize*iLine*nDataSize*16;
375 0 : nBytesToRead = nDataSize*nRasterXSize*16;
376 0 : if (( VSIFSeek( afpImage[0], offset, SEEK_SET ) != 0 ) ||
377 : (int) VSIFRead( ( GByte *) padfStokesMatrix, 1, nBytesToRead,
378 : afpImage[0] ) != nBytesToRead )
379 : {
380 : CPLError( CE_Failure, CPLE_FileIO,
381 : "Error reading %d bytes of Stokes Convair at offset %d.\n"
382 : "Reading file %s failed.",
383 0 : nBytesToRead, offset, GetDescription() );
384 0 : CPLFree( padfStokesMatrix );
385 0 : padfStokesMatrix = NULL;
386 0 : nLoadedStokesLine = -1;
387 0 : return CE_Failure;
388 : }
389 : }
390 0 : else if ( nInterleave == BIL )
391 : {
392 0 : for ( band_index = 0; band_index < 16; band_index++)
393 : {
394 : offset = nDataSize * (nRasterXSize*iLine +
395 0 : nRasterXSize*band_index);
396 0 : nBytesToRead = nDataSize*nRasterXSize;
397 0 : if (( VSIFSeek( afpImage[0], offset, SEEK_SET ) != 0 ) ||
398 : (int) VSIFRead(
399 : ( GByte *) padfStokesMatrix + nBytesToRead*band_index,
400 : 1, nBytesToRead,
401 : afpImage[0] ) != nBytesToRead )
402 : {
403 : CPLError( CE_Failure, CPLE_FileIO,
404 : "Error reading %d bytes of Stokes Convair at offset %d.\n"
405 : "Reading file %s failed.",
406 0 : nBytesToRead, offset, GetDescription() );
407 0 : CPLFree( padfStokesMatrix );
408 0 : padfStokesMatrix = NULL;
409 0 : nLoadedStokesLine = -1;
410 0 : return CE_Failure;
411 :
412 : }
413 : }
414 : }
415 : else
416 : {
417 0 : for ( band_index = 0; band_index < 16; band_index++)
418 : {
419 : offset = nDataSize * (nRasterXSize*iLine +
420 0 : nRasterXSize*nRasterYSize*band_index);
421 0 : nBytesToRead = nDataSize*nRasterXSize;
422 0 : if (( VSIFSeek( afpImage[0], offset, SEEK_SET ) != 0 ) ||
423 : (int) VSIFRead(
424 : ( GByte *) padfStokesMatrix + nBytesToRead*band_index,
425 : 1, nBytesToRead,
426 : afpImage[0] ) != nBytesToRead )
427 : {
428 : CPLError( CE_Failure, CPLE_FileIO,
429 : "Error reading %d bytes of Stokes Convair at offset %d.\n"
430 : "Reading file %s failed.",
431 0 : nBytesToRead, offset, GetDescription() );
432 0 : CPLFree( padfStokesMatrix );
433 0 : padfStokesMatrix = NULL;
434 0 : nLoadedStokesLine = -1;
435 0 : return CE_Failure;
436 :
437 : }
438 : }
439 : }
440 :
441 0 : if (!bNativeOrder)
442 0 : GDALSwapWords( padfStokesMatrix,nDataSize,nRasterXSize*16, nDataSize );
443 :
444 0 : nLoadedStokesLine = iLine;
445 :
446 0 : return CE_None;
447 : }
448 :
449 : /************************************************************************/
450 : /* Parse header information and initialize dataset for the */
451 : /* appropriate Convair dataset style. */
452 : /* Returns dataset if successful; NULL if there was a problem. */
453 : /************************************************************************/
454 :
455 1 : GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
456 : {
457 :
458 : /* -------------------------------------------------------------------- */
459 : /* Read the .hdr file (the hh one for the .sso and polgasp cases) */
460 : /* and parse it. */
461 : /* -------------------------------------------------------------------- */
462 : char **papszHdrLines;
463 : int iLine;
464 1 : int nLines = 0, nSamples = 0;
465 1 : int nError = 0;
466 1 : int nNameLen = 0;
467 :
468 : /* Parameters required for pseudo-geocoding. GCPs map */
469 : /* slant range to ground range at 16 points. */
470 1 : int iGeoParamsFound = 0, itransposed = 0;
471 1 : double dfaltitude = 0.0, dfnear_srd = 0.0;
472 1 : double dfsample_size = 0.0, dfsample_size_az = 0.0;
473 :
474 : /* Parameters in geogratis geocoded images */
475 1 : int iUTMParamsFound = 0, iUTMZone=0, iCorner=0;
476 1 : double dfnorth = 0.0, dfeast = 0.0;
477 :
478 1 : char* pszWorkname = CPLStrdup(pszFilename);
479 1 : AdjustFilename( &pszWorkname, "hh", "hdr" );
480 1 : papszHdrLines = CSLLoad( pszWorkname );
481 :
482 8 : for( iLine = 0; papszHdrLines && papszHdrLines[iLine] != NULL; iLine++ )
483 : {
484 7 : char **papszTokens = CSLTokenizeString( papszHdrLines[iLine] );
485 :
486 : /* Note: some cv580 file seem to have comments with #, hence the >=
487 : * instead of = for token checking, and the equalN for the corner.
488 : */
489 :
490 7 : if( CSLCount( papszTokens ) < 2 )
491 : {
492 : /* ignore */;
493 : }
494 7 : else if ( ( CSLCount( papszTokens ) >= 3 ) &&
495 0 : EQUAL(papszTokens[0],"reference") &&
496 0 : EQUAL(papszTokens[1],"north") )
497 : {
498 0 : dfnorth = atof(papszTokens[2]);
499 0 : iUTMParamsFound++;
500 : }
501 7 : else if ( ( CSLCount( papszTokens ) >= 3 ) &&
502 0 : EQUAL(papszTokens[0],"reference") &&
503 0 : EQUAL(papszTokens[1],"east") )
504 : {
505 0 : dfeast = atof(papszTokens[2]);
506 0 : iUTMParamsFound++;
507 : }
508 7 : else if ( ( CSLCount( papszTokens ) >= 5 ) &&
509 0 : EQUAL(papszTokens[0],"reference") &&
510 0 : EQUAL(papszTokens[1],"projection") &&
511 0 : EQUAL(papszTokens[2],"UTM") &&
512 0 : EQUAL(papszTokens[3],"zone") )
513 : {
514 0 : iUTMZone = atoi(papszTokens[4]);
515 0 : iUTMParamsFound++;
516 : }
517 7 : else if ( ( CSLCount( papszTokens ) >= 3 ) &&
518 0 : EQUAL(papszTokens[0],"reference") &&
519 0 : EQUAL(papszTokens[1],"corner") &&
520 0 : EQUALN(papszTokens[2],"Upper_Left",10) )
521 : {
522 0 : iCorner = 0;
523 0 : iUTMParamsFound++;
524 : }
525 7 : else if( EQUAL(papszTokens[0],"number_lines") )
526 1 : nLines = atoi(papszTokens[1]);
527 :
528 6 : else if( EQUAL(papszTokens[0],"number_samples") )
529 1 : nSamples = atoi(papszTokens[1]);
530 :
531 20 : else if( (EQUAL(papszTokens[0],"header_offset")
532 0 : && atoi(papszTokens[1]) != 0)
533 5 : || (EQUAL(papszTokens[0],"number_channels")
534 0 : && (atoi(papszTokens[1]) != 1)
535 0 : && (atoi(papszTokens[1]) != 10))
536 5 : || (EQUAL(papszTokens[0],"datatype")
537 0 : && atoi(papszTokens[1]) != 1)
538 5 : || (EQUAL(papszTokens[0],"number_format")
539 0 : && !EQUAL(papszTokens[1],"float32")
540 0 : && !EQUAL(papszTokens[1],"int8")))
541 : {
542 : CPLError( CE_Failure, CPLE_AppDefined,
543 : "Keyword %s has value %s which does not match CPG driver expectation.",
544 0 : papszTokens[0], papszTokens[1] );
545 0 : nError = 1;
546 : }
547 5 : else if( EQUAL(papszTokens[0],"altitude") )
548 : {
549 1 : dfaltitude = atof(papszTokens[1]);
550 1 : iGeoParamsFound++;
551 : }
552 4 : else if( EQUAL(papszTokens[0],"near_srd") )
553 : {
554 1 : dfnear_srd = atof(papszTokens[1]);
555 1 : iGeoParamsFound++;
556 : }
557 :
558 3 : else if( EQUAL(papszTokens[0],"sample_size") )
559 : {
560 1 : dfsample_size = atof(papszTokens[1]);
561 1 : iGeoParamsFound++;
562 1 : iUTMParamsFound++;
563 : }
564 2 : else if( EQUAL(papszTokens[0],"sample_size_az") )
565 : {
566 1 : dfsample_size_az = atof(papszTokens[1]);
567 1 : iGeoParamsFound++;
568 1 : iUTMParamsFound++;
569 : }
570 1 : else if( EQUAL(papszTokens[0],"transposed") )
571 : {
572 1 : itransposed = atoi(papszTokens[1]);
573 1 : iGeoParamsFound++;
574 1 : iUTMParamsFound++;
575 : }
576 :
577 :
578 :
579 7 : CSLDestroy( papszTokens );
580 : }
581 1 : CSLDestroy( papszHdrLines );
582 : /* -------------------------------------------------------------------- */
583 : /* Check for successful completion. */
584 : /* -------------------------------------------------------------------- */
585 1 : if( nError )
586 : {
587 0 : CPLFree(pszWorkname);
588 0 : return NULL;
589 : }
590 :
591 1 : if( nLines <= 0 || nSamples <= 0 )
592 : {
593 : CPLError( CE_Failure, CPLE_AppDefined,
594 : "Did not find valid number_lines or number_samples keywords in %s.",
595 0 : pszWorkname );
596 0 : CPLFree(pszWorkname);
597 0 : return NULL;
598 : }
599 :
600 : /* -------------------------------------------------------------------- */
601 : /* Initialize dataset. */
602 : /* -------------------------------------------------------------------- */
603 1 : int iBand=0;
604 : CPGDataset *poDS;
605 :
606 1 : poDS = new CPGDataset();
607 :
608 1 : poDS->nRasterXSize = nSamples;
609 1 : poDS->nRasterYSize = nLines;
610 :
611 : /* -------------------------------------------------------------------- */
612 : /* Open the four bands. */
613 : /* -------------------------------------------------------------------- */
614 : static const char *apszPolarizations[4] = { "hh", "hv", "vv", "vh" };
615 :
616 1 : nNameLen = strlen(pszWorkname);
617 :
618 2 : if ( EQUAL(pszWorkname+nNameLen-7,"IRC.hdr") ||
619 : EQUAL(pszWorkname+nNameLen-7,"IRC.img") )
620 : {
621 :
622 1 : AdjustFilename( &pszWorkname, "" , "img" );
623 1 : poDS->afpImage[0] = VSIFOpen( pszWorkname, "rb" );
624 1 : if( poDS->afpImage[0] == NULL )
625 : {
626 : CPLError( CE_Failure, CPLE_OpenFailed,
627 : "Failed to open .img file: %s",
628 0 : pszWorkname );
629 0 : CPLFree(pszWorkname);
630 0 : delete poDS;
631 0 : return NULL;
632 : }
633 10 : for( iBand = 0; iBand < 4; iBand++ )
634 : {
635 : SIRC_QSLCRasterBand *poBand;
636 :
637 4 : poBand = new SIRC_QSLCRasterBand( poDS, iBand+1, GDT_CFloat32 );
638 4 : poDS->SetBand( iBand+1, poBand );
639 : poBand->SetMetadataItem( "POLARIMETRIC_INTERP",
640 4 : apszPolarizations[iBand] );
641 : }
642 : }
643 : else
644 : {
645 0 : for( iBand = 0; iBand < 4; iBand++ )
646 : {
647 : RawRasterBand *poBand;
648 :
649 0 : AdjustFilename( &pszWorkname, apszPolarizations[iBand], "img" );
650 :
651 0 : poDS->afpImage[iBand] = VSIFOpen( pszWorkname, "rb" );
652 0 : if( poDS->afpImage[iBand] == NULL )
653 : {
654 : CPLError( CE_Failure, CPLE_OpenFailed,
655 : "Failed to open .img file: %s",
656 0 : pszWorkname );
657 0 : CPLFree(pszWorkname);
658 0 : delete poDS;
659 0 : return NULL;
660 : }
661 :
662 : poBand =
663 0 : new RawRasterBand( poDS, iBand+1, poDS->afpImage[iBand],
664 : 0, 8, 8*nSamples,
665 0 : GDT_CFloat32, !CPL_IS_LSB, FALSE );
666 0 : poDS->SetBand( iBand+1, poBand );
667 :
668 : poBand->SetMetadataItem( "POLARIMETRIC_INTERP",
669 0 : apszPolarizations[iBand] );
670 : }
671 : }
672 :
673 : /* Set an appropriate matrix representation metadata item for the set */
674 1 : if ( poDS->GetRasterCount() == 4 ) {
675 1 : poDS->SetMetadataItem( "MATRIX_REPRESENTATION", "SCATTERING" );
676 : }
677 :
678 : /* ------------------------------------------------------------------------- */
679 : /* Add georeferencing or pseudo-geocoding, if enough information found. */
680 : /* ------------------------------------------------------------------------- */
681 1 : if (iUTMParamsFound == 7)
682 : {
683 0 : OGRSpatialReference oUTM;
684 : double dfnorth_center;
685 :
686 0 : poDS->adfGeoTransform[1] = 0.0;
687 0 : poDS->adfGeoTransform[2] = 0.0;
688 0 : poDS->adfGeoTransform[4] = 0.0;
689 0 : poDS->adfGeoTransform[5] = 0.0;
690 :
691 0 : if (itransposed == 1)
692 : {
693 : printf("Warning- did not have a convair SIRC-style test dataset\n"
694 0 : "with transposed=1 for testing. Georefencing may be wrong.\n");
695 0 : dfnorth_center = dfnorth - nSamples*dfsample_size/2.0;
696 0 : poDS->adfGeoTransform[0] = dfeast;
697 0 : poDS->adfGeoTransform[2] = dfsample_size_az;
698 0 : poDS->adfGeoTransform[3] = dfnorth;
699 0 : poDS->adfGeoTransform[4] = -1*dfsample_size;
700 : }
701 : else
702 : {
703 0 : dfnorth_center = dfnorth - nLines*dfsample_size/2.0;
704 0 : poDS->adfGeoTransform[0] = dfeast;
705 0 : poDS->adfGeoTransform[1] = dfsample_size_az;
706 0 : poDS->adfGeoTransform[3] = dfnorth;
707 0 : poDS->adfGeoTransform[5] = -1*dfsample_size;
708 : }
709 0 : if (dfnorth_center < 0)
710 0 : oUTM.SetUTM(iUTMZone, 0);
711 : else
712 0 : oUTM.SetUTM(iUTMZone, 1);
713 :
714 : /* Assuming WGS84 */
715 0 : oUTM.SetWellKnownGeogCS( "WGS84" );
716 0 : CPLFree( poDS->pszProjection );
717 0 : poDS->pszProjection = NULL;
718 0 : oUTM.exportToWkt( &(poDS->pszProjection) );
719 :
720 :
721 :
722 : }
723 1 : else if (iGeoParamsFound == 5)
724 : {
725 : int ngcp;
726 : double dfgcpLine, dfgcpPixel, dfgcpX, dfgcpY, dftemp;
727 :
728 1 : poDS->nGCPCount = 16;
729 1 : poDS->pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),poDS->nGCPCount);
730 1 : GDALInitGCPs(poDS->nGCPCount, poDS->pasGCPList);
731 :
732 17 : for( ngcp = 0; ngcp < 16; ngcp ++ )
733 : {
734 : char szID[32];
735 :
736 16 : sprintf(szID,"%d",ngcp+1);
737 16 : if (itransposed == 1)
738 : {
739 0 : if (ngcp < 4)
740 0 : dfgcpPixel = 0.0;
741 0 : else if (ngcp < 8)
742 0 : dfgcpPixel = nSamples/3.0;
743 0 : else if (ngcp < 12)
744 0 : dfgcpPixel = 2.0*nSamples/3.0;
745 : else
746 0 : dfgcpPixel = nSamples;
747 :
748 0 : dfgcpLine = nLines*( ngcp % 4 )/3.0;
749 :
750 0 : dftemp = dfnear_srd + (dfsample_size*dfgcpLine);
751 : /* -1 so that 0,0 maps to largest Y */
752 0 : dfgcpY = -1*sqrt( dftemp*dftemp - dfaltitude*dfaltitude );
753 0 : dfgcpX = dfgcpPixel*dfsample_size_az;
754 :
755 : }
756 : else
757 : {
758 16 : if (ngcp < 4)
759 4 : dfgcpLine = 0.0;
760 12 : else if (ngcp < 8)
761 4 : dfgcpLine = nLines/3.0;
762 8 : else if (ngcp < 12)
763 4 : dfgcpLine = 2.0*nLines/3.0;
764 : else
765 4 : dfgcpLine = nLines;
766 :
767 16 : dfgcpPixel = nSamples*( ngcp % 4 )/3.0;
768 :
769 16 : dftemp = dfnear_srd + (dfsample_size*dfgcpPixel);
770 16 : dfgcpX = sqrt( dftemp*dftemp - dfaltitude*dfaltitude );
771 16 : dfgcpY = (nLines - dfgcpLine)*dfsample_size_az;
772 :
773 : }
774 16 : poDS->pasGCPList[ngcp].dfGCPX = dfgcpX;
775 16 : poDS->pasGCPList[ngcp].dfGCPY = dfgcpY;
776 16 : poDS->pasGCPList[ngcp].dfGCPZ = 0.0;
777 :
778 16 : poDS->pasGCPList[ngcp].dfGCPPixel = dfgcpPixel;
779 16 : poDS->pasGCPList[ngcp].dfGCPLine = dfgcpLine;
780 :
781 16 : CPLFree(poDS->pasGCPList[ngcp].pszId);
782 16 : poDS->pasGCPList[ngcp].pszId = CPLStrdup( szID );
783 :
784 : }
785 :
786 1 : CPLFree(poDS->pszGCPProjection);
787 1 : poDS->pszGCPProjection = CPLStrdup("LOCAL_CS[\"Ground range view / unreferenced meters\",UNIT[\"Meter\",1.0]]");
788 :
789 : }
790 :
791 1 : CPLFree(pszWorkname);
792 :
793 1 : return poDS;
794 : }
795 :
796 0 : GDALDataset *CPGDataset::InitializeType3Dataset( const char *pszFilename )
797 : {
798 :
799 : char **papszHdrLines;
800 0 : int iLine, iBytesPerPixel = 0, iInterleave=-1;
801 0 : int nLines = 0, nSamples = 0, nBands = 0;
802 0 : int nError = 0;
803 :
804 : /* Parameters in geogratis geocoded images */
805 0 : int iUTMParamsFound = 0, iUTMZone=0;
806 0 : double dfnorth = 0.0, dfeast = 0.0, dfOffsetX = 0.0, dfOffsetY = 0.0;
807 0 : double dfxsize = 0.0, dfysize = 0.0;
808 :
809 0 : char* pszWorkname = CPLStrdup(pszFilename);
810 0 : AdjustFilename( &pszWorkname, "stokes", "img_def" );
811 0 : papszHdrLines = CSLLoad( pszWorkname );
812 :
813 0 : for( iLine = 0; papszHdrLines && papszHdrLines[iLine] != NULL; iLine++ )
814 : {
815 0 : char **papszTokens = CSLTokenizeString2( papszHdrLines[iLine],
816 : " \t",
817 0 : CSLT_HONOURSTRINGS & CSLT_ALLOWEMPTYTOKENS );
818 :
819 : /* Note: some cv580 file seem to have comments with #, hence the >=
820 : * instead of = for token checking, and the equalN for the corner.
821 : */
822 :
823 0 : if ( ( CSLCount( papszTokens ) >= 3 ) &&
824 0 : EQUAL(papszTokens[0],"data") &&
825 0 : EQUAL(papszTokens[1],"organization:"))
826 : {
827 :
828 0 : if( EQUALN(papszTokens[2], "BSQ", 3) )
829 0 : iInterleave = BSQ;
830 0 : else if( EQUALN(papszTokens[2], "BIL", 3) )
831 0 : iInterleave = BIL;
832 0 : else if( EQUALN(papszTokens[2], "BIP", 3) )
833 0 : iInterleave = BIP;
834 : else
835 : {
836 : CPLError( CE_Failure, CPLE_AppDefined,
837 : "The interleaving type of the file (%s) is not supported.",
838 0 : papszTokens[2] );
839 0 : nError = 1;
840 : }
841 :
842 : }
843 0 : else if ( ( CSLCount( papszTokens ) >= 3 ) &&
844 0 : EQUAL(papszTokens[0],"data") &&
845 0 : EQUAL(papszTokens[1],"state:") )
846 : {
847 :
848 0 : if( !EQUALN(papszTokens[2], "RAW", 3) &&
849 0 : !EQUALN(papszTokens[2], "GEO", 3) )
850 : {
851 : CPLError( CE_Failure, CPLE_AppDefined,
852 : "The data state of the file (%s) is not supported.\n. Only RAW and GEO are currently recognized.",
853 0 : papszTokens[2] );
854 0 : nError = 1;
855 : }
856 :
857 :
858 : }
859 0 : else if ( ( CSLCount( papszTokens ) >= 4 ) &&
860 0 : EQUAL(papszTokens[0],"data") &&
861 0 : EQUAL(papszTokens[1],"origin") &&
862 0 : EQUAL(papszTokens[2],"point:") )
863 : {
864 0 : if (!EQUALN(papszTokens[3], "Upper_Left", 10))
865 : {
866 : CPLError( CE_Failure, CPLE_AppDefined,
867 : "Unexpected value (%s) for data origin point- expect Upper_Left.",
868 0 : papszTokens[3] );
869 0 : nError = 1;
870 : }
871 0 : iUTMParamsFound++;
872 : }
873 0 : else if ( ( CSLCount( papszTokens ) >= 5 ) &&
874 0 : EQUAL(papszTokens[0],"map") &&
875 0 : EQUAL(papszTokens[1],"projection:") &&
876 0 : EQUAL(papszTokens[2],"UTM") &&
877 0 : EQUAL(papszTokens[3],"zone") )
878 : {
879 0 : iUTMZone = atoi(papszTokens[4]);
880 0 : iUTMParamsFound++;
881 : }
882 0 : else if ( ( CSLCount( papszTokens ) >= 4 ) &&
883 0 : EQUAL(papszTokens[0],"project") &&
884 0 : EQUAL(papszTokens[1],"origin:") )
885 : {
886 0 : dfeast = atof(papszTokens[2]);
887 0 : dfnorth = atof(papszTokens[3]);
888 0 : iUTMParamsFound+=2;
889 : }
890 0 : else if ( ( CSLCount( papszTokens ) >= 4 ) &&
891 0 : EQUAL(papszTokens[0],"file") &&
892 0 : EQUAL(papszTokens[1],"start:"))
893 : {
894 0 : dfOffsetX = atof(papszTokens[2]);
895 0 : dfOffsetY = atof(papszTokens[3]);
896 0 : iUTMParamsFound+=2;
897 : }
898 0 : else if ( ( CSLCount( papszTokens ) >= 6 ) &&
899 0 : EQUAL(papszTokens[0],"pixel") &&
900 0 : EQUAL(papszTokens[1],"size") &&
901 0 : EQUAL(papszTokens[2],"on") &&
902 0 : EQUAL(papszTokens[3],"ground:"))
903 : {
904 0 : dfxsize = atof(papszTokens[4]);
905 0 : dfysize = atof(papszTokens[5]);
906 0 : iUTMParamsFound+=2;
907 :
908 : }
909 0 : else if ( ( CSLCount( papszTokens ) >= 4 ) &&
910 0 : EQUAL(papszTokens[0],"number") &&
911 0 : EQUAL(papszTokens[1],"of") &&
912 0 : EQUAL(papszTokens[2],"pixels:"))
913 : {
914 0 : nSamples = atoi(papszTokens[3]);
915 : }
916 0 : else if ( ( CSLCount( papszTokens ) >= 4 ) &&
917 0 : EQUAL(papszTokens[0],"number") &&
918 0 : EQUAL(papszTokens[1],"of") &&
919 0 : EQUAL(papszTokens[2],"lines:"))
920 : {
921 0 : nLines = atoi(papszTokens[3]);
922 : }
923 0 : else if ( ( CSLCount( papszTokens ) >= 4 ) &&
924 0 : EQUAL(papszTokens[0],"number") &&
925 0 : EQUAL(papszTokens[1],"of") &&
926 0 : EQUAL(papszTokens[2],"bands:"))
927 : {
928 0 : nBands = atoi(papszTokens[3]);
929 0 : if ( nBands != 16)
930 : {
931 : CPLError( CE_Failure, CPLE_AppDefined,
932 : "Number of bands has a value %s which does not match CPG driver\nexpectation (expect a value of 16).",
933 0 : papszTokens[3] );
934 0 : nError = 1;
935 : }
936 : }
937 0 : else if ( ( CSLCount( papszTokens ) >= 4 ) &&
938 0 : EQUAL(papszTokens[0],"bytes") &&
939 0 : EQUAL(papszTokens[1],"per") &&
940 0 : EQUAL(papszTokens[2],"pixel:"))
941 : {
942 0 : iBytesPerPixel = atoi(papszTokens[3]);
943 0 : if (iBytesPerPixel != 4)
944 : {
945 : CPLError( CE_Failure, CPLE_AppDefined,
946 : "Bytes per pixel has a value %s which does not match CPG driver\nexpectation (expect a value of 4).",
947 0 : papszTokens[1] );
948 0 : nError = 1;
949 : }
950 : }
951 0 : CSLDestroy( papszTokens );
952 : }
953 :
954 0 : CSLDestroy( papszHdrLines );
955 :
956 : /* -------------------------------------------------------------------- */
957 : /* Check for successful completion. */
958 : /* -------------------------------------------------------------------- */
959 0 : if( nError )
960 : {
961 0 : CPLFree(pszWorkname);
962 0 : return NULL;
963 : }
964 :
965 0 : if (!GDALCheckDatasetDimensions(nSamples, nLines) ||
966 : !GDALCheckBandCount(nBands, FALSE) || iInterleave == -1 ||
967 : iBytesPerPixel == 0 )
968 : {
969 : CPLError( CE_Failure, CPLE_AppDefined,
970 : "%s is missing a required parameter (number of pixels, number of lines,\nnumber of bands, bytes per pixel, or data organization).",
971 0 : pszWorkname );
972 0 : CPLFree(pszWorkname);
973 0 : return NULL;
974 : }
975 :
976 : /* -------------------------------------------------------------------- */
977 : /* Initialize dataset. */
978 : /* -------------------------------------------------------------------- */
979 0 : int iBand=0;
980 : CPGDataset *poDS;
981 :
982 0 : poDS = new CPGDataset();
983 :
984 0 : poDS->nRasterXSize = nSamples;
985 0 : poDS->nRasterYSize = nLines;
986 :
987 0 : if( iInterleave == BSQ )
988 0 : poDS->nInterleave = BSQ;
989 0 : else if( iInterleave == BIL )
990 0 : poDS->nInterleave = BIL;
991 : else
992 0 : poDS->nInterleave = BIP;
993 :
994 : /* -------------------------------------------------------------------- */
995 : /* Open the 16 bands. */
996 : /* -------------------------------------------------------------------- */
997 :
998 0 : AdjustFilename( &pszWorkname, "stokes" , "img" );
999 0 : poDS->afpImage[0] = VSIFOpen( pszWorkname, "rb" );
1000 0 : if( poDS->afpImage[0] == NULL )
1001 : {
1002 : CPLError( CE_Failure, CPLE_OpenFailed,
1003 : "Failed to open .img file: %s",
1004 0 : pszWorkname );
1005 0 : CPLFree(pszWorkname);
1006 0 : delete poDS;
1007 0 : return NULL;
1008 : }
1009 0 : for( iBand = 0; iBand < 16; iBand++ )
1010 : {
1011 : CPG_STOKESRasterBand *poBand;
1012 :
1013 : poBand = new CPG_STOKESRasterBand( poDS, iBand+1, GDT_CFloat32,
1014 0 : !CPL_IS_LSB );
1015 0 : poDS->SetBand( iBand+1, poBand );
1016 : }
1017 :
1018 : /* -------------------------------------------------------------------- */
1019 : /* Set appropriate MATRIX_REPRESENTATION. */
1020 : /* -------------------------------------------------------------------- */
1021 0 : if ( poDS->GetRasterCount() == 6 ) {
1022 : poDS->SetMetadataItem( "MATRIX_REPRESENTATION",
1023 0 : "COVARIANCE" );
1024 : }
1025 :
1026 :
1027 : /* ------------------------------------------------------------------------- */
1028 : /* Add georeferencing, if enough information found. */
1029 : /* ------------------------------------------------------------------------- */
1030 0 : if (iUTMParamsFound == 8)
1031 : {
1032 0 : OGRSpatialReference oUTM;
1033 : double dfnorth_center;
1034 :
1035 :
1036 0 : dfnorth_center = dfnorth - nLines*dfysize/2.0;
1037 0 : poDS->adfGeoTransform[0] = dfeast + dfOffsetX;
1038 0 : poDS->adfGeoTransform[1] = dfxsize;
1039 0 : poDS->adfGeoTransform[2] = 0.0;
1040 0 : poDS->adfGeoTransform[3] = dfnorth + dfOffsetY;
1041 0 : poDS->adfGeoTransform[4] = 0.0;
1042 0 : poDS->adfGeoTransform[5] = -1*dfysize;
1043 :
1044 0 : if (dfnorth_center < 0)
1045 0 : oUTM.SetUTM(iUTMZone, 0);
1046 : else
1047 0 : oUTM.SetUTM(iUTMZone, 1);
1048 :
1049 : /* Assuming WGS84 */
1050 0 : oUTM.SetWellKnownGeogCS( "WGS84" );
1051 0 : CPLFree( poDS->pszProjection );
1052 0 : poDS->pszProjection = NULL;
1053 0 : oUTM.exportToWkt( &(poDS->pszProjection) );
1054 : }
1055 :
1056 0 : return poDS;
1057 : }
1058 :
1059 : /************************************************************************/
1060 : /* Open() */
1061 : /************************************************************************/
1062 :
1063 11982 : GDALDataset *CPGDataset::Open( GDALOpenInfo * poOpenInfo )
1064 :
1065 : {
1066 : /* -------------------------------------------------------------------- */
1067 : /* Is this a PolGASP fileset? We expect fileset to follow */
1068 : /* one of these patterns: */
1069 : /* 1) <stuff>hh<stuff2>.img, <stuff>hh<stuff2>.hdr, */
1070 : /* <stuff>hv<stuff2>.img, <stuff>hv<stuff2>.hdr, */
1071 : /* <stuff>vh<stuff2>.img, <stuff>vh<stuff2>.hdr, */
1072 : /* <stuff>vv<stuff2>.img, <stuff>vv<stuff2>.hdr, */
1073 : /* where <stuff> or <stuff2> should contain the */
1074 : /* substring "sso" or "polgasp" */
1075 : /* 2) <stuff>SIRC.hdr and <stuff>SIRC.img */
1076 : /* 3) <stuff>.img and <stuff>.img_def */
1077 : /* where <stuff> should contain the */
1078 : /* substring "sso" or "polgasp" */
1079 : /* -------------------------------------------------------------------- */
1080 11982 : int nNameLen = strlen(poOpenInfo->pszFilename);
1081 11982 : int CPGType = 0;
1082 :
1083 11982 : if ( FindType1( poOpenInfo->pszFilename ))
1084 0 : CPGType = 1;
1085 11982 : else if ( FindType2( poOpenInfo->pszFilename ))
1086 1 : CPGType = 2;
1087 :
1088 : /* Stokes matrix convair data: not quite working yet- something
1089 : * is wrong in the interpretation of the matrix elements in terms
1090 : * of hh, hv, vv, vh. Data will load if the next two lines are
1091 : * uncommented, but values will be incorrect. Expect C11 = hh*conj(hh),
1092 : * C12 = hh*conj(hv), etc. Used geogratis data in both scattering
1093 : * matrix and stokes format for comparison.
1094 : */
1095 : //else if ( FindType3( poOpenInfo->pszFilename ))
1096 : // CPGType = 3;
1097 :
1098 : /* Set working name back to original */
1099 :
1100 11982 : if ( CPGType == 0 )
1101 : {
1102 11981 : nNameLen = strlen(poOpenInfo->pszFilename);
1103 11981 : if ( (nNameLen > 8) &&
1104 : ( ( strstr(poOpenInfo->pszFilename,"sso") != NULL ) ||
1105 : ( strstr(poOpenInfo->pszFilename,"polgasp") != NULL ) ) &&
1106 : ( EQUAL(poOpenInfo->pszFilename+nNameLen-4,"img") ||
1107 : EQUAL(poOpenInfo->pszFilename+nNameLen-4,"hdr") ||
1108 : EQUAL(poOpenInfo->pszFilename+nNameLen-7,"img_def") ) )
1109 : {
1110 : CPLError( CE_Failure, CPLE_OpenFailed,
1111 : "Apparent attempt to open Convair PolGASP data failed as\n"
1112 : "one or more of the required files is missing (eight files\n"
1113 0 : "are expected for scattering matrix format, two for Stokes)." );
1114 : }
1115 11981 : else if ( (nNameLen > 8) &&
1116 : ( strstr(poOpenInfo->pszFilename,"SIRC") != NULL ) &&
1117 : ( EQUAL(poOpenInfo->pszFilename+nNameLen-4,"img") ||
1118 : EQUAL(poOpenInfo->pszFilename+nNameLen-4,"hdr")))
1119 : {
1120 : CPLError( CE_Failure, CPLE_OpenFailed,
1121 : "Apparent attempt to open SIRC Convair PolGASP data failed \n"
1122 0 : "as one of the expected files is missing (hdr or img)!" );
1123 : }
1124 11981 : return NULL;
1125 : }
1126 :
1127 : /* -------------------------------------------------------------------- */
1128 : /* Confirm the requested access is supported. */
1129 : /* -------------------------------------------------------------------- */
1130 1 : if( poOpenInfo->eAccess == GA_Update )
1131 : {
1132 : CPLError( CE_Failure, CPLE_NotSupported,
1133 : "The CPG driver does not support update access to existing"
1134 0 : " datasets.\n" );
1135 0 : return NULL;
1136 : }
1137 :
1138 : /* Read the header info and create the dataset */
1139 : CPGDataset *poDS;
1140 :
1141 1 : if ( CPGType < 3 )
1142 1 : poDS = (CPGDataset *) InitializeType1Or2Dataset( poOpenInfo->pszFilename );
1143 : else
1144 0 : poDS = (CPGDataset *) InitializeType3Dataset( poOpenInfo->pszFilename );
1145 :
1146 1 : if (poDS == NULL)
1147 0 : return NULL;
1148 : /* -------------------------------------------------------------------- */
1149 : /* Check for overviews. */
1150 : /* -------------------------------------------------------------------- */
1151 : // Need to think about this.
1152 : // poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
1153 :
1154 : /* -------------------------------------------------------------------- */
1155 : /* Initialize any PAM information. */
1156 : /* -------------------------------------------------------------------- */
1157 1 : poDS->SetDescription( poOpenInfo->pszFilename );
1158 1 : poDS->TryLoadXML();
1159 :
1160 1 : return( poDS );
1161 : }
1162 :
1163 : /************************************************************************/
1164 : /* GetGCPCount() */
1165 : /************************************************************************/
1166 :
1167 0 : int CPGDataset::GetGCPCount()
1168 :
1169 : {
1170 0 : return nGCPCount;
1171 : }
1172 :
1173 : /************************************************************************/
1174 : /* GetGCPProjection() */
1175 : /************************************************************************/
1176 :
1177 0 : const char *CPGDataset::GetGCPProjection()
1178 :
1179 : {
1180 0 : return pszGCPProjection;
1181 : }
1182 :
1183 : /************************************************************************/
1184 : /* GetGCPs() */
1185 : /************************************************************************/
1186 :
1187 0 : const GDAL_GCP *CPGDataset::GetGCPs()
1188 :
1189 : {
1190 0 : return pasGCPList;
1191 : }
1192 :
1193 : /************************************************************************/
1194 : /* GetProjectionRef() */
1195 : /************************************************************************/
1196 :
1197 0 : const char *CPGDataset::GetProjectionRef()
1198 :
1199 : {
1200 0 : return( pszProjection );
1201 : }
1202 :
1203 : /************************************************************************/
1204 : /* GetGeoTransform() */
1205 : /************************************************************************/
1206 :
1207 0 : CPLErr CPGDataset::GetGeoTransform( double * padfTransform )
1208 :
1209 : {
1210 0 : memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
1211 0 : return( CE_None );
1212 : }
1213 :
1214 : /************************************************************************/
1215 : /* SIRC_QSLCRasterBand() */
1216 : /************************************************************************/
1217 :
1218 4 : SIRC_QSLCRasterBand::SIRC_QSLCRasterBand( CPGDataset *poGDS, int nBand,
1219 4 : GDALDataType eType )
1220 :
1221 : {
1222 4 : this->poDS = poGDS;
1223 4 : this->nBand = nBand;
1224 :
1225 4 : eDataType = eType;
1226 :
1227 4 : nBlockXSize = poGDS->nRasterXSize;
1228 4 : nBlockYSize = 1;
1229 :
1230 4 : if( nBand == 1 )
1231 1 : SetMetadataItem( "POLARIMETRIC_INTERP", "HH" );
1232 3 : else if( nBand == 2 )
1233 1 : SetMetadataItem( "POLARIMETRIC_INTERP", "HV" );
1234 2 : else if( nBand == 3 )
1235 1 : SetMetadataItem( "POLARIMETRIC_INTERP", "VH" );
1236 1 : else if( nBand == 4 )
1237 1 : SetMetadataItem( "POLARIMETRIC_INTERP", "VV" );
1238 4 : }
1239 :
1240 : /************************************************************************/
1241 : /* IReadBlock() */
1242 : /************************************************************************/
1243 :
1244 : /* From: http://southport.jpl.nasa.gov/software/dcomp/dcomp.html
1245 :
1246 : ysca = sqrt{ [ (Byte(2) / 254 ) + 1.5] 2Byte(1) }
1247 :
1248 : Re(SHH) = byte(3) ysca/127
1249 :
1250 : Im(SHH) = byte(4) ysca/127
1251 :
1252 : Re(SHV) = byte(5) ysca/127
1253 :
1254 : Im(SHV) = byte(6) ysca/127
1255 :
1256 : Re(SVH) = byte(7) ysca/127
1257 :
1258 : Im(SVH) = byte(8) ysca/127
1259 :
1260 : Re(SVV) = byte(9) ysca/127
1261 :
1262 : Im(SVV) = byte(10) ysca/127
1263 :
1264 : */
1265 :
1266 1 : CPLErr SIRC_QSLCRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
1267 : void * pImage )
1268 :
1269 : {
1270 1 : int offset, nBytesPerSample=10;
1271 : GByte *pabyRecord;
1272 1 : CPGDataset *poGDS = (CPGDataset *) poDS;
1273 : static float afPowTable[256];
1274 : static int bPowTableInitialized = FALSE;
1275 :
1276 1 : offset = nBlockXSize* nBlockYOff*nBytesPerSample;
1277 :
1278 : /* -------------------------------------------------------------------- */
1279 : /* Load all the pixel data associated with this scanline. */
1280 : /* -------------------------------------------------------------------- */
1281 1 : int nBytesToRead = nBytesPerSample * nBlockXSize;
1282 :
1283 1 : pabyRecord = (GByte *) CPLMalloc( nBytesToRead );
1284 :
1285 1 : if( VSIFSeek( poGDS->afpImage[0], offset, SEEK_SET ) != 0
1286 : || (int) VSIFRead( pabyRecord, 1, nBytesToRead,
1287 : poGDS->afpImage[0] ) != nBytesToRead )
1288 : {
1289 : CPLError( CE_Failure, CPLE_FileIO,
1290 : "Error reading %d bytes of SIRC Convair at offset %d.\n"
1291 : "Reading file %s failed.",
1292 0 : nBytesToRead, offset, poGDS->GetDescription() );
1293 0 : CPLFree( pabyRecord );
1294 0 : return CE_Failure;
1295 : }
1296 :
1297 : /* -------------------------------------------------------------------- */
1298 : /* Initialize our power table if this is our first time through. */
1299 : /* -------------------------------------------------------------------- */
1300 1 : if( !bPowTableInitialized )
1301 : {
1302 : int i;
1303 :
1304 1 : bPowTableInitialized = TRUE;
1305 :
1306 257 : for( i = 0; i < 256; i++ )
1307 : {
1308 256 : afPowTable[i] = (float) pow( 2.0, i-128 );
1309 : }
1310 : }
1311 :
1312 : /* -------------------------------------------------------------------- */
1313 : /* Copy the desired band out based on the size of the type, and */
1314 : /* the interleaving mode. */
1315 : /* -------------------------------------------------------------------- */
1316 : int iX;
1317 :
1318 2 : for( iX = 0; iX < nBlockXSize; iX++ )
1319 : {
1320 1 : unsigned char *pabyGroup = pabyRecord + iX * nBytesPerSample;
1321 1 : signed char *Byte = (signed char*)pabyGroup-1; /* A ones based alias */
1322 : double dfReSHH, dfImSHH, dfReSHV, dfImSHV,
1323 : dfReSVH, dfImSVH, dfReSVV, dfImSVV, dfScale;
1324 :
1325 1 : dfScale = sqrt( (Byte[2] / 254 + 1.5) * afPowTable[Byte[1] + 128] );
1326 :
1327 1 : if( nBand == 1 )
1328 : {
1329 1 : dfReSHH = Byte[3] * dfScale / 127.0;
1330 1 : dfImSHH = Byte[4] * dfScale / 127.0;
1331 :
1332 1 : ((float *) pImage)[iX*2 ] = (float) dfReSHH;
1333 1 : ((float *) pImage)[iX*2+1] = (float) dfImSHH;
1334 : }
1335 0 : else if( nBand == 2 )
1336 : {
1337 0 : dfReSHV = Byte[5] * dfScale / 127.0;
1338 0 : dfImSHV = Byte[6] * dfScale / 127.0;
1339 :
1340 0 : ((float *) pImage)[iX*2 ] = (float) dfReSHV;
1341 0 : ((float *) pImage)[iX*2+1] = (float) dfImSHV;
1342 : }
1343 0 : else if( nBand == 3 )
1344 : {
1345 0 : dfReSVH = Byte[7] * dfScale / 127.0;
1346 0 : dfImSVH = Byte[8] * dfScale / 127.0;
1347 :
1348 0 : ((float *) pImage)[iX*2 ] = (float) dfReSVH;
1349 0 : ((float *) pImage)[iX*2+1] = (float) dfImSVH;
1350 : }
1351 0 : else if( nBand == 4 )
1352 : {
1353 0 : dfReSVV = Byte[9] * dfScale / 127.0;
1354 0 : dfImSVV = Byte[10]* dfScale / 127.0;
1355 :
1356 0 : ((float *) pImage)[iX*2 ] = (float) dfReSVV;
1357 0 : ((float *) pImage)[iX*2+1] = (float) dfImSVV;
1358 : }
1359 : }
1360 :
1361 1 : CPLFree( pabyRecord );
1362 :
1363 1 : return CE_None;
1364 : }
1365 :
1366 : /************************************************************************/
1367 : /* CPG_STOKESRasterBand() */
1368 : /************************************************************************/
1369 :
1370 0 : CPG_STOKESRasterBand::CPG_STOKESRasterBand( GDALDataset *poDS, int nBand,
1371 : GDALDataType eType,
1372 0 : int bNativeOrder )
1373 :
1374 : {
1375 : static const char *apszPolarizations[16] = { "Covariance_11",
1376 : "Covariance_12",
1377 : "Covariance_13",
1378 : "Covariance_14",
1379 : "Covariance_21",
1380 : "Covariance_22",
1381 : "Covariance_23",
1382 : "Covariance_24",
1383 : "Covariance_31",
1384 : "Covariance_32",
1385 : "Covariance_33",
1386 : "Covariance_34",
1387 : "Covariance_41",
1388 : "Covariance_42",
1389 : "Covariance_43",
1390 : "Covariance_44" };
1391 :
1392 0 : this->poDS = poDS;
1393 0 : this->nBand = nBand;
1394 0 : this->eDataType = eType;
1395 0 : this->bNativeOrder = bNativeOrder;
1396 :
1397 0 : nBlockXSize = poDS->GetRasterXSize();
1398 0 : nBlockYSize = 1;
1399 :
1400 0 : SetMetadataItem( "POLARIMETRIC_INTERP",apszPolarizations[nBand-1] );
1401 0 : SetDescription( apszPolarizations[nBand-1] );
1402 0 : }
1403 :
1404 : /************************************************************************/
1405 : /* ~CPG_STOKESRasterBand() */
1406 : /************************************************************************/
1407 :
1408 0 : CPG_STOKESRasterBand::~CPG_STOKESRasterBand()
1409 :
1410 : {
1411 0 : }
1412 :
1413 : /************************************************************************/
1414 : /* IReadBlock() */
1415 : /************************************************************************/
1416 :
1417 : /* Convert from Stokes to Covariance representation */
1418 :
1419 0 : CPLErr CPG_STOKESRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
1420 : void * pImage )
1421 :
1422 : {
1423 : int iPixel;
1424 : int m11, m12, m13, m14, m21, m22, m23, m24, step;
1425 : int m31, m32, m33, m34, m41, m42, m43, m44;
1426 0 : CPGDataset *poGDS = (CPGDataset *) poDS;
1427 : float *M;
1428 : float *pafLine;
1429 : CPLErr eErr;
1430 :
1431 0 : CPLAssert( nBlockXOff == 0 );
1432 :
1433 0 : eErr = poGDS->LoadStokesLine(nBlockYOff, bNativeOrder);
1434 0 : if( eErr != CE_None )
1435 0 : return eErr;
1436 :
1437 0 : M = poGDS->padfStokesMatrix;
1438 0 : pafLine = ( float * ) pImage;
1439 :
1440 0 : if ( poGDS->nInterleave == BIP)
1441 : {
1442 0 : step = 16;
1443 0 : m11 = M11;
1444 0 : m12 = M12;
1445 0 : m13 = M13;
1446 0 : m14 = M14;
1447 0 : m21 = M21;
1448 0 : m22 = M22;
1449 0 : m23 = M23;
1450 0 : m24 = M24;
1451 0 : m31 = M31;
1452 0 : m32 = M32;
1453 0 : m33 = M33;
1454 0 : m34 = M34;
1455 0 : m41 = M41;
1456 0 : m42 = M42;
1457 0 : m43 = M43;
1458 0 : m44 = M44;
1459 : }
1460 : else
1461 : {
1462 0 : step = 1;
1463 0 : m11=0;
1464 0 : m12=nRasterXSize;
1465 0 : m13=nRasterXSize*2;
1466 0 : m14=nRasterXSize*3;
1467 0 : m21=nRasterXSize*4;
1468 0 : m22=nRasterXSize*5;
1469 0 : m23=nRasterXSize*6;
1470 0 : m24=nRasterXSize*7;
1471 0 : m31=nRasterXSize*8;
1472 0 : m32=nRasterXSize*9;
1473 0 : m33=nRasterXSize*10;
1474 0 : m34=nRasterXSize*11;
1475 0 : m41=nRasterXSize*12;
1476 0 : m42=nRasterXSize*13;
1477 0 : m43=nRasterXSize*14;
1478 0 : m44=nRasterXSize*15;
1479 : }
1480 0 : if ( nBand == 1 ) /* C11 */
1481 : {
1482 0 : for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
1483 : {
1484 0 : pafLine[iPixel*2+0] = M[m11]-M[m22]-M[m33]+M[m44];
1485 0 : pafLine[iPixel*2+1] = 0.0;
1486 0 : m11 += step;
1487 0 : m22 += step;
1488 0 : m33 += step;
1489 0 : m44 += step;
1490 : }
1491 : }
1492 0 : else if ( nBand == 2 ) /* C12 */
1493 : {
1494 0 : for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
1495 : {
1496 0 : pafLine[iPixel*2+0] = M[m13]-M[m23];
1497 0 : pafLine[iPixel*2+1] = M[m14]-M[m24];
1498 0 : m13 += step;
1499 0 : m23 += step;
1500 0 : m14 += step;
1501 0 : m24 += step;
1502 : }
1503 : }
1504 0 : else if ( nBand == 3 ) /* C13 */
1505 : {
1506 0 : for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
1507 : {
1508 0 : pafLine[iPixel*2+0] = M[m33]-M[m44];
1509 0 : pafLine[iPixel*2+1] = M[m43]+M[m34];
1510 0 : m33 += step;
1511 0 : m44 += step;
1512 0 : m43 += step;
1513 0 : m34 += step;
1514 : }
1515 : }
1516 0 : else if ( nBand == 4 ) /* C14 */
1517 : {
1518 0 : for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
1519 : {
1520 0 : pafLine[iPixel*2+0] = M[m31]-M[m32];
1521 0 : pafLine[iPixel*2+1] = M[m41]-M[m42];
1522 0 : m31 += step;
1523 0 : m32 += step;
1524 0 : m41 += step;
1525 0 : m42 += step;
1526 : }
1527 : }
1528 0 : else if ( nBand == 5 ) /* C21 */
1529 : {
1530 0 : for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
1531 : {
1532 0 : pafLine[iPixel*2+0] = M[m13]-M[m23];
1533 0 : pafLine[iPixel*2+1] = M[m24]-M[m14];
1534 0 : m13 += step;
1535 0 : m23 += step;
1536 0 : m14 += step;
1537 0 : m24 += step;
1538 : }
1539 : }
1540 0 : else if ( nBand == 6 ) /* C22 */
1541 : {
1542 0 : for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
1543 : {
1544 0 : pafLine[iPixel*2+0] = M[m11]+M[m22]-M[m33]-M[m44];
1545 0 : pafLine[iPixel*2+1] = 0.0;
1546 0 : m11 += step;
1547 0 : m22 += step;
1548 0 : m33 += step;
1549 0 : m44 += step;
1550 : }
1551 : }
1552 0 : else if ( nBand == 7 ) /* C23 */
1553 : {
1554 0 : for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
1555 : {
1556 0 : pafLine[iPixel*2+0] = M[m31]+M[m32];
1557 0 : pafLine[iPixel*2+1] = M[m41]+M[m42];
1558 0 : m31 += step;
1559 0 : m32 += step;
1560 0 : m41 += step;
1561 0 : m42 += step;
1562 : }
1563 : }
1564 0 : else if ( nBand == 8 ) /* C24 */
1565 : {
1566 0 : for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
1567 : {
1568 0 : pafLine[iPixel*2+0] = M[m33]+M[m44];
1569 0 : pafLine[iPixel*2+1] = M[m43]-M[m34];
1570 0 : m33 += step;
1571 0 : m44 += step;
1572 0 : m43 += step;
1573 0 : m34 += step;
1574 : }
1575 : }
1576 0 : else if ( nBand == 9 ) /* C31 */
1577 : {
1578 0 : for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
1579 : {
1580 0 : pafLine[iPixel*2+0] = M[m33]-M[m44];
1581 0 : pafLine[iPixel*2+1] = -1*M[m43]-M[m34];
1582 0 : m33 += step;
1583 0 : m44 += step;
1584 0 : m43 += step;
1585 0 : m34 += step;
1586 : }
1587 : }
1588 0 : else if ( nBand == 10 ) /* C32 */
1589 : {
1590 0 : for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
1591 : {
1592 0 : pafLine[iPixel*2+0] = M[m31]+M[m32];
1593 0 : pafLine[iPixel*2+1] = -1*M[m41]-M[m42];
1594 0 : m31 += step;
1595 0 : m32 += step;
1596 0 : m41 += step;
1597 0 : m42 += step;
1598 : }
1599 : }
1600 0 : else if ( nBand == 11 ) /* C33 */
1601 : {
1602 0 : for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
1603 : {
1604 0 : pafLine[iPixel*2+0] = M[m11]+M[m22]+M[m33]+M[m44];
1605 0 : pafLine[iPixel*2+1] = 0.0;
1606 0 : m11 += step;
1607 0 : m22 += step;
1608 0 : m33 += step;
1609 0 : m44 += step;
1610 : }
1611 :
1612 : }
1613 0 : else if ( nBand == 12 ) /* C34 */
1614 : {
1615 0 : for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
1616 : {
1617 0 : pafLine[iPixel*2+0] = M[m13]-M[m23];
1618 0 : pafLine[iPixel*2+1] = -1*M[m14]-M[m24];
1619 0 : m13 += step;
1620 0 : m23 += step;
1621 0 : m14 += step;
1622 0 : m24 += step;
1623 : }
1624 : }
1625 0 : else if ( nBand == 13 ) /* C41 */
1626 : {
1627 0 : for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
1628 : {
1629 0 : pafLine[iPixel*2+0] = M[m31]-M[m32];
1630 0 : pafLine[iPixel*2+1] = M[m42]-M[m41];
1631 0 : m31 += step;
1632 0 : m32 += step;
1633 0 : m41 += step;
1634 0 : m42 += step;
1635 : }
1636 : }
1637 0 : else if ( nBand == 14 ) /* C42 */
1638 : {
1639 0 : for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
1640 : {
1641 0 : pafLine[iPixel*2+0] = M[m33]+M[m44];
1642 0 : pafLine[iPixel*2+1] = M[m34]-M[m43];
1643 0 : m33 += step;
1644 0 : m44 += step;
1645 0 : m43 += step;
1646 0 : m34 += step;
1647 : }
1648 : }
1649 0 : else if ( nBand == 15 ) /* C43 */
1650 : {
1651 0 : for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
1652 : {
1653 0 : pafLine[iPixel*2+0] = M[m13]-M[m23];
1654 0 : pafLine[iPixel*2+1] = M[m14]+M[m24];
1655 0 : m13 += step;
1656 0 : m23 += step;
1657 0 : m14 += step;
1658 0 : m24 += step;
1659 : }
1660 : }
1661 : else /* C44 */
1662 : {
1663 0 : for ( iPixel = 0; iPixel < nRasterXSize; iPixel++ )
1664 : {
1665 0 : pafLine[iPixel*2+0] = M[m11]-M[m22]+M[m33]-M[m44];
1666 0 : pafLine[iPixel*2+1] = 0.0;
1667 0 : m11 += step;
1668 0 : m22 += step;
1669 0 : m33 += step;
1670 0 : m44 += step;
1671 : }
1672 : }
1673 :
1674 0 : return CE_None;
1675 : }
1676 :
1677 : /************************************************************************/
1678 : /* GDALRegister_CPG() */
1679 : /************************************************************************/
1680 :
1681 582 : void GDALRegister_CPG()
1682 :
1683 : {
1684 : GDALDriver *poDriver;
1685 :
1686 582 : if( GDALGetDriverByName( "CPG" ) == NULL )
1687 : {
1688 561 : poDriver = new GDALDriver();
1689 :
1690 561 : poDriver->SetDescription( "CPG" );
1691 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
1692 561 : "Convair PolGASP" );
1693 :
1694 561 : poDriver->pfnOpen = CPGDataset::Open;
1695 :
1696 561 : GetGDALDriverManager()->RegisterDriver( poDriver );
1697 : }
1698 582 : }
1699 :
|