1 : /******************************************************************************
2 : * $Id: vrtrawrasterband.cpp 19011 2010-03-05 20:03:41Z warmerdam $
3 : *
4 : * Project: Virtual GDAL Datasets
5 : * Purpose: Implementation of VRTRawRasterBand
6 : * Author: Frank Warmerdam <warmerdam@pobox.com>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2004, 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 "vrtdataset.h"
31 : #include "cpl_minixml.h"
32 : #include "cpl_string.h"
33 : #include "rawdataset.h"
34 :
35 : CPL_CVSID("$Id: vrtrawrasterband.cpp 19011 2010-03-05 20:03:41Z warmerdam $");
36 :
37 : /************************************************************************/
38 : /* ==================================================================== */
39 : /* VRTRawRasterBand */
40 : /* ==================================================================== */
41 : /************************************************************************/
42 :
43 : /************************************************************************/
44 : /* VRTRawRasterBand() */
45 : /************************************************************************/
46 :
47 : VRTRawRasterBand::VRTRawRasterBand( GDALDataset *poDS, int nBand,
48 9 : GDALDataType eType )
49 :
50 : {
51 9 : Initialize( poDS->GetRasterXSize(), poDS->GetRasterYSize() );
52 :
53 9 : this->poDS = poDS;
54 9 : this->nBand = nBand;
55 :
56 9 : if( eType != GDT_Unknown )
57 2 : this->eDataType = eType;
58 :
59 9 : poRawRaster = NULL;
60 9 : pszSourceFilename = NULL;
61 9 : }
62 :
63 : /************************************************************************/
64 : /* ~VRTRawRasterBand() */
65 : /************************************************************************/
66 :
67 9 : VRTRawRasterBand::~VRTRawRasterBand()
68 :
69 : {
70 9 : FlushCache();
71 9 : ClearRawLink();
72 9 : }
73 :
74 : /************************************************************************/
75 : /* IRasterIO() */
76 : /************************************************************************/
77 :
78 : CPLErr VRTRawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
79 : int nXOff, int nYOff, int nXSize, int nYSize,
80 : void * pData, int nBufXSize, int nBufYSize,
81 : GDALDataType eBufType,
82 213 : int nPixelSpace, int nLineSpace )
83 :
84 : {
85 213 : if( poRawRaster == NULL )
86 : {
87 : CPLError( CE_Failure, CPLE_AppDefined,
88 0 : "No raw raster band configured on VRTRawRasterBand." );
89 0 : return CE_Failure;
90 : }
91 :
92 213 : if( eRWFlag == GF_Write && eAccess == GA_ReadOnly )
93 : {
94 : CPLError( CE_Failure, CPLE_NoWriteAccess,
95 : "Attempt to write to read only dataset in"
96 0 : "VRTRawRasterBand::IRasterIO().\n" );
97 :
98 0 : return( CE_Failure );
99 : }
100 :
101 : /* -------------------------------------------------------------------- */
102 : /* Do we have overviews that would be appropriate to satisfy */
103 : /* this request? */
104 : /* -------------------------------------------------------------------- */
105 213 : if( (nBufXSize < nXSize || nBufYSize < nYSize)
106 : && GetOverviewCount() > 0 )
107 : {
108 0 : if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
109 : pData, nBufXSize, nBufYSize,
110 : eBufType, nPixelSpace, nLineSpace ) == CE_None )
111 0 : return CE_None;
112 : }
113 :
114 213 : poRawRaster->SetAccess(eAccess);
115 :
116 : return poRawRaster->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
117 : pData, nBufXSize, nBufYSize,
118 213 : eBufType, nPixelSpace, nLineSpace );
119 : }
120 :
121 : /************************************************************************/
122 : /* IReadBlock() */
123 : /************************************************************************/
124 :
125 : CPLErr VRTRawRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
126 35 : void * pImage )
127 :
128 : {
129 35 : if( poRawRaster == NULL )
130 : {
131 : CPLError( CE_Failure, CPLE_AppDefined,
132 0 : "No raw raster band configured on VRTRawRasterBand." );
133 0 : return CE_Failure;
134 : }
135 :
136 35 : return poRawRaster->ReadBlock( nBlockXOff, nBlockYOff, pImage );
137 : }
138 :
139 : /************************************************************************/
140 : /* IWriteBlock() */
141 : /************************************************************************/
142 :
143 : CPLErr VRTRawRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
144 0 : void * pImage )
145 :
146 : {
147 0 : if( poRawRaster == NULL )
148 : {
149 : CPLError( CE_Failure, CPLE_AppDefined,
150 0 : "No raw raster band configured on VRTRawRasterBand." );
151 0 : return CE_Failure;
152 : }
153 :
154 0 : poRawRaster->SetAccess(eAccess);
155 :
156 0 : return poRawRaster->WriteBlock( nBlockXOff, nBlockYOff, pImage );
157 : }
158 :
159 : /************************************************************************/
160 : /* SetRawLink() */
161 : /************************************************************************/
162 :
163 : CPLErr VRTRawRasterBand::SetRawLink( const char *pszFilename,
164 : const char *pszVRTPath,
165 : int bRelativeToVRT,
166 : vsi_l_offset nImageOffset,
167 : int nPixelOffset, int nLineOffset,
168 9 : const char *pszByteOrder )
169 :
170 : {
171 9 : ClearRawLink();
172 :
173 9 : ((VRTDataset *)poDS)->SetNeedsFlush();
174 :
175 : /* -------------------------------------------------------------------- */
176 : /* Prepare filename. */
177 : /* -------------------------------------------------------------------- */
178 9 : char *pszExpandedFilename = NULL;
179 :
180 9 : if( pszFilename == NULL )
181 : {
182 : CPLError( CE_Warning, CPLE_AppDefined,
183 0 : "Missing <SourceFilename> element in VRTRasterBand." );
184 0 : return CE_Failure;
185 : }
186 :
187 13 : if( pszVRTPath != NULL && bRelativeToVRT )
188 : {
189 : pszExpandedFilename = CPLStrdup(
190 4 : CPLProjectRelativeFilename( pszVRTPath, pszFilename ) );
191 : }
192 : else
193 5 : pszExpandedFilename = CPLStrdup( pszFilename );
194 :
195 : /* -------------------------------------------------------------------- */
196 : /* Try and open the file. We always use the large file API. */
197 : /* -------------------------------------------------------------------- */
198 9 : FILE *fp = CPLOpenShared( pszExpandedFilename, "rb+", TRUE );
199 :
200 9 : if( fp == NULL )
201 0 : fp = CPLOpenShared( pszExpandedFilename, "rb", TRUE );
202 :
203 9 : if( fp == NULL )
204 : {
205 : CPLError( CE_Failure, CPLE_OpenFailed,
206 : "Unable to open %s.\n%s",
207 : pszExpandedFilename,
208 0 : VSIStrerror( errno ) );
209 :
210 0 : CPLFree( pszExpandedFilename );
211 0 : return CE_Failure;
212 : }
213 :
214 9 : CPLFree( pszExpandedFilename );
215 :
216 9 : pszSourceFilename = CPLStrdup(pszFilename);
217 9 : this->bRelativeToVRT = bRelativeToVRT;
218 :
219 : /* -------------------------------------------------------------------- */
220 : /* Work out if we are in native mode or not. */
221 : /* -------------------------------------------------------------------- */
222 9 : int bNative = TRUE;
223 :
224 9 : if( pszByteOrder != NULL )
225 : {
226 8 : if( EQUAL(pszByteOrder,"LSB") )
227 6 : bNative = CPL_IS_LSB;
228 2 : else if( EQUAL(pszByteOrder,"MSB") )
229 2 : bNative = !CPL_IS_LSB;
230 : else
231 : {
232 : CPLError( CE_Failure, CPLE_AppDefined,
233 : "Illegal ByteOrder value '%s', should be LSB or MSB.",
234 0 : pszByteOrder );
235 0 : return CE_Failure;
236 : }
237 : }
238 :
239 : /* -------------------------------------------------------------------- */
240 : /* Create a corresponding RawRasterBand. */
241 : /* -------------------------------------------------------------------- */
242 : poRawRaster = new RawRasterBand( fp, nImageOffset, nPixelOffset,
243 : nLineOffset, GetRasterDataType(),
244 9 : bNative, GetXSize(), GetYSize(), TRUE );
245 :
246 : /* -------------------------------------------------------------------- */
247 : /* Reset block size to match the raw raster. */
248 : /* -------------------------------------------------------------------- */
249 9 : poRawRaster->GetBlockSize( &nBlockXSize, &nBlockYSize );
250 :
251 9 : return CE_None;
252 : }
253 :
254 : /************************************************************************/
255 : /* ClearRawLink() */
256 : /************************************************************************/
257 :
258 18 : void VRTRawRasterBand::ClearRawLink()
259 :
260 : {
261 18 : if( poRawRaster != NULL )
262 : {
263 9 : FILE* fp = poRawRaster->GetFP();
264 9 : delete poRawRaster;
265 9 : poRawRaster = NULL;
266 : /* We close the file after deleting the raster band */
267 : /* since data can be flushed in the destructor */
268 9 : if( fp != NULL )
269 : {
270 9 : CPLCloseShared( fp );
271 : }
272 : }
273 18 : CPLFree( pszSourceFilename );
274 18 : pszSourceFilename = NULL;
275 18 : }
276 :
277 : /************************************************************************/
278 : /* XMLInit() */
279 : /************************************************************************/
280 :
281 : CPLErr VRTRawRasterBand::XMLInit( CPLXMLNode * psTree,
282 7 : const char *pszVRTPath )
283 :
284 : {
285 : CPLErr eErr;
286 :
287 7 : eErr = VRTRasterBand::XMLInit( psTree, pszVRTPath );
288 7 : if( eErr != CE_None )
289 0 : return eErr;
290 :
291 :
292 : /* -------------------------------------------------------------------- */
293 : /* Validate a bit. */
294 : /* -------------------------------------------------------------------- */
295 7 : if( psTree == NULL || psTree->eType != CXT_Element
296 : || !EQUAL(psTree->pszValue,"VRTRasterBand")
297 : || !EQUAL(CPLGetXMLValue(psTree,"subClass",""),"VRTRawRasterBand") )
298 : {
299 : CPLError( CE_Failure, CPLE_AppDefined,
300 0 : "Invalid node passed to VRTRawRasterBand::XMLInit()." );
301 0 : return CE_Failure;
302 : }
303 :
304 : /* -------------------------------------------------------------------- */
305 : /* Prepare filename. */
306 : /* -------------------------------------------------------------------- */
307 : int bRelativeToVRT;
308 :
309 : const char *pszFilename =
310 7 : CPLGetXMLValue(psTree, "SourceFilename", NULL);
311 :
312 7 : if( pszFilename == NULL )
313 : {
314 : CPLError( CE_Warning, CPLE_AppDefined,
315 0 : "Missing <SourceFilename> element in VRTRasterBand." );
316 0 : return CE_Failure;
317 : }
318 :
319 : bRelativeToVRT = atoi(CPLGetXMLValue(psTree,"SourceFilename.relativeToVRT",
320 7 : "1"));
321 :
322 : /* -------------------------------------------------------------------- */
323 : /* Collect layout information. */
324 : /* -------------------------------------------------------------------- */
325 : vsi_l_offset nImageOffset;
326 : int nPixelOffset, nLineOffset;
327 7 : int nWordDataSize = GDALGetDataTypeSize( GetRasterDataType() ) / 8;
328 :
329 7 : nImageOffset = atoi(CPLGetXMLValue( psTree, "ImageOffset", "0") );
330 :
331 7 : if( CPLGetXMLValue( psTree, "PixelOffset", NULL ) == NULL )
332 0 : nPixelOffset = nWordDataSize;
333 : else
334 7 : nPixelOffset = atoi(CPLGetXMLValue( psTree, "PixelOffset", "0") );
335 7 : if (nPixelOffset <= 0)
336 : {
337 : CPLError( CE_Failure, CPLE_AppDefined,
338 0 : "Invalid value for <PixelOffset> element : %d", nPixelOffset );
339 0 : return CE_Failure;
340 : }
341 :
342 7 : if( CPLGetXMLValue( psTree, "LineOffset", NULL ) == NULL )
343 0 : nLineOffset = nWordDataSize * GetXSize();
344 : else
345 7 : nLineOffset = atoi(CPLGetXMLValue( psTree, "LineOffset", "0") );
346 :
347 7 : const char *pszByteOrder = CPLGetXMLValue( psTree, "ByteOrder", NULL );
348 :
349 : /* -------------------------------------------------------------------- */
350 : /* Open the file, and setup the raw layer access to the data. */
351 : /* -------------------------------------------------------------------- */
352 : return SetRawLink( pszFilename, pszVRTPath, bRelativeToVRT,
353 : nImageOffset, nPixelOffset, nLineOffset,
354 7 : pszByteOrder );
355 : }
356 :
357 : /************************************************************************/
358 : /* SerializeToXML() */
359 : /************************************************************************/
360 :
361 3 : CPLXMLNode *VRTRawRasterBand::SerializeToXML( const char *pszVRTPath )
362 :
363 : {
364 : CPLXMLNode *psTree;
365 :
366 3 : psTree = VRTRasterBand::SerializeToXML( pszVRTPath );
367 :
368 : /* -------------------------------------------------------------------- */
369 : /* Set subclass. */
370 : /* -------------------------------------------------------------------- */
371 : CPLCreateXMLNode(
372 : CPLCreateXMLNode( psTree, CXT_Attribute, "subClass" ),
373 3 : CXT_Text, "VRTRawRasterBand" );
374 :
375 : /* -------------------------------------------------------------------- */
376 : /* Setup the filename with relative flag. */
377 : /* -------------------------------------------------------------------- */
378 : CPLXMLNode *psNode;
379 :
380 : psNode =
381 : CPLCreateXMLElementAndValue( psTree, "SourceFilename",
382 3 : pszSourceFilename );
383 :
384 : CPLCreateXMLNode(
385 : CPLCreateXMLNode( psNode, CXT_Attribute, "relativeToVRT" ),
386 3 : CXT_Text, bRelativeToVRT ? "1" : "0" );
387 :
388 : /* -------------------------------------------------------------------- */
389 : /* We can't set the layout if there is no open rawband. */
390 : /* -------------------------------------------------------------------- */
391 3 : if( poRawRaster == NULL )
392 : {
393 : CPLError( CE_Failure, CPLE_AppDefined,
394 0 : "VRTRawRasterBand::SerializeToXML() fails because poRawRaster is NULL." );
395 0 : return NULL;
396 : }
397 :
398 : /* -------------------------------------------------------------------- */
399 : /* Set other layout information. */
400 : /* -------------------------------------------------------------------- */
401 : CPLCreateXMLElementAndValue(
402 : psTree, "ImageOffset",
403 3 : CPLSPrintf("%d",(int) poRawRaster->GetImgOffset()) );
404 :
405 : CPLCreateXMLElementAndValue(
406 : psTree, "PixelOffset",
407 3 : CPLSPrintf("%d",(int) poRawRaster->GetPixelOffset()) );
408 :
409 : CPLCreateXMLElementAndValue(
410 : psTree, "LineOffset",
411 3 : CPLSPrintf("%d",(int) poRawRaster->GetLineOffset()) );
412 :
413 3 : if( (poRawRaster->GetNativeOrder() && CPL_IS_LSB)
414 : || (!poRawRaster->GetNativeOrder() && !CPL_IS_LSB) )
415 2 : CPLCreateXMLElementAndValue( psTree, "ByteOrder", "LSB" );
416 : else
417 1 : CPLCreateXMLElementAndValue( psTree, "ByteOrder", "MSB" );
418 :
419 3 : return psTree;
420 : }
421 :
422 : /************************************************************************/
423 : /* GetFileList() */
424 : /************************************************************************/
425 :
426 : void VRTRawRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
427 0 : int *pnMaxSize, CPLHashSet* hSetFiles)
428 : {
429 0 : if (pszSourceFilename == NULL)
430 0 : return;
431 :
432 : /* -------------------------------------------------------------------- */
433 : /* Is it already in the list ? */
434 : /* -------------------------------------------------------------------- */
435 0 : if( CPLHashSetLookup(hSetFiles, pszSourceFilename) != NULL )
436 0 : return;
437 :
438 : /* -------------------------------------------------------------------- */
439 : /* Grow array if necessary */
440 : /* -------------------------------------------------------------------- */
441 0 : if (*pnSize + 1 >= *pnMaxSize)
442 : {
443 0 : *pnMaxSize = 2 + 2 * (*pnMaxSize);
444 : *ppapszFileList = (char **) CPLRealloc(
445 0 : *ppapszFileList, sizeof(char*) * (*pnMaxSize) );
446 : }
447 :
448 : /* -------------------------------------------------------------------- */
449 : /* Add the string to the list */
450 : /* -------------------------------------------------------------------- */
451 0 : (*ppapszFileList)[*pnSize] = CPLStrdup(pszSourceFilename);
452 0 : (*ppapszFileList)[(*pnSize + 1)] = NULL;
453 0 : CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
454 :
455 0 : (*pnSize) ++;
456 :
457 : VRTRasterBand::GetFileList( ppapszFileList, pnSize,
458 0 : pnMaxSize, hSetFiles);
459 : }
|