• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OSGeo / gdal / 13741725950

08 Mar 2025 09:43PM UTC coverage: 70.343% (-0.002%) from 70.345%
13741725950

Pull #11933

github

web-flow
Merge d1b82d9e2 into b047461f3
Pull Request #11933: Doc: Fix axis order of points in osr.CoordinateTransformation examples

552732 of 785762 relevant lines covered (70.34%)

221540.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

39.61
/frmts/raw/cpgdataset.cpp
1
/******************************************************************************
2
 *
3
 * Project:  Polarimetric Workstation
4
 * Purpose:  Convair PolGASP data (.img/.hdr format).
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.com>
9
 * Copyright (c) 2009, Even Rouault <even dot rouault at spatialys.com>
10
 *
11
 * SPDX-License-Identifier: MIT
12
 ****************************************************************************/
13

14
#include "cpl_string.h"
15
#include "gdal_frmts.h"
16
#include "ogr_spatialref.h"
17
#include "rawdataset.h"
18

19
#include <vector>
20

21
/************************************************************************/
22
/* ==================================================================== */
23
/*                              CPGDataset                              */
24
/* ==================================================================== */
25
/************************************************************************/
26

27
class SIRC_QSLCRasterBand;
28
class CPG_STOKESRasterBand;
29

30
class CPGDataset final : public RawDataset
31
{
32
    friend class SIRC_QSLCRasterBand;
33
    friend class CPG_STOKESRasterBand;
34

35
    static constexpr int NUMBER_OF_BANDS = 4;
36
    std::vector<VSILFILE *> afpImage{NUMBER_OF_BANDS};
37
    std::vector<CPLString> aosImageFilenames{};
38

39
    int nGCPCount;
40
    GDAL_GCP *pasGCPList;
41
    OGRSpatialReference m_oGCPSRS{};
42

43
    double adfGeoTransform[6];
44
    OGRSpatialReference m_oSRS{};
45

46
    int nLoadedStokesLine;
47
    float *padfStokesMatrix;
48

49
    Interleave eInterleave = Interleave::BSQ;
50
    static int AdjustFilename(char **, const char *, const char *);
51
    static int FindType1(const char *pszWorkname);
52
    static int FindType2(const char *pszWorkname);
53
#ifdef notdef
54
    static int FindType3(const char *pszWorkname);
55
#endif
56
    static GDALDataset *InitializeType1Or2Dataset(const char *pszWorkname);
57
#ifdef notdef
58
    static GDALDataset *InitializeType3Dataset(const char *pszWorkname);
59
#endif
60
    CPLErr LoadStokesLine(int iLine, int bNativeOrder);
61

62
    CPL_DISALLOW_COPY_ASSIGN(CPGDataset)
63

64
    CPLErr Close() override;
65

66
  public:
67
    CPGDataset();
68
    ~CPGDataset() override;
69

70
    int GetGCPCount() override;
71

72
    const OGRSpatialReference *GetGCPSpatialRef() const override
×
73
    {
74
        return m_oGCPSRS.IsEmpty() ? nullptr : &m_oGCPSRS;
×
75
    }
76

77
    const GDAL_GCP *GetGCPs() override;
78

79
    const OGRSpatialReference *GetSpatialRef() const override
×
80
    {
81
        return m_oSRS.IsEmpty() ? nullptr : &m_oSRS;
×
82
    }
83

84
    CPLErr GetGeoTransform(double *) override;
85

86
    char **GetFileList() override;
87

88
    static GDALDataset *Open(GDALOpenInfo *);
89
};
90

91
/************************************************************************/
92
/*                            CPGDataset()                             */
93
/************************************************************************/
94

95
CPGDataset::CPGDataset()
2✔
96
    : nGCPCount(0), pasGCPList(nullptr), nLoadedStokesLine(-1),
97
      padfStokesMatrix(nullptr)
2✔
98
{
99
    m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
2✔
100
    m_oGCPSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
2✔
101
    adfGeoTransform[0] = 0.0;
2✔
102
    adfGeoTransform[1] = 1.0;
2✔
103
    adfGeoTransform[2] = 0.0;
2✔
104
    adfGeoTransform[3] = 0.0;
2✔
105
    adfGeoTransform[4] = 0.0;
2✔
106
    adfGeoTransform[5] = 1.0;
2✔
107
}
2✔
108

109
/************************************************************************/
110
/*                            ~CPGDataset()                            */
111
/************************************************************************/
112

113
CPGDataset::~CPGDataset()
4✔
114

115
{
116
    CPGDataset::Close();
2✔
117
}
4✔
118

119
/************************************************************************/
120
/*                              Close()                                 */
121
/************************************************************************/
122

123
CPLErr CPGDataset::Close()
4✔
124
{
125
    CPLErr eErr = CE_None;
4✔
126
    if (nOpenFlags != OPEN_FLAGS_CLOSED)
4✔
127
    {
128
        if (CPGDataset::FlushCache(true) != CE_None)
2✔
129
            eErr = CE_Failure;
×
130

131
        for (auto poFile : afpImage)
10✔
132
        {
133
            if (poFile != nullptr)
8✔
134
                VSIFCloseL(poFile);
2✔
135
        }
136

137
        if (nGCPCount > 0)
2✔
138
        {
139
            GDALDeinitGCPs(nGCPCount, pasGCPList);
2✔
140
            CPLFree(pasGCPList);
2✔
141
        }
142

143
        CPLFree(padfStokesMatrix);
2✔
144

145
        if (GDALPamDataset::Close() != CE_None)
2✔
146
            eErr = CE_Failure;
×
147
    }
148
    return eErr;
4✔
149
}
150

151
/************************************************************************/
152
/*                            GetFileList()                             */
153
/************************************************************************/
154

155
char **CPGDataset::GetFileList()
1✔
156

157
{
158
    char **papszFileList = RawDataset::GetFileList();
1✔
159
    for (size_t i = 0; i < aosImageFilenames.size(); ++i)
2✔
160
        papszFileList = CSLAddString(papszFileList, aosImageFilenames[i]);
1✔
161
    return papszFileList;
1✔
162
}
163

164
/************************************************************************/
165
/* ==================================================================== */
166
/*                          SIRC_QSLCPRasterBand                        */
167
/* ==================================================================== */
168
/************************************************************************/
169

170
class SIRC_QSLCRasterBand final : public GDALRasterBand
171
{
172
    friend class CPGDataset;
173

174
  public:
175
    SIRC_QSLCRasterBand(CPGDataset *, int, GDALDataType);
176

177
    ~SIRC_QSLCRasterBand() override
16✔
178
    {
8✔
179
    }
16✔
180

181
    CPLErr IReadBlock(int, int, void *) override;
182
};
183

184
constexpr int M11 = 0;
185
// constexpr int M12 = 1;
186
constexpr int M13 = 2;
187
constexpr int M14 = 3;
188
// constexpr int M21 = 4;
189
constexpr int M22 = 5;
190
constexpr int M23 = 6;
191
constexpr int M24 = 7;
192
constexpr int M31 = 8;
193
constexpr int M32 = 9;
194
constexpr int M33 = 10;
195
constexpr int M34 = 11;
196
constexpr int M41 = 12;
197
constexpr int M42 = 13;
198
constexpr int M43 = 14;
199
constexpr int M44 = 15;
200

201
/************************************************************************/
202
/* ==================================================================== */
203
/*                          CPG_STOKESRasterBand                        */
204
/* ==================================================================== */
205
/************************************************************************/
206

207
class CPG_STOKESRasterBand final : public GDALRasterBand
208
{
209
    friend class CPGDataset;
210

211
    int bNativeOrder;
212

213
  public:
214
    CPG_STOKESRasterBand(GDALDataset *poDS, GDALDataType eType,
215
                         int bNativeOrder);
216

217
    ~CPG_STOKESRasterBand() override
×
218
    {
×
219
    }
×
220

221
    CPLErr IReadBlock(int, int, void *) override;
222
};
223

224
/************************************************************************/
225
/*                           AdjustFilename()                           */
226
/*                                                                      */
227
/*      Try to find the file with the request polarization and          */
228
/*      extension and update the passed filename accordingly.           */
229
/*                                                                      */
230
/*      Return TRUE if file found otherwise FALSE.                      */
231
/************************************************************************/
232

233
int CPGDataset::AdjustFilename(char **pszFilename, const char *pszPolarization,
8✔
234
                               const char *pszExtension)
235

236
{
237
    // TODO: Eventually we should handle upper/lower case.
238
    if (EQUAL(pszPolarization, "stokes"))
8✔
239
    {
240
        const std::string osNewName =
241
            CPLResetExtensionSafe(*pszFilename, pszExtension);
×
242
        CPLFree(*pszFilename);
×
243
        *pszFilename = CPLStrdup(osNewName.c_str());
×
244
    }
245
    else if (strlen(pszPolarization) == 2)
8✔
246
    {
247
        char *subptr = strstr(*pszFilename, "hh");
2✔
248
        if (subptr == nullptr)
2✔
249
            subptr = strstr(*pszFilename, "hv");
2✔
250
        if (subptr == nullptr)
2✔
251
            subptr = strstr(*pszFilename, "vv");
2✔
252
        if (subptr == nullptr)
2✔
253
            subptr = strstr(*pszFilename, "vh");
2✔
254
        if (subptr == nullptr)
2✔
255
            return FALSE;
2✔
256

257
        strncpy(subptr, pszPolarization, 2);
×
258
        const std::string osNewName =
259
            CPLResetExtensionSafe(*pszFilename, pszExtension);
×
260
        CPLFree(*pszFilename);
×
261
        *pszFilename = CPLStrdup(osNewName.c_str());
×
262
    }
263
    else
264
    {
265
        const std::string osNewName =
266
            CPLResetExtensionSafe(*pszFilename, pszExtension);
6✔
267
        CPLFree(*pszFilename);
6✔
268
        *pszFilename = CPLStrdup(osNewName.c_str());
6✔
269
    }
270
    VSIStatBufL sStatBuf;
271
    return VSIStatL(*pszFilename, &sStatBuf) == 0;
6✔
272
}
273

274
/************************************************************************/
275
/*         Search for the various types of Convair filesets             */
276
/*         Return TRUE for a match, FALSE for no match                  */
277
/************************************************************************/
278
int CPGDataset::FindType1(const char *pszFilename)
29,301✔
279
{
280
    const int nNameLen = static_cast<int>(strlen(pszFilename));
29,301✔
281

282
    if ((strstr(pszFilename, "sso") == nullptr) &&
29,301✔
283
        (strstr(pszFilename, "polgasp") == nullptr))
29,295✔
284
        return FALSE;
29,299✔
285

286
    if ((strlen(pszFilename) < 5) ||
2✔
287
        (!EQUAL(pszFilename + nNameLen - 4, ".hdr") &&
×
288
         !EQUAL(pszFilename + nNameLen - 4, ".img")))
×
289
        return FALSE;
×
290

291
    /* Expect all bands and headers to be present */
292
    char *pszTemp = CPLStrdup(pszFilename);
2✔
293

294
    const bool bNotFound = !AdjustFilename(&pszTemp, "hh", "img") ||
×
295
                           !AdjustFilename(&pszTemp, "hh", "hdr") ||
×
296
                           !AdjustFilename(&pszTemp, "hv", "img") ||
×
297
                           !AdjustFilename(&pszTemp, "hv", "hdr") ||
×
298
                           !AdjustFilename(&pszTemp, "vh", "img") ||
×
299
                           !AdjustFilename(&pszTemp, "vh", "hdr") ||
×
300
                           !AdjustFilename(&pszTemp, "vv", "img") ||
×
301
                           !AdjustFilename(&pszTemp, "vv", "hdr");
×
302

303
    CPLFree(pszTemp);
×
304

305
    return !bNotFound;
×
306
}
307

308
int CPGDataset::FindType2(const char *pszFilename)
29,298✔
309
{
310
    const int nNameLen = static_cast<int>(strlen(pszFilename));
29,298✔
311

312
    if ((strlen(pszFilename) < 9) ||
29,298✔
313
        (!EQUAL(pszFilename + nNameLen - 8, "SIRC.hdr") &&
28,772✔
314
         !EQUAL(pszFilename + nNameLen - 8, "SIRC.img")))
28,775✔
315
        return FALSE;
29,296✔
316

317
    char *pszTemp = CPLStrdup(pszFilename);
2✔
318
    const bool bNotFound = !AdjustFilename(&pszTemp, "", "img") ||
4✔
319
                           !AdjustFilename(&pszTemp, "", "hdr");
2✔
320
    CPLFree(pszTemp);
2✔
321

322
    return !bNotFound;
2✔
323
}
324

325
#ifdef notdef
326
int CPGDataset::FindType3(const char *pszFilename)
327
{
328
    const int nNameLen = static_cast<int>(strlen(pszFilename));
329

330
    if ((strstr(pszFilename, "sso") == NULL) &&
331
        (strstr(pszFilename, "polgasp") == NULL))
332
        return FALSE;
333

334
    if ((strlen(pszFilename) < 9) ||
335
        (!EQUAL(pszFilename + nNameLen - 4, ".img") &&
336
         !EQUAL(pszFilename + nNameLen - 8, ".img_def")))
337
        return FALSE;
338

339
    char *pszTemp = CPLStrdup(pszFilename);
340
    const bool bNotFound = !AdjustFilename(&pszTemp, "stokes", "img") ||
341
                           !AdjustFilename(&pszTemp, "stokes", "img_def");
342
    CPLFree(pszTemp);
343

344
    return !bNotFound;
345
}
346
#endif
347

348
/************************************************************************/
349
/*                        LoadStokesLine()                              */
350
/************************************************************************/
351

352
CPLErr CPGDataset::LoadStokesLine(int iLine, int bNativeOrder)
×
353

354
{
355
    if (iLine == nLoadedStokesLine)
×
356
        return CE_None;
×
357

358
    const int nDataSize = GDALGetDataTypeSize(GDT_Float32) / 8;
×
359

360
    /* -------------------------------------------------------------------- */
361
    /*      allocate working buffers if we don't have them already.         */
362
    /* -------------------------------------------------------------------- */
363
    if (padfStokesMatrix == nullptr)
×
364
    {
365
        padfStokesMatrix = reinterpret_cast<float *>(
×
366
            CPLMalloc(sizeof(float) * nRasterXSize * 16));
×
367
    }
368

369
    /* -------------------------------------------------------------------- */
370
    /*      Load all the pixel data associated with this scanline.          */
371
    /*      Retains same interleaving as original dataset.                  */
372
    /* -------------------------------------------------------------------- */
373
    if (eInterleave == Interleave::BIP)
×
374
    {
375
        const int offset = nRasterXSize * iLine * nDataSize * 16;
×
376
        const int nBytesToRead = nDataSize * nRasterXSize * 16;
×
377
        if ((VSIFSeekL(afpImage[0], offset, SEEK_SET) != 0) ||
×
378
            static_cast<int>(
379
                VSIFReadL(reinterpret_cast<GByte *>(padfStokesMatrix), 1,
×
380
                          nBytesToRead, afpImage[0])) != nBytesToRead)
×
381
        {
382
            CPLError(CE_Failure, CPLE_FileIO,
×
383
                     "Error reading %d bytes of Stokes Convair at offset %d.\n"
384
                     "Reading file %s failed.",
385
                     nBytesToRead, offset, GetDescription());
×
386
            CPLFree(padfStokesMatrix);
×
387
            padfStokesMatrix = nullptr;
×
388
            nLoadedStokesLine = -1;
×
389
            return CE_Failure;
×
390
        }
391
    }
392
    else if (eInterleave == Interleave::BIL)
×
393
    {
394
        for (int band_index = 0; band_index < 16; band_index++)
×
395
        {
396
            const int offset =
×
397
                nDataSize * (nRasterXSize * iLine + nRasterXSize * band_index);
×
398
            const int nBytesToRead = nDataSize * nRasterXSize;
×
399
            if ((VSIFSeekL(afpImage[0], offset, SEEK_SET) != 0) ||
×
400
                static_cast<int>(
401
                    VSIFReadL(reinterpret_cast<GByte *>(
×
402
                                  padfStokesMatrix + nBytesToRead * band_index),
×
403
                              1, nBytesToRead, afpImage[0])) != nBytesToRead)
×
404
            {
405
                CPLError(
×
406
                    CE_Failure, CPLE_FileIO,
407
                    "Error reading %d bytes of Stokes Convair at offset %d.\n"
408
                    "Reading file %s failed.",
409
                    nBytesToRead, offset, GetDescription());
×
410
                CPLFree(padfStokesMatrix);
×
411
                padfStokesMatrix = nullptr;
×
412
                nLoadedStokesLine = -1;
×
413
                return CE_Failure;
×
414
            }
415
        }
416
    }
417
    else
418
    {
419
        for (int band_index = 0; band_index < 16; band_index++)
×
420
        {
421
            const int offset =
×
422
                nDataSize * (nRasterXSize * iLine +
×
423
                             nRasterXSize * nRasterYSize * band_index);
×
424
            const int nBytesToRead = nDataSize * nRasterXSize;
×
425
            if ((VSIFSeekL(afpImage[0], offset, SEEK_SET) != 0) ||
×
426
                static_cast<int>(
427
                    VSIFReadL(reinterpret_cast<GByte *>(
×
428
                                  padfStokesMatrix + nBytesToRead * band_index),
×
429
                              1, nBytesToRead, afpImage[0])) != nBytesToRead)
×
430
            {
431
                CPLError(
×
432
                    CE_Failure, CPLE_FileIO,
433
                    "Error reading %d bytes of Stokes Convair at offset %d.\n"
434
                    "Reading file %s failed.",
435
                    nBytesToRead, offset, GetDescription());
×
436
                CPLFree(padfStokesMatrix);
×
437
                padfStokesMatrix = nullptr;
×
438
                nLoadedStokesLine = -1;
×
439
                return CE_Failure;
×
440
            }
441
        }
442
    }
443

444
    if (!bNativeOrder)
×
445
        GDALSwapWords(padfStokesMatrix, nDataSize, nRasterXSize * 16,
×
446
                      nDataSize);
447

448
    nLoadedStokesLine = iLine;
×
449

450
    return CE_None;
×
451
}
452

453
/************************************************************************/
454
/*       Parse header information and initialize dataset for the        */
455
/*       appropriate Convair dataset style.                             */
456
/*       Returns dataset if successful; NULL if there was a problem.    */
457
/************************************************************************/
458

459
GDALDataset *CPGDataset::InitializeType1Or2Dataset(const char *pszFilename)
2✔
460
{
461

462
    /* -------------------------------------------------------------------- */
463
    /*      Read the .hdr file (the hh one for the .sso and polgasp cases)  */
464
    /*      and parse it.                                                   */
465
    /* -------------------------------------------------------------------- */
466
    int nLines = 0;
2✔
467
    int nSamples = 0;
2✔
468
    int nError = 0;
2✔
469

470
    /* Parameters required for pseudo-geocoding.  GCPs map */
471
    /* slant range to ground range at 16 points.           */
472
    int iGeoParamsFound = 0;
2✔
473
    int itransposed = 0;
2✔
474
    double dfaltitude = 0.0;
2✔
475
    double dfnear_srd = 0.0;
2✔
476
    double dfsample_size = 0.0;
2✔
477
    double dfsample_size_az = 0.0;
2✔
478

479
    /* Parameters in geogratis geocoded images */
480
    int iUTMParamsFound = 0;
2✔
481
    int iUTMZone = 0;
2✔
482
    // int iCorner = 0;
483
    double dfnorth = 0.0;
2✔
484
    double dfeast = 0.0;
2✔
485

486
    std::string osWorkName;
4✔
487
    {
488
        char *pszWorkname = CPLStrdup(pszFilename);
2✔
489
        AdjustFilename(&pszWorkname, "hh", "hdr");
2✔
490
        osWorkName = pszWorkname;
2✔
491
        CPLFree(pszWorkname);
2✔
492
    }
493

494
    char **papszHdrLines = CSLLoad(osWorkName.c_str());
2✔
495

496
    for (int iLine = 0; papszHdrLines && papszHdrLines[iLine] != nullptr;
16✔
497
         iLine++)
498
    {
499
        char **papszTokens = CSLTokenizeString(papszHdrLines[iLine]);
14✔
500

501
        /* Note: some cv580 file seem to have comments with #, hence the >=
502
         *       instead of = for token checking, and the equalN for the corner.
503
         */
504

505
        if (CSLCount(papszTokens) < 2)
14✔
506
        {
507
            /* ignore */;
508
        }
509
        else if ((CSLCount(papszTokens) >= 3) &&
14✔
510
                 EQUAL(papszTokens[0], "reference") &&
14✔
511
                 EQUAL(papszTokens[1], "north"))
×
512
        {
513
            dfnorth = CPLAtof(papszTokens[2]);
×
514
            iUTMParamsFound++;
×
515
        }
516
        else if ((CSLCount(papszTokens) >= 3) &&
14✔
517
                 EQUAL(papszTokens[0], "reference") &&
14✔
518
                 EQUAL(papszTokens[1], "east"))
×
519
        {
520
            dfeast = CPLAtof(papszTokens[2]);
×
521
            iUTMParamsFound++;
×
522
        }
523
        else if ((CSLCount(papszTokens) >= 5) &&
14✔
524
                 EQUAL(papszTokens[0], "reference") &&
×
525
                 EQUAL(papszTokens[1], "projection") &&
×
526
                 EQUAL(papszTokens[2], "UTM") && EQUAL(papszTokens[3], "zone"))
14✔
527
        {
528
            iUTMZone = atoi(papszTokens[4]);
×
529
            iUTMParamsFound++;
×
530
        }
531
        else if ((CSLCount(papszTokens) >= 3) &&
14✔
532
                 EQUAL(papszTokens[0], "reference") &&
×
533
                 EQUAL(papszTokens[1], "corner") &&
14✔
534
                 STARTS_WITH_CI(papszTokens[2], "Upper_Left"))
×
535
        {
536
            /* iCorner = 0; */
537
            iUTMParamsFound++;
×
538
        }
539
        else if (EQUAL(papszTokens[0], "number_lines"))
14✔
540
            nLines = atoi(papszTokens[1]);
2✔
541

542
        else if (EQUAL(papszTokens[0], "number_samples"))
12✔
543
            nSamples = atoi(papszTokens[1]);
2✔
544

545
        else if ((EQUAL(papszTokens[0], "header_offset") &&
10✔
546
                  atoi(papszTokens[1]) != 0) ||
×
547
                 (EQUAL(papszTokens[0], "number_channels") &&
10✔
548
                  (atoi(papszTokens[1]) != 1) &&
×
549
                  (atoi(papszTokens[1]) != 10)) ||
×
550
                 (EQUAL(papszTokens[0], "datatype") &&
10✔
551
                  atoi(papszTokens[1]) != 1) ||
×
552
                 (EQUAL(papszTokens[0], "number_format") &&
10✔
553
                  !EQUAL(papszTokens[1], "float32") &&
×
554
                  !EQUAL(papszTokens[1], "int8")))
×
555
        {
556
            CPLError(CE_Failure, CPLE_AppDefined,
×
557
                     "Keyword %s has value %s which does not match CPG driver "
558
                     "expectation.",
559
                     papszTokens[0], papszTokens[1]);
×
560
            nError = 1;
×
561
        }
562
        else if (EQUAL(papszTokens[0], "altitude"))
10✔
563
        {
564
            dfaltitude = CPLAtof(papszTokens[1]);
2✔
565
            iGeoParamsFound++;
2✔
566
        }
567
        else if (EQUAL(papszTokens[0], "near_srd"))
8✔
568
        {
569
            dfnear_srd = CPLAtof(papszTokens[1]);
2✔
570
            iGeoParamsFound++;
2✔
571
        }
572

573
        else if (EQUAL(papszTokens[0], "sample_size"))
6✔
574
        {
575
            dfsample_size = CPLAtof(papszTokens[1]);
2✔
576
            iGeoParamsFound++;
2✔
577
            iUTMParamsFound++;
2✔
578
        }
579
        else if (EQUAL(papszTokens[0], "sample_size_az"))
4✔
580
        {
581
            dfsample_size_az = CPLAtof(papszTokens[1]);
2✔
582
            iGeoParamsFound++;
2✔
583
            iUTMParamsFound++;
2✔
584
        }
585
        else if (EQUAL(papszTokens[0], "transposed"))
2✔
586
        {
587
            itransposed = atoi(papszTokens[1]);
2✔
588
            iGeoParamsFound++;
2✔
589
            iUTMParamsFound++;
2✔
590
        }
591

592
        CSLDestroy(papszTokens);
14✔
593
    }
594
    CSLDestroy(papszHdrLines);
2✔
595
    /* -------------------------------------------------------------------- */
596
    /*      Check for successful completion.                                */
597
    /* -------------------------------------------------------------------- */
598
    if (nError)
2✔
599
    {
600
        return nullptr;
×
601
    }
602

603
    if (nLines <= 0 || nSamples <= 0)
2✔
604
    {
605
        CPLError(
×
606
            CE_Failure, CPLE_AppDefined,
607
            "Did not find valid number_lines or number_samples keywords in %s.",
608
            osWorkName.c_str());
609
        return nullptr;
×
610
    }
611

612
    /* -------------------------------------------------------------------- */
613
    /*      Initialize dataset.                                             */
614
    /* -------------------------------------------------------------------- */
615
    auto poDS = std::make_unique<CPGDataset>();
4✔
616

617
    poDS->nRasterXSize = nSamples;
2✔
618
    poDS->nRasterYSize = nLines;
2✔
619

620
    /* -------------------------------------------------------------------- */
621
    /*      Open the four bands.                                            */
622
    /* -------------------------------------------------------------------- */
623
    static const char *const apszPolarizations[NUMBER_OF_BANDS] = {"hh", "hv",
624
                                                                   "vv", "vh"};
625

626
    const int nNameLen = static_cast<int>(osWorkName.size());
2✔
627

628
    if (EQUAL(osWorkName.c_str() + nNameLen - 7, "IRC.hdr") ||
2✔
629
        EQUAL(osWorkName.c_str() + nNameLen - 7, "IRC.img"))
×
630
    {
631
        {
632
            char *pszWorkname = CPLStrdup(osWorkName.c_str());
2✔
633
            AdjustFilename(&pszWorkname, "", "img");
2✔
634
            osWorkName = pszWorkname;
2✔
635
            CPLFree(pszWorkname);
2✔
636
        }
637

638
        poDS->afpImage[0] = VSIFOpenL(osWorkName.c_str(), "rb");
2✔
639
        if (poDS->afpImage[0] == nullptr)
2✔
640
        {
641
            CPLError(CE_Failure, CPLE_OpenFailed,
×
642
                     "Failed to open .img file: %s", osWorkName.c_str());
643
            return nullptr;
×
644
        }
645
        poDS->aosImageFilenames.push_back(osWorkName.c_str());
2✔
646
        for (int iBand = 0; iBand < NUMBER_OF_BANDS; iBand++)
10✔
647
        {
648
            SIRC_QSLCRasterBand *poBand =
649
                new SIRC_QSLCRasterBand(poDS.get(), iBand + 1, GDT_CFloat32);
8✔
650
            poDS->SetBand(iBand + 1, poBand);
8✔
651
            poBand->SetMetadataItem("POLARIMETRIC_INTERP",
8✔
652
                                    apszPolarizations[iBand]);
8✔
653
        }
654
    }
655
    else
656
    {
657
        CPLAssert(poDS->afpImage.size() == NUMBER_OF_BANDS);
×
658
        for (int iBand = 0; iBand < NUMBER_OF_BANDS; iBand++)
×
659
        {
660
            {
661
                char *pszWorkname = CPLStrdup(osWorkName.c_str());
×
662
                AdjustFilename(&pszWorkname, apszPolarizations[iBand], "img");
×
663
                osWorkName = pszWorkname;
×
664
                CPLFree(pszWorkname);
×
665
            }
666

667
            poDS->afpImage[iBand] = VSIFOpenL(osWorkName.c_str(), "rb");
×
668
            if (poDS->afpImage[iBand] == nullptr)
×
669
            {
670
                CPLError(CE_Failure, CPLE_OpenFailed,
×
671
                         "Failed to open .img file: %s", osWorkName.c_str());
672
                return nullptr;
×
673
            }
674
            poDS->aosImageFilenames.push_back(osWorkName.c_str());
×
675

676
            auto poBand = RawRasterBand::Create(
677
                poDS.get(), iBand + 1, poDS->afpImage[iBand], 0, 8,
×
678
                8 * nSamples, GDT_CFloat32,
679
                RawRasterBand::ByteOrder::ORDER_BIG_ENDIAN,
680
                RawRasterBand::OwnFP::NO);
×
681
            if (!poBand)
×
682
                return nullptr;
×
683
            poBand->SetMetadataItem("POLARIMETRIC_INTERP",
×
684
                                    apszPolarizations[iBand]);
×
685
            poDS->SetBand(iBand + 1, std::move(poBand));
×
686
        }
687
    }
688

689
    /* Set an appropriate matrix representation metadata item for the set */
690
    poDS->SetMetadataItem("MATRIX_REPRESENTATION", "SCATTERING");
2✔
691

692
    /* -------------------------------------------------------------------------
693
     */
694
    /*  Add georeferencing or pseudo-geocoding, if enough information found. */
695
    /* -------------------------------------------------------------------------
696
     */
697
    if (iUTMParamsFound == 7)
2✔
698
    {
699
        poDS->adfGeoTransform[1] = 0.0;
×
700
        poDS->adfGeoTransform[2] = 0.0;
×
701
        poDS->adfGeoTransform[4] = 0.0;
×
702
        poDS->adfGeoTransform[5] = 0.0;
×
703

704
        double dfnorth_center;
705
        if (itransposed == 1)
×
706
        {
707
            CPLError(CE_Warning, CPLE_AppDefined,
×
708
                     "Did not have a convair SIRC-style test dataset\n"
709
                     "with transposed=1 for testing.  Georeferencing may be "
710
                     "wrong.\n");
711
            dfnorth_center = dfnorth - nSamples * dfsample_size / 2.0;
×
712
            poDS->adfGeoTransform[0] = dfeast;
×
713
            poDS->adfGeoTransform[2] = dfsample_size_az;
×
714
            poDS->adfGeoTransform[3] = dfnorth;
×
715
            poDS->adfGeoTransform[4] = -1 * dfsample_size;
×
716
        }
717
        else
718
        {
719
            dfnorth_center = dfnorth - nLines * dfsample_size / 2.0;
×
720
            poDS->adfGeoTransform[0] = dfeast;
×
721
            poDS->adfGeoTransform[1] = dfsample_size_az;
×
722
            poDS->adfGeoTransform[3] = dfnorth;
×
723
            poDS->adfGeoTransform[5] = -1 * dfsample_size;
×
724
        }
725

726
        if (dfnorth_center < 0)
×
727
            poDS->m_oSRS.SetUTM(iUTMZone, 0);
×
728
        else
729
            poDS->m_oSRS.SetUTM(iUTMZone, 1);
×
730

731
        /* Assuming WGS84 */
732
        poDS->m_oSRS.SetWellKnownGeogCS("WGS84");
×
733
    }
734
    else if (iGeoParamsFound == 5)
2✔
735
    {
736
        double dfgcpLine, dfgcpPixel, dfgcpX, dfgcpY, dftemp;
737

738
        poDS->nGCPCount = 16;
2✔
739
        poDS->pasGCPList = reinterpret_cast<GDAL_GCP *>(
4✔
740
            CPLCalloc(sizeof(GDAL_GCP), poDS->nGCPCount));
2✔
741
        GDALInitGCPs(poDS->nGCPCount, poDS->pasGCPList);
2✔
742

743
        for (int ngcp = 0; ngcp < 16; ngcp++)
34✔
744
        {
745
            char szID[32];
746

747
            snprintf(szID, sizeof(szID), "%d", ngcp + 1);
32✔
748
            if (itransposed == 1)
32✔
749
            {
750
                if (ngcp < 4)
×
751
                    dfgcpPixel = 0.0;
×
752
                else if (ngcp < 8)
×
753
                    dfgcpPixel = nSamples / 3.0;
×
754
                else if (ngcp < 12)
×
755
                    dfgcpPixel = 2.0 * nSamples / 3.0;
×
756
                else
757
                    dfgcpPixel = nSamples;
×
758

759
                dfgcpLine = nLines * (ngcp % 4) / 3.0;
×
760

761
                dftemp = dfnear_srd + (dfsample_size * dfgcpLine);
×
762
                /* -1 so that 0,0 maps to largest Y */
763
                dfgcpY = -1 * sqrt(dftemp * dftemp - dfaltitude * dfaltitude);
×
764
                dfgcpX = dfgcpPixel * dfsample_size_az;
×
765
            }
766
            else
767
            {
768
                if (ngcp < 4)
32✔
769
                    dfgcpLine = 0.0;
8✔
770
                else if (ngcp < 8)
24✔
771
                    dfgcpLine = nLines / 3.0;
8✔
772
                else if (ngcp < 12)
16✔
773
                    dfgcpLine = 2.0 * nLines / 3.0;
8✔
774
                else
775
                    dfgcpLine = nLines;
8✔
776

777
                dfgcpPixel = nSamples * (ngcp % 4) / 3.0;
32✔
778

779
                dftemp = dfnear_srd + (dfsample_size * dfgcpPixel);
32✔
780
                dfgcpX = sqrt(dftemp * dftemp - dfaltitude * dfaltitude);
32✔
781
                dfgcpY = (nLines - dfgcpLine) * dfsample_size_az;
32✔
782
            }
783
            poDS->pasGCPList[ngcp].dfGCPX = dfgcpX;
32✔
784
            poDS->pasGCPList[ngcp].dfGCPY = dfgcpY;
32✔
785
            poDS->pasGCPList[ngcp].dfGCPZ = 0.0;
32✔
786

787
            poDS->pasGCPList[ngcp].dfGCPPixel = dfgcpPixel;
32✔
788
            poDS->pasGCPList[ngcp].dfGCPLine = dfgcpLine;
32✔
789

790
            CPLFree(poDS->pasGCPList[ngcp].pszId);
32✔
791
            poDS->pasGCPList[ngcp].pszId = CPLStrdup(szID);
32✔
792
        }
793

794
        poDS->m_oGCPSRS.importFromWkt(
2✔
795
            "LOCAL_CS[\"Ground range view / unreferenced meters\","
796
            "UNIT[\"Meter\",1.0]]");
797
    }
798

799
    return poDS.release();
2✔
800
}
801

802
#ifdef notdef
803
GDALDataset *CPGDataset::InitializeType3Dataset(const char *pszFilename)
804
{
805
    int iBytesPerPixel = 0;
806
    Interleave::eInterleave = Interleave::BSQ;
807
    bool bInterleaveSpecified = false;
808
    int nLines = 0;
809
    int nSamples = 0;
810
    int nBands = 0;
811
    int nError = 0;
812

813
    /* Parameters in geogratis geocoded images */
814
    int iUTMParamsFound = 0;
815
    int iUTMZone = 0;
816
    double dfnorth = 0.0;
817
    double dfeast = 0.0;
818
    double dfOffsetX = 0.0;
819
    double dfOffsetY = 0.0;
820
    double dfxsize = 0.0;
821
    double dfysize = 0.0;
822

823
    char *pszWorkname = CPLStrdup(pszFilename);
824
    AdjustFilename(&pszWorkname, "stokes", "img_def");
825
    char **papszHdrLines = CSLLoad(pszWorkname);
826

827
    for (int iLine = 0; papszHdrLines && papszHdrLines[iLine] != NULL; iLine++)
828
    {
829
        char **papszTokens =
830
            CSLTokenizeString2(papszHdrLines[iLine], " \t",
831
                               CSLT_HONOURSTRINGS & CSLT_ALLOWEMPTYTOKENS);
832

833
        /* Note: some cv580 file seem to have comments with #, hence the >=
834
         * instead of = for token checking, and the equalN for the corner.
835
         */
836

837
        if ((CSLCount(papszTokens) >= 3) && EQUAL(papszTokens[0], "data") &&
838
            EQUAL(papszTokens[1], "organization:"))
839
        {
840

841
            if (STARTS_WITH_CI(papszTokens[2], "BSQ"))
842
            {
843
                bInterleaveSpecified = true;
844
                eInterleave = Interleave::BSQ;
845
            }
846
            else if (STARTS_WITH_CI(papszTokens[2], "BIL"))
847
            {
848
                bInterleaveSpecified = true;
849
                eInterleave = Interleave::BIL;
850
            }
851
            else if (STARTS_WITH_CI(papszTokens[2], "BIP"))
852
            {
853
                bInterleaveSpecified = true;
854
                eInterleave = Interleave::BIP;
855
            }
856
            else
857
            {
858
                CPLError(
859
                    CE_Failure, CPLE_AppDefined,
860
                    "The interleaving type of the file (%s) is not supported.",
861
                    papszTokens[2]);
862
                nError = 1;
863
            }
864
        }
865
        else if ((CSLCount(papszTokens) >= 3) &&
866
                 EQUAL(papszTokens[0], "data") &&
867
                 EQUAL(papszTokens[1], "state:"))
868
        {
869

870
            if (!STARTS_WITH_CI(papszTokens[2], "RAW") &&
871
                !STARTS_WITH_CI(papszTokens[2], "GEO"))
872
            {
873
                CPLError(CE_Failure, CPLE_AppDefined,
874
                         "The data state of the file (%s) is not "
875
                         "supported.\n.  Only RAW and GEO are currently "
876
                         "recognized.",
877
                         papszTokens[2]);
878
                nError = 1;
879
            }
880
        }
881
        else if ((CSLCount(papszTokens) >= 4) &&
882
                 EQUAL(papszTokens[0], "data") &&
883
                 EQUAL(papszTokens[1], "origin") &&
884
                 EQUAL(papszTokens[2], "point:"))
885
        {
886
            if (!STARTS_WITH_CI(papszTokens[3], "Upper_Left"))
887
            {
888
                CPLError(CE_Failure, CPLE_AppDefined,
889
                         "Unexpected value (%s) for data origin point- expect "
890
                         "Upper_Left.",
891
                         papszTokens[3]);
892
                nError = 1;
893
            }
894
            iUTMParamsFound++;
895
        }
896
        else if ((CSLCount(papszTokens) >= 5) && EQUAL(papszTokens[0], "map") &&
897
                 EQUAL(papszTokens[1], "projection:") &&
898
                 EQUAL(papszTokens[2], "UTM") && EQUAL(papszTokens[3], "zone"))
899
        {
900
            iUTMZone = atoi(papszTokens[4]);
901
            iUTMParamsFound++;
902
        }
903
        else if ((CSLCount(papszTokens) >= 4) &&
904
                 EQUAL(papszTokens[0], "project") &&
905
                 EQUAL(papszTokens[1], "origin:"))
906
        {
907
            dfeast = CPLAtof(papszTokens[2]);
908
            dfnorth = CPLAtof(papszTokens[3]);
909
            iUTMParamsFound += 2;
910
        }
911
        else if ((CSLCount(papszTokens) >= 4) &&
912
                 EQUAL(papszTokens[0], "file") &&
913
                 EQUAL(papszTokens[1], "start:"))
914
        {
915
            dfOffsetX = CPLAtof(papszTokens[2]);
916
            dfOffsetY = CPLAtof(papszTokens[3]);
917
            iUTMParamsFound += 2;
918
        }
919
        else if ((CSLCount(papszTokens) >= 6) &&
920
                 EQUAL(papszTokens[0], "pixel") &&
921
                 EQUAL(papszTokens[1], "size") && EQUAL(papszTokens[2], "on") &&
922
                 EQUAL(papszTokens[3], "ground:"))
923
        {
924
            dfxsize = CPLAtof(papszTokens[4]);
925
            dfysize = CPLAtof(papszTokens[5]);
926
            iUTMParamsFound += 2;
927
        }
928
        else if ((CSLCount(papszTokens) >= 4) &&
929
                 EQUAL(papszTokens[0], "number") &&
930
                 EQUAL(papszTokens[1], "of") &&
931
                 EQUAL(papszTokens[2], "pixels:"))
932
        {
933
            nSamples = atoi(papszTokens[3]);
934
        }
935
        else if ((CSLCount(papszTokens) >= 4) &&
936
                 EQUAL(papszTokens[0], "number") &&
937
                 EQUAL(papszTokens[1], "of") && EQUAL(papszTokens[2], "lines:"))
938
        {
939
            nLines = atoi(papszTokens[3]);
940
        }
941
        else if ((CSLCount(papszTokens) >= 4) &&
942
                 EQUAL(papszTokens[0], "number") &&
943
                 EQUAL(papszTokens[1], "of") && EQUAL(papszTokens[2], "bands:"))
944
        {
945
            nBands = atoi(papszTokens[3]);
946
            if (nBands != 16)
947
            {
948
                CPLError(CE_Failure, CPLE_AppDefined,
949
                         "Number of bands has a value %s which does not match "
950
                         "CPG driver\nexpectation (expect a value of 16).",
951
                         papszTokens[3]);
952
                nError = 1;
953
            }
954
        }
955
        else if ((CSLCount(papszTokens) >= 4) &&
956
                 EQUAL(papszTokens[0], "bytes") &&
957
                 EQUAL(papszTokens[1], "per") &&
958
                 EQUAL(papszTokens[2], "pixel:"))
959
        {
960
            iBytesPerPixel = atoi(papszTokens[3]);
961
            if (iBytesPerPixel != 4)
962
            {
963
                CPLError(CE_Failure, CPLE_AppDefined,
964
                         "Bytes per pixel has a value %s which does not match "
965
                         "CPG driver\nexpectation (expect a value of 4).",
966
                         papszTokens[1]);
967
                nError = 1;
968
            }
969
        }
970
        CSLDestroy(papszTokens);
971
    }
972

973
    CSLDestroy(papszHdrLines);
974

975
    /* -------------------------------------------------------------------- */
976
    /*      Check for successful completion.                                */
977
    /* -------------------------------------------------------------------- */
978
    if (nError)
979
    {
980
        CPLFree(pszWorkname);
981
        return NULL;
982
    }
983

984
    if (!GDALCheckDatasetDimensions(nSamples, nLines) ||
985
        !GDALCheckBandCount(nBands, FALSE) || !bInterleaveSpecified ||
986
        iBytesPerPixel == 0)
987
    {
988
        CPLError(CE_Failure, CPLE_AppDefined,
989
                 "%s is missing a required parameter (number of pixels, "
990
                 "number of lines,\number of bands, bytes per pixel, or "
991
                 "data organization).",
992
                 pszWorkname);
993
        CPLFree(pszWorkname);
994
        return NULL;
995
    }
996

997
    /* -------------------------------------------------------------------- */
998
    /*      Initialize dataset.                                             */
999
    /* -------------------------------------------------------------------- */
1000
    CPGDataset *poDS = new CPGDataset();
1001

1002
    poDS->nRasterXSize = nSamples;
1003
    poDS->nRasterYSize = nLines;
1004
    poDS->eInterleave = eInterleave;
1005

1006
    /* -------------------------------------------------------------------- */
1007
    /*      Open the 16 bands.                                              */
1008
    /* -------------------------------------------------------------------- */
1009

1010
    AdjustFilename(&pszWorkname, "stokes", "img");
1011
    poDS->afpImage[0] = VSIFOpenL(pszWorkname, "rb");
1012
    if (poDS->afpImage[0] == NULL)
1013
    {
1014
        CPLError(CE_Failure, CPLE_OpenFailed, "Failed to open .img file: %s",
1015
                 pszWorkname);
1016
        CPLFree(pszWorkname);
1017
        delete poDS;
1018
        return NULL;
1019
    }
1020
    aosImageFilenames.push_back(pszWorkname);
1021
    for (int iBand = 0; iBand < 16; iBand++)
1022
    {
1023
        CPG_STOKESRasterBand *poBand =
1024
            new CPG_STOKESRasterBand(poDS, GDT_CFloat32, !CPL_IS_LSB);
1025
        poDS->SetBand(iBand + 1, poBand);
1026
    }
1027

1028
    /* -------------------------------------------------------------------- */
1029
    /*      Set appropriate MATRIX_REPRESENTATION.                          */
1030
    /* -------------------------------------------------------------------- */
1031
    if (poDS->GetRasterCount() == 6)
1032
    {
1033
        poDS->SetMetadataItem("MATRIX_REPRESENTATION", "COVARIANCE");
1034
    }
1035

1036
    /* -------------------------------------------------------------------------
1037
     */
1038
    /*  Add georeferencing, if enough information found. */
1039
    /* -------------------------------------------------------------------------
1040
     */
1041
    if (iUTMParamsFound == 8)
1042
    {
1043
        double dfnorth_center = dfnorth - nLines * dfysize / 2.0;
1044
        poDS->adfGeoTransform[0] = dfeast + dfOffsetX;
1045
        poDS->adfGeoTransform[1] = dfxsize;
1046
        poDS->adfGeoTransform[2] = 0.0;
1047
        poDS->adfGeoTransform[3] = dfnorth + dfOffsetY;
1048
        poDS->adfGeoTransform[4] = 0.0;
1049
        poDS->adfGeoTransform[5] = -1 * dfysize;
1050

1051
        OGRSpatialReference oUTM;
1052
        if (dfnorth_center < 0)
1053
            oUTM.SetUTM(iUTMZone, 0);
1054
        else
1055
            oUTM.SetUTM(iUTMZone, 1);
1056

1057
        /* Assuming WGS84 */
1058
        oUTM.SetWellKnownGeogCS("WGS84");
1059
        CPLFree(poDS->pszProjection);
1060
        poDS->pszProjection = NULL;
1061
        oUTM.exportToWkt(&(poDS->pszProjection));
1062
    }
1063

1064
    return poDS;
1065
}
1066
#endif
1067

1068
/************************************************************************/
1069
/*                                Open()                                */
1070
/************************************************************************/
1071

1072
GDALDataset *CPGDataset::Open(GDALOpenInfo *poOpenInfo)
29,302✔
1073

1074
{
1075
    /* -------------------------------------------------------------------- */
1076
    /*      Is this a PolGASP fileset?  We expect fileset to follow         */
1077
    /*      one of these patterns:                                          */
1078
    /*               1) <stuff>hh<stuff2>.img, <stuff>hh<stuff2>.hdr,       */
1079
    /*                  <stuff>hv<stuff2>.img, <stuff>hv<stuff2>.hdr,       */
1080
    /*                  <stuff>vh<stuff2>.img, <stuff>vh<stuff2>.hdr,       */
1081
    /*                  <stuff>vv<stuff2>.img, <stuff>vv<stuff2>.hdr,       */
1082
    /*                  where <stuff> or <stuff2> should contain the        */
1083
    /*                  substring "sso" or "polgasp"                        */
1084
    /*               2) <stuff>SIRC.hdr and <stuff>SIRC.img                 */
1085
    /*               3) <stuff>.img and <stuff>.img_def                     */
1086
    /*                  where <stuff> should contain the                    */
1087
    /*                  substring "sso" or "polgasp"                        */
1088
    /* -------------------------------------------------------------------- */
1089
    int CPGType = 0;
29,302✔
1090
    if (FindType1(poOpenInfo->pszFilename))
29,302✔
1091
        CPGType = 1;
×
1092
    else if (FindType2(poOpenInfo->pszFilename))
29,296✔
1093
        CPGType = 2;
2✔
1094

1095
    /* Stokes matrix convair data: not quite working yet- something
1096
     * is wrong in the interpretation of the matrix elements in terms
1097
     * of hh, hv, vv, vh.  Data will load if the next two lines are
1098
     * uncommented, but values will be incorrect.  Expect C11 = hh*conj(hh),
1099
     * C12 = hh*conj(hv), etc.  Used geogratis data in both scattering
1100
     * matrix and stokes format for comparison.
1101
     */
1102
    // else if ( FindType3( poOpenInfo->pszFilename ))
1103
    //   CPGType = 3;
1104

1105
    /* Set working name back to original */
1106

1107
    if (CPGType == 0)
29,296✔
1108
    {
1109
        int nNameLen = static_cast<int>(strlen(poOpenInfo->pszFilename));
29,297✔
1110
        if ((nNameLen > 8) &&
29,297✔
1111
            ((strstr(poOpenInfo->pszFilename, "sso") != nullptr) ||
28,772✔
1112
             (strstr(poOpenInfo->pszFilename, "polgasp") != nullptr)) &&
28,776✔
1113
            (EQUAL(poOpenInfo->pszFilename + nNameLen - 4, "img") ||
×
1114
             EQUAL(poOpenInfo->pszFilename + nNameLen - 4, "hdr") ||
×
1115
             EQUAL(poOpenInfo->pszFilename + nNameLen - 7, "img_def")))
×
1116
        {
1117
            CPLError(
×
1118
                CE_Failure, CPLE_OpenFailed,
1119
                "Apparent attempt to open Convair PolGASP data failed as\n"
1120
                "one or more of the required files is missing (eight files\n"
1121
                "are expected for scattering matrix format, two for Stokes).");
1122
        }
1123
        else if ((nNameLen > 8) &&
29,301✔
1124
                 (strstr(poOpenInfo->pszFilename, "SIRC") != nullptr) &&
28,775✔
1125
                 (EQUAL(poOpenInfo->pszFilename + nNameLen - 4, "img") ||
×
1126
                  EQUAL(poOpenInfo->pszFilename + nNameLen - 4, "hdr")))
×
1127
        {
1128
            CPLError(
×
1129
                CE_Failure, CPLE_OpenFailed,
1130
                "Apparent attempt to open SIRC Convair PolGASP data failed \n"
1131
                "as one of the expected files is missing (hdr or img)!");
1132
        }
1133
        return nullptr;
29,296✔
1134
    }
1135

1136
    /* -------------------------------------------------------------------- */
1137
    /*      Confirm the requested access is supported.                      */
1138
    /* -------------------------------------------------------------------- */
1139
    if (poOpenInfo->eAccess == GA_Update)
×
1140
    {
1141
        ReportUpdateNotSupportedByDriver("CPG");
×
1142
        return nullptr;
×
1143
    }
1144

1145
    /* Read the header info and create the dataset */
1146
#ifdef notdef
1147
    if (CPGType < 3)
1148
#endif
1149
        CPGDataset *poDS = reinterpret_cast<CPGDataset *>(
1150
            InitializeType1Or2Dataset(poOpenInfo->pszFilename));
×
1151
#ifdef notdef
1152
    else
1153
        poDS = reinterpret_cast<CPGDataset *>(
1154
            InitializeType3Dataset(poOpenInfo->pszFilename));
1155
#endif
1156
    if (poDS == nullptr)
2✔
1157
        return nullptr;
×
1158

1159
    /* -------------------------------------------------------------------- */
1160
    /*      Check for overviews.                                            */
1161
    /* -------------------------------------------------------------------- */
1162
    // Need to think about this.
1163
    // poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
1164

1165
    /* -------------------------------------------------------------------- */
1166
    /*      Initialize any PAM information.                                 */
1167
    /* -------------------------------------------------------------------- */
1168
    poDS->SetDescription(poOpenInfo->pszFilename);
2✔
1169
    poDS->TryLoadXML();
2✔
1170

1171
    return poDS;
2✔
1172
}
1173

1174
/************************************************************************/
1175
/*                            GetGCPCount()                             */
1176
/************************************************************************/
1177

1178
int CPGDataset::GetGCPCount()
×
1179

1180
{
1181
    return nGCPCount;
×
1182
}
1183

1184
/************************************************************************/
1185
/*                               GetGCPs()                               */
1186
/************************************************************************/
1187

1188
const GDAL_GCP *CPGDataset::GetGCPs()
×
1189

1190
{
1191
    return pasGCPList;
×
1192
}
1193

1194
/************************************************************************/
1195
/*                          GetGeoTransform()                           */
1196
/************************************************************************/
1197

1198
CPLErr CPGDataset::GetGeoTransform(double *padfTransform)
×
1199

1200
{
1201
    memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6);
×
1202
    return CE_None;
×
1203
}
1204

1205
/************************************************************************/
1206
/*                           SIRC_QSLCRasterBand()                      */
1207
/************************************************************************/
1208

1209
SIRC_QSLCRasterBand::SIRC_QSLCRasterBand(CPGDataset *poGDSIn, int nBandIn,
8✔
1210
                                         GDALDataType eType)
8✔
1211

1212
{
1213
    poDS = poGDSIn;
8✔
1214
    nBand = nBandIn;
8✔
1215

1216
    eDataType = eType;
8✔
1217

1218
    nBlockXSize = poGDSIn->nRasterXSize;
8✔
1219
    nBlockYSize = 1;
8✔
1220

1221
    if (nBand == 1)
8✔
1222
        SetMetadataItem("POLARIMETRIC_INTERP", "HH");
2✔
1223
    else if (nBand == 2)
6✔
1224
        SetMetadataItem("POLARIMETRIC_INTERP", "HV");
2✔
1225
    else if (nBand == 3)
4✔
1226
        SetMetadataItem("POLARIMETRIC_INTERP", "VH");
2✔
1227
    else if (nBand == 4)
2✔
1228
        SetMetadataItem("POLARIMETRIC_INTERP", "VV");
2✔
1229
}
8✔
1230

1231
/************************************************************************/
1232
/*                             IReadBlock()                             */
1233
/************************************************************************/
1234

1235
/* From: http://southport.jpl.nasa.gov/software/dcomp/dcomp.html
1236

1237
ysca = sqrt{ [ (Byte(2) / 254 ) + 1.5] 2Byte(1) }
1238
Re(SHH) = byte(3) ysca/127
1239
Im(SHH) = byte(4) ysca/127
1240
Re(SHV) = byte(5) ysca/127
1241
Im(SHV) = byte(6) ysca/127
1242
Re(SVH) = byte(7) ysca/127
1243
Im(SVH) = byte(8) ysca/127
1244
Re(SVV) = byte(9) ysca/127
1245
Im(SVV) = byte(10) ysca/127
1246
*/
1247

1248
CPLErr SIRC_QSLCRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
1✔
1249
                                       int nBlockYOff, void *pImage)
1250
{
1251
    const int nBytesPerSample = 10;
1✔
1252
    CPGDataset *poGDS = reinterpret_cast<CPGDataset *>(poDS);
1✔
1253
    const int offset = nBlockXSize * nBlockYOff * nBytesPerSample;
1✔
1254

1255
    /* -------------------------------------------------------------------- */
1256
    /*      Load all the pixel data associated with this scanline.          */
1257
    /* -------------------------------------------------------------------- */
1258
    const int nBytesToRead = nBytesPerSample * nBlockXSize;
1✔
1259

1260
    GByte *pabyRecord = reinterpret_cast<GByte *>(CPLMalloc(nBytesToRead));
1✔
1261

1262
    if (VSIFSeekL(poGDS->afpImage[0], offset, SEEK_SET) != 0 ||
2✔
1263
        static_cast<int>(VSIFReadL(pabyRecord, 1, nBytesToRead,
1✔
1264
                                   poGDS->afpImage[0])) != nBytesToRead)
2✔
1265
    {
1266
        CPLError(CE_Failure, CPLE_FileIO,
×
1267
                 "Error reading %d bytes of SIRC Convair at offset %d.\n"
1268
                 "Reading file %s failed.",
1269
                 nBytesToRead, offset, poGDS->GetDescription());
×
1270
        CPLFree(pabyRecord);
×
1271
        return CE_Failure;
×
1272
    }
1273

1274
    /* -------------------------------------------------------------------- */
1275
    /*      Initialize our power table if this is our first time through.   */
1276
    /* -------------------------------------------------------------------- */
1277
    static float afPowTable[256];
1278
    static bool bPowTableInitialized = false;
1279

1280
    if (!bPowTableInitialized)
1✔
1281
    {
1282
        bPowTableInitialized = true;
1✔
1283

1284
        for (int i = 0; i < 256; i++)
257✔
1285
        {
1286
            afPowTable[i] = static_cast<float>(pow(2.0, i - 128));
256✔
1287
        }
1288
    }
1289

1290
    /* -------------------------------------------------------------------- */
1291
    /*      Copy the desired band out based on the size of the type, and    */
1292
    /*      the interleaving mode.                                          */
1293
    /* -------------------------------------------------------------------- */
1294
    for (int iX = 0; iX < nBlockXSize; iX++)
2✔
1295
    {
1296
        unsigned char *pabyGroup = pabyRecord + iX * nBytesPerSample;
1✔
1297
        const signed char *Byte = reinterpret_cast<signed char *>(
1✔
1298
            pabyGroup - 1); /* A ones based alias */
1299

1300
        /* coverity[tainted_data] */
1301
        const double dfScale = sqrt((static_cast<double>(Byte[2]) / 254 + 1.5) *
1✔
1302
                                    afPowTable[Byte[1] + 128]);
1✔
1303

1304
        float *pafImage = reinterpret_cast<float *>(pImage);
1✔
1305

1306
        if (nBand == 1)
1✔
1307
        {
1308
            const float fReSHH = static_cast<float>(Byte[3] * dfScale / 127.0);
1✔
1309
            const float fImSHH = static_cast<float>(Byte[4] * dfScale / 127.0);
1✔
1310

1311
            pafImage[iX * 2] = fReSHH;
1✔
1312
            pafImage[iX * 2 + 1] = fImSHH;
1✔
1313
        }
1314
        else if (nBand == 2)
×
1315
        {
1316
            const float fReSHV = static_cast<float>(Byte[5] * dfScale / 127.0);
×
1317
            const float fImSHV = static_cast<float>(Byte[6] * dfScale / 127.0);
×
1318

1319
            pafImage[iX * 2] = fReSHV;
×
1320
            pafImage[iX * 2 + 1] = fImSHV;
×
1321
        }
1322
        else if (nBand == 3)
×
1323
        {
1324
            const float fReSVH = static_cast<float>(Byte[7] * dfScale / 127.0);
×
1325
            const float fImSVH = static_cast<float>(Byte[8] * dfScale / 127.0);
×
1326

1327
            pafImage[iX * 2] = fReSVH;
×
1328
            pafImage[iX * 2 + 1] = fImSVH;
×
1329
        }
1330
        else if (nBand == 4)
×
1331
        {
1332
            const float fReSVV = static_cast<float>(Byte[9] * dfScale / 127.0);
×
1333
            const float fImSVV = static_cast<float>(Byte[10] * dfScale / 127.0);
×
1334

1335
            pafImage[iX * 2] = fReSVV;
×
1336
            pafImage[iX * 2 + 1] = fImSVV;
×
1337
        }
1338
    }
1339

1340
    CPLFree(pabyRecord);
1✔
1341

1342
    return CE_None;
1✔
1343
}
1344

1345
/************************************************************************/
1346
/*                        CPG_STOKESRasterBand()                        */
1347
/************************************************************************/
1348

1349
CPG_STOKESRasterBand::CPG_STOKESRasterBand(GDALDataset *poDSIn,
×
1350
                                           GDALDataType eType,
1351
                                           int bNativeOrderIn)
×
1352
    : bNativeOrder(bNativeOrderIn)
×
1353
{
1354
    static const char *const apszPolarizations[16] = {
1355
        "Covariance_11", "Covariance_12", "Covariance_13", "Covariance_14",
1356
        "Covariance_21", "Covariance_22", "Covariance_23", "Covariance_24",
1357
        "Covariance_31", "Covariance_32", "Covariance_33", "Covariance_34",
1358
        "Covariance_41", "Covariance_42", "Covariance_43", "Covariance_44"};
1359

1360
    poDS = poDSIn;
×
1361
    eDataType = eType;
×
1362

1363
    nBlockXSize = poDSIn->GetRasterXSize();
×
1364
    nBlockYSize = 1;
×
1365

1366
    SetMetadataItem("POLARIMETRIC_INTERP", apszPolarizations[nBand - 1]);
×
1367
    SetDescription(apszPolarizations[nBand - 1]);
×
1368
}
×
1369

1370
/************************************************************************/
1371
/*                             IReadBlock()                             */
1372
/************************************************************************/
1373

1374
/* Convert from Stokes to Covariance representation */
1375

1376
CPLErr CPG_STOKESRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
×
1377
                                        int nBlockYOff, void *pImage)
1378

1379
{
1380
    CPLAssert(nBlockXOff == 0);
×
1381

1382
    int m11, /* m12, */ m13, m14, /* m21, */ m22, m23, m24, step;
1383
    int m31, m32, m33, m34, m41, m42, m43, m44;
1384
    CPGDataset *poGDS = reinterpret_cast<CPGDataset *>(poDS);
×
1385

1386
    CPLErr eErr = poGDS->LoadStokesLine(nBlockYOff, bNativeOrder);
×
1387
    if (eErr != CE_None)
×
1388
        return eErr;
×
1389

1390
    float *M = poGDS->padfStokesMatrix;
×
1391
    float *pafLine = reinterpret_cast<float *>(pImage);
×
1392

1393
    if (poGDS->eInterleave == RawDataset::Interleave::BIP)
×
1394
    {
1395
        step = 16;
×
1396
        m11 = M11;
×
1397
        // m12 = M12;
1398
        m13 = M13;
×
1399
        m14 = M14;
×
1400
        // m21 = M21;
1401
        m22 = M22;
×
1402
        m23 = M23;
×
1403
        m24 = M24;
×
1404
        m31 = M31;
×
1405
        m32 = M32;
×
1406
        m33 = M33;
×
1407
        m34 = M34;
×
1408
        m41 = M41;
×
1409
        m42 = M42;
×
1410
        m43 = M43;
×
1411
        m44 = M44;
×
1412
    }
1413
    else
1414
    {
1415
        step = 1;
×
1416
        m11 = 0;
×
1417
        // m12=nRasterXSize;
1418
        m13 = nRasterXSize * 2;
×
1419
        m14 = nRasterXSize * 3;
×
1420
        // m21=nRasterXSize*4;
1421
        m22 = nRasterXSize * 5;
×
1422
        m23 = nRasterXSize * 6;
×
1423
        m24 = nRasterXSize * 7;
×
1424
        m31 = nRasterXSize * 8;
×
1425
        m32 = nRasterXSize * 9;
×
1426
        m33 = nRasterXSize * 10;
×
1427
        m34 = nRasterXSize * 11;
×
1428
        m41 = nRasterXSize * 12;
×
1429
        m42 = nRasterXSize * 13;
×
1430
        m43 = nRasterXSize * 14;
×
1431
        m44 = nRasterXSize * 15;
×
1432
    }
1433
    if (nBand == 1) /* C11 */
×
1434
    {
1435
        for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
×
1436
        {
1437
            pafLine[iPixel * 2 + 0] = M[m11] - M[m22] - M[m33] + M[m44];
×
1438
            pafLine[iPixel * 2 + 1] = 0.0;
×
1439
            m11 += step;
×
1440
            m22 += step;
×
1441
            m33 += step;
×
1442
            m44 += step;
×
1443
        }
1444
    }
1445
    else if (nBand == 2) /* C12 */
×
1446
    {
1447
        for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
×
1448
        {
1449
            pafLine[iPixel * 2 + 0] = M[m13] - M[m23];
×
1450
            pafLine[iPixel * 2 + 1] = M[m14] - M[m24];
×
1451
            m13 += step;
×
1452
            m23 += step;
×
1453
            m14 += step;
×
1454
            m24 += step;
×
1455
        }
1456
    }
1457
    else if (nBand == 3) /* C13 */
×
1458
    {
1459
        for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
×
1460
        {
1461
            pafLine[iPixel * 2 + 0] = M[m33] - M[m44];
×
1462
            pafLine[iPixel * 2 + 1] = M[m43] + M[m34];
×
1463
            m33 += step;
×
1464
            m44 += step;
×
1465
            m43 += step;
×
1466
            m34 += step;
×
1467
        }
1468
    }
1469
    else if (nBand == 4) /* C14 */
×
1470
    {
1471
        for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
×
1472
        {
1473
            pafLine[iPixel * 2 + 0] = M[m31] - M[m32];
×
1474
            pafLine[iPixel * 2 + 1] = M[m41] - M[m42];
×
1475
            m31 += step;
×
1476
            m32 += step;
×
1477
            m41 += step;
×
1478
            m42 += step;
×
1479
        }
1480
    }
1481
    else if (nBand == 5) /* C21 */
×
1482
    {
1483
        for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
×
1484
        {
1485
            pafLine[iPixel * 2 + 0] = M[m13] - M[m23];
×
1486
            pafLine[iPixel * 2 + 1] = M[m24] - M[m14];
×
1487
            m13 += step;
×
1488
            m23 += step;
×
1489
            m14 += step;
×
1490
            m24 += step;
×
1491
        }
1492
    }
1493
    else if (nBand == 6) /* C22 */
×
1494
    {
1495
        for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
×
1496
        {
1497
            pafLine[iPixel * 2 + 0] = M[m11] + M[m22] - M[m33] - M[m44];
×
1498
            pafLine[iPixel * 2 + 1] = 0.0;
×
1499
            m11 += step;
×
1500
            m22 += step;
×
1501
            m33 += step;
×
1502
            m44 += step;
×
1503
        }
1504
    }
1505
    else if (nBand == 7) /* C23 */
×
1506
    {
1507
        for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
×
1508
        {
1509
            pafLine[iPixel * 2 + 0] = M[m31] + M[m32];
×
1510
            pafLine[iPixel * 2 + 1] = M[m41] + M[m42];
×
1511
            m31 += step;
×
1512
            m32 += step;
×
1513
            m41 += step;
×
1514
            m42 += step;
×
1515
        }
1516
    }
1517
    else if (nBand == 8) /* C24 */
×
1518
    {
1519
        for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
×
1520
        {
1521
            pafLine[iPixel * 2 + 0] = M[m33] + M[m44];
×
1522
            pafLine[iPixel * 2 + 1] = M[m43] - M[m34];
×
1523
            m33 += step;
×
1524
            m44 += step;
×
1525
            m43 += step;
×
1526
            m34 += step;
×
1527
        }
1528
    }
1529
    else if (nBand == 9) /* C31 */
×
1530
    {
1531
        for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
×
1532
        {
1533
            pafLine[iPixel * 2 + 0] = M[m33] - M[m44];
×
1534
            pafLine[iPixel * 2 + 1] = -1 * M[m43] - M[m34];
×
1535
            m33 += step;
×
1536
            m44 += step;
×
1537
            m43 += step;
×
1538
            m34 += step;
×
1539
        }
1540
    }
1541
    else if (nBand == 10) /* C32 */
×
1542
    {
1543
        for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
×
1544
        {
1545
            pafLine[iPixel * 2 + 0] = M[m31] + M[m32];
×
1546
            pafLine[iPixel * 2 + 1] = -1 * M[m41] - M[m42];
×
1547
            m31 += step;
×
1548
            m32 += step;
×
1549
            m41 += step;
×
1550
            m42 += step;
×
1551
        }
1552
    }
1553
    else if (nBand == 11) /* C33 */
×
1554
    {
1555
        for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
×
1556
        {
1557
            pafLine[iPixel * 2 + 0] = M[m11] + M[m22] + M[m33] + M[m44];
×
1558
            pafLine[iPixel * 2 + 1] = 0.0;
×
1559
            m11 += step;
×
1560
            m22 += step;
×
1561
            m33 += step;
×
1562
            m44 += step;
×
1563
        }
1564
    }
1565
    else if (nBand == 12) /* C34 */
×
1566
    {
1567
        for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
×
1568
        {
1569
            pafLine[iPixel * 2 + 0] = M[m13] - M[m23];
×
1570
            pafLine[iPixel * 2 + 1] = -1 * M[m14] - M[m24];
×
1571
            m13 += step;
×
1572
            m23 += step;
×
1573
            m14 += step;
×
1574
            m24 += step;
×
1575
        }
1576
    }
1577
    else if (nBand == 13) /* C41 */
×
1578
    {
1579
        for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
×
1580
        {
1581
            pafLine[iPixel * 2 + 0] = M[m31] - M[m32];
×
1582
            pafLine[iPixel * 2 + 1] = M[m42] - M[m41];
×
1583
            m31 += step;
×
1584
            m32 += step;
×
1585
            m41 += step;
×
1586
            m42 += step;
×
1587
        }
1588
    }
1589
    else if (nBand == 14) /* C42 */
×
1590
    {
1591
        for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
×
1592
        {
1593
            pafLine[iPixel * 2 + 0] = M[m33] + M[m44];
×
1594
            pafLine[iPixel * 2 + 1] = M[m34] - M[m43];
×
1595
            m33 += step;
×
1596
            m44 += step;
×
1597
            m43 += step;
×
1598
            m34 += step;
×
1599
        }
1600
    }
1601
    else if (nBand == 15) /* C43 */
×
1602
    {
1603
        for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
×
1604
        {
1605
            pafLine[iPixel * 2 + 0] = M[m13] - M[m23];
×
1606
            pafLine[iPixel * 2 + 1] = M[m14] + M[m24];
×
1607
            m13 += step;
×
1608
            m23 += step;
×
1609
            m14 += step;
×
1610
            m24 += step;
×
1611
        }
1612
    }
1613
    else /* C44 */
1614
    {
1615
        for (int iPixel = 0; iPixel < nRasterXSize; iPixel++)
×
1616
        {
1617
            pafLine[iPixel * 2 + 0] = M[m11] - M[m22] + M[m33] - M[m44];
×
1618
            pafLine[iPixel * 2 + 1] = 0.0;
×
1619
            m11 += step;
×
1620
            m22 += step;
×
1621
            m33 += step;
×
1622
            m44 += step;
×
1623
        }
1624
    }
1625

1626
    return CE_None;
×
1627
}
1628

1629
/************************************************************************/
1630
/*                         GDALRegister_CPG()                           */
1631
/************************************************************************/
1632

1633
void GDALRegister_CPG()
1,667✔
1634

1635
{
1636
    if (GDALGetDriverByName("CPG") != nullptr)
1,667✔
1637
        return;
302✔
1638

1639
    GDALDriver *poDriver = new GDALDriver();
1,365✔
1640

1641
    poDriver->SetDescription("CPG");
1,365✔
1642
    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
1,365✔
1643
    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Convair PolGASP");
1,365✔
1644
    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
1,365✔
1645

1646
    poDriver->pfnOpen = CPGDataset::Open;
1,365✔
1647

1648
    GetGDALDriverManager()->RegisterDriver(poDriver);
1,365✔
1649
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc