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

OSGeo / gdal / 15885686134

25 Jun 2025 07:44PM UTC coverage: 71.084%. Remained the same
15885686134

push

github

rouault
gdal_priv.h: fix C++11 compatibility

573814 of 807237 relevant lines covered (71.08%)

250621.56 hits per line

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

77.08
/frmts/raw/roipacdataset.cpp
1
/******************************************************************************
2
 *
3
 * Project:  ROI_PAC Raster Reader
4
 * Purpose:  Implementation of the ROI_PAC raster reader
5
 * Author:   Matthieu Volat (ISTerre), matthieu.volat@ujf-grenoble.fr
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2014, Matthieu Volat <matthieu.volat@ujf-grenoble.fr>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12

13
#include "gdal_frmts.h"
14
#include "ogr_spatialref.h"
15
#include "rawdataset.h"
16

17
#include <algorithm>
18

19
/************************************************************************/
20
/* ==================================================================== */
21
/*                             ROIPACDataset                            */
22
/* ==================================================================== */
23
/************************************************************************/
24

25
class ROIPACDataset final : public RawDataset
26
{
27
    VSILFILE *fpImage;
28
    VSILFILE *fpRsc;
29

30
    char *pszRscFilename;
31

32
    GDALGeoTransform m_gt{};
33
    bool bValidGeoTransform;
34

35
    OGRSpatialReference m_oSRS{};
36

37
    CPL_DISALLOW_COPY_ASSIGN(ROIPACDataset)
38

39
    CPLErr Close() override;
40

41
  public:
42
    ROIPACDataset();
43
    ~ROIPACDataset() override;
44

45
    static GDALDataset *Open(GDALOpenInfo *poOpenInfo);
46
    static int Identify(GDALOpenInfo *poOpenInfo);
47
    static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize,
48
                               int nBandsIn, GDALDataType eType,
49
                               char **papszOptions);
50

51
    CPLErr FlushCache(bool bAtClosing) override;
52
    CPLErr GetGeoTransform(GDALGeoTransform &gt) const override;
53
    CPLErr SetGeoTransform(const GDALGeoTransform &gt) override;
54

55
    const OGRSpatialReference *GetSpatialRef() const override
3✔
56
    {
57
        return m_oSRS.IsEmpty() ? nullptr : &m_oSRS;
3✔
58
    }
59

60
    CPLErr SetSpatialRef(const OGRSpatialReference *poSRS) override;
61

62
    char **GetFileList() override;
63
};
64

65
/************************************************************************/
66
/*                           getRscFilename()                           */
67
/************************************************************************/
68

69
static CPLString getRscFilename(GDALOpenInfo *poOpenInfo)
174✔
70
{
71
    char **papszSiblingFiles = poOpenInfo->GetSiblingFiles();
174✔
72
    if (papszSiblingFiles == nullptr)
174✔
73
    {
74
        CPLString osRscFilename =
75
            CPLFormFilenameSafe(nullptr, poOpenInfo->pszFilename, "rsc");
186✔
76
        VSIStatBufL psRscStatBuf;
77
        if (VSIStatL(osRscFilename, &psRscStatBuf) != 0)
93✔
78
        {
79
            return "";
93✔
80
        }
81
        return osRscFilename;
×
82
    }
83

84
    /* ------------------------------------------------------------ */
85
    /*      We need to tear apart the filename to form a .rsc       */
86
    /*      filename.                                               */
87
    /* ------------------------------------------------------------ */
88
    const CPLString osPath = CPLGetPathSafe(poOpenInfo->pszFilename);
162✔
89
    const CPLString osName = CPLGetFilename(poOpenInfo->pszFilename);
162✔
90

91
    int iFile = CSLFindString(
81✔
92
        papszSiblingFiles, CPLFormFilenameSafe(nullptr, osName, "rsc").c_str());
162✔
93
    if (iFile >= 0)
81✔
94
    {
95
        return CPLFormFilenameSafe(osPath, papszSiblingFiles[iFile], nullptr);
90✔
96
    }
97

98
    return "";
36✔
99
}
100

101
/************************************************************************/
102
/*                            ROIPACDataset()                           */
103
/************************************************************************/
104

105
ROIPACDataset::ROIPACDataset()
15✔
106
    : fpImage(nullptr), fpRsc(nullptr), pszRscFilename(nullptr),
107
      bValidGeoTransform(false)
15✔
108
{
109
    m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
15✔
110
}
15✔
111

112
/************************************************************************/
113
/*                            ~ROIPACDataset()                          */
114
/************************************************************************/
115

116
ROIPACDataset::~ROIPACDataset()
30✔
117
{
118
    ROIPACDataset::Close();
15✔
119
}
30✔
120

121
/************************************************************************/
122
/*                              Close()                                 */
123
/************************************************************************/
124

125
CPLErr ROIPACDataset::Close()
30✔
126
{
127
    CPLErr eErr = CE_None;
30✔
128
    if (nOpenFlags != OPEN_FLAGS_CLOSED)
30✔
129
    {
130
        if (ROIPACDataset::FlushCache(true) != CE_None)
15✔
131
            eErr = CE_Failure;
×
132

133
        if (fpRsc != nullptr && VSIFCloseL(fpRsc) != 0)
15✔
134
        {
135
            eErr = CE_Failure;
×
136
            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
×
137
        }
138
        if (fpImage != nullptr && VSIFCloseL(fpImage) != 0)
15✔
139
        {
140
            eErr = CE_Failure;
×
141
            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
×
142
        }
143
        CPLFree(pszRscFilename);
15✔
144

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

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

155
GDALDataset *ROIPACDataset::Open(GDALOpenInfo *poOpenInfo)
15✔
156
{
157
    /* -------------------------------------------------------------------- */
158
    /*      Confirm that the header is compatible with a ROIPAC dataset.    */
159
    /* -------------------------------------------------------------------- */
160
    if (!Identify(poOpenInfo) || poOpenInfo->fpL == nullptr)
15✔
161
    {
162
        return nullptr;
×
163
    }
164

165
    /* -------------------------------------------------------------------- */
166
    /*      Open the .rsc file                                              */
167
    /* -------------------------------------------------------------------- */
168
    CPLString osRscFilename = getRscFilename(poOpenInfo);
30✔
169
    if (osRscFilename.empty())
15✔
170
    {
171
        return nullptr;
×
172
    }
173
    VSILFILE *fpRsc = nullptr;
15✔
174
    if (poOpenInfo->eAccess == GA_Update)
15✔
175
    {
176
        fpRsc = VSIFOpenL(osRscFilename, "r+");
3✔
177
    }
178
    else
179
    {
180
        fpRsc = VSIFOpenL(osRscFilename, "r");
12✔
181
    }
182
    if (fpRsc == nullptr)
15✔
183
    {
184
        return nullptr;
×
185
    }
186

187
    /* -------------------------------------------------------------------- */
188
    /*      Load the .rsc information.                                      */
189
    /* -------------------------------------------------------------------- */
190
    CPLStringList aosRSC;
30✔
191
    while (true)
192
    {
193
        const char *pszLine = CPLReadLineL(fpRsc);
189✔
194
        if (pszLine == nullptr)
189✔
195
        {
196
            break;
15✔
197
        }
198

199
        char **papszTokens =
200
            CSLTokenizeString2(pszLine, " \t",
174✔
201
                               CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES |
202
                                   CSLT_PRESERVEQUOTES | CSLT_PRESERVEESCAPES);
203
        if (papszTokens == nullptr || papszTokens[0] == nullptr ||
174✔
204
            papszTokens[1] == nullptr)
174✔
205
        {
206
            CSLDestroy(papszTokens);
×
207
            break;
×
208
        }
209
        aosRSC.SetNameValue(papszTokens[0], papszTokens[1]);
174✔
210

211
        CSLDestroy(papszTokens);
174✔
212
    }
174✔
213

214
    /* -------------------------------------------------------------------- */
215
    /*      Fetch required fields.                                          */
216
    /* -------------------------------------------------------------------- */
217
    if (aosRSC.FetchNameValue("WIDTH") == nullptr ||
30✔
218
        aosRSC.FetchNameValue("FILE_LENGTH") == nullptr)
15✔
219
    {
220
        CPL_IGNORE_RET_VAL(VSIFCloseL(fpRsc));
×
221
        return nullptr;
×
222
    }
223
    const int nWidth = atoi(aosRSC.FetchNameValue("WIDTH"));
15✔
224
    const int nFileLength = atoi(aosRSC.FetchNameValue("FILE_LENGTH"));
15✔
225

226
    if (!GDALCheckDatasetDimensions(nWidth, nFileLength))
15✔
227
    {
228
        CPL_IGNORE_RET_VAL(VSIFCloseL(fpRsc));
×
229
        return nullptr;
×
230
    }
231

232
    /* -------------------------------------------------------------------- */
233
    /*      Create a corresponding GDALDataset.                             */
234
    /* -------------------------------------------------------------------- */
235
    auto poDS = std::make_unique<ROIPACDataset>();
30✔
236
    poDS->nRasterXSize = nWidth;
15✔
237
    poDS->nRasterYSize = nFileLength;
15✔
238
    poDS->eAccess = poOpenInfo->eAccess;
15✔
239
    poDS->fpRsc = fpRsc;
15✔
240
    poDS->pszRscFilename = CPLStrdup(osRscFilename.c_str());
15✔
241
    std::swap(poDS->fpImage, poOpenInfo->fpL);
15✔
242

243
    /* -------------------------------------------------------------------- */
244
    /*      Create band information objects.                                */
245
    /* -------------------------------------------------------------------- */
246
    GDALDataType eDataType = GDT_Unknown;
15✔
247
    int nBands = 0;
15✔
248

249
    enum Interleave
250
    {
251
        UNKNOWN,
252
        LINE,
253
        PIXEL
254
    } eInterleave = UNKNOWN;
15✔
255

256
    const char *pszExtension = poOpenInfo->osExtension.c_str();
15✔
257
    if (strcmp(pszExtension, "raw") == 0)
15✔
258
    {
259
        /* ------------------------------------------------------------ */
260
        /* TODO: ROI_PAC raw images are what would be GDT_CInt8 typed,  */
261
        /* but since that type do not exist, we will have to implement  */
262
        /* a specific case in the RasterBand to convert it to           */
263
        /* GDT_CInt16 for example                                       */
264
        /* ------------------------------------------------------------ */
265
#if 0
266
        eDataType = GDT_CInt8;
267
        nBands = 1;
268
        eInterleave = PIXEL;
269
#else
270
        CPLError(CE_Failure, CPLE_NotSupported,
×
271
                 "Reading ROI_PAC raw files is not supported yet.");
272
        return nullptr;
×
273
#endif
274
    }
275
    else if (strcmp(pszExtension, "int") == 0 ||
15✔
276
             strcmp(pszExtension, "slc") == 0)
15✔
277
    {
278
        eDataType = GDT_CFloat32;
×
279
        nBands = 1;
×
280
        eInterleave = PIXEL;
×
281
    }
282
    else if (strcmp(pszExtension, "amp") == 0)
15✔
283
    {
284
        eDataType = GDT_Float32;
×
285
        nBands = 2;
×
286
        eInterleave = PIXEL;
×
287
    }
288
    else if (strcmp(pszExtension, "cor") == 0 ||
15✔
289
             strcmp(pszExtension, "hgt") == 0 ||
15✔
290
             strcmp(pszExtension, "unw") == 0 ||
15✔
291
             strcmp(pszExtension, "msk") == 0 ||
15✔
292
             strcmp(pszExtension, "trans") == 0)
15✔
293
    {
294
        eDataType = GDT_Float32;
×
295
        nBands = 2;
×
296
        eInterleave = LINE;
×
297
    }
298
    else if (strcmp(pszExtension, "dem") == 0)
15✔
299
    {
300
        eDataType = GDT_Int16;
12✔
301
        nBands = 1;
12✔
302
        eInterleave = PIXEL;
12✔
303
    }
304
    else if (strcmp(pszExtension, "flg") == 0)
3✔
305
    {
306
        eDataType = GDT_Byte;
3✔
307
        nBands = 1;
3✔
308
        eInterleave = PIXEL;
3✔
309
    }
310
    else
311
    { /* Eeek */
312
        return nullptr;
×
313
    }
314

315
    int nPixelOffset = 0;
15✔
316
    int nLineOffset = 0;
15✔
317
    vsi_l_offset nBandOffset = 0;
15✔
318
    const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
15✔
319
    bool bIntOverflow = false;
15✔
320
    if (eInterleave == LINE)
15✔
321
    {
322
        nPixelOffset = nDTSize;
×
323
        if (nWidth > INT_MAX / (nPixelOffset * nBands))
×
324
            bIntOverflow = true;
×
325
        else
326
        {
327
            nLineOffset = nPixelOffset * nWidth * nBands;
×
328
            nBandOffset = static_cast<vsi_l_offset>(nDTSize) * nWidth;
×
329
        }
330
    }
331
    else
332
    { /* PIXEL */
333
        nPixelOffset = nDTSize * nBands;
15✔
334
        if (nWidth > INT_MAX / nPixelOffset)
15✔
335
            bIntOverflow = true;
×
336
        else
337
        {
338
            nLineOffset = nPixelOffset * nWidth;
15✔
339
            nBandOffset = nDTSize;
15✔
340

341
            if (nBands > 1)
15✔
342
            {
343
                // GDAL 2.0.[0-3] and 2.1.0  had a value of nLineOffset that was
344
                // equal to the theoretical nLineOffset multiplied by nBands.
345
                VSIFSeekL(poDS->fpImage, 0, SEEK_END);
×
346
                const GUIntBig nWrongFileSize =
×
347
                    static_cast<GUIntBig>(nDTSize) * nWidth *
×
348
                    (static_cast<GUIntBig>(nFileLength - 1) * nBands * nBands +
×
349
                     nBands);
350
                if (VSIFTellL(poDS->fpImage) == nWrongFileSize)
×
351
                {
352
                    CPLError(
×
353
                        CE_Warning, CPLE_AppDefined,
354
                        "This file has been incorrectly generated by an older "
355
                        "GDAL version whose line offset computation was "
356
                        "erroneous.  Taking that into account, "
357
                        "but the file should be re-encoded ideally.");
358
                    nLineOffset = nLineOffset * nBands;
×
359
                }
360
            }
361
        }
362
    }
363

364
    if (bIntOverflow)
15✔
365
    {
366
        CPLError(CE_Failure, CPLE_AppDefined, "Int overflow occurred.");
×
367
        return nullptr;
×
368
    }
369

370
    for (int b = 0; b < nBands; b++)
30✔
371
    {
372
        auto poBand = RawRasterBand::Create(
373
            poDS.get(), b + 1, poDS->fpImage, nBandOffset * b, nPixelOffset,
30✔
374
            nLineOffset, eDataType,
375
            RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN,
376
            RawRasterBand::OwnFP::NO);
15✔
377
        if (!poBand)
15✔
378
            return nullptr;
×
379
        poDS->SetBand(b + 1, std::move(poBand));
15✔
380
    }
381

382
    /* -------------------------------------------------------------------- */
383
    /*      Interpret georeferencing, if present.                           */
384
    /* -------------------------------------------------------------------- */
385
    if (aosRSC.FetchNameValue("X_FIRST") != nullptr &&
15✔
386
        aosRSC.FetchNameValue("X_STEP") != nullptr &&
12✔
387
        aosRSC.FetchNameValue("Y_FIRST") != nullptr &&
39✔
388
        aosRSC.FetchNameValue("Y_STEP") != nullptr)
12✔
389
    {
390
        poDS->m_gt[0] = CPLAtof(aosRSC.FetchNameValue("X_FIRST"));
12✔
391
        poDS->m_gt[1] = CPLAtof(aosRSC.FetchNameValue("X_STEP"));
12✔
392
        poDS->m_gt[2] = 0.0;
12✔
393
        poDS->m_gt[3] = CPLAtof(aosRSC.FetchNameValue("Y_FIRST"));
12✔
394
        poDS->m_gt[4] = 0.0;
12✔
395
        poDS->m_gt[5] = CPLAtof(aosRSC.FetchNameValue("Y_STEP"));
12✔
396
        poDS->bValidGeoTransform = true;
12✔
397
    }
398
    if (aosRSC.FetchNameValue("PROJECTION") != nullptr)
15✔
399
    {
400
        /* ------------------------------------------------------------ */
401
        /* In ROI_PAC, images are georeferenced either with lat/long or */
402
        /* UTM projection. However, using UTM projection is dangerous   */
403
        /* because there is no North/South field, or use of latitude    */
404
        /* bands!                                                       */
405
        /* ------------------------------------------------------------ */
406
        OGRSpatialReference oSRS;
24✔
407
        if (strcmp(aosRSC.FetchNameValue("PROJECTION"), "LL") == 0)
12✔
408
        {
409
            if (aosRSC.FetchNameValue("DATUM") != nullptr)
10✔
410
            {
411
                oSRS.SetWellKnownGeogCS(aosRSC.FetchNameValue("DATUM"));
10✔
412
            }
413
            else
414
            {
415
                oSRS.SetWellKnownGeogCS("WGS84");
×
416
            }
417
        }
418
        else if (STARTS_WITH(aosRSC.FetchNameValue("PROJECTION"), "UTM"))
2✔
419
        {
420
            const char *pszZone = aosRSC.FetchNameValue("PROJECTION") + 3;
2✔
421
            oSRS.SetUTM(atoi(pszZone), TRUE); /* FIXME: north/south? */
2✔
422
            if (aosRSC.FetchNameValue("DATUM") != nullptr)
2✔
423
            {
424
                oSRS.SetWellKnownGeogCS(aosRSC.FetchNameValue("DATUM"));
2✔
425
            }
426
            else
427
            {
428
                oSRS.SetWellKnownGeogCS("NAD27");
×
429
            }
430
        }
431
        poDS->m_oSRS = std::move(oSRS);
12✔
432
        poDS->m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
12✔
433
    }
434
    if (aosRSC.FetchNameValue("Z_OFFSET") != nullptr)
15✔
435
    {
436
        const double dfOffset =
437
            strtod(aosRSC.FetchNameValue("Z_OFFSET"), nullptr);
12✔
438
        for (int b = 1; b <= nBands; b++)
24✔
439
        {
440
            GDALRasterBand *poBand = poDS->GetRasterBand(b);
12✔
441
            poBand->SetOffset(dfOffset);
12✔
442
        }
443
    }
444
    if (aosRSC.FetchNameValue("Z_SCALE") != nullptr)
15✔
445
    {
446
        const double dfScale =
447
            strtod(aosRSC.FetchNameValue("Z_SCALE"), nullptr);
12✔
448
        for (int b = 1; b <= nBands; b++)
24✔
449
        {
450
            GDALRasterBand *poBand = poDS->GetRasterBand(b);
12✔
451
            poBand->SetScale(dfScale);
12✔
452
        }
453
    }
454

455
    /* -------------------------------------------------------------------- */
456
    /*      Set all the other header metadata into the ROI_PAC domain       */
457
    /* -------------------------------------------------------------------- */
458
    for (int i = 0; i < aosRSC.size(); ++i)
189✔
459
    {
460
        char **papszTokens = CSLTokenizeString2(
348✔
461
            aosRSC[i], "=", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
174✔
462
        if (CSLCount(papszTokens) < 2 || strcmp(papszTokens[0], "WIDTH") == 0 ||
348✔
463
            strcmp(papszTokens[0], "FILE_LENGTH") == 0 ||
159✔
464
            strcmp(papszTokens[0], "X_FIRST") == 0 ||
144✔
465
            strcmp(papszTokens[0], "X_STEP") == 0 ||
132✔
466
            strcmp(papszTokens[0], "Y_FIRST") == 0 ||
120✔
467
            strcmp(papszTokens[0], "Y_STEP") == 0 ||
108✔
468
            strcmp(papszTokens[0], "PROJECTION") == 0 ||
96✔
469
            strcmp(papszTokens[0], "DATUM") == 0 ||
84✔
470
            strcmp(papszTokens[0], "Z_OFFSET") == 0 ||
408✔
471
            strcmp(papszTokens[0], "Z_SCALE") == 0)
60✔
472
        {
473
            CSLDestroy(papszTokens);
126✔
474
            continue;
126✔
475
        }
476
        poDS->SetMetadataItem(papszTokens[0], papszTokens[1], "ROI_PAC");
48✔
477
        CSLDestroy(papszTokens);
48✔
478
    }
479
    /* -------------------------------------------------------------------- */
480
    /*      Initialize any PAM information.                                 */
481
    /* -------------------------------------------------------------------- */
482
    poDS->SetDescription(poOpenInfo->pszFilename);
15✔
483
    poDS->TryLoadXML();
15✔
484

485
    /* -------------------------------------------------------------------- */
486
    /*      Check for overviews.                                            */
487
    /* -------------------------------------------------------------------- */
488
    poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename);
15✔
489

490
    return poDS.release();
15✔
491
}
492

493
/************************************************************************/
494
/*                             Identify()                               */
495
/************************************************************************/
496

497
int ROIPACDataset::Identify(GDALOpenInfo *poOpenInfo)
57,066✔
498
{
499
    /* -------------------------------------------------------------------- */
500
    /*      Check if:                                                       */
501
    /*      * 1. The data file extension is known                           */
502
    /* -------------------------------------------------------------------- */
503
    const char *pszExtension = poOpenInfo->osExtension.c_str();
57,066✔
504
    if (strcmp(pszExtension, "raw") == 0)
57,066✔
505
    {
506
        /* Since gdal do not read natively CInt8, more work is needed
507
         * to read raw files */
508
        return false;
23✔
509
    }
510
    const bool bExtensionIsValid =
57,043✔
511
        strcmp(pszExtension, "int") == 0 || strcmp(pszExtension, "slc") == 0 ||
57,037✔
512
        strcmp(pszExtension, "amp") == 0 || strcmp(pszExtension, "cor") == 0 ||
57,018✔
513
        strcmp(pszExtension, "hgt") == 0 || strcmp(pszExtension, "unw") == 0 ||
57,020✔
514
        strcmp(pszExtension, "msk") == 0 ||
56,996✔
515
        strcmp(pszExtension, "trans") == 0 ||
56,951✔
516
        strcmp(pszExtension, "dem") == 0 || strcmp(pszExtension, "flg") == 0;
114,080✔
517
    if (!bExtensionIsValid)
57,043✔
518
    {
519
        return false;
56,882✔
520
    }
521

522
    /* -------------------------------------------------------------------- */
523
    /*      * 2. there is a .rsc file                                      */
524
    /* -------------------------------------------------------------------- */
525
    CPLString osRscFilename = getRscFilename(poOpenInfo);
320✔
526
    if (osRscFilename.empty())
159✔
527
    {
528
        return false;
129✔
529
    }
530

531
    return true;
30✔
532
}
533

534
/************************************************************************/
535
/*                              Create()                                */
536
/************************************************************************/
537

538
GDALDataset *ROIPACDataset::Create(const char *pszFilename, int nXSize,
52✔
539
                                   int nYSize, int nBandsIn, GDALDataType eType,
540
                                   char ** /* papszOptions */)
541
{
542
    /* -------------------------------------------------------------------- */
543
    /*      Verify input options.                                           */
544
    /* -------------------------------------------------------------------- */
545
    const std::string osExtension = CPLGetExtensionSafe(pszFilename);
104✔
546
    const char *pszExtension = osExtension.c_str();
52✔
547
    if (strcmp(pszExtension, "int") == 0 || strcmp(pszExtension, "slc") == 0)
52✔
548
    {
549
        if (nBandsIn != 1 || eType != GDT_CFloat32)
×
550
        {
551
            CPLError(CE_Failure, CPLE_AppDefined,
×
552
                     "Attempt to create ROI_PAC %s dataset with an illegal "
553
                     "number of bands (%d) and/or data type (%s).",
554
                     pszExtension, nBandsIn, GDALGetDataTypeName(eType));
555
            return nullptr;
×
556
        }
557
    }
558
    else if (strcmp(pszExtension, "amp") == 0)
52✔
559
    {
560
        if (nBandsIn != 2 || eType != GDT_Float32)
×
561
        {
562
            CPLError(CE_Failure, CPLE_AppDefined,
×
563
                     "Attempt to create ROI_PAC %s dataset with an illegal "
564
                     "number of bands (%d) and/or data type (%s).",
565
                     pszExtension, nBandsIn, GDALGetDataTypeName(eType));
566
            return nullptr;
×
567
        }
568
    }
569
    else if (strcmp(pszExtension, "cor") == 0 ||
52✔
570
             strcmp(pszExtension, "hgt") == 0 ||
52✔
571
             strcmp(pszExtension, "unw") == 0 ||
52✔
572
             strcmp(pszExtension, "msk") == 0 ||
52✔
573
             strcmp(pszExtension, "trans") == 0)
52✔
574
    {
575
        if (nBandsIn != 2 || eType != GDT_Float32)
×
576
        {
577
            CPLError(CE_Failure, CPLE_AppDefined,
×
578
                     "Attempt to create ROI_PAC %s dataset with an illegal "
579
                     "number of bands (%d) and/or data type (%s).",
580
                     pszExtension, nBandsIn, GDALGetDataTypeName(eType));
581
            return nullptr;
×
582
        }
583
    }
584
    else if (strcmp(pszExtension, "dem") == 0)
52✔
585
    {
586
        if (nBandsIn != 1 || eType != GDT_Int16)
2✔
587
        {
588
            CPLError(CE_Failure, CPLE_AppDefined,
×
589
                     "Attempt to create ROI_PAC %s dataset with an illegal "
590
                     "number of bands (%d) and/or data type (%s).",
591
                     pszExtension, nBandsIn, GDALGetDataTypeName(eType));
592
            return nullptr;
×
593
        }
594
    }
595
    else if (strcmp(pszExtension, "flg") == 0)
50✔
596
    {
597
        if (nBandsIn != 1 || eType != GDT_Byte)
1✔
598
        {
599
            CPLError(CE_Failure, CPLE_AppDefined,
×
600
                     "Attempt to create ROI_PAC %s dataset with an illegal "
601
                     "number of bands (%d) and/or data type (%s).",
602
                     pszExtension, nBandsIn, GDALGetDataTypeName(eType));
603
            return nullptr;
×
604
        }
605
    }
606
    else
607
    { /* Eeek */
608
        CPLError(CE_Failure, CPLE_AppDefined,
49✔
609
                 "Attempt to create ROI_PAC dataset with an unknown type (%s)",
610
                 pszExtension);
611
        return nullptr;
49✔
612
    }
613

614
    /* -------------------------------------------------------------------- */
615
    /*      Try to create the file.                                         */
616
    /* -------------------------------------------------------------------- */
617
    VSILFILE *fp = VSIFOpenL(pszFilename, "wb");
3✔
618
    if (fp == nullptr)
3✔
619
    {
620
        CPLError(CE_Failure, CPLE_OpenFailed,
×
621
                 "Attempt to create file `%s' failed.", pszFilename);
622
        return nullptr;
×
623
    }
624

625
    /* -------------------------------------------------------------------- */
626
    /*      Just write out a couple of bytes to establish the binary        */
627
    /*      file, and then close it.                                        */
628
    /* -------------------------------------------------------------------- */
629
    CPL_IGNORE_RET_VAL(VSIFWriteL("\0\0", 2, 1, fp));
3✔
630
    CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
3✔
631

632
    /* -------------------------------------------------------------------- */
633
    /*      Open the RSC file.                                              */
634
    /* -------------------------------------------------------------------- */
635
    const std::string osRSCFilename =
636
        CPLFormFilenameSafe(nullptr, pszFilename, "rsc");
6✔
637
    fp = VSIFOpenL(osRSCFilename.c_str(), "wt");
3✔
638
    if (fp == nullptr)
3✔
639
    {
640
        CPLError(CE_Failure, CPLE_OpenFailed,
×
641
                 "Attempt to create file `%s' failed.", osRSCFilename.c_str());
642
        return nullptr;
×
643
    }
644

645
    /* -------------------------------------------------------------------- */
646
    /*      Write out the header.                                           */
647
    /* -------------------------------------------------------------------- */
648
    CPL_IGNORE_RET_VAL(VSIFPrintfL(fp, "%-40s %d\n", "WIDTH", nXSize));
3✔
649
    CPL_IGNORE_RET_VAL(VSIFPrintfL(fp, "%-40s %d\n", "FILE_LENGTH", nYSize));
3✔
650
    CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
3✔
651

652
    return GDALDataset::FromHandle(GDALOpen(pszFilename, GA_Update));
3✔
653
}
654

655
/************************************************************************/
656
/*                             FlushCache()                             */
657
/************************************************************************/
658

659
CPLErr ROIPACDataset::FlushCache(bool bAtClosing)
15✔
660
{
661
    CPLErr eErr = RawDataset::FlushCache(bAtClosing);
15✔
662

663
    GDALRasterBand *band = (GetRasterCount() > 0) ? GetRasterBand(1) : nullptr;
15✔
664

665
    if (eAccess == GA_ReadOnly || band == nullptr)
15✔
666
        return eErr;
12✔
667

668
    // If opening an existing file in Update mode (i.e. "r+") we need to make
669
    // sure any existing content is cleared, otherwise the file may contain
670
    // trailing content from the previous write.
671
    bool bOK = VSIFTruncateL(fpRsc, 0) == 0;
3✔
672

673
    bOK &= VSIFSeekL(fpRsc, 0, SEEK_SET) == 0;
3✔
674
    /* -------------------------------------------------------------------- */
675
    /*      Rewrite out the header.                                         */
676
    /* -------------------------------------------------------------------- */
677
    /* -------------------------------------------------------------------- */
678
    /*      Raster dimensions.                                              */
679
    /* -------------------------------------------------------------------- */
680
    bOK &= VSIFPrintfL(fpRsc, "%-40s %d\n", "WIDTH", nRasterXSize) > 0;
3✔
681
    bOK &= VSIFPrintfL(fpRsc, "%-40s %d\n", "FILE_LENGTH", nRasterYSize) > 0;
3✔
682

683
    /* -------------------------------------------------------------------- */
684
    /*      Georeferencing.                                                 */
685
    /* -------------------------------------------------------------------- */
686
    if (!m_oSRS.IsEmpty())
3✔
687
    {
688
        int bNorth = FALSE;
3✔
689
        int iUTMZone = m_oSRS.GetUTMZone(&bNorth);
3✔
690
        if (iUTMZone != 0)
3✔
691
        {
692
            bOK &= VSIFPrintfL(fpRsc, "%-40s %s%d\n", "PROJECTION", "UTM",
1✔
693
                               iUTMZone) > 0;
1✔
694
        }
695
        else if (m_oSRS.IsGeographic())
2✔
696
        {
697
            bOK &= VSIFPrintfL(fpRsc, "%-40s %s\n", "PROJECTION", "LL") > 0;
2✔
698
        }
699
        else
700
        {
701
            CPLError(CE_Warning, CPLE_AppDefined,
×
702
                     "ROI_PAC format only support Latitude/Longitude and "
703
                     "UTM projections, discarding projection.");
704
        }
705

706
        if (m_oSRS.GetAttrValue("DATUM") != nullptr)
3✔
707
        {
708
            if (strcmp(m_oSRS.GetAttrValue("DATUM"), "WGS_1984") == 0)
3✔
709
            {
710
                bOK &= VSIFPrintfL(fpRsc, "%-40s %s\n", "DATUM", "WGS84") > 0;
2✔
711
            }
712
            else
713
            {
714
                CPLError(CE_Warning, CPLE_AppDefined,
1✔
715
                         "Datum \"%s\" probably not supported in the "
716
                         "ROI_PAC format, saving it anyway",
717
                         m_oSRS.GetAttrValue("DATUM"));
718
                bOK &= VSIFPrintfL(fpRsc, "%-40s %s\n", "DATUM",
1✔
719
                                   m_oSRS.GetAttrValue("DATUM")) > 0;
1✔
720
            }
721
        }
722
        if (m_oSRS.GetAttrValue("UNIT") != nullptr)
3✔
723
        {
724
            bOK &= VSIFPrintfL(fpRsc, "%-40s %s\n", "X_UNIT",
3✔
725
                               m_oSRS.GetAttrValue("UNIT")) > 0;
3✔
726
            bOK &= VSIFPrintfL(fpRsc, "%-40s %s\n", "Y_UNIT",
3✔
727
                               m_oSRS.GetAttrValue("UNIT")) > 0;
3✔
728
        }
729
    }
730
    if (bValidGeoTransform)
3✔
731
    {
732
        if (m_gt[2] != 0 || m_gt[4] != 0)
3✔
733
        {
734
            CPLError(CE_Warning, CPLE_AppDefined,
×
735
                     "ROI_PAC format do not support geotransform with "
736
                     "rotation, discarding info.");
737
        }
738
        else
739
        {
740
            bOK &= VSIFPrintfL(fpRsc, "%-40s %.16g\n", "X_FIRST", m_gt[0]) > 0;
3✔
741
            bOK &= VSIFPrintfL(fpRsc, "%-40s %.16g\n", "X_STEP", m_gt[1]) > 0;
3✔
742
            bOK &= VSIFPrintfL(fpRsc, "%-40s %.16g\n", "Y_FIRST", m_gt[3]) > 0;
3✔
743
            bOK &= VSIFPrintfL(fpRsc, "%-40s %.16g\n", "Y_STEP", m_gt[5]) > 0;
3✔
744
            bOK &= VSIFPrintfL(fpRsc, "%-40s %.16g\n", "Z_OFFSET",
3✔
745
                               band->GetOffset(nullptr)) > 0;
3✔
746
            bOK &= VSIFPrintfL(fpRsc, "%-40s %.16g\n", "Z_SCALE",
3✔
747
                               band->GetScale(nullptr)) > 0;
6✔
748
        }
749
    }
750

751
    /* -------------------------------------------------------------------- */
752
    /*      Metadata stored in the ROI_PAC domain.                          */
753
    /* -------------------------------------------------------------------- */
754
    char **papszROIPACMetadata = GetMetadata("ROI_PAC");
3✔
755
    for (int i = 0; i < CSLCount(papszROIPACMetadata); i++)
3✔
756
    {
757
        /* Get the tokens from the metadata item */
758
        char **papszTokens =
759
            CSLTokenizeString2(papszROIPACMetadata[i], "=",
×
760
                               CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
761
        if (CSLCount(papszTokens) != 2)
×
762
        {
763
            CPLDebug("ROI_PAC",
×
764
                     "Line of header file could not be split at = "
765
                     "into two elements: %s",
766
                     papszROIPACMetadata[i]);
×
767
            CSLDestroy(papszTokens);
×
768
            continue;
×
769
        }
770

771
        /* Don't write it out if it is one of the bits of metadata that is
772
         * written out elsewhere in this routine */
773
        if (strcmp(papszTokens[0], "WIDTH") == 0 ||
×
774
            strcmp(papszTokens[0], "FILE_LENGTH") == 0)
×
775
        {
776
            CSLDestroy(papszTokens);
×
777
            continue;
×
778
        }
779
        bOK &= VSIFPrintfL(fpRsc, "%-40s %s\n", papszTokens[0],
×
780
                           papszTokens[1]) > 0;
×
781
        CSLDestroy(papszTokens);
×
782
    }
783
    if (!bOK)
3✔
784
        eErr = CE_Failure;
×
785
    return eErr;
3✔
786
}
787

788
/************************************************************************/
789
/*                         GetGeoTransform()                            */
790
/************************************************************************/
791

792
CPLErr ROIPACDataset::GetGeoTransform(GDALGeoTransform &gt) const
8✔
793
{
794
    gt = m_gt;
8✔
795
    return bValidGeoTransform ? CE_None : CE_Failure;
8✔
796
}
797

798
/************************************************************************/
799
/*                          SetGeoTransform()                           */
800
/************************************************************************/
801

802
CPLErr ROIPACDataset::SetGeoTransform(const GDALGeoTransform &gt)
3✔
803
{
804
    m_gt = gt;
3✔
805
    bValidGeoTransform = true;
3✔
806
    return CE_None;
3✔
807
}
808

809
/************************************************************************/
810
/*                           SetSpatialRef()                            */
811
/************************************************************************/
812

813
CPLErr ROIPACDataset::SetSpatialRef(const OGRSpatialReference *poSRS)
3✔
814

815
{
816
    if (poSRS)
3✔
817
        m_oSRS = *poSRS;
3✔
818
    else
819
        m_oSRS.Clear();
×
820
    return CE_None;
3✔
821
}
822

823
/************************************************************************/
824
/*                            GetFileList()                             */
825
/************************************************************************/
826

827
char **ROIPACDataset::GetFileList()
4✔
828
{
829
    // Main data file, etc.
830
    char **papszFileList = RawDataset::GetFileList();
4✔
831

832
    // RSC file.
833
    papszFileList = CSLAddString(papszFileList, pszRscFilename);
4✔
834

835
    return papszFileList;
4✔
836
}
837

838
/************************************************************************/
839
/*                        GDALRegister_ROIPAC()                         */
840
/************************************************************************/
841

842
void GDALRegister_ROIPAC()
1,911✔
843
{
844
    if (GDALGetDriverByName("ROI_PAC") != nullptr)
1,911✔
845
        return;
282✔
846

847
    GDALDriver *poDriver = new GDALDriver();
1,629✔
848

849
    poDriver->SetDescription("ROI_PAC");
1,629✔
850
    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "ROI_PAC raster");
1,629✔
851
    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
1,629✔
852
                              "drivers/raster/roi_pac.html");
1,629✔
853
    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
1,629✔
854
    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
1,629✔
855

856
    poDriver->pfnOpen = ROIPACDataset::Open;
1,629✔
857
    poDriver->pfnIdentify = ROIPACDataset::Identify;
1,629✔
858
    poDriver->pfnCreate = ROIPACDataset::Create;
1,629✔
859

860
    GetGDALDriverManager()->RegisterDriver(poDriver);
1,629✔
861
}
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