• 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

55.81
/frmts/raw/landataset.cpp
1
/******************************************************************************
2
 *
3
 * Project:  eCognition
4
 * Purpose:  Implementation of Erdas .LAN / .GIS format.
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2004, Frank Warmerdam
9
 * Copyright (c) 2008-2011, 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 <cmath>
20

21
#include <algorithm>
22

23
/**
24

25
Erdas Header format: "HEAD74"
26

27
Offset   Size    Type      Description
28
------   ----    ----      -----------
29
0          6     char      magic cookie / version (i.e. HEAD74).
30
6          2    Int16      Pixel type, 0=8bit, 1=4bit, 2=16bit
31
8          2    Int16      Number of Bands.
32
10         6     char      Unknown.
33
16         4    Int32      Width
34
20         4    Int32      Height
35
24         4    Int32      X Start (offset in original file?)
36
28         4    Int32      Y Start (offset in original file?)
37
32        56     char      Unknown.
38
88         2    Int16      0=LAT, 1=UTM, 2=StatePlane, 3- are projections?
39
90         2    Int16      Classes in coverage.
40
92        14     char      Unknown.
41
106        2    Int16      Area Unit (0=none, 1=Acre, 2=Hectare, 3=Other)
42
108        4  Float32      Pixel area.
43
112        4  Float32      Upper Left corner X (center of pixel?)
44
116        4  Float32      Upper Left corner Y (center of pixel?)
45
120        4  Float32      Width of a pixel.
46
124        4  Float32      Height of a pixel.
47

48
Erdas Header format: "HEADER"
49

50
Offset   Size    Type      Description
51
------   ----    ----      -----------
52
0          6     char      magic cookie / version (i.e. HEAD74).
53
6          2    Int16      Pixel type, 0=8bit, 1=4bit, 2=16bit
54
8          2    Int16      Number of Bands.
55
10         6     char      Unknown.
56
16         4  Float32      Width
57
20         4  Float32      Height
58
24         4    Int32      X Start (offset in original file?)
59
28         4    Int32      Y Start (offset in original file?)
60
32        56     char      Unknown.
61
88         2    Int16      0=LAT, 1=UTM, 2=StatePlane, 3- are projections?
62
90         2    Int16      Classes in coverage.
63
92        14     char      Unknown.
64
106        2    Int16      Area Unit (0=none, 1=Acre, 2=Hectare, 3=Other)
65
108        4  Float32      Pixel area.
66
112        4  Float32      Upper Left corner X (center of pixel?)
67
116        4  Float32      Upper Left corner Y (center of pixel?)
68
120        4  Float32      Width of a pixel.
69
124        4  Float32      Height of a pixel.
70

71
All binary fields are in the same byte order but it may be big endian or
72
little endian depending on what platform the file was written on.  Usually
73
this can be checked against the number of bands though this test won't work
74
if there are more than 255 bands.
75

76
There is also some information on .STA and .TRL files at:
77

78
  http://www.pcigeomatics.com/cgi-bin/pcihlp/ERDASWR%7CTRAILER+FORMAT
79

80
**/
81

82
constexpr int ERD_HEADER_SIZE = 128;
83

84
/************************************************************************/
85
/* ==================================================================== */
86
/*                         LAN4BitRasterBand                            */
87
/* ==================================================================== */
88
/************************************************************************/
89

90
class LANDataset;
91

92
class LAN4BitRasterBand final : public GDALPamRasterBand
93
{
94
    GDALColorTable *poCT;
95
    GDALColorInterp eInterp;
96

97
    CPL_DISALLOW_COPY_ASSIGN(LAN4BitRasterBand)
98

99
  public:
100
    LAN4BitRasterBand(LANDataset *, int);
101
    ~LAN4BitRasterBand() override;
102

103
    GDALColorTable *GetColorTable() override;
104
    GDALColorInterp GetColorInterpretation() override;
105
    CPLErr SetColorTable(GDALColorTable *) override;
106
    CPLErr SetColorInterpretation(GDALColorInterp) override;
107

108
    CPLErr IReadBlock(int, int, void *) override;
109
};
110

111
/************************************************************************/
112
/* ==================================================================== */
113
/*                              LANDataset                              */
114
/* ==================================================================== */
115
/************************************************************************/
116

117
class LANDataset final : public RawDataset
118
{
119
    CPL_DISALLOW_COPY_ASSIGN(LANDataset)
120

121
  public:
122
    VSILFILE *fpImage;  // Image data file.
123

124
    char pachHeader[ERD_HEADER_SIZE];
125

126
    OGRSpatialReference *m_poSRS = nullptr;
127

128
    GDALGeoTransform m_gt{};
129

130
    CPLString osSTAFilename{};
131
    void CheckForStatistics(void);
132

133
    char **GetFileList() override;
134

135
    CPLErr Close() override;
136

137
  public:
138
    LANDataset();
139
    ~LANDataset() override;
140

141
    CPLErr GetGeoTransform(GDALGeoTransform &gt) const override;
142

143
    const OGRSpatialReference *GetSpatialRef() const override;
144

145
    static GDALDataset *Open(GDALOpenInfo *);
146
};
147

148
/************************************************************************/
149
/* ==================================================================== */
150
/*                         LAN4BitRasterBand                            */
151
/* ==================================================================== */
152
/************************************************************************/
153

154
/************************************************************************/
155
/*                         LAN4BitRasterBand()                          */
156
/************************************************************************/
157

158
LAN4BitRasterBand::LAN4BitRasterBand(LANDataset *poDSIn, int nBandIn)
2✔
159
    : poCT(nullptr), eInterp(GCI_Undefined)
2✔
160
{
161
    poDS = poDSIn;
2✔
162
    nBand = nBandIn;
2✔
163
    eDataType = GDT_Byte;
2✔
164

165
    nBlockXSize = poDSIn->GetRasterXSize();
2✔
166
    nBlockYSize = 1;
2✔
167
}
2✔
168

169
/************************************************************************/
170
/*                         ~LAN4BitRasterBand()                         */
171
/************************************************************************/
172

173
LAN4BitRasterBand::~LAN4BitRasterBand()
4✔
174

175
{
176
    if (poCT)
2✔
177
        delete poCT;
×
178
}
4✔
179

180
/************************************************************************/
181
/*                             IReadBlock()                             */
182
/************************************************************************/
183

184
CPLErr LAN4BitRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff,
2✔
185
                                     void *pImage)
186

187
{
188
    LANDataset *poLAN_DS = reinterpret_cast<LANDataset *>(poDS);
2✔
189
    CPLAssert(nBlockXOff == 0);
2✔
190

191
    /* -------------------------------------------------------------------- */
192
    /*      Seek to profile.                                                */
193
    /* -------------------------------------------------------------------- */
194
    const vsi_l_offset nOffset =
195
        ERD_HEADER_SIZE +
196
        (static_cast<vsi_l_offset>(nBlockYOff) * nRasterXSize *
4✔
197
         poLAN_DS->GetRasterCount()) /
2✔
198
            2 +
2✔
199
        (static_cast<vsi_l_offset>(nBand - 1) * nRasterXSize) / 2;
2✔
200

201
    if (VSIFSeekL(poLAN_DS->fpImage, nOffset, SEEK_SET) != 0)
2✔
202
    {
203
        CPLError(CE_Failure, CPLE_FileIO, "LAN Seek failed:%s",
×
204
                 VSIStrerror(errno));
×
205
        return CE_Failure;
×
206
    }
207

208
    /* -------------------------------------------------------------------- */
209
    /*      Read the profile.                                               */
210
    /* -------------------------------------------------------------------- */
211
    if (VSIFReadL(pImage, 1, nRasterXSize / 2, poLAN_DS->fpImage) !=
2✔
212
        static_cast<size_t>(nRasterXSize) / 2)
2✔
213
    {
214
        CPLError(CE_Failure, CPLE_FileIO, "LAN Read failed:%s",
×
215
                 VSIStrerror(errno));
×
216
        return CE_Failure;
×
217
    }
218

219
    /* -------------------------------------------------------------------- */
220
    /*      Convert 4bit to 8bit.                                           */
221
    /* -------------------------------------------------------------------- */
222
    for (int i = nRasterXSize - 1; i >= 0; i--)
6✔
223
    {
224
        if ((i & 0x01) != 0)
4✔
225
            reinterpret_cast<GByte *>(pImage)[i] =
2✔
226
                reinterpret_cast<GByte *>(pImage)[i / 2] & 0x0f;
2✔
227
        else
228
            reinterpret_cast<GByte *>(pImage)[i] =
2✔
229
                (reinterpret_cast<GByte *>(pImage)[i / 2] & 0xf0) / 16;
2✔
230
    }
231

232
    return CE_None;
2✔
233
}
234

235
/************************************************************************/
236
/*                           SetColorTable()                            */
237
/************************************************************************/
238

239
CPLErr LAN4BitRasterBand::SetColorTable(GDALColorTable *poNewCT)
×
240

241
{
242
    if (poCT)
×
243
        delete poCT;
×
244
    if (poNewCT == nullptr)
×
245
        poCT = nullptr;
×
246
    else
247
        poCT = poNewCT->Clone();
×
248

249
    return CE_None;
×
250
}
251

252
/************************************************************************/
253
/*                           GetColorTable()                            */
254
/************************************************************************/
255

256
GDALColorTable *LAN4BitRasterBand::GetColorTable()
×
257

258
{
259
    if (poCT != nullptr)
×
260
        return poCT;
×
261

262
    return GDALPamRasterBand::GetColorTable();
×
263
}
264

265
/************************************************************************/
266
/*                       SetColorInterpretation()                       */
267
/************************************************************************/
268

269
CPLErr LAN4BitRasterBand::SetColorInterpretation(GDALColorInterp eNewInterp)
×
270

271
{
272
    eInterp = eNewInterp;
×
273

274
    return CE_None;
×
275
}
276

277
/************************************************************************/
278
/*                       GetColorInterpretation()                       */
279
/************************************************************************/
280

281
GDALColorInterp LAN4BitRasterBand::GetColorInterpretation()
×
282

283
{
284
    return eInterp;
×
285
}
286

287
/************************************************************************/
288
/* ==================================================================== */
289
/*                              LANDataset                              */
290
/* ==================================================================== */
291
/************************************************************************/
292

293
/************************************************************************/
294
/*                             LANDataset()                             */
295
/************************************************************************/
296

297
LANDataset::LANDataset() : fpImage(nullptr)
4✔
298
{
299
    memset(pachHeader, 0, sizeof(pachHeader));
4✔
300
}
4✔
301

302
/************************************************************************/
303
/*                            ~LANDataset()                             */
304
/************************************************************************/
305

306
LANDataset::~LANDataset()
8✔
307

308
{
309
    LANDataset::Close();
4✔
310
}
8✔
311

312
/************************************************************************/
313
/*                              Close()                                 */
314
/************************************************************************/
315

316
CPLErr LANDataset::Close()
8✔
317
{
318
    CPLErr eErr = CE_None;
8✔
319
    if (nOpenFlags != OPEN_FLAGS_CLOSED)
8✔
320
    {
321
        if (LANDataset::FlushCache(true) != CE_None)
4✔
322
            eErr = CE_Failure;
×
323

324
        if (fpImage)
4✔
325
        {
326
            if (VSIFCloseL(fpImage) != 0)
4✔
327
            {
328
                CPLError(CE_Failure, CPLE_FileIO, "I/O error");
×
329
                eErr = CE_Failure;
×
330
            }
331
        }
332

333
        if (m_poSRS)
4✔
334
            m_poSRS->Release();
4✔
335

336
        if (GDALPamDataset::Close() != CE_None)
4✔
337
            eErr = CE_Failure;
×
338
    }
339
    return eErr;
8✔
340
}
341

342
/************************************************************************/
343
/*                                Open()                                */
344
/************************************************************************/
345

346
GDALDataset *LANDataset::Open(GDALOpenInfo *poOpenInfo)
33,262✔
347

348
{
349
    /* -------------------------------------------------------------------- */
350
    /*      We assume the user is pointing to the header (.pcb) file.       */
351
    /*      Does this appear to be a pcb file?                              */
352
    /* -------------------------------------------------------------------- */
353
    if (poOpenInfo->nHeaderBytes < ERD_HEADER_SIZE ||
33,262✔
354
        poOpenInfo->fpL == nullptr)
3,072✔
355
        return nullptr;
30,219✔
356

357
    if (!STARTS_WITH_CI(reinterpret_cast<char *>(poOpenInfo->pabyHeader),
3,043✔
358
                        "HEADER") &&
3,043✔
359
        !STARTS_WITH_CI(reinterpret_cast<char *>(poOpenInfo->pabyHeader),
3,043✔
360
                        "HEAD74"))
361
        return nullptr;
3,039✔
362

363
    if (memcmp(poOpenInfo->pabyHeader + 16, "S LAT   ", 8) == 0)
4✔
364
    {
365
        // NTV1 format
366
        return nullptr;
×
367
    }
368

369
    /* -------------------------------------------------------------------- */
370
    /*      Create a corresponding GDALDataset.                             */
371
    /* -------------------------------------------------------------------- */
372
    auto poDS = std::make_unique<LANDataset>();
8✔
373

374
    poDS->eAccess = poOpenInfo->eAccess;
4✔
375
    std::swap(poDS->fpImage, poOpenInfo->fpL);
4✔
376

377
    /* -------------------------------------------------------------------- */
378
    /*      Do we need to byte swap the headers to local machine order?     */
379
    /* -------------------------------------------------------------------- */
380
    const RawRasterBand::ByteOrder eByteOrder =
4✔
381
        poOpenInfo->pabyHeader[8] == 0
4✔
382
            ? RawRasterBand::ByteOrder::ORDER_BIG_ENDIAN
4✔
383
            : RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN;
384

385
    memcpy(poDS->pachHeader, poOpenInfo->pabyHeader, ERD_HEADER_SIZE);
4✔
386

387
    if (eByteOrder != RawRasterBand::NATIVE_BYTE_ORDER)
4✔
388
    {
389
        CPL_SWAP16PTR(poDS->pachHeader + 6);
×
390
        CPL_SWAP16PTR(poDS->pachHeader + 8);
×
391

392
        CPL_SWAP32PTR(poDS->pachHeader + 16);
×
393
        CPL_SWAP32PTR(poDS->pachHeader + 20);
×
394
        CPL_SWAP32PTR(poDS->pachHeader + 24);
×
395
        CPL_SWAP32PTR(poDS->pachHeader + 28);
×
396

397
        CPL_SWAP16PTR(poDS->pachHeader + 88);
×
398
        CPL_SWAP16PTR(poDS->pachHeader + 90);
×
399

400
        CPL_SWAP16PTR(poDS->pachHeader + 106);
×
401
        CPL_SWAP32PTR(poDS->pachHeader + 108);
×
402
        CPL_SWAP32PTR(poDS->pachHeader + 112);
×
403
        CPL_SWAP32PTR(poDS->pachHeader + 116);
×
404
        CPL_SWAP32PTR(poDS->pachHeader + 120);
×
405
        CPL_SWAP32PTR(poDS->pachHeader + 124);
×
406
    }
407

408
    /* -------------------------------------------------------------------- */
409
    /*      Capture some information from the file that is of interest.     */
410
    /* -------------------------------------------------------------------- */
411
    if (STARTS_WITH_CI(poDS->pachHeader, "HEADER"))
4✔
412
    {
413
        float fTmp = 0.0;
×
414
        memcpy(&fTmp, poDS->pachHeader + 16, 4);
×
415
        poDS->nRasterXSize = static_cast<int>(fTmp);
×
416
        memcpy(&fTmp, poDS->pachHeader + 20, 4);
×
417
        poDS->nRasterYSize = static_cast<int>(fTmp);
×
418
    }
419
    else
420
    {
421
        GInt32 nTmp = 0;
4✔
422
        memcpy(&nTmp, poDS->pachHeader + 16, 4);
4✔
423
        poDS->nRasterXSize = nTmp;
4✔
424
        memcpy(&nTmp, poDS->pachHeader + 20, 4);
4✔
425
        poDS->nRasterYSize = nTmp;
4✔
426
    }
427

428
    GInt16 nTmp16 = 0;
4✔
429
    memcpy(&nTmp16, poDS->pachHeader + 6, 2);
4✔
430

431
    int nPixelOffset = 0;
4✔
432
    GDALDataType eDataType = GDT_Unknown;
4✔
433
    if (nTmp16 == 0)
4✔
434
    {
435
        eDataType = GDT_Byte;
2✔
436
        nPixelOffset = 1;
2✔
437
    }
438
    else if (nTmp16 == 1)  // 4 bit
2✔
439
    {
440
        eDataType = GDT_Byte;
2✔
441
        nPixelOffset = -1;
2✔
442
    }
443
    else if (nTmp16 == 2)
×
444
    {
445
        nPixelOffset = 2;
×
446
        eDataType = GDT_Int16;
×
447
    }
448
    else
449
    {
450
        CPLError(CE_Failure, CPLE_AppDefined, "Unsupported pixel type (%d).",
×
451
                 nTmp16);
452
        return nullptr;
×
453
    }
454

455
    memcpy(&nTmp16, poDS->pachHeader + 8, 2);
4✔
456
    const int nBandCount = nTmp16;
4✔
457

458
    if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
8✔
459
        !GDALCheckBandCount(nBandCount, FALSE))
4✔
460
    {
461
        return nullptr;
×
462
    }
463

464
    // cppcheck-suppress knownConditionTrueFalse
465
    if (nPixelOffset != -1 &&
6✔
466
        poDS->nRasterXSize > INT_MAX / (nPixelOffset * nBandCount))
2✔
467
    {
468
        CPLError(CE_Failure, CPLE_AppDefined, "Int overflow occurred.");
×
469
        return nullptr;
×
470
    }
471

472
    /* -------------------------------------------------------------------- */
473
    /*      Create band information object.                                 */
474
    /* -------------------------------------------------------------------- */
475
    for (int iBand = 1; iBand <= nBandCount; iBand++)
8✔
476
    {
477
        if (nPixelOffset == -1) /* 4 bit case */
4✔
478
            poDS->SetBand(iBand, new LAN4BitRasterBand(poDS.get(), iBand));
2✔
479
        else
480
        {
481
            auto poBand = RawRasterBand::Create(
482
                poDS.get(), iBand, poDS->fpImage,
4✔
483
                ERD_HEADER_SIZE +
2✔
484
                    (iBand - 1) * nPixelOffset * poDS->nRasterXSize,
4✔
485
                nPixelOffset, poDS->nRasterXSize * nPixelOffset * nBandCount,
2✔
486
                eDataType, eByteOrder, RawRasterBand::OwnFP::NO);
2✔
487
            if (!poBand)
2✔
488
                return nullptr;
×
489
            poDS->SetBand(iBand, std::move(poBand));
2✔
490
        }
491
    }
492

493
    /* -------------------------------------------------------------------- */
494
    /*      Initialize any PAM information.                                 */
495
    /* -------------------------------------------------------------------- */
496
    poDS->SetDescription(poOpenInfo->pszFilename);
4✔
497
    poDS->CheckForStatistics();
4✔
498
    poDS->TryLoadXML();
4✔
499

500
    /* -------------------------------------------------------------------- */
501
    /*      Check for overviews.                                            */
502
    /* -------------------------------------------------------------------- */
503
    poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename);
4✔
504

505
    /* -------------------------------------------------------------------- */
506
    /*      Try to interpret georeferencing.                                */
507
    /* -------------------------------------------------------------------- */
508
    float fTmp = 0.0;
4✔
509

510
    memcpy(&fTmp, poDS->pachHeader + 112, 4);
4✔
511
    poDS->m_gt[0] = fTmp;
4✔
512
    memcpy(&fTmp, poDS->pachHeader + 120, 4);
4✔
513
    poDS->m_gt[1] = fTmp;
4✔
514
    poDS->m_gt[2] = 0.0;
4✔
515
    memcpy(&fTmp, poDS->pachHeader + 116, 4);
4✔
516
    poDS->m_gt[3] = fTmp;
4✔
517
    poDS->m_gt[4] = 0.0;
4✔
518
    memcpy(&fTmp, poDS->pachHeader + 124, 4);
4✔
519
    poDS->m_gt[5] = -fTmp;
4✔
520

521
    // adjust for center of pixel vs. top left corner of pixel.
522
    poDS->m_gt[0] -= poDS->m_gt[1] * 0.5;
4✔
523
    poDS->m_gt[3] -= poDS->m_gt[5] * 0.5;
4✔
524

525
    /* -------------------------------------------------------------------- */
526
    /*      If we didn't get any georeferencing, try for a worldfile.       */
527
    /* -------------------------------------------------------------------- */
528
    if (poDS->m_gt[1] == 0.0 || poDS->m_gt[5] == 0.0)
4✔
529
    {
530
        if (!GDALReadWorldFile(poOpenInfo->pszFilename, nullptr,
×
531
                               poDS->m_gt.data()))
×
532
            GDALReadWorldFile(poOpenInfo->pszFilename, ".wld",
×
533
                              poDS->m_gt.data());
×
534
    }
535

536
    /* -------------------------------------------------------------------- */
537
    /*      Try to come up with something for the coordinate system.        */
538
    /* -------------------------------------------------------------------- */
539
    memcpy(&nTmp16, poDS->pachHeader + 88, 2);
4✔
540
    int nCoordSys = nTmp16;
4✔
541

542
    poDS->m_poSRS = new OGRSpatialReference();
4✔
543
    poDS->m_poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
4✔
544
    if (nCoordSys == 0)
4✔
545
    {
546
        poDS->m_poSRS->SetFromUserInput(SRS_WKT_WGS84_LAT_LONG);
4✔
547
    }
548
    else if (nCoordSys == 1)
×
549
    {
550
        poDS->m_poSRS->SetFromUserInput(
×
551
            "LOCAL_CS[\"UTM - Zone Unknown\",UNIT[\"Meter\",1]]");
552
    }
553
    else if (nCoordSys == 2)
×
554
    {
555
        poDS->m_poSRS->SetFromUserInput(
×
556
            "LOCAL_CS[\"State Plane - Zone Unknown\","
557
            "UNIT[\"US survey foot\",0.3048006096012192]]");
558
    }
559
    else
560
    {
561
        poDS->m_poSRS->SetFromUserInput(
×
562
            "LOCAL_CS[\"Unknown\",UNIT[\"Meter\",1]]");
563
    }
564

565
    /* -------------------------------------------------------------------- */
566
    /*      Check for a trailer file with a colormap in it.                 */
567
    /* -------------------------------------------------------------------- */
568
    char *pszPath = CPLStrdup(CPLGetPathSafe(poOpenInfo->pszFilename).c_str());
4✔
569
    char *pszBasename =
570
        CPLStrdup(CPLGetBasenameSafe(poOpenInfo->pszFilename).c_str());
4✔
571
    const std::string osTRLFilename =
572
        CPLFormCIFilenameSafe(pszPath, pszBasename, "trl");
8✔
573
    VSILFILE *fpTRL = VSIFOpenL(osTRLFilename.c_str(), "rb");
4✔
574
    if (fpTRL != nullptr)
4✔
575
    {
576
        char szTRLData[896] = {'\0'};
×
577

578
        CPL_IGNORE_RET_VAL(VSIFReadL(szTRLData, 1, 896, fpTRL));
×
579
        CPL_IGNORE_RET_VAL(VSIFCloseL(fpTRL));
×
580

581
        GDALColorTable oCT;
×
582
        for (int iColor = 0; iColor < 256; iColor++)
×
583
        {
584
            GDALColorEntry sEntry = {0, 0, 0, 0};
×
585

586
            sEntry.c2 = reinterpret_cast<GByte *>(szTRLData)[iColor + 128];
×
587
            sEntry.c1 =
×
588
                reinterpret_cast<GByte *>(szTRLData)[iColor + 128 + 256];
×
589
            sEntry.c3 =
×
590
                reinterpret_cast<GByte *>(szTRLData)[iColor + 128 + 512];
×
591
            sEntry.c4 = 255;
×
592
            oCT.SetColorEntry(iColor, &sEntry);
×
593

594
            // Only 16 colors in 4bit files.
595
            if (nPixelOffset == -1 && iColor == 15)
×
596
                break;
×
597
        }
598

599
        poDS->GetRasterBand(1)->SetColorTable(&oCT);
×
600
        poDS->GetRasterBand(1)->SetColorInterpretation(GCI_PaletteIndex);
×
601
    }
602

603
    CPLFree(pszPath);
4✔
604
    CPLFree(pszBasename);
4✔
605

606
    return poDS.release();
4✔
607
}
608

609
/************************************************************************/
610
/*                          GetGeoTransform()                           */
611
/************************************************************************/
612

613
CPLErr LANDataset::GetGeoTransform(GDALGeoTransform &gt) const
×
614

615
{
616
    if (m_gt[1] != 0.0 && m_gt[5] != 0.0)
×
617
    {
618
        gt = m_gt;
×
619
        return CE_None;
×
620
    }
621

622
    return GDALPamDataset::GetGeoTransform(gt);
×
623
}
624

625
/************************************************************************/
626
/*                          GetSpatialRef()                             */
627
/*                                                                      */
628
/*      Use PAM coordinate system if available in preference to the     */
629
/*      generally poor value derived from the file itself.              */
630
/************************************************************************/
631

632
const OGRSpatialReference *LANDataset::GetSpatialRef() const
×
633

634
{
635
    const auto poSRS = GDALPamDataset::GetSpatialRef();
×
636
    if (poSRS)
×
637
        return poSRS;
×
638

639
    return m_poSRS;
×
640
}
641

642
/************************************************************************/
643
/*                            GetFileList()                             */
644
/************************************************************************/
645

646
char **LANDataset::GetFileList()
2✔
647

648
{
649
    // Main data file, etc.
650
    char **papszFileList = GDALPamDataset::GetFileList();
2✔
651

652
    if (!osSTAFilename.empty())
2✔
653
        papszFileList = CSLAddString(papszFileList, osSTAFilename);
×
654

655
    return papszFileList;
2✔
656
}
657

658
/************************************************************************/
659
/*                         CheckForStatistics()                         */
660
/************************************************************************/
661

662
void LANDataset::CheckForStatistics()
4✔
663

664
{
665
    /* -------------------------------------------------------------------- */
666
    /*      Do we have a statistics file?                                   */
667
    /* -------------------------------------------------------------------- */
668
    osSTAFilename = CPLResetExtensionSafe(GetDescription(), "sta");
4✔
669

670
    VSILFILE *fpSTA = VSIFOpenL(osSTAFilename, "r");
4✔
671

672
    if (fpSTA == nullptr && VSIIsCaseSensitiveFS(osSTAFilename))
4✔
673
    {
674
        osSTAFilename = CPLResetExtensionSafe(GetDescription(), "STA");
4✔
675
        fpSTA = VSIFOpenL(osSTAFilename, "r");
4✔
676
    }
677

678
    if (fpSTA == nullptr)
4✔
679
    {
680
        osSTAFilename = "";
4✔
681
        return;
4✔
682
    }
683

684
    /* -------------------------------------------------------------------- */
685
    /*      Read it one band at a time.                                     */
686
    /* -------------------------------------------------------------------- */
687
    GByte abyBandInfo[1152] = {'\0'};
×
688

689
    for (int iBand = 0; iBand < nBands; iBand++)
×
690
    {
691
        if (VSIFReadL(abyBandInfo, 1152, 1, fpSTA) != 1)
×
692
            break;
×
693

694
        const int nBandNumber = abyBandInfo[7];
×
695
        GDALRasterBand *poBand = GetRasterBand(nBandNumber);
×
696
        if (poBand == nullptr)
×
697
            break;
×
698

699
        GInt16 nMin = 0;
×
700
        GInt16 nMax = 0;
×
701

702
        if (poBand->GetRasterDataType() != GDT_Byte)
×
703
        {
704
            memcpy(&nMin, abyBandInfo + 28, 2);
×
705
            memcpy(&nMax, abyBandInfo + 30, 2);
×
706
            CPL_LSBPTR16(&nMin);
×
707
            CPL_LSBPTR16(&nMax);
×
708
        }
709
        else
710
        {
711
            nMin = abyBandInfo[9];
×
712
            nMax = abyBandInfo[8];
×
713
        }
714

715
        float fMean = 0.0;
×
716
        float fStdDev = 0.0;
×
717
        memcpy(&fMean, abyBandInfo + 12, 4);
×
718
        memcpy(&fStdDev, abyBandInfo + 24, 4);
×
719
        CPL_LSBPTR32(&fMean);
×
720
        CPL_LSBPTR32(&fStdDev);
×
721

722
        poBand->SetStatistics(nMin, nMax, fMean, fStdDev);
×
723
    }
724

725
    CPL_IGNORE_RET_VAL(VSIFCloseL(fpSTA));
×
726
}
727

728
/************************************************************************/
729
/*                          GDALRegister_LAN()                          */
730
/************************************************************************/
731

732
void GDALRegister_LAN()
1,911✔
733

734
{
735
    if (GDALGetDriverByName("LAN") != nullptr)
1,911✔
736
        return;
282✔
737

738
    GDALDriver *poDriver = new GDALDriver();
1,629✔
739

740
    poDriver->SetDescription("LAN");
1,629✔
741
    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
1,629✔
742
    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Erdas .LAN/.GIS");
1,629✔
743
    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/lan.html");
1,629✔
744
    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
1,629✔
745

746
    poDriver->pfnOpen = LANDataset::Open;
1,629✔
747

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