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