Line data Source code
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 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : #include "cpl_conv.h"
30 : #include "cpl_multiproc.h"
31 : #include "gdal_priv.h"
32 : #include "pcidsk.h"
33 :
34 : using PCIDSK::CHN_16S;
35 : using PCIDSK::CHN_16U;
36 : using PCIDSK::CHN_32R;
37 : using PCIDSK::CHN_8U;
38 : using PCIDSK::CHN_C16S;
39 : using PCIDSK::CHN_UNKNOWN;
40 : using PCIDSK::eChanType;
41 : using PCIDSK::EDBFile;
42 : using PCIDSK::ThrowPCIDSKException;
43 :
44 : EDBFile *GDAL_EDBOpen(const std::string &osFilename,
45 : const std::string &osAccess);
46 :
47 : /************************************************************************/
48 : /* ==================================================================== */
49 : /* GDAL_EDBFile */
50 : /* ==================================================================== */
51 : /************************************************************************/
52 :
53 : class GDAL_EDBFile final : public EDBFile
54 : {
55 : GDALDataset *poDS;
56 :
57 : public:
58 0 : explicit GDAL_EDBFile(GDALDataset *poDSIn)
59 0 : {
60 0 : poDS = poDSIn;
61 0 : }
62 :
63 0 : ~GDAL_EDBFile()
64 0 : {
65 0 : if (poDS)
66 0 : GDAL_EDBFile::Close();
67 0 : }
68 :
69 : int Close() const override;
70 : int GetWidth() const override;
71 : int GetHeight() const override;
72 : int GetChannels() const override;
73 : int GetBlockWidth(int channel) const override;
74 : int GetBlockHeight(int channel) const override;
75 : eChanType GetType(int channel) const override;
76 : int ReadBlock(int channel, int block_index, void *buffer, int win_xoff,
77 : int win_yoff, int win_xsize, int win_ysize) override;
78 : int WriteBlock(int channel, int block_index, void *buffer) override;
79 : };
80 :
81 : /************************************************************************/
82 : /* GDAL_EDBOpen() */
83 : /************************************************************************/
84 :
85 2 : EDBFile *GDAL_EDBOpen(const std::string &osFilename,
86 : const std::string &osAccess)
87 :
88 : {
89 2 : GDALDataset *poDS = nullptr;
90 :
91 2 : if (osAccess == "r")
92 : poDS =
93 2 : GDALDataset::FromHandle(GDALOpen(osFilename.c_str(), GA_ReadOnly));
94 : else
95 0 : poDS = GDALDataset::FromHandle(GDALOpen(osFilename.c_str(), GA_Update));
96 :
97 2 : if (poDS == nullptr)
98 2 : ThrowPCIDSKException("%s", CPLGetLastErrorMsg());
99 :
100 0 : return new GDAL_EDBFile(poDS);
101 : }
102 :
103 : /************************************************************************/
104 : /* Close() */
105 : /************************************************************************/
106 :
107 0 : int GDAL_EDBFile::Close() const
108 :
109 : {
110 0 : if (poDS != nullptr)
111 : {
112 0 : delete poDS;
113 0 : const_cast<GDAL_EDBFile *>(this)->poDS = nullptr;
114 : }
115 :
116 0 : return 1;
117 : }
118 :
119 : /************************************************************************/
120 : /* GetWidth() */
121 : /************************************************************************/
122 :
123 0 : int GDAL_EDBFile::GetWidth() const
124 :
125 : {
126 0 : return poDS->GetRasterXSize();
127 : }
128 :
129 : /************************************************************************/
130 : /* GetHeight() */
131 : /************************************************************************/
132 :
133 0 : int GDAL_EDBFile::GetHeight() const
134 :
135 : {
136 0 : return poDS->GetRasterYSize();
137 : }
138 :
139 : /************************************************************************/
140 : /* GetChannels() */
141 : /************************************************************************/
142 :
143 0 : int GDAL_EDBFile::GetChannels() const
144 :
145 : {
146 0 : return poDS->GetRasterCount();
147 : }
148 :
149 : /************************************************************************/
150 : /* GetBlockWidth() */
151 : /************************************************************************/
152 :
153 0 : int GDAL_EDBFile::GetBlockWidth(int nChannel) const
154 :
155 : {
156 : int nWidth, nHeight;
157 :
158 0 : poDS->GetRasterBand(nChannel)->GetBlockSize(&nWidth, &nHeight);
159 :
160 0 : return nWidth;
161 : }
162 :
163 : /************************************************************************/
164 : /* GetBlockHeight() */
165 : /************************************************************************/
166 :
167 0 : int GDAL_EDBFile::GetBlockHeight(int nChannel) const
168 :
169 : {
170 : int nWidth, nHeight;
171 :
172 0 : poDS->GetRasterBand(nChannel)->GetBlockSize(&nWidth, &nHeight);
173 :
174 0 : return nHeight;
175 : }
176 :
177 : /************************************************************************/
178 : /* GetType() */
179 : /************************************************************************/
180 :
181 0 : eChanType GDAL_EDBFile::GetType(int nChannel) const
182 : {
183 0 : switch (poDS->GetRasterBand(nChannel)->GetRasterDataType())
184 : {
185 0 : case GDT_Byte:
186 0 : return CHN_8U;
187 :
188 0 : case GDT_Int16:
189 0 : return CHN_16S;
190 :
191 0 : case GDT_UInt16:
192 0 : return CHN_16U;
193 :
194 0 : case GDT_Float32:
195 0 : return CHN_32R;
196 :
197 0 : case GDT_CInt16:
198 0 : return CHN_C16S;
199 :
200 0 : default:
201 0 : return CHN_UNKNOWN;
202 : }
203 : }
204 :
205 : /************************************************************************/
206 : /* ReadBlock() */
207 : /************************************************************************/
208 :
209 0 : int GDAL_EDBFile::ReadBlock(int channel, int block_index, void *buffer,
210 : int win_xoff, int win_yoff, int win_xsize,
211 : int win_ysize)
212 :
213 : {
214 0 : GDALRasterBand *poBand = poDS->GetRasterBand(channel);
215 :
216 0 : if (GetType(channel) == CHN_UNKNOWN)
217 : {
218 0 : ThrowPCIDSKException("%s channel type not supported for PCIDSK access.",
219 : GDALGetDataTypeName(poBand->GetRasterDataType()));
220 : }
221 :
222 : int nBlockXSize, nBlockYSize;
223 0 : poBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
224 :
225 : const int nWidthInBlocks =
226 0 : (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize;
227 :
228 0 : const int nBlockX = block_index % nWidthInBlocks;
229 0 : const int nBlockY = block_index / nWidthInBlocks;
230 :
231 : const int nPixelOffset =
232 0 : GDALGetDataTypeSize(poBand->GetRasterDataType()) / 8;
233 0 : const int nLineOffset = win_xsize * nPixelOffset;
234 :
235 : /* -------------------------------------------------------------------- */
236 : /* Are we reading a partial block at the edge of the database? */
237 : /* If so, ensure we don't read off the database. */
238 : /* -------------------------------------------------------------------- */
239 0 : if (nBlockX * nBlockXSize + win_xoff + win_xsize > poBand->GetXSize())
240 0 : win_xsize = poBand->GetXSize() - nBlockX * nBlockXSize - win_xoff;
241 :
242 0 : if (nBlockY * nBlockYSize + win_yoff + win_ysize > poBand->GetYSize())
243 0 : win_ysize = poBand->GetYSize() - nBlockY * nBlockYSize - win_yoff;
244 :
245 0 : const CPLErr eErr = poBand->RasterIO(
246 0 : GF_Read, nBlockX * nBlockXSize + win_xoff,
247 0 : nBlockY * nBlockYSize + win_yoff, win_xsize, win_ysize, buffer,
248 : win_xsize, win_ysize, poBand->GetRasterDataType(), nPixelOffset,
249 : nLineOffset, nullptr);
250 :
251 0 : if (eErr != CE_None)
252 : {
253 0 : ThrowPCIDSKException("%s", CPLGetLastErrorMsg());
254 : }
255 :
256 0 : return 1;
257 : }
258 :
259 : /************************************************************************/
260 : /* WriteBlock() */
261 : /************************************************************************/
262 :
263 0 : int GDAL_EDBFile::WriteBlock(int channel, int block_index, void *buffer)
264 :
265 : {
266 0 : GDALRasterBand *poBand = poDS->GetRasterBand(channel);
267 :
268 0 : if (GetType(channel) == CHN_UNKNOWN)
269 : {
270 0 : ThrowPCIDSKException("%s channel type not supported for PCIDSK access.",
271 : GDALGetDataTypeName(poBand->GetRasterDataType()));
272 : }
273 :
274 : int nBlockXSize, nBlockYSize;
275 0 : poBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
276 :
277 : const int nWidthInBlocks =
278 0 : (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize;
279 :
280 0 : const int nBlockX = block_index % nWidthInBlocks;
281 0 : const int nBlockY = block_index / nWidthInBlocks;
282 :
283 : /* -------------------------------------------------------------------- */
284 : /* Are we reading a partial block at the edge of the database? */
285 : /* If so, ensure we don't read off the database. */
286 : /* -------------------------------------------------------------------- */
287 : int nWinXSize, nWinYSize;
288 :
289 0 : if (nBlockX * nBlockXSize + nBlockXSize > poBand->GetXSize())
290 0 : nWinXSize = poBand->GetXSize() - nBlockX * nBlockXSize;
291 : else
292 0 : nWinXSize = nBlockXSize;
293 :
294 0 : if (nBlockY * nBlockYSize + nBlockYSize > poBand->GetYSize())
295 0 : nWinYSize = poBand->GetYSize() - nBlockY * nBlockYSize;
296 : else
297 0 : nWinYSize = nBlockYSize;
298 :
299 : const CPLErr eErr =
300 0 : poBand->RasterIO(GF_Write, nBlockX * nBlockXSize, nBlockY * nBlockYSize,
301 : nWinXSize, nWinYSize, buffer, nWinXSize, nWinYSize,
302 : poBand->GetRasterDataType(), 0, 0, nullptr);
303 :
304 0 : if (eErr != CE_None)
305 : {
306 0 : ThrowPCIDSKException("%s", CPLGetLastErrorMsg());
307 : }
308 :
309 0 : return 1;
310 : }
|