Coverage Report

Created: 2025-06-09 07:42

/src/gdal/frmts/pcidsk/gdal_edb.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Project:  PCIDSK Database File
4
 * Purpose:  External Database access interface implementation (EDBFile).
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2010, Frank Warmerdam <warmerdam@pobox.com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#include "cpl_conv.h"
14
#include "cpl_multiproc.h"
15
#include "gdal_priv.h"
16
#include "pcidsk.h"
17
18
using PCIDSK::CHN_16S;
19
using PCIDSK::CHN_16U;
20
using PCIDSK::CHN_32R;
21
using PCIDSK::CHN_8U;
22
using PCIDSK::CHN_C16S;
23
using PCIDSK::CHN_UNKNOWN;
24
using PCIDSK::eChanType;
25
using PCIDSK::EDBFile;
26
using PCIDSK::ThrowPCIDSKException;
27
28
EDBFile *GDAL_EDBOpen(const std::string &osFilename,
29
                      const std::string &osAccess);
30
31
/************************************************************************/
32
/* ==================================================================== */
33
/*                            GDAL_EDBFile                              */
34
/* ==================================================================== */
35
/************************************************************************/
36
37
class GDAL_EDBFile final : public EDBFile
38
{
39
    GDALDataset *poDS;
40
41
  public:
42
    explicit GDAL_EDBFile(GDALDataset *poDSIn)
43
15.2k
    {
44
15.2k
        poDS = poDSIn;
45
15.2k
    }
46
47
    ~GDAL_EDBFile()
48
15.2k
    {
49
15.2k
        if (poDS)
50
15.2k
            GDAL_EDBFile::Close();
51
15.2k
    }
52
53
    int Close() const override;
54
    int GetWidth() const override;
55
    int GetHeight() const override;
56
    int GetChannels() const override;
57
    int GetBlockWidth(int channel) const override;
58
    int GetBlockHeight(int channel) const override;
59
    eChanType GetType(int channel) const override;
60
    int ReadBlock(int channel, int block_index, void *buffer, int win_xoff,
61
                  int win_yoff, int win_xsize, int win_ysize) override;
62
    int WriteBlock(int channel, int block_index, void *buffer) override;
63
};
64
65
/************************************************************************/
66
/*                            GDAL_EDBOpen()                            */
67
/************************************************************************/
68
69
EDBFile *GDAL_EDBOpen(const std::string &osFilename,
70
                      const std::string &osAccess)
71
72
492k
{
73
492k
    GDALDataset *poDS = nullptr;
74
75
492k
    if (osAccess == "r")
76
492k
        poDS =
77
492k
            GDALDataset::FromHandle(GDALOpen(osFilename.c_str(), GA_ReadOnly));
78
0
    else
79
0
        poDS = GDALDataset::FromHandle(GDALOpen(osFilename.c_str(), GA_Update));
80
81
492k
    if (poDS == nullptr)
82
477k
        ThrowPCIDSKException("%s", CPLGetLastErrorMsg());
83
84
492k
    return new GDAL_EDBFile(poDS);
85
492k
}
86
87
/************************************************************************/
88
/*                               Close()                                */
89
/************************************************************************/
90
91
int GDAL_EDBFile::Close() const
92
93
15.2k
{
94
15.2k
    if (poDS != nullptr)
95
15.2k
    {
96
15.2k
        delete poDS;
97
15.2k
        const_cast<GDAL_EDBFile *>(this)->poDS = nullptr;
98
15.2k
    }
99
100
15.2k
    return 1;
101
15.2k
}
102
103
/************************************************************************/
104
/*                              GetWidth()                              */
105
/************************************************************************/
106
107
int GDAL_EDBFile::GetWidth() const
108
109
0
{
110
0
    return poDS->GetRasterXSize();
111
0
}
112
113
/************************************************************************/
114
/*                             GetHeight()                              */
115
/************************************************************************/
116
117
int GDAL_EDBFile::GetHeight() const
118
119
0
{
120
0
    return poDS->GetRasterYSize();
121
0
}
122
123
/************************************************************************/
124
/*                            GetChannels()                             */
125
/************************************************************************/
126
127
int GDAL_EDBFile::GetChannels() const
128
129
0
{
130
0
    return poDS->GetRasterCount();
131
0
}
132
133
/************************************************************************/
134
/*                           GetBlockWidth()                            */
135
/************************************************************************/
136
137
int GDAL_EDBFile::GetBlockWidth(int nChannel) const
138
139
0
{
140
0
    int nWidth, nHeight;
141
142
0
    poDS->GetRasterBand(nChannel)->GetBlockSize(&nWidth, &nHeight);
143
144
0
    return nWidth;
145
0
}
146
147
/************************************************************************/
148
/*                           GetBlockHeight()                           */
149
/************************************************************************/
150
151
int GDAL_EDBFile::GetBlockHeight(int nChannel) const
152
153
0
{
154
0
    int nWidth, nHeight;
155
156
0
    poDS->GetRasterBand(nChannel)->GetBlockSize(&nWidth, &nHeight);
157
158
0
    return nHeight;
159
0
}
160
161
/************************************************************************/
162
/*                              GetType()                               */
163
/************************************************************************/
164
165
eChanType GDAL_EDBFile::GetType(int nChannel) const
166
0
{
167
0
    switch (poDS->GetRasterBand(nChannel)->GetRasterDataType())
168
0
    {
169
0
        case GDT_Byte:
170
0
            return CHN_8U;
171
172
0
        case GDT_Int16:
173
0
            return CHN_16S;
174
175
0
        case GDT_UInt16:
176
0
            return CHN_16U;
177
178
0
        case GDT_Float32:
179
0
            return CHN_32R;
180
181
0
        case GDT_CInt16:
182
0
            return CHN_C16S;
183
184
0
        default:
185
0
            return CHN_UNKNOWN;
186
0
    }
187
0
}
188
189
/************************************************************************/
190
/*                             ReadBlock()                              */
191
/************************************************************************/
192
193
int GDAL_EDBFile::ReadBlock(int channel, int block_index, void *buffer,
194
                            int win_xoff, int win_yoff, int win_xsize,
195
                            int win_ysize)
196
197
0
{
198
0
    GDALRasterBand *poBand = poDS->GetRasterBand(channel);
199
200
0
    if (GetType(channel) == CHN_UNKNOWN)
201
0
    {
202
0
        ThrowPCIDSKException("%s channel type not supported for PCIDSK access.",
203
0
                             GDALGetDataTypeName(poBand->GetRasterDataType()));
204
0
    }
205
206
0
    int nBlockXSize, nBlockYSize;
207
0
    poBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
208
209
0
    const int nWidthInBlocks = DIV_ROUND_UP(poBand->GetXSize(), nBlockXSize);
210
211
0
    const int nBlockX = block_index % nWidthInBlocks;
212
0
    const int nBlockY = block_index / nWidthInBlocks;
213
214
0
    const int nPixelOffset =
215
0
        GDALGetDataTypeSize(poBand->GetRasterDataType()) / 8;
216
0
    const int nLineOffset = win_xsize * nPixelOffset;
217
218
    /* -------------------------------------------------------------------- */
219
    /*      Are we reading a partial block at the edge of the database?     */
220
    /*      If so, ensure we don't read off the database.                   */
221
    /* -------------------------------------------------------------------- */
222
0
    if (nBlockX * nBlockXSize + win_xoff + win_xsize > poBand->GetXSize())
223
0
        win_xsize = poBand->GetXSize() - nBlockX * nBlockXSize - win_xoff;
224
225
0
    if (nBlockY * nBlockYSize + win_yoff + win_ysize > poBand->GetYSize())
226
0
        win_ysize = poBand->GetYSize() - nBlockY * nBlockYSize - win_yoff;
227
228
0
    const CPLErr eErr = poBand->RasterIO(
229
0
        GF_Read, nBlockX * nBlockXSize + win_xoff,
230
0
        nBlockY * nBlockYSize + win_yoff, win_xsize, win_ysize, buffer,
231
0
        win_xsize, win_ysize, poBand->GetRasterDataType(), nPixelOffset,
232
0
        nLineOffset, nullptr);
233
234
0
    if (eErr != CE_None)
235
0
    {
236
0
        ThrowPCIDSKException("%s", CPLGetLastErrorMsg());
237
0
    }
238
239
0
    return 1;
240
0
}
241
242
/************************************************************************/
243
/*                             WriteBlock()                             */
244
/************************************************************************/
245
246
int GDAL_EDBFile::WriteBlock(int channel, int block_index, void *buffer)
247
248
0
{
249
0
    GDALRasterBand *poBand = poDS->GetRasterBand(channel);
250
251
0
    if (GetType(channel) == CHN_UNKNOWN)
252
0
    {
253
0
        ThrowPCIDSKException("%s channel type not supported for PCIDSK access.",
254
0
                             GDALGetDataTypeName(poBand->GetRasterDataType()));
255
0
    }
256
257
0
    int nBlockXSize, nBlockYSize;
258
0
    poBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
259
260
0
    const int nWidthInBlocks = DIV_ROUND_UP(poBand->GetXSize(), nBlockXSize);
261
262
0
    const int nBlockX = block_index % nWidthInBlocks;
263
0
    const int nBlockY = block_index / nWidthInBlocks;
264
265
    /* -------------------------------------------------------------------- */
266
    /*      Are we reading a partial block at the edge of the database?     */
267
    /*      If so, ensure we don't read off the database.                   */
268
    /* -------------------------------------------------------------------- */
269
0
    int nWinXSize, nWinYSize;
270
271
0
    if (nBlockX * nBlockXSize + nBlockXSize > poBand->GetXSize())
272
0
        nWinXSize = poBand->GetXSize() - nBlockX * nBlockXSize;
273
0
    else
274
0
        nWinXSize = nBlockXSize;
275
276
0
    if (nBlockY * nBlockYSize + nBlockYSize > poBand->GetYSize())
277
0
        nWinYSize = poBand->GetYSize() - nBlockY * nBlockYSize;
278
0
    else
279
0
        nWinYSize = nBlockYSize;
280
281
0
    const CPLErr eErr =
282
0
        poBand->RasterIO(GF_Write, nBlockX * nBlockXSize, nBlockY * nBlockYSize,
283
0
                         nWinXSize, nWinYSize, buffer, nWinXSize, nWinYSize,
284
0
                         poBand->GetRasterDataType(), 0, 0, nullptr);
285
286
0
    if (eErr != CE_None)
287
0
    {
288
0
        ThrowPCIDSKException("%s", CPLGetLastErrorMsg());
289
0
    }
290
291
0
    return 1;
292
0
}