1 : /******************************************************************************
2 : * $Id: vrtrawrasterband.cpp 22776 2011-07-23 18:07:58Z rouault $
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 22776 2011-07-23 18:07:58Z rouault $");
36 :
37 : /************************************************************************/
38 : /* ==================================================================== */
39 : /* VRTRawRasterBand */
40 : /* ==================================================================== */
41 : /************************************************************************/
42 :
43 : /************************************************************************/
44 : /* VRTRawRasterBand() */
45 : /************************************************************************/
46 :
47 13 : VRTRawRasterBand::VRTRawRasterBand( GDALDataset *poDS, int nBand,
48 13 : GDALDataType eType )
49 :
50 : {
51 13 : Initialize( poDS->GetRasterXSize(), poDS->GetRasterYSize() );
52 :
53 13 : this->poDS = poDS;
54 13 : this->nBand = nBand;
55 :
56 13 : if( eType != GDT_Unknown )
57 2 : this->eDataType = eType;
58 :
59 13 : poRawRaster = NULL;
60 13 : pszSourceFilename = NULL;
61 13 : }
62 :
63 : /************************************************************************/
64 : /* ~VRTRawRasterBand() */
65 : /************************************************************************/
66 :
67 13 : VRTRawRasterBand::~VRTRawRasterBand()
68 :
69 : {
70 13 : FlushCache();
71 13 : ClearRawLink();
72 13 : }
73 :
74 : /************************************************************************/
75 : /* IRasterIO() */
76 : /************************************************************************/
77 :
78 353 : 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 : int nPixelSpace, int nLineSpace )
83 :
84 : {
85 353 : 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 353 : 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 353 : if( (nBufXSize < nXSize || nBufYSize < nYSize)
106 0 : && 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 353 : poRawRaster->SetAccess(eAccess);
115 :
116 : return poRawRaster->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
117 : pData, nBufXSize, nBufYSize,
118 353 : eBufType, nPixelSpace, nLineSpace );
119 : }
120 :
121 : /************************************************************************/
122 : /* IReadBlock() */
123 : /************************************************************************/
124 :
125 35 : CPLErr VRTRawRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
126 : 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 0 : CPLErr VRTRawRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
144 : 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 13 : CPLErr VRTRawRasterBand::SetRawLink( const char *pszFilename,
164 : const char *pszVRTPath,
165 : int bRelativeToVRT,
166 : vsi_l_offset nImageOffset,
167 : int nPixelOffset, int nLineOffset,
168 : const char *pszByteOrder )
169 :
170 : {
171 13 : ClearRawLink();
172 :
173 13 : ((VRTDataset *)poDS)->SetNeedsFlush();
174 :
175 : /* -------------------------------------------------------------------- */
176 : /* Prepare filename. */
177 : /* -------------------------------------------------------------------- */
178 13 : char *pszExpandedFilename = NULL;
179 :
180 13 : 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 21 : if( pszVRTPath != NULL && bRelativeToVRT )
188 : {
189 : pszExpandedFilename = CPLStrdup(
190 8 : 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 13 : FILE *fp = CPLOpenShared( pszExpandedFilename, "rb+", TRUE );
199 :
200 13 : if( fp == NULL )
201 0 : fp = CPLOpenShared( pszExpandedFilename, "rb", TRUE );
202 :
203 13 : if( fp == NULL && ((VRTDataset *)poDS)->GetAccess() == GA_Update )
204 : {
205 0 : fp = CPLOpenShared( pszExpandedFilename, "wb+", TRUE );
206 : }
207 :
208 13 : if( fp == NULL )
209 : {
210 : CPLError( CE_Failure, CPLE_OpenFailed,
211 : "Unable to open %s.\n%s",
212 : pszExpandedFilename,
213 0 : VSIStrerror( errno ) );
214 :
215 0 : CPLFree( pszExpandedFilename );
216 0 : return CE_Failure;
217 : }
218 :
219 13 : CPLFree( pszExpandedFilename );
220 :
221 13 : pszSourceFilename = CPLStrdup(pszFilename);
222 13 : this->bRelativeToVRT = bRelativeToVRT;
223 :
224 : /* -------------------------------------------------------------------- */
225 : /* Work out if we are in native mode or not. */
226 : /* -------------------------------------------------------------------- */
227 13 : int bNative = TRUE;
228 :
229 13 : if( pszByteOrder != NULL )
230 : {
231 12 : if( EQUAL(pszByteOrder,"LSB") )
232 10 : bNative = CPL_IS_LSB;
233 2 : else if( EQUAL(pszByteOrder,"MSB") )
234 2 : bNative = !CPL_IS_LSB;
235 : else
236 : {
237 : CPLError( CE_Failure, CPLE_AppDefined,
238 : "Illegal ByteOrder value '%s', should be LSB or MSB.",
239 0 : pszByteOrder );
240 0 : return CE_Failure;
241 : }
242 : }
243 :
244 : /* -------------------------------------------------------------------- */
245 : /* Create a corresponding RawRasterBand. */
246 : /* -------------------------------------------------------------------- */
247 : poRawRaster = new RawRasterBand( fp, nImageOffset, nPixelOffset,
248 : nLineOffset, GetRasterDataType(),
249 13 : bNative, GetXSize(), GetYSize(), TRUE );
250 :
251 : /* -------------------------------------------------------------------- */
252 : /* Reset block size to match the raw raster. */
253 : /* -------------------------------------------------------------------- */
254 13 : poRawRaster->GetBlockSize( &nBlockXSize, &nBlockYSize );
255 :
256 13 : return CE_None;
257 : }
258 :
259 : /************************************************************************/
260 : /* ClearRawLink() */
261 : /************************************************************************/
262 :
263 26 : void VRTRawRasterBand::ClearRawLink()
264 :
265 : {
266 26 : if( poRawRaster != NULL )
267 : {
268 13 : VSILFILE* fp = poRawRaster->GetFPL();
269 13 : delete poRawRaster;
270 13 : poRawRaster = NULL;
271 : /* We close the file after deleting the raster band */
272 : /* since data can be flushed in the destructor */
273 13 : if( fp != NULL )
274 : {
275 13 : CPLCloseShared( (FILE*) fp );
276 : }
277 : }
278 26 : CPLFree( pszSourceFilename );
279 26 : pszSourceFilename = NULL;
280 26 : }
281 :
282 : /************************************************************************/
283 : /* XMLInit() */
284 : /************************************************************************/
285 :
286 11 : CPLErr VRTRawRasterBand::XMLInit( CPLXMLNode * psTree,
287 : const char *pszVRTPath )
288 :
289 : {
290 : CPLErr eErr;
291 :
292 11 : eErr = VRTRasterBand::XMLInit( psTree, pszVRTPath );
293 11 : if( eErr != CE_None )
294 0 : return eErr;
295 :
296 :
297 : /* -------------------------------------------------------------------- */
298 : /* Validate a bit. */
299 : /* -------------------------------------------------------------------- */
300 11 : if( psTree == NULL || psTree->eType != CXT_Element
301 : || !EQUAL(psTree->pszValue,"VRTRasterBand")
302 : || !EQUAL(CPLGetXMLValue(psTree,"subClass",""),"VRTRawRasterBand") )
303 : {
304 : CPLError( CE_Failure, CPLE_AppDefined,
305 0 : "Invalid node passed to VRTRawRasterBand::XMLInit()." );
306 0 : return CE_Failure;
307 : }
308 :
309 : /* -------------------------------------------------------------------- */
310 : /* Prepare filename. */
311 : /* -------------------------------------------------------------------- */
312 : int bRelativeToVRT;
313 :
314 : const char *pszFilename =
315 11 : CPLGetXMLValue(psTree, "SourceFilename", NULL);
316 :
317 11 : if( pszFilename == NULL )
318 : {
319 : CPLError( CE_Warning, CPLE_AppDefined,
320 0 : "Missing <SourceFilename> element in VRTRasterBand." );
321 0 : return CE_Failure;
322 : }
323 :
324 : bRelativeToVRT = atoi(CPLGetXMLValue(psTree,"SourceFilename.relativeToVRT",
325 11 : "1"));
326 :
327 : /* -------------------------------------------------------------------- */
328 : /* Collect layout information. */
329 : /* -------------------------------------------------------------------- */
330 : vsi_l_offset nImageOffset;
331 : int nPixelOffset, nLineOffset;
332 11 : int nWordDataSize = GDALGetDataTypeSize( GetRasterDataType() ) / 8;
333 :
334 11 : nImageOffset = atoi(CPLGetXMLValue( psTree, "ImageOffset", "0") );
335 :
336 11 : if( CPLGetXMLValue( psTree, "PixelOffset", NULL ) == NULL )
337 0 : nPixelOffset = nWordDataSize;
338 : else
339 11 : nPixelOffset = atoi(CPLGetXMLValue( psTree, "PixelOffset", "0") );
340 11 : if (nPixelOffset <= 0)
341 : {
342 : CPLError( CE_Failure, CPLE_AppDefined,
343 0 : "Invalid value for <PixelOffset> element : %d", nPixelOffset );
344 0 : return CE_Failure;
345 : }
346 :
347 11 : if( CPLGetXMLValue( psTree, "LineOffset", NULL ) == NULL )
348 0 : nLineOffset = nWordDataSize * GetXSize();
349 : else
350 11 : nLineOffset = atoi(CPLGetXMLValue( psTree, "LineOffset", "0") );
351 :
352 11 : const char *pszByteOrder = CPLGetXMLValue( psTree, "ByteOrder", NULL );
353 :
354 : /* -------------------------------------------------------------------- */
355 : /* Open the file, and setup the raw layer access to the data. */
356 : /* -------------------------------------------------------------------- */
357 : return SetRawLink( pszFilename, pszVRTPath, bRelativeToVRT,
358 : nImageOffset, nPixelOffset, nLineOffset,
359 11 : pszByteOrder );
360 : }
361 :
362 : /************************************************************************/
363 : /* SerializeToXML() */
364 : /************************************************************************/
365 :
366 3 : CPLXMLNode *VRTRawRasterBand::SerializeToXML( const char *pszVRTPath )
367 :
368 : {
369 : CPLXMLNode *psTree;
370 :
371 3 : psTree = VRTRasterBand::SerializeToXML( pszVRTPath );
372 :
373 : /* -------------------------------------------------------------------- */
374 : /* Set subclass. */
375 : /* -------------------------------------------------------------------- */
376 : CPLCreateXMLNode(
377 : CPLCreateXMLNode( psTree, CXT_Attribute, "subClass" ),
378 3 : CXT_Text, "VRTRawRasterBand" );
379 :
380 : /* -------------------------------------------------------------------- */
381 : /* Setup the filename with relative flag. */
382 : /* -------------------------------------------------------------------- */
383 : CPLXMLNode *psNode;
384 :
385 : psNode =
386 : CPLCreateXMLElementAndValue( psTree, "SourceFilename",
387 3 : pszSourceFilename );
388 :
389 : CPLCreateXMLNode(
390 : CPLCreateXMLNode( psNode, CXT_Attribute, "relativeToVRT" ),
391 3 : CXT_Text, bRelativeToVRT ? "1" : "0" );
392 :
393 : /* -------------------------------------------------------------------- */
394 : /* We can't set the layout if there is no open rawband. */
395 : /* -------------------------------------------------------------------- */
396 3 : if( poRawRaster == NULL )
397 : {
398 : CPLError( CE_Failure, CPLE_AppDefined,
399 0 : "VRTRawRasterBand::SerializeToXML() fails because poRawRaster is NULL." );
400 0 : return NULL;
401 : }
402 :
403 : /* -------------------------------------------------------------------- */
404 : /* Set other layout information. */
405 : /* -------------------------------------------------------------------- */
406 : CPLCreateXMLElementAndValue(
407 : psTree, "ImageOffset",
408 3 : CPLSPrintf("%d",(int) poRawRaster->GetImgOffset()) );
409 :
410 : CPLCreateXMLElementAndValue(
411 : psTree, "PixelOffset",
412 3 : CPLSPrintf("%d",(int) poRawRaster->GetPixelOffset()) );
413 :
414 : CPLCreateXMLElementAndValue(
415 : psTree, "LineOffset",
416 3 : CPLSPrintf("%d",(int) poRawRaster->GetLineOffset()) );
417 :
418 3 : if( (poRawRaster->GetNativeOrder() && CPL_IS_LSB)
419 : || (!poRawRaster->GetNativeOrder() && !CPL_IS_LSB) )
420 2 : CPLCreateXMLElementAndValue( psTree, "ByteOrder", "LSB" );
421 : else
422 1 : CPLCreateXMLElementAndValue( psTree, "ByteOrder", "MSB" );
423 :
424 3 : return psTree;
425 : }
426 :
427 : /************************************************************************/
428 : /* GetFileList() */
429 : /************************************************************************/
430 :
431 0 : void VRTRawRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
432 : int *pnMaxSize, CPLHashSet* hSetFiles)
433 : {
434 0 : if (pszSourceFilename == NULL)
435 0 : return;
436 :
437 : /* -------------------------------------------------------------------- */
438 : /* Is it already in the list ? */
439 : /* -------------------------------------------------------------------- */
440 0 : if( CPLHashSetLookup(hSetFiles, pszSourceFilename) != NULL )
441 0 : return;
442 :
443 : /* -------------------------------------------------------------------- */
444 : /* Grow array if necessary */
445 : /* -------------------------------------------------------------------- */
446 0 : if (*pnSize + 1 >= *pnMaxSize)
447 : {
448 0 : *pnMaxSize = 2 + 2 * (*pnMaxSize);
449 : *ppapszFileList = (char **) CPLRealloc(
450 0 : *ppapszFileList, sizeof(char*) * (*pnMaxSize) );
451 : }
452 :
453 : /* -------------------------------------------------------------------- */
454 : /* Add the string to the list */
455 : /* -------------------------------------------------------------------- */
456 0 : (*ppapszFileList)[*pnSize] = CPLStrdup(pszSourceFilename);
457 0 : (*ppapszFileList)[(*pnSize + 1)] = NULL;
458 0 : CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
459 :
460 0 : (*pnSize) ++;
461 :
462 : VRTRasterBand::GetFileList( ppapszFileList, pnSize,
463 0 : pnMaxSize, hSetFiles);
464 : }
|