• 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

8.79
/frmts/map/mapdataset.cpp
1
/******************************************************************************
2
 *
3
 * Project:  OziExplorer .MAP Driver
4
 * Purpose:  GDALDataset driver for OziExplorer .MAP files
5
 * Author:   Jean-Claude Repetto, <jrepetto at @free dot fr>
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2012, Jean-Claude Repetto
9
 * Copyright (c) 2012, Even Rouault <even dot rouault at spatialys.com>
10
 *
11
 * SPDX-License-Identifier: MIT
12
 ****************************************************************************/
13

14
#include "gdal_frmts.h"
15
#include "gdal_pam.h"
16
#include "gdal_proxy.h"
17
#include "ogr_geometry.h"
18
#include "ogr_spatialref.h"
19

20
/************************************************************************/
21
/* ==================================================================== */
22
/*                                MAPDataset                            */
23
/* ==================================================================== */
24
/************************************************************************/
25

26
class MAPDataset final : public GDALDataset
27
{
28
    GDALDataset *poImageDS{};
29

30
    OGRSpatialReference m_oSRS{};
31
    int bGeoTransformValid{};
32
    GDALGeoTransform m_gt{};
33
    int nGCPCount{};
34
    GDAL_GCP *pasGCPList{};
35
    OGRPolygon *poNeatLine{};
36
    CPLString osImgFilename{};
37

38
    CPL_DISALLOW_COPY_ASSIGN(MAPDataset)
39

40
  public:
41
    MAPDataset();
42
    virtual ~MAPDataset();
43

44
    const OGRSpatialReference *GetSpatialRef() const override;
45
    virtual CPLErr GetGeoTransform(GDALGeoTransform &gt) const override;
46
    virtual int GetGCPCount() override;
47
    const OGRSpatialReference *GetGCPSpatialRef() const override;
48
    virtual const GDAL_GCP *GetGCPs() override;
49
    virtual char **GetFileList() override;
50

51
    virtual int CloseDependentDatasets() override;
52

53
    static GDALDataset *Open(GDALOpenInfo *);
54
    static int Identify(GDALOpenInfo *poOpenInfo);
55
};
56

57
/************************************************************************/
58
/* ==================================================================== */
59
/*                         MAPWrapperRasterBand                         */
60
/* ==================================================================== */
61
/************************************************************************/
62
class MAPWrapperRasterBand final : public GDALProxyRasterBand
63
{
64
    GDALRasterBand *poBaseBand{};
65

66
    CPL_DISALLOW_COPY_ASSIGN(MAPWrapperRasterBand)
67

68
  protected:
69
    virtual GDALRasterBand *
70
    RefUnderlyingRasterBand(bool /*bForceOpen*/) const override;
71

72
  public:
73
    explicit MAPWrapperRasterBand(GDALRasterBand *poBaseBandIn)
×
74
    {
×
75
        this->poBaseBand = poBaseBandIn;
×
76
        eDataType = poBaseBand->GetRasterDataType();
×
77
        poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
×
78
    }
×
79

80
    ~MAPWrapperRasterBand()
×
81
    {
×
82
    }
×
83
};
84

85
GDALRasterBand *
86
MAPWrapperRasterBand::RefUnderlyingRasterBand(bool /*bForceOpen*/) const
×
87
{
88
    return poBaseBand;
×
89
}
90

91
/************************************************************************/
92
/* ==================================================================== */
93
/*                             MAPDataset                               */
94
/* ==================================================================== */
95
/************************************************************************/
96

97
MAPDataset::MAPDataset()
×
98
    : poImageDS(nullptr), bGeoTransformValid(false), nGCPCount(0),
99
      pasGCPList(nullptr), poNeatLine(nullptr)
×
100
{
101
    m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
×
102
}
×
103

104
/************************************************************************/
105
/*                            ~MAPDataset()                             */
106
/************************************************************************/
107

108
MAPDataset::~MAPDataset()
×
109

110
{
111
    if (poImageDS != nullptr)
×
112
    {
113
        GDALClose(poImageDS);
×
114
        poImageDS = nullptr;
×
115
    }
116

117
    if (nGCPCount)
×
118
    {
119
        GDALDeinitGCPs(nGCPCount, pasGCPList);
×
120
        CPLFree(pasGCPList);
×
121
    }
122

123
    if (poNeatLine != nullptr)
×
124
    {
125
        delete poNeatLine;
×
126
        poNeatLine = nullptr;
×
127
    }
128
}
×
129

130
/************************************************************************/
131
/*                       CloseDependentDatasets()                       */
132
/************************************************************************/
133

134
int MAPDataset::CloseDependentDatasets()
×
135
{
136
    int bRet = GDALDataset::CloseDependentDatasets();
×
137
    if (poImageDS != nullptr)
×
138
    {
139
        GDALClose(poImageDS);
×
140
        poImageDS = nullptr;
×
141
        bRet = TRUE;
×
142
    }
143
    return bRet;
×
144
}
145

146
/************************************************************************/
147
/*                              Identify()                              */
148
/************************************************************************/
149

150
int MAPDataset::Identify(GDALOpenInfo *poOpenInfo)
58,260✔
151

152
{
153
    if (poOpenInfo->nHeaderBytes < 200 ||
62,187✔
154
        !poOpenInfo->IsExtensionEqualToCI("MAP"))
3,927✔
155
        return FALSE;
58,260✔
156

157
    if (strstr(reinterpret_cast<const char *>(poOpenInfo->pabyHeader),
×
158
               "OziExplorer Map Data File") == nullptr)
159
        return FALSE;
×
160

161
    return TRUE;
×
162
}
163

164
/************************************************************************/
165
/*                                Open()                                */
166
/************************************************************************/
167

168
GDALDataset *MAPDataset::Open(GDALOpenInfo *poOpenInfo)
×
169
{
170
    if (!Identify(poOpenInfo))
×
171
        return nullptr;
×
172

173
    /* -------------------------------------------------------------------- */
174
    /*      Confirm the requested access is supported.                      */
175
    /* -------------------------------------------------------------------- */
176
    if (poOpenInfo->eAccess == GA_Update)
×
177
    {
178
        ReportUpdateNotSupportedByDriver("MAP");
×
179
        return nullptr;
×
180
    }
181

182
    /* -------------------------------------------------------------------- */
183
    /*      Create a corresponding GDALDataset.                             */
184
    /* -------------------------------------------------------------------- */
185

186
    MAPDataset *poDS = new MAPDataset();
×
187

188
    /* -------------------------------------------------------------------- */
189
    /*      Try to load and parse the .MAP file.                            */
190
    /* -------------------------------------------------------------------- */
191

192
    char *pszWKT = nullptr;
×
193
    bool bOziFileOK = CPL_TO_BOOL(
×
194
        GDALLoadOziMapFile(poOpenInfo->pszFilename, poDS->m_gt.data(), &pszWKT,
×
195
                           &poDS->nGCPCount, &poDS->pasGCPList));
196
    if (pszWKT)
×
197
    {
198
        poDS->m_oSRS.importFromWkt(pszWKT);
×
199
        CPLFree(pszWKT);
×
200
    }
201

202
    if (bOziFileOK && poDS->nGCPCount == 0)
×
203
        poDS->bGeoTransformValid = TRUE;
×
204

205
    /* We need to read again the .map file because the GDALLoadOziMapFile
206
       function does not returns all required data . An API change is necessary
207
       : maybe in GDAL 2.0 ? */
208

209
    char **papszLines = CSLLoad2(poOpenInfo->pszFilename, 200, 200, nullptr);
×
210

211
    if (!papszLines)
×
212
    {
213
        delete poDS;
×
214
        return nullptr;
×
215
    }
216

217
    const int nLines = CSLCount(papszLines);
×
218
    if (nLines < 3)
×
219
    {
220
        delete poDS;
×
221
        CSLDestroy(papszLines);
×
222
        return nullptr;
×
223
    }
224

225
    /* -------------------------------------------------------------------- */
226
    /*      We need to open the image in order to establish                 */
227
    /*      details like the band count and types.                          */
228
    /* -------------------------------------------------------------------- */
229
    poDS->osImgFilename = papszLines[2];
×
230

231
    const CPLString osPath = CPLGetPathSafe(poOpenInfo->pszFilename);
×
232
    if (CPLIsFilenameRelative(poDS->osImgFilename))
×
233
    {
234
        poDS->osImgFilename =
235
            CPLFormCIFilenameSafe(osPath, poDS->osImgFilename, nullptr);
×
236
    }
237
    else
238
    {
239
        VSIStatBufL sStat;
240
        if (VSIStatL(poDS->osImgFilename, &sStat) != 0)
×
241
        {
242
            poDS->osImgFilename = CPLGetFilename(poDS->osImgFilename);
×
243
            poDS->osImgFilename =
244
                CPLFormCIFilenameSafe(osPath, poDS->osImgFilename, nullptr);
×
245
        }
246
    }
247

248
    /* -------------------------------------------------------------------- */
249
    /*      Try and open the file.                                          */
250
    /* -------------------------------------------------------------------- */
251
    poDS->poImageDS =
×
252
        GDALDataset::FromHandle(GDALOpen(poDS->osImgFilename, GA_ReadOnly));
×
253
    if (poDS->poImageDS == nullptr || poDS->poImageDS->GetRasterCount() == 0)
×
254
    {
255
        CSLDestroy(papszLines);
×
256
        delete poDS;
×
257
        return nullptr;
×
258
    }
259

260
    /* -------------------------------------------------------------------- */
261
    /*      Attach the bands.                                               */
262
    /* -------------------------------------------------------------------- */
263
    poDS->nRasterXSize = poDS->poImageDS->GetRasterXSize();
×
264
    poDS->nRasterYSize = poDS->poImageDS->GetRasterYSize();
×
265
    if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
×
266
    {
267
        CSLDestroy(papszLines);
×
268
        GDALClose(poDS->poImageDS);
×
269
        delete poDS;
×
270
        return nullptr;
×
271
    }
272

273
    for (int iBand = 1; iBand <= poDS->poImageDS->GetRasterCount(); iBand++)
×
274
        poDS->SetBand(iBand, new MAPWrapperRasterBand(
×
275
                                 poDS->poImageDS->GetRasterBand(iBand)));
×
276

277
    /* -------------------------------------------------------------------- */
278
    /*      Add the neatline/cutline, if required                           */
279
    /* -------------------------------------------------------------------- */
280

281
    /* First, we need to check if it is necessary to define a neatline */
282
    bool bNeatLine = false;
×
283
    for (int iLine = 10; iLine < nLines; iLine++)
×
284
    {
285
        if (STARTS_WITH_CI(papszLines[iLine], "MMPXY,"))
×
286
        {
287
            char **papszTok =
288
                CSLTokenizeString2(papszLines[iLine], ",",
×
289
                                   CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
290

291
            if (CSLCount(papszTok) != 4)
×
292
            {
293
                CSLDestroy(papszTok);
×
294
                continue;
×
295
            }
296

297
            const int x = atoi(papszTok[2]);
×
298
            const int y = atoi(papszTok[3]);
×
299
            if ((x != 0 && x != poDS->nRasterXSize) ||
×
300
                (y != 0 && y != poDS->nRasterYSize))
×
301
            {
302
                bNeatLine = true;
×
303
                CSLDestroy(papszTok);
×
304
                break;
×
305
            }
306
            CSLDestroy(papszTok);
×
307
        }
308
    }
309

310
    /* Create and fill the neatline polygon */
311
    if (bNeatLine)
×
312
    {
313
        poDS->poNeatLine =
×
314
            new OGRPolygon(); /* Create a polygon to store the neatline */
×
315
        OGRLinearRing *poRing = new OGRLinearRing();
×
316

317
        if (poDS->bGeoTransformValid) /* Compute the projected coordinates of
×
318
                                         the corners */
319
        {
320
            for (int iLine = 10; iLine < nLines; iLine++)
×
321
            {
322
                if (STARTS_WITH_CI(papszLines[iLine], "MMPXY,"))
×
323
                {
324
                    char **papszTok = CSLTokenizeString2(
×
325
                        papszLines[iLine], ",",
×
326
                        CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
327

328
                    if (CSLCount(papszTok) != 4)
×
329
                    {
330
                        CSLDestroy(papszTok);
×
331
                        continue;
×
332
                    }
333

334
                    const double x = CPLAtofM(papszTok[2]);
×
335
                    const double y = CPLAtofM(papszTok[3]);
×
336
                    const double X =
337
                        poDS->m_gt[0] + x * poDS->m_gt[1] + y * poDS->m_gt[2];
×
338
                    const double Y =
339
                        poDS->m_gt[3] + x * poDS->m_gt[4] + y * poDS->m_gt[5];
×
340
                    poRing->addPoint(X, Y);
×
341
                    CPLDebug("CORNER MMPXY", "%f, %f, %f, %f", x, y, X, Y);
×
342
                    CSLDestroy(papszTok);
×
343
                }
344
            }
345
        }
346
        else /* Convert the geographic coordinates to projected coordinates */
347
        {
348
            OGRCoordinateTransformation *poTransform = nullptr;
×
349
            if (!poDS->m_oSRS.IsEmpty())
×
350
            {
351
                OGRSpatialReference *poLongLat = poDS->m_oSRS.CloneGeogCS();
×
352
                if (poLongLat)
×
353
                {
354
                    poLongLat->SetAxisMappingStrategy(
×
355
                        OAMS_TRADITIONAL_GIS_ORDER);
356
                    poTransform = OGRCreateCoordinateTransformation(
×
357
                        poLongLat, &poDS->m_oSRS);
×
358
                    delete poLongLat;
×
359
                }
360
            }
361

362
            for (int iLine = 10; iLine < nLines; iLine++)
×
363
            {
364
                if (STARTS_WITH_CI(papszLines[iLine], "MMPLL,"))
×
365
                {
366
                    CPLDebug("MMPLL", "%s", papszLines[iLine]);
×
367

368
                    char **papszTok = CSLTokenizeString2(
×
369
                        papszLines[iLine], ",",
×
370
                        CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
371

372
                    if (CSLCount(papszTok) != 4)
×
373
                    {
374
                        CSLDestroy(papszTok);
×
375
                        continue;
×
376
                    }
377

378
                    double dfLon = CPLAtofM(papszTok[2]);
×
379
                    double dfLat = CPLAtofM(papszTok[3]);
×
380

381
                    if (poTransform)
×
382
                        poTransform->Transform(1, &dfLon, &dfLat);
×
383
                    poRing->addPoint(dfLon, dfLat);
×
384
                    CPLDebug("CORNER MMPLL", "%f, %f", dfLon, dfLat);
×
385
                    CSLDestroy(papszTok);
×
386
                }
387
            }
388
            if (poTransform)
×
389
                delete poTransform;
×
390
        }
391

392
        poRing->closeRings();
×
393
        poDS->poNeatLine->addRingDirectly(poRing);
×
394

395
        char *pszNeatLineWkt = nullptr;
×
396
        poDS->poNeatLine->exportToWkt(&pszNeatLineWkt);
×
397
        CPLDebug("NEATLINE", "%s", pszNeatLineWkt);
×
398
        poDS->SetMetadataItem("NEATLINE", pszNeatLineWkt);
×
399
        CPLFree(pszNeatLineWkt);
×
400
    }
401

402
    CSLDestroy(papszLines);
×
403

404
    return poDS;
×
405
}
406

407
/************************************************************************/
408
/*                          GetSpatialRef()                             */
409
/************************************************************************/
410

411
const OGRSpatialReference *MAPDataset::GetSpatialRef() const
×
412
{
413
    return (!m_oSRS.IsEmpty() && nGCPCount == 0) ? &m_oSRS : nullptr;
×
414
}
415

416
/************************************************************************/
417
/*                          GetGeoTransform()                           */
418
/************************************************************************/
419

420
CPLErr MAPDataset::GetGeoTransform(GDALGeoTransform &gt) const
×
421

422
{
423
    gt = m_gt;
×
424

425
    return (nGCPCount == 0) ? CE_None : CE_Failure;
×
426
}
427

428
/************************************************************************/
429
/*                           GetGCPCount()                              */
430
/************************************************************************/
431

432
int MAPDataset::GetGCPCount()
×
433
{
434
    return nGCPCount;
×
435
}
436

437
/************************************************************************/
438
/*                          GetGCPSpatialRef()                          */
439
/************************************************************************/
440

441
const OGRSpatialReference *MAPDataset::GetGCPSpatialRef() const
×
442
{
443
    return (!m_oSRS.IsEmpty() && nGCPCount != 0) ? &m_oSRS : nullptr;
×
444
}
445

446
/************************************************************************/
447
/*                               GetGCPs()                              */
448
/************************************************************************/
449

450
const GDAL_GCP *MAPDataset::GetGCPs()
×
451
{
452
    return pasGCPList;
×
453
}
454

455
/************************************************************************/
456
/*                            GetFileList()                             */
457
/************************************************************************/
458

459
char **MAPDataset::GetFileList()
×
460
{
461
    char **papszFileList = GDALDataset::GetFileList();
×
462

463
    papszFileList = CSLAddString(papszFileList, osImgFilename);
×
464

465
    return papszFileList;
×
466
}
467

468
/************************************************************************/
469
/*                          GDALRegister_MAP()                          */
470
/************************************************************************/
471

472
void GDALRegister_MAP()
1,911✔
473

474
{
475
    if (GDALGetDriverByName("MAP") != nullptr)
1,911✔
476
        return;
282✔
477

478
    GDALDriver *poDriver = new GDALDriver();
1,629✔
479

480
    poDriver->SetDescription("MAP");
1,629✔
481
    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
1,629✔
482
    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "OziExplorer .MAP");
1,629✔
483
    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/map.html");
1,629✔
484

485
    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
1,629✔
486

487
    poDriver->pfnOpen = MAPDataset::Open;
1,629✔
488
    poDriver->pfnIdentify = MAPDataset::Identify;
1,629✔
489

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