1 : /******************************************************************************
2 : * $Id: vrtsources.cpp 25109 2012-10-13 11:51:23Z rouault $
3 : *
4 : * Project: Virtual GDAL Datasets
5 : * Purpose: Implementation of VRTSimpleSource, VRTFuncSource and
6 : * VRTAveragedSource.
7 : * Author: Frank Warmerdam <warmerdam@pobox.com>
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2001, Frank Warmerdam <warmerdam@pobox.com>
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "vrtdataset.h"
32 : #include "gdal_proxy.h"
33 : #include "cpl_minixml.h"
34 : #include "cpl_string.h"
35 :
36 : #include <algorithm>
37 :
38 : CPL_CVSID("$Id: vrtsources.cpp 25109 2012-10-13 11:51:23Z rouault $");
39 :
40 : /************************************************************************/
41 : /* ==================================================================== */
42 : /* VRTSource */
43 : /* ==================================================================== */
44 : /************************************************************************/
45 :
46 5567 : VRTSource::~VRTSource()
47 : {
48 5567 : }
49 :
50 : /************************************************************************/
51 : /* GetFileList() */
52 : /************************************************************************/
53 :
54 0 : void VRTSource::GetFileList(char*** ppapszFileList, int *pnSize,
55 : int *pnMaxSize, CPLHashSet* hSetFiles)
56 : {
57 0 : }
58 :
59 : /************************************************************************/
60 : /* ==================================================================== */
61 : /* VRTSimpleSource */
62 : /* ==================================================================== */
63 : /************************************************************************/
64 :
65 : /************************************************************************/
66 : /* VRTSimpleSource() */
67 : /************************************************************************/
68 :
69 5567 : VRTSimpleSource::VRTSimpleSource()
70 :
71 : {
72 5567 : poRasterBand = NULL;
73 5567 : poMaskBandMainBand = NULL;
74 5567 : bNoDataSet = FALSE;
75 5567 : dfNoDataValue = VRT_NODATA_UNSET;
76 5567 : }
77 :
78 : /************************************************************************/
79 : /* ~VRTSimpleSource() */
80 : /************************************************************************/
81 :
82 5567 : VRTSimpleSource::~VRTSimpleSource()
83 :
84 : {
85 5567 : if( poMaskBandMainBand != NULL )
86 : {
87 13 : if (poMaskBandMainBand->GetDataset() != NULL )
88 : {
89 13 : if( poMaskBandMainBand->GetDataset()->GetShared() )
90 12 : GDALClose( (GDALDatasetH) poMaskBandMainBand->GetDataset() );
91 : else
92 1 : poMaskBandMainBand->GetDataset()->Dereference();
93 : }
94 : }
95 5554 : else if( poRasterBand != NULL && poRasterBand->GetDataset() != NULL )
96 : {
97 5453 : if( poRasterBand->GetDataset()->GetShared() )
98 3745 : GDALClose( (GDALDatasetH) poRasterBand->GetDataset() );
99 : else
100 1708 : poRasterBand->GetDataset()->Dereference();
101 : }
102 5567 : }
103 :
104 : /************************************************************************/
105 : /* SetSrcBand() */
106 : /************************************************************************/
107 :
108 5101 : void VRTSimpleSource::SetSrcBand( GDALRasterBand *poNewSrcBand )
109 :
110 : {
111 5101 : poRasterBand = poNewSrcBand;
112 5101 : }
113 :
114 :
115 : /************************************************************************/
116 : /* SetSrcMaskBand() */
117 : /************************************************************************/
118 :
119 : /* poSrcBand is not the mask band, but the band from which the mask band is taken */
120 5 : void VRTSimpleSource::SetSrcMaskBand( GDALRasterBand *poNewSrcBand )
121 :
122 : {
123 5 : poRasterBand = poNewSrcBand->GetMaskBand();
124 5 : poMaskBandMainBand = poNewSrcBand;
125 5 : }
126 :
127 : /************************************************************************/
128 : /* SetSrcWindow() */
129 : /************************************************************************/
130 :
131 5106 : void VRTSimpleSource::SetSrcWindow( int nNewXOff, int nNewYOff,
132 : int nNewXSize, int nNewYSize )
133 :
134 : {
135 5106 : nSrcXOff = nNewXOff;
136 5106 : nSrcYOff = nNewYOff;
137 5106 : nSrcXSize = nNewXSize;
138 5106 : nSrcYSize = nNewYSize;
139 5106 : }
140 :
141 : /************************************************************************/
142 : /* SetDstWindow() */
143 : /************************************************************************/
144 :
145 5106 : void VRTSimpleSource::SetDstWindow( int nNewXOff, int nNewYOff,
146 : int nNewXSize, int nNewYSize )
147 :
148 : {
149 5106 : nDstXOff = nNewXOff;
150 5106 : nDstYOff = nNewYOff;
151 5106 : nDstXSize = nNewXSize;
152 5106 : nDstYSize = nNewYSize;
153 5106 : }
154 :
155 : /************************************************************************/
156 : /* SetNoDataValue() */
157 : /************************************************************************/
158 :
159 8 : void VRTSimpleSource::SetNoDataValue( double dfNewNoDataValue )
160 :
161 : {
162 8 : if( dfNewNoDataValue == VRT_NODATA_UNSET )
163 : {
164 0 : bNoDataSet = FALSE;
165 0 : dfNoDataValue = VRT_NODATA_UNSET;
166 : }
167 : else
168 : {
169 8 : bNoDataSet = TRUE;
170 8 : dfNoDataValue = dfNewNoDataValue;
171 : }
172 8 : }
173 :
174 : /************************************************************************/
175 : /* SerializeToXML() */
176 : /************************************************************************/
177 :
178 195 : CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
179 :
180 : {
181 : CPLXMLNode *psSrc;
182 : int bRelativeToVRT;
183 : const char *pszRelativePath;
184 : int nBlockXSize, nBlockYSize;
185 :
186 195 : if( poRasterBand == NULL )
187 0 : return NULL;
188 :
189 : GDALDataset *poDS;
190 :
191 195 : if (poMaskBandMainBand)
192 : {
193 5 : poDS = poMaskBandMainBand->GetDataset();
194 5 : if( poDS == NULL || poMaskBandMainBand->GetBand() < 1 )
195 0 : return NULL;
196 : }
197 : else
198 : {
199 190 : poDS = poRasterBand->GetDataset();
200 190 : if( poDS == NULL || poRasterBand->GetBand() < 1 )
201 0 : return NULL;
202 : }
203 :
204 195 : psSrc = CPLCreateXMLNode( NULL, CXT_Element, "SimpleSource" );
205 :
206 : VSIStatBufL sStat;
207 390 : if ( strstr(poDS->GetDescription(), "/vsicurl/http") != NULL ||
208 195 : strstr(poDS->GetDescription(), "/vsicurl/ftp") != NULL )
209 : {
210 : /* Testing the existence of remote ressources can be excruciating */
211 : /* slow, so let's just suppose they exist */
212 0 : pszRelativePath = poDS->GetDescription();
213 0 : bRelativeToVRT = FALSE;
214 : }
215 : /* If this isn't actually a file, don't even try to know if it is */
216 : /* a relative path. It can't be !, and unfortunately */
217 : /* CPLIsFilenameRelative() can only work with strings that are filenames */
218 : /* To be clear NITF_TOC_ENTRY:CADRG_JOG-A_250K_1_0:some_path isn't a relative */
219 : /* file path */
220 195 : else if( VSIStatExL( poDS->GetDescription(), &sStat, VSI_STAT_EXISTS_FLAG ) != 0 )
221 : {
222 1 : pszRelativePath = poDS->GetDescription();
223 1 : bRelativeToVRT = FALSE;
224 : }
225 : else
226 : {
227 : pszRelativePath =
228 194 : CPLExtractRelativePath( pszVRTPath, poDS->GetDescription(),
229 388 : &bRelativeToVRT );
230 : }
231 :
232 195 : CPLSetXMLValue( psSrc, "SourceFilename", pszRelativePath );
233 :
234 : CPLCreateXMLNode(
235 : CPLCreateXMLNode( CPLGetXMLNode( psSrc, "SourceFilename" ),
236 : CXT_Attribute, "relativeToVRT" ),
237 195 : CXT_Text, bRelativeToVRT ? "1" : "0" );
238 :
239 195 : if (poMaskBandMainBand)
240 : CPLSetXMLValue( psSrc, "SourceBand",
241 5 : CPLSPrintf("mask,%d",poMaskBandMainBand->GetBand()) );
242 : else
243 : CPLSetXMLValue( psSrc, "SourceBand",
244 190 : CPLSPrintf("%d",poRasterBand->GetBand()) );
245 :
246 : /* Write a few additional useful properties of the dataset */
247 : /* so that we can use a proxy dataset when re-opening. See XMLInit() */
248 : /* below */
249 : CPLSetXMLValue( psSrc, "SourceProperties.#RasterXSize",
250 195 : CPLSPrintf("%d",poRasterBand->GetXSize()) );
251 : CPLSetXMLValue( psSrc, "SourceProperties.#RasterYSize",
252 195 : CPLSPrintf("%d",poRasterBand->GetYSize()) );
253 : CPLSetXMLValue( psSrc, "SourceProperties.#DataType",
254 195 : GDALGetDataTypeName( poRasterBand->GetRasterDataType() ) );
255 195 : poRasterBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
256 : CPLSetXMLValue( psSrc, "SourceProperties.#BlockXSize",
257 195 : CPLSPrintf("%d",nBlockXSize) );
258 : CPLSetXMLValue( psSrc, "SourceProperties.#BlockYSize",
259 195 : CPLSPrintf("%d",nBlockYSize) );
260 :
261 195 : if( nSrcXOff != -1
262 : || nSrcYOff != -1
263 : || nSrcXSize != -1
264 : || nSrcYSize != -1 )
265 : {
266 : CPLSetXMLValue( psSrc, "SrcRect.#xOff",
267 192 : CPLSPrintf( "%d", nSrcXOff ) );
268 : CPLSetXMLValue( psSrc, "SrcRect.#yOff",
269 192 : CPLSPrintf( "%d", nSrcYOff ) );
270 : CPLSetXMLValue( psSrc, "SrcRect.#xSize",
271 192 : CPLSPrintf( "%d", nSrcXSize ) );
272 : CPLSetXMLValue( psSrc, "SrcRect.#ySize",
273 192 : CPLSPrintf( "%d", nSrcYSize ) );
274 : }
275 :
276 195 : if( nDstXOff != -1
277 : || nDstYOff != -1
278 : || nDstXSize != -1
279 : || nDstYSize != -1 )
280 : {
281 192 : CPLSetXMLValue( psSrc, "DstRect.#xOff", CPLSPrintf( "%d", nDstXOff ) );
282 192 : CPLSetXMLValue( psSrc, "DstRect.#yOff", CPLSPrintf( "%d", nDstYOff ) );
283 192 : CPLSetXMLValue( psSrc, "DstRect.#xSize",CPLSPrintf( "%d", nDstXSize ));
284 192 : CPLSetXMLValue( psSrc, "DstRect.#ySize",CPLSPrintf( "%d", nDstYSize ));
285 : }
286 :
287 195 : return psSrc;
288 : }
289 :
290 : /************************************************************************/
291 : /* XMLInit() */
292 : /************************************************************************/
293 :
294 461 : CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
295 :
296 : {
297 : /* -------------------------------------------------------------------- */
298 : /* Prepare filename. */
299 : /* -------------------------------------------------------------------- */
300 461 : char *pszSrcDSName = NULL;
301 461 : CPLXMLNode* psSourceFileNameNode = CPLGetXMLNode(psSrc,"SourceFilename");
302 : const char *pszFilename =
303 461 : psSourceFileNameNode ? CPLGetXMLValue(psSourceFileNameNode,NULL, NULL) : NULL;
304 :
305 461 : if( pszFilename == NULL )
306 : {
307 : CPLError( CE_Warning, CPLE_AppDefined,
308 0 : "Missing <SourceFilename> element in VRTRasterBand." );
309 0 : return CE_Failure;
310 : }
311 :
312 461 : if( pszVRTPath != NULL
313 : && atoi(CPLGetXMLValue( psSourceFileNameNode, "relativetoVRT", "0")) )
314 : {
315 : pszSrcDSName = CPLStrdup(
316 296 : CPLProjectRelativeFilename( pszVRTPath, pszFilename ) );
317 : }
318 : else
319 165 : pszSrcDSName = CPLStrdup( pszFilename );
320 :
321 461 : const char* pszSourceBand = CPLGetXMLValue(psSrc,"SourceBand","1");
322 461 : int nSrcBand = 0;
323 461 : int bGetMaskBand = FALSE;
324 461 : if (EQUALN(pszSourceBand, "mask",4))
325 : {
326 8 : bGetMaskBand = TRUE;
327 8 : if (pszSourceBand[4] == ',')
328 8 : nSrcBand = atoi(pszSourceBand + 5);
329 : else
330 0 : nSrcBand = 1;
331 : }
332 : else
333 453 : nSrcBand = atoi(pszSourceBand);
334 461 : if (!GDALCheckBandCount(nSrcBand, 0))
335 : {
336 : CPLError( CE_Warning, CPLE_AppDefined,
337 0 : "Invalid <SourceBand> element in VRTRasterBand." );
338 0 : CPLFree( pszSrcDSName );
339 0 : return CE_Failure;
340 : }
341 :
342 : /* Newly generated VRT will have RasterXSize, RasterYSize, DataType, */
343 : /* BlockXSize, BlockYSize tags, so that we don't have actually to */
344 : /* open the real dataset immediately, but we can use a proxy dataset */
345 : /* instead. This is particularly usefull when dealing with huge VRT */
346 : /* For example, a VRT with the world coverage of DTED0 (25594 files) */
347 461 : CPLXMLNode* psSrcProperties = CPLGetXMLNode(psSrc,"SourceProperties");
348 461 : int nRasterXSize = 0, nRasterYSize =0;
349 461 : GDALDataType eDataType = (GDALDataType)-1;
350 461 : int nBlockXSize = 0, nBlockYSize = 0;
351 461 : if (psSrcProperties)
352 : {
353 236 : nRasterXSize = atoi(CPLGetXMLValue(psSrcProperties,"RasterXSize","0"));
354 236 : nRasterYSize = atoi(CPLGetXMLValue(psSrcProperties,"RasterYSize","0"));
355 236 : const char *pszDataType = CPLGetXMLValue(psSrcProperties, "DataType", NULL);
356 236 : if( pszDataType != NULL )
357 : {
358 523 : for( int iType = 0; iType < GDT_TypeCount; iType++ )
359 : {
360 523 : const char *pszThisName = GDALGetDataTypeName((GDALDataType)iType);
361 :
362 523 : if( pszThisName != NULL && EQUAL(pszDataType,pszThisName) )
363 : {
364 236 : eDataType = (GDALDataType) iType;
365 236 : break;
366 : }
367 : }
368 : }
369 236 : nBlockXSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockXSize","0"));
370 236 : nBlockYSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockYSize","0"));
371 : }
372 :
373 : GDALDataset *poSrcDS;
374 686 : if (nRasterXSize == 0 || nRasterYSize == 0 || eDataType == (GDALDataType)-1 ||
375 : nBlockXSize == 0 || nBlockYSize == 0)
376 : {
377 : /* -------------------------------------------------------------------- */
378 : /* Open the file (shared). */
379 : /* -------------------------------------------------------------------- */
380 225 : poSrcDS = (GDALDataset *) GDALOpenShared( pszSrcDSName, GA_ReadOnly );
381 : }
382 : else
383 : {
384 : /* -------------------------------------------------------------------- */
385 : /* Create a proxy dataset */
386 : /* -------------------------------------------------------------------- */
387 : int i;
388 236 : GDALProxyPoolDataset* proxyDS = new GDALProxyPoolDataset(pszSrcDSName, nRasterXSize, nRasterYSize, GA_ReadOnly, TRUE);
389 236 : poSrcDS = proxyDS;
390 :
391 : /* Only the information of rasterBand nSrcBand will be accurate */
392 : /* but that's OK since we only use that band afterwards */
393 529 : for(i=1;i<=nSrcBand;i++)
394 293 : proxyDS->AddSrcBandDescription(eDataType, nBlockXSize, nBlockYSize);
395 236 : if (bGetMaskBand)
396 8 : ((GDALProxyPoolRasterBand*)proxyDS->GetRasterBand(nSrcBand))->AddSrcMaskBandDescription(eDataType, nBlockXSize, nBlockYSize);
397 : }
398 :
399 461 : CPLFree( pszSrcDSName );
400 :
401 461 : if( poSrcDS == NULL )
402 101 : return CE_Failure;
403 :
404 : /* -------------------------------------------------------------------- */
405 : /* Get the raster band. */
406 : /* -------------------------------------------------------------------- */
407 :
408 360 : poRasterBand = poSrcDS->GetRasterBand(nSrcBand);
409 360 : if( poRasterBand == NULL )
410 : {
411 0 : if( poSrcDS->GetShared() )
412 0 : GDALClose( (GDALDatasetH) poSrcDS );
413 0 : return CE_Failure;
414 : }
415 360 : if (bGetMaskBand)
416 : {
417 8 : poMaskBandMainBand = poRasterBand;
418 8 : poRasterBand = poRasterBand->GetMaskBand();
419 8 : if( poRasterBand == NULL )
420 0 : return CE_Failure;
421 : }
422 :
423 : /* -------------------------------------------------------------------- */
424 : /* Set characteristics. */
425 : /* -------------------------------------------------------------------- */
426 360 : CPLXMLNode* psSrcRect = CPLGetXMLNode(psSrc,"SrcRect");
427 360 : if (psSrcRect)
428 : {
429 337 : nSrcXOff = atoi(CPLGetXMLValue(psSrcRect,"xOff","-1"));
430 337 : nSrcYOff = atoi(CPLGetXMLValue(psSrcRect,"yOff","-1"));
431 337 : nSrcXSize = atoi(CPLGetXMLValue(psSrcRect,"xSize","-1"));
432 337 : nSrcYSize = atoi(CPLGetXMLValue(psSrcRect,"ySize","-1"));
433 : }
434 : else
435 : {
436 23 : nSrcXOff = nSrcYOff = nSrcXSize = nSrcYSize = -1;
437 : }
438 :
439 360 : CPLXMLNode* psDstRect = CPLGetXMLNode(psSrc,"DstRect");
440 360 : if (psDstRect)
441 : {
442 337 : nDstXOff = atoi(CPLGetXMLValue(psDstRect,"xOff","-1"));
443 337 : nDstYOff = atoi(CPLGetXMLValue(psDstRect,"yOff","-1"));
444 337 : nDstXSize = atoi(CPLGetXMLValue(psDstRect,"xSize","-1"));
445 337 : nDstYSize = atoi(CPLGetXMLValue(psDstRect,"ySize","-1"));
446 : }
447 : else
448 : {
449 23 : nDstXOff = nDstYOff = nDstXSize = nDstYSize = -1;
450 : }
451 :
452 360 : return CE_None;
453 : }
454 :
455 : /************************************************************************/
456 : /* GetFileList() */
457 : /************************************************************************/
458 :
459 5 : void VRTSimpleSource::GetFileList(char*** ppapszFileList, int *pnSize,
460 : int *pnMaxSize, CPLHashSet* hSetFiles)
461 : {
462 : const char* pszFilename;
463 10 : if (poRasterBand != NULL && poRasterBand->GetDataset() != NULL &&
464 5 : (pszFilename = poRasterBand->GetDataset()->GetDescription()) != NULL)
465 : {
466 : /* -------------------------------------------------------------------- */
467 : /* Is the filename even a real filesystem object? */
468 : /* -------------------------------------------------------------------- */
469 5 : if ( strstr(pszFilename, "/vsicurl/http") != NULL ||
470 : strstr(pszFilename, "/vsicurl/ftp") != NULL )
471 : {
472 : /* Testing the existence of remote ressources can be excruciating */
473 : /* slow, so let's just suppose they exist */
474 : }
475 : else
476 : {
477 : VSIStatBufL sStat;
478 5 : if( VSIStatExL( pszFilename, &sStat, VSI_STAT_EXISTS_FLAG ) != 0 )
479 0 : return;
480 : }
481 :
482 : /* -------------------------------------------------------------------- */
483 : /* Is it already in the list ? */
484 : /* -------------------------------------------------------------------- */
485 5 : if( CPLHashSetLookup(hSetFiles, pszFilename) != NULL )
486 0 : return;
487 :
488 : /* -------------------------------------------------------------------- */
489 : /* Grow array if necessary */
490 : /* -------------------------------------------------------------------- */
491 5 : if (*pnSize + 1 >= *pnMaxSize)
492 : {
493 5 : *pnMaxSize = 2 + 2 * (*pnMaxSize);
494 : *ppapszFileList = (char **) CPLRealloc(
495 5 : *ppapszFileList, sizeof(char*) * (*pnMaxSize) );
496 : }
497 :
498 : /* -------------------------------------------------------------------- */
499 : /* Add the string to the list */
500 : /* -------------------------------------------------------------------- */
501 5 : (*ppapszFileList)[*pnSize] = CPLStrdup(pszFilename);
502 5 : (*ppapszFileList)[(*pnSize + 1)] = NULL;
503 5 : CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
504 :
505 5 : (*pnSize) ++;
506 : }
507 : }
508 :
509 : /************************************************************************/
510 : /* GetBand() */
511 : /************************************************************************/
512 :
513 31961 : GDALRasterBand* VRTSimpleSource::GetBand()
514 : {
515 31961 : return poMaskBandMainBand ? NULL : poRasterBand;
516 : }
517 :
518 : /************************************************************************/
519 : /* IsSameExceptBandNumber() */
520 : /************************************************************************/
521 :
522 3652 : int VRTSimpleSource::IsSameExceptBandNumber(VRTSimpleSource* poOtherSource)
523 : {
524 : return nSrcXOff == poOtherSource->nSrcXOff &&
525 : nSrcYOff == poOtherSource->nSrcYOff &&
526 : nSrcXSize == poOtherSource->nSrcXSize &&
527 : nSrcYSize == poOtherSource->nSrcYSize &&
528 : nDstXOff == poOtherSource->nDstXOff &&
529 : nDstYOff == poOtherSource->nDstYOff &&
530 : nDstXSize == poOtherSource->nDstXSize &&
531 : nDstYSize == poOtherSource->nDstYSize &&
532 : bNoDataSet == poOtherSource->bNoDataSet &&
533 : dfNoDataValue == poOtherSource->dfNoDataValue &&
534 : GetBand() != NULL && poOtherSource->GetBand() != NULL &&
535 : GetBand()->GetDataset() != NULL &&
536 : poOtherSource->GetBand()->GetDataset() != NULL &&
537 3652 : EQUAL(GetBand()->GetDataset()->GetDescription(),
538 : poOtherSource->GetBand()->GetDataset()->GetDescription());
539 : }
540 :
541 : /************************************************************************/
542 : /* SrcToDst() */
543 : /* */
544 : /* Note: this is a no-op if the dst window is -1,-1,-1,-1. */
545 : /************************************************************************/
546 :
547 11818 : void VRTSimpleSource::SrcToDst( double dfX, double dfY,
548 : double &dfXOut, double &dfYOut )
549 :
550 : {
551 11818 : dfXOut = ((dfX - nSrcXOff) / nSrcXSize) * nDstXSize + nDstXOff;
552 11818 : dfYOut = ((dfY - nSrcYOff) / nSrcYSize) * nDstYSize + nDstYOff;
553 11818 : }
554 :
555 : /************************************************************************/
556 : /* DstToSrc() */
557 : /* */
558 : /* Note: this is a no-op if the dst window is -1,-1,-1,-1. */
559 : /************************************************************************/
560 :
561 3400 : void VRTSimpleSource::DstToSrc( double dfX, double dfY,
562 : double &dfXOut, double &dfYOut )
563 :
564 : {
565 3400 : dfXOut = ((dfX - nDstXOff) / nDstXSize) * nSrcXSize + nSrcXOff;
566 3400 : dfYOut = ((dfY - nDstYOff) / nDstYSize) * nSrcYSize + nSrcYOff;
567 3400 : }
568 :
569 : /************************************************************************/
570 : /* GetSrcDstWindow() */
571 : /************************************************************************/
572 :
573 : int
574 19557 : VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
575 : int nBufXSize, int nBufYSize,
576 : int *pnReqXOff, int *pnReqYOff,
577 : int *pnReqXSize, int *pnReqYSize,
578 : int *pnOutXOff, int *pnOutYOff,
579 : int *pnOutXSize, int *pnOutYSize )
580 :
581 : {
582 : int bDstWinSet = nDstXOff != -1 || nDstXSize != -1
583 19557 : || nDstYOff != -1 || nDstYSize != -1;
584 :
585 : #ifdef DEBUG
586 : int bSrcWinSet = nSrcXOff != -1 || nSrcXSize != -1
587 19557 : || nSrcYOff != -1 || nSrcYSize != -1;
588 :
589 19557 : if( bSrcWinSet != bDstWinSet )
590 : {
591 0 : return FALSE;
592 : }
593 : #endif
594 :
595 : /* -------------------------------------------------------------------- */
596 : /* If the input window completely misses the portion of the */
597 : /* virtual dataset provided by this source we have nothing to do. */
598 : /* -------------------------------------------------------------------- */
599 19557 : if( bDstWinSet )
600 : {
601 19484 : if( nXOff >= nDstXOff + nDstXSize
602 : || nYOff >= nDstYOff + nDstYSize
603 : || nXOff + nXSize < nDstXOff
604 : || nYOff + nYSize < nDstYOff )
605 400 : return FALSE;
606 : }
607 :
608 : /* -------------------------------------------------------------------- */
609 : /* This request window corresponds to the whole output buffer. */
610 : /* -------------------------------------------------------------------- */
611 19157 : *pnOutXOff = 0;
612 19157 : *pnOutYOff = 0;
613 19157 : *pnOutXSize = nBufXSize;
614 19157 : *pnOutYSize = nBufYSize;
615 :
616 : /* -------------------------------------------------------------------- */
617 : /* If the input window extents outside the portion of the on */
618 : /* the virtual file that this source can set, then clip down */
619 : /* the requested window. */
620 : /* -------------------------------------------------------------------- */
621 19157 : int bModifiedX = FALSE, bModifiedY = FALSE;
622 19157 : int nRXOff = nXOff;
623 19157 : int nRYOff = nYOff;
624 19157 : int nRXSize = nXSize;
625 19157 : int nRYSize = nYSize;
626 :
627 :
628 19157 : if( bDstWinSet )
629 : {
630 19084 : if( nRXOff < nDstXOff )
631 : {
632 2934 : nRXSize = nRXSize + nRXOff - nDstXOff;
633 2934 : nRXOff = nDstXOff;
634 2934 : bModifiedX = TRUE;
635 : }
636 :
637 19084 : if( nRYOff < nDstYOff )
638 : {
639 18 : nRYSize = nRYSize + nRYOff - nDstYOff;
640 18 : nRYOff = nDstYOff;
641 18 : bModifiedY = TRUE;
642 : }
643 :
644 19084 : if( nRXOff + nRXSize > nDstXOff + nDstXSize )
645 : {
646 2998 : nRXSize = nDstXOff + nDstXSize - nRXOff;
647 2998 : bModifiedX = TRUE;
648 : }
649 :
650 19084 : if( nRYOff + nRYSize > nDstYOff + nDstYSize )
651 : {
652 3 : nRYSize = nDstYOff + nDstYSize - nRYOff;
653 3 : bModifiedY = TRUE;
654 : }
655 : }
656 :
657 : /* -------------------------------------------------------------------- */
658 : /* Translate requested region in virtual file into the source */
659 : /* band coordinates. */
660 : /* -------------------------------------------------------------------- */
661 19157 : double dfScaleX = nSrcXSize / (double) nDstXSize;
662 19157 : double dfScaleY = nSrcYSize / (double) nDstYSize;
663 :
664 19157 : *pnReqXOff = (int) floor((nRXOff - nDstXOff) * dfScaleX + nSrcXOff);
665 19157 : *pnReqYOff = (int) floor((nRYOff - nDstYOff) * dfScaleY + nSrcYOff);
666 :
667 19157 : *pnReqXSize = (int) floor(nRXSize * dfScaleX + 0.5);
668 19157 : *pnReqYSize = (int) floor(nRYSize * dfScaleY + 0.5);
669 :
670 : /* -------------------------------------------------------------------- */
671 : /* Clamp within the bounds of the available source data. */
672 : /* -------------------------------------------------------------------- */
673 19157 : if( *pnReqXOff < 0 )
674 : {
675 0 : *pnReqXSize += *pnReqXOff;
676 0 : *pnReqXOff = 0;
677 :
678 0 : bModifiedX = TRUE;
679 : }
680 :
681 19157 : if( *pnReqYOff < 0 )
682 : {
683 0 : *pnReqYSize += *pnReqYOff;
684 0 : *pnReqYOff = 0;
685 0 : bModifiedY = TRUE;
686 : }
687 :
688 19157 : if( *pnReqXSize == 0 )
689 0 : *pnReqXSize = 1;
690 19157 : if( *pnReqYSize == 0 )
691 16 : *pnReqYSize = 1;
692 :
693 19157 : if( *pnReqXOff + *pnReqXSize > poRasterBand->GetXSize() )
694 : {
695 4 : *pnReqXSize = poRasterBand->GetXSize() - *pnReqXOff;
696 4 : bModifiedX = TRUE;
697 : }
698 :
699 19157 : if( *pnReqYOff + *pnReqYSize > poRasterBand->GetYSize() )
700 : {
701 4 : *pnReqYSize = poRasterBand->GetYSize() - *pnReqYOff;
702 4 : bModifiedY = TRUE;
703 : }
704 :
705 : /* -------------------------------------------------------------------- */
706 : /* Don't do anything if the requesting region is completely off */
707 : /* the source image. */
708 : /* -------------------------------------------------------------------- */
709 19157 : if( *pnReqXOff >= poRasterBand->GetXSize()
710 : || *pnReqYOff >= poRasterBand->GetYSize()
711 : || *pnReqXSize <= 0 || *pnReqYSize <= 0 )
712 : {
713 0 : return FALSE;
714 : }
715 :
716 : /* -------------------------------------------------------------------- */
717 : /* If we haven't had to modify the source rectangle, then the */
718 : /* destination rectangle must be the whole region. */
719 : /* -------------------------------------------------------------------- */
720 19157 : if( !bModifiedX && !bModifiedY )
721 13248 : return TRUE;
722 :
723 : /* -------------------------------------------------------------------- */
724 : /* Now transform this possibly reduced request back into the */
725 : /* destination buffer coordinates in case the output region is */
726 : /* less than the whole buffer. */
727 : /* -------------------------------------------------------------------- */
728 : double dfDstULX, dfDstULY, dfDstLRX, dfDstLRY;
729 : double dfScaleWinToBufX, dfScaleWinToBufY;
730 :
731 5909 : SrcToDst( (double) *pnReqXOff, (double) *pnReqYOff, dfDstULX, dfDstULY );
732 : SrcToDst( *pnReqXOff + *pnReqXSize, *pnReqYOff + *pnReqYSize,
733 5909 : dfDstLRX, dfDstLRY );
734 :
735 5909 : if( bModifiedX )
736 : {
737 5909 : dfScaleWinToBufX = nBufXSize / (double) nXSize;
738 :
739 5909 : *pnOutXOff = (int) ((dfDstULX - nXOff) * dfScaleWinToBufX+0.001);
740 : *pnOutXSize = (int) ((dfDstLRX - nXOff) * dfScaleWinToBufX+0.001)
741 5909 : - *pnOutXOff;
742 :
743 5909 : *pnOutXOff = MAX(0,*pnOutXOff);
744 5909 : if( *pnOutXOff + *pnOutXSize > nBufXSize )
745 0 : *pnOutXSize = nBufXSize - *pnOutXOff;
746 : }
747 :
748 5909 : if( bModifiedY )
749 : {
750 24 : dfScaleWinToBufY = nBufYSize / (double) nYSize;
751 :
752 24 : *pnOutYOff = (int) ((dfDstULY - nYOff) * dfScaleWinToBufY+0.001);
753 : *pnOutYSize = (int) ((dfDstLRY - nYOff) * dfScaleWinToBufY+0.001)
754 24 : - *pnOutYOff;
755 :
756 24 : *pnOutYOff = MAX(0,*pnOutYOff);
757 24 : if( *pnOutYOff + *pnOutYSize > nBufYSize )
758 16 : *pnOutYSize = nBufYSize - *pnOutYOff;
759 : }
760 :
761 5909 : if( *pnOutXSize < 1 || *pnOutYSize < 1 )
762 16 : return FALSE;
763 : else
764 5893 : return TRUE;
765 : }
766 :
767 : /************************************************************************/
768 : /* RasterIO() */
769 : /************************************************************************/
770 :
771 : CPLErr
772 17058 : VRTSimpleSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
773 : void *pData, int nBufXSize, int nBufYSize,
774 : GDALDataType eBufType,
775 : int nPixelSpace, int nLineSpace )
776 :
777 : {
778 : // The window we will actually request from the source raster band.
779 : int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
780 :
781 : // The window we will actual set _within_ the pData buffer.
782 : int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
783 :
784 17058 : if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize,
785 : nBufXSize, nBufYSize,
786 : &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
787 : &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
788 : {
789 416 : return CE_None;
790 : }
791 :
792 : /* -------------------------------------------------------------------- */
793 : /* Actually perform the IO request. */
794 : /* -------------------------------------------------------------------- */
795 : CPLErr eErr;
796 :
797 : eErr =
798 : poRasterBand->RasterIO( GF_Read,
799 : nReqXOff, nReqYOff, nReqXSize, nReqYSize,
800 : ((unsigned char *) pData)
801 : + nOutXOff * nPixelSpace
802 : + nOutYOff * nLineSpace,
803 : nOutXSize, nOutYSize,
804 16642 : eBufType, nPixelSpace, nLineSpace );
805 :
806 16642 : return eErr;
807 : }
808 :
809 : /************************************************************************/
810 : /* GetMinimum() */
811 : /************************************************************************/
812 :
813 9 : double VRTSimpleSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
814 : {
815 : // The window we will actually request from the source raster band.
816 : int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
817 :
818 : // The window we will actual set _within_ the pData buffer.
819 : int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
820 :
821 9 : if( !GetSrcDstWindow( 0, 0, nXSize, nYSize,
822 : nXSize, nYSize,
823 : &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
824 : &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ||
825 : nReqXOff != 0 || nReqYOff != 0 ||
826 : nReqXSize != poRasterBand->GetXSize() ||
827 : nReqYSize != poRasterBand->GetYSize())
828 : {
829 0 : *pbSuccess = FALSE;
830 0 : return 0;
831 : }
832 :
833 9 : return poRasterBand->GetMinimum(pbSuccess);
834 : }
835 :
836 : /************************************************************************/
837 : /* GetMaximum() */
838 : /************************************************************************/
839 :
840 9 : double VRTSimpleSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
841 : {
842 : // The window we will actually request from the source raster band.
843 : int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
844 :
845 : // The window we will actual set _within_ the pData buffer.
846 : int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
847 :
848 9 : if( !GetSrcDstWindow( 0, 0, nXSize, nYSize,
849 : nXSize, nYSize,
850 : &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
851 : &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ||
852 : nReqXOff != 0 || nReqYOff != 0 ||
853 : nReqXSize != poRasterBand->GetXSize() ||
854 : nReqYSize != poRasterBand->GetYSize())
855 : {
856 0 : *pbSuccess = FALSE;
857 0 : return 0;
858 : }
859 :
860 9 : return poRasterBand->GetMaximum(pbSuccess);
861 : }
862 :
863 : /************************************************************************/
864 : /* ComputeRasterMinMax() */
865 : /************************************************************************/
866 :
867 1 : CPLErr VRTSimpleSource::ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax )
868 : {
869 : // The window we will actually request from the source raster band.
870 : int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
871 :
872 : // The window we will actual set _within_ the pData buffer.
873 : int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
874 :
875 1 : if( !GetSrcDstWindow( 0, 0, nXSize, nYSize,
876 : nXSize, nYSize,
877 : &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
878 : &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ||
879 : nReqXOff != 0 || nReqYOff != 0 ||
880 : nReqXSize != poRasterBand->GetXSize() ||
881 : nReqYSize != poRasterBand->GetYSize())
882 : {
883 0 : return CE_Failure;
884 : }
885 :
886 1 : return poRasterBand->ComputeRasterMinMax(bApproxOK, adfMinMax);
887 : }
888 :
889 : /************************************************************************/
890 : /* ComputeStatistics() */
891 : /************************************************************************/
892 :
893 2 : CPLErr VRTSimpleSource::ComputeStatistics( int nXSize, int nYSize,
894 : int bApproxOK,
895 : double *pdfMin, double *pdfMax,
896 : double *pdfMean, double *pdfStdDev,
897 : GDALProgressFunc pfnProgress, void *pProgressData )
898 : {
899 : // The window we will actually request from the source raster band.
900 : int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
901 :
902 : // The window we will actual set _within_ the pData buffer.
903 : int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
904 :
905 2 : if( !GetSrcDstWindow( 0, 0, nXSize, nYSize,
906 : nXSize, nYSize,
907 : &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
908 : &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ||
909 : nReqXOff != 0 || nReqYOff != 0 ||
910 : nReqXSize != poRasterBand->GetXSize() ||
911 : nReqYSize != poRasterBand->GetYSize())
912 : {
913 0 : return CE_Failure;
914 : }
915 :
916 : return poRasterBand->ComputeStatistics(bApproxOK, pdfMin, pdfMax,
917 : pdfMean, pdfStdDev,
918 2 : pfnProgress, pProgressData);
919 : }
920 :
921 : /************************************************************************/
922 : /* GetHistogram() */
923 : /************************************************************************/
924 :
925 1 : CPLErr VRTSimpleSource::GetHistogram( int nXSize, int nYSize,
926 : double dfMin, double dfMax,
927 : int nBuckets, int * panHistogram,
928 : int bIncludeOutOfRange, int bApproxOK,
929 : GDALProgressFunc pfnProgress, void *pProgressData )
930 : {
931 : // The window we will actually request from the source raster band.
932 : int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
933 :
934 : // The window we will actual set _within_ the pData buffer.
935 : int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
936 :
937 1 : if( !GetSrcDstWindow( 0, 0, nXSize, nYSize,
938 : nXSize, nYSize,
939 : &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
940 : &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ||
941 : nReqXOff != 0 || nReqYOff != 0 ||
942 : nReqXSize != poRasterBand->GetXSize() ||
943 : nReqYSize != poRasterBand->GetYSize())
944 : {
945 0 : return CE_Failure;
946 : }
947 :
948 : return poRasterBand->GetHistogram( dfMin, dfMax, nBuckets,
949 : panHistogram,
950 : bIncludeOutOfRange, bApproxOK,
951 1 : pfnProgress, pProgressData );
952 : }
953 :
954 : /************************************************************************/
955 : /* DatasetRasterIO() */
956 : /************************************************************************/
957 :
958 56 : CPLErr VRTSimpleSource::DatasetRasterIO(
959 : int nXOff, int nYOff, int nXSize, int nYSize,
960 : void * pData, int nBufXSize, int nBufYSize,
961 : GDALDataType eBufType,
962 : int nBandCount, int *panBandMap,
963 : int nPixelSpace, int nLineSpace, int nBandSpace)
964 : {
965 56 : if (!EQUAL(GetType(), "SimpleSource"))
966 : {
967 : CPLError(CE_Failure, CPLE_NotSupported,
968 0 : "DatasetRasterIO() not implemented for %s", GetType());
969 0 : return CE_Failure;
970 : }
971 :
972 : // The window we will actually request from the source raster band.
973 : int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
974 :
975 : // The window we will actual set _within_ the pData buffer.
976 : int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
977 :
978 56 : if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize,
979 : nBufXSize, nBufYSize,
980 : &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
981 : &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
982 : {
983 0 : return CE_None;
984 : }
985 :
986 56 : GDALDataset* poDS = poRasterBand->GetDataset();
987 56 : if (poDS == NULL)
988 0 : return CE_Failure;
989 :
990 : return poDS->RasterIO( GF_Read,
991 : nReqXOff, nReqYOff, nReqXSize, nReqYSize,
992 : ((unsigned char *) pData)
993 : + nOutXOff * nPixelSpace
994 : + nOutYOff * nLineSpace,
995 : nOutXSize, nOutYSize,
996 : eBufType, nBandCount, panBandMap,
997 56 : nPixelSpace, nLineSpace, nBandSpace );
998 : }
999 :
1000 : /************************************************************************/
1001 : /* ==================================================================== */
1002 : /* VRTAveragedSource */
1003 : /* ==================================================================== */
1004 : /************************************************************************/
1005 :
1006 : /************************************************************************/
1007 : /* VRTAveragedSource() */
1008 : /************************************************************************/
1009 :
1010 2 : VRTAveragedSource::VRTAveragedSource()
1011 : {
1012 2 : }
1013 :
1014 : /************************************************************************/
1015 : /* SerializeToXML() */
1016 : /************************************************************************/
1017 :
1018 0 : CPLXMLNode *VRTAveragedSource::SerializeToXML( const char *pszVRTPath )
1019 :
1020 : {
1021 0 : CPLXMLNode *psSrc = VRTSimpleSource::SerializeToXML( pszVRTPath );
1022 :
1023 0 : if( psSrc == NULL )
1024 0 : return NULL;
1025 :
1026 0 : CPLFree( psSrc->pszValue );
1027 0 : psSrc->pszValue = CPLStrdup( "AveragedSource" );
1028 :
1029 0 : return psSrc;
1030 : }
1031 :
1032 : /************************************************************************/
1033 : /* RasterIO() */
1034 : /************************************************************************/
1035 :
1036 : CPLErr
1037 50 : VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
1038 : void *pData, int nBufXSize, int nBufYSize,
1039 : GDALDataType eBufType,
1040 : int nPixelSpace, int nLineSpace )
1041 :
1042 : {
1043 : // The window we will actually request from the source raster band.
1044 : int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
1045 :
1046 : // The window we will actual set _within_ the pData buffer.
1047 : int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
1048 :
1049 50 : if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
1050 : &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
1051 : &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
1052 0 : return CE_None;
1053 :
1054 : /* -------------------------------------------------------------------- */
1055 : /* Allocate a temporary buffer to whole the full resolution */
1056 : /* data from the area of interest. */
1057 : /* -------------------------------------------------------------------- */
1058 : float *pafSrc;
1059 :
1060 50 : pafSrc = (float *) VSIMalloc3(sizeof(float), nReqXSize, nReqYSize);
1061 50 : if( pafSrc == NULL )
1062 : {
1063 : CPLError( CE_Failure, CPLE_OutOfMemory,
1064 0 : "Out of memory allocating working buffer in VRTAveragedSource::RasterIO()." );
1065 0 : return CE_Failure;
1066 : }
1067 :
1068 : /* -------------------------------------------------------------------- */
1069 : /* Load it. */
1070 : /* -------------------------------------------------------------------- */
1071 : CPLErr eErr;
1072 :
1073 : eErr = poRasterBand->RasterIO( GF_Read,
1074 : nReqXOff, nReqYOff, nReqXSize, nReqYSize,
1075 : pafSrc, nReqXSize, nReqYSize, GDT_Float32,
1076 50 : 0, 0 );
1077 :
1078 50 : if( eErr != CE_None )
1079 : {
1080 0 : VSIFree( pafSrc );
1081 0 : return eErr;
1082 : }
1083 :
1084 : /* -------------------------------------------------------------------- */
1085 : /* Do the averaging. */
1086 : /* -------------------------------------------------------------------- */
1087 100 : for( int iBufLine = nOutYOff; iBufLine < nOutYOff + nOutYSize; iBufLine++ )
1088 : {
1089 : double dfYDst;
1090 :
1091 50 : dfYDst = (iBufLine / (double) nBufYSize) * nYSize + nYOff;
1092 :
1093 1750 : for( int iBufPixel = nOutXOff;
1094 : iBufPixel < nOutXOff + nOutXSize;
1095 : iBufPixel++ )
1096 : {
1097 : double dfXDst;
1098 : double dfXSrcStart, dfXSrcEnd, dfYSrcStart, dfYSrcEnd;
1099 : int iXSrcStart, iYSrcStart, iXSrcEnd, iYSrcEnd;
1100 :
1101 1700 : dfXDst = (iBufPixel / (double) nBufXSize) * nXSize + nXOff;
1102 :
1103 : // Compute the source image rectangle needed for this pixel.
1104 1700 : DstToSrc( dfXDst, dfYDst, dfXSrcStart, dfYSrcStart );
1105 1700 : DstToSrc( dfXDst+1.0, dfYDst+1.0, dfXSrcEnd, dfYSrcEnd );
1106 :
1107 : // Convert to integers, assuming that the center of the source
1108 : // pixel must be in our rect to get included.
1109 1700 : if (dfXSrcEnd >= dfXSrcStart + 1)
1110 : {
1111 100 : iXSrcStart = (int) floor(dfXSrcStart+0.5);
1112 100 : iXSrcEnd = (int) floor(dfXSrcEnd+0.5);
1113 : }
1114 : else
1115 : {
1116 : /* If the resampling factor is less than 100%, the distance */
1117 : /* between the source pixel is < 1, so we stick to nearest */
1118 : /* neighbour */
1119 1600 : iXSrcStart = (int) floor(dfXSrcStart);
1120 1600 : iXSrcEnd = iXSrcStart + 1;
1121 : }
1122 1700 : if (dfYSrcEnd >= dfYSrcStart + 1)
1123 : {
1124 100 : iYSrcStart = (int) floor(dfYSrcStart+0.5);
1125 100 : iYSrcEnd = (int) floor(dfYSrcEnd+0.5);
1126 : }
1127 : else
1128 : {
1129 1600 : iYSrcStart = (int) floor(dfYSrcStart);
1130 1600 : iYSrcEnd = iYSrcStart + 1;
1131 : }
1132 :
1133 : // Transform into the coordinate system of the source *buffer*
1134 1700 : iXSrcStart -= nReqXOff;
1135 1700 : iYSrcStart -= nReqYOff;
1136 1700 : iXSrcEnd -= nReqXOff;
1137 1700 : iYSrcEnd -= nReqYOff;
1138 :
1139 1700 : double dfSum = 0.0;
1140 1700 : int nPixelCount = 0;
1141 :
1142 3500 : for( int iY = iYSrcStart; iY < iYSrcEnd; iY++ )
1143 : {
1144 1800 : if( iY < 0 || iY >= nReqYSize )
1145 0 : continue;
1146 :
1147 3800 : for( int iX = iXSrcStart; iX < iXSrcEnd; iX++ )
1148 : {
1149 2000 : if( iX < 0 || iX >= nReqXSize )
1150 0 : continue;
1151 :
1152 2000 : float fSampledValue = pafSrc[iX + iY * nReqXSize];
1153 2000 : if (CPLIsNan(fSampledValue))
1154 0 : continue;
1155 :
1156 2000 : if( bNoDataSet && ARE_REAL_EQUAL(fSampledValue, dfNoDataValue))
1157 0 : continue;
1158 :
1159 2000 : nPixelCount++;
1160 2000 : dfSum += pafSrc[iX + iY * nReqXSize];
1161 : }
1162 : }
1163 :
1164 1700 : if( nPixelCount == 0 )
1165 0 : continue;
1166 :
1167 : // Compute output value.
1168 1700 : float dfOutputValue = (float) (dfSum / nPixelCount);
1169 :
1170 : // Put it in the output buffer.
1171 : GByte *pDstLocation;
1172 :
1173 : pDstLocation = ((GByte *)pData)
1174 : + nPixelSpace * iBufPixel
1175 1700 : + nLineSpace * iBufLine;
1176 :
1177 1700 : if( eBufType == GDT_Byte )
1178 0 : *pDstLocation = (GByte) MIN(255,MAX(0,dfOutputValue + 0.5));
1179 : else
1180 : GDALCopyWords( &dfOutputValue, GDT_Float32, 4,
1181 1700 : pDstLocation, eBufType, 8, 1 );
1182 : }
1183 : }
1184 :
1185 50 : VSIFree( pafSrc );
1186 :
1187 50 : return CE_None;
1188 : }
1189 :
1190 : /************************************************************************/
1191 : /* GetMinimum() */
1192 : /************************************************************************/
1193 :
1194 0 : double VRTAveragedSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
1195 : {
1196 0 : *pbSuccess = FALSE;
1197 0 : return 0;
1198 : }
1199 :
1200 : /************************************************************************/
1201 : /* GetMaximum() */
1202 : /************************************************************************/
1203 :
1204 0 : double VRTAveragedSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
1205 : {
1206 0 : *pbSuccess = FALSE;
1207 0 : return 0;
1208 : }
1209 :
1210 : /************************************************************************/
1211 : /* ComputeRasterMinMax() */
1212 : /************************************************************************/
1213 :
1214 0 : CPLErr VRTAveragedSource::ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax )
1215 : {
1216 0 : return CE_Failure;
1217 : }
1218 :
1219 : /************************************************************************/
1220 : /* ComputeStatistics() */
1221 : /************************************************************************/
1222 :
1223 0 : CPLErr VRTAveragedSource::ComputeStatistics( int nXSize, int nYSize,
1224 : int bApproxOK,
1225 : double *pdfMin, double *pdfMax,
1226 : double *pdfMean, double *pdfStdDev,
1227 : GDALProgressFunc pfnProgress, void *pProgressData )
1228 : {
1229 0 : return CE_Failure;
1230 : }
1231 :
1232 : /************************************************************************/
1233 : /* GetHistogram() */
1234 : /************************************************************************/
1235 :
1236 0 : CPLErr VRTAveragedSource::GetHistogram( int nXSize, int nYSize,
1237 : double dfMin, double dfMax,
1238 : int nBuckets, int * panHistogram,
1239 : int bIncludeOutOfRange, int bApproxOK,
1240 : GDALProgressFunc pfnProgress, void *pProgressData )
1241 : {
1242 0 : return CE_Failure;
1243 : }
1244 :
1245 : /************************************************************************/
1246 : /* ==================================================================== */
1247 : /* VRTComplexSource */
1248 : /* ==================================================================== */
1249 : /************************************************************************/
1250 :
1251 : /************************************************************************/
1252 : /* VRTComplexSource() */
1253 : /************************************************************************/
1254 :
1255 61 : VRTComplexSource::VRTComplexSource()
1256 :
1257 : {
1258 61 : bDoScaling = FALSE;
1259 61 : dfScaleOff = 0.0;
1260 61 : dfScaleRatio = 1.0;
1261 :
1262 61 : bNoDataSet = FALSE;
1263 61 : dfNoDataValue = 0.0;
1264 :
1265 61 : padfLUTInputs = NULL;
1266 61 : padfLUTOutputs = NULL;
1267 61 : nLUTItemCount = 0;
1268 61 : nColorTableComponent = 0;
1269 61 : }
1270 :
1271 61 : VRTComplexSource::~VRTComplexSource()
1272 : {
1273 61 : if (padfLUTInputs)
1274 7 : VSIFree( padfLUTInputs );
1275 61 : if (padfLUTOutputs)
1276 7 : VSIFree( padfLUTOutputs );
1277 61 : }
1278 :
1279 : /************************************************************************/
1280 : /* SerializeToXML() */
1281 : /************************************************************************/
1282 :
1283 15 : CPLXMLNode *VRTComplexSource::SerializeToXML( const char *pszVRTPath )
1284 :
1285 : {
1286 15 : CPLXMLNode *psSrc = VRTSimpleSource::SerializeToXML( pszVRTPath );
1287 :
1288 15 : if( psSrc == NULL )
1289 0 : return NULL;
1290 :
1291 15 : CPLFree( psSrc->pszValue );
1292 15 : psSrc->pszValue = CPLStrdup( "ComplexSource" );
1293 :
1294 15 : if( bNoDataSet )
1295 : {
1296 8 : if (CPLIsNan(dfNoDataValue))
1297 0 : CPLSetXMLValue( psSrc, "NODATA", "nan");
1298 : else
1299 : CPLSetXMLValue( psSrc, "NODATA",
1300 8 : CPLSPrintf("%g", dfNoDataValue) );
1301 : }
1302 :
1303 15 : if( bDoScaling )
1304 : {
1305 : CPLSetXMLValue( psSrc, "ScaleOffset",
1306 0 : CPLSPrintf("%g", dfScaleOff) );
1307 : CPLSetXMLValue( psSrc, "ScaleRatio",
1308 0 : CPLSPrintf("%g", dfScaleRatio) );
1309 : }
1310 :
1311 15 : if ( nLUTItemCount )
1312 : {
1313 0 : CPLString osLUT = CPLString().Printf("%g:%g", padfLUTInputs[0], padfLUTOutputs[0]);
1314 : int i;
1315 0 : for ( i = 1; i < nLUTItemCount; i++ )
1316 0 : osLUT += CPLString().Printf(",%g:%g", padfLUTInputs[i], padfLUTOutputs[i]);
1317 0 : CPLSetXMLValue( psSrc, "LUT", osLUT );
1318 : }
1319 :
1320 15 : if ( nColorTableComponent )
1321 : {
1322 : CPLSetXMLValue( psSrc, "ColorTableComponent",
1323 7 : CPLSPrintf("%d", nColorTableComponent) );
1324 : }
1325 :
1326 15 : return psSrc;
1327 : }
1328 :
1329 : /************************************************************************/
1330 : /* XMLInit() */
1331 : /************************************************************************/
1332 :
1333 37 : CPLErr VRTComplexSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
1334 :
1335 : {
1336 : CPLErr eErr;
1337 :
1338 : /* -------------------------------------------------------------------- */
1339 : /* Do base initialization. */
1340 : /* -------------------------------------------------------------------- */
1341 37 : eErr = VRTSimpleSource::XMLInit( psSrc, pszVRTPath );
1342 37 : if( eErr != CE_None )
1343 0 : return eErr;
1344 :
1345 : /* -------------------------------------------------------------------- */
1346 : /* Complex parameters. */
1347 : /* -------------------------------------------------------------------- */
1348 37 : if( CPLGetXMLValue(psSrc, "ScaleOffset", NULL) != NULL
1349 : || CPLGetXMLValue(psSrc, "ScaleRatio", NULL) != NULL )
1350 : {
1351 1 : bDoScaling = TRUE;
1352 1 : dfScaleOff = atof(CPLGetXMLValue(psSrc, "ScaleOffset", "0") );
1353 1 : dfScaleRatio = atof(CPLGetXMLValue(psSrc, "ScaleRatio", "1") );
1354 : }
1355 :
1356 37 : if( CPLGetXMLValue(psSrc, "NODATA", NULL) != NULL )
1357 : {
1358 10 : bNoDataSet = TRUE;
1359 10 : dfNoDataValue = CPLAtofM(CPLGetXMLValue(psSrc, "NODATA", "0"));
1360 : }
1361 :
1362 37 : if( CPLGetXMLValue(psSrc, "LUT", NULL) != NULL )
1363 : {
1364 : int nIndex;
1365 7 : char **papszValues = CSLTokenizeString2(CPLGetXMLValue(psSrc, "LUT", ""), ",:", CSLT_ALLOWEMPTYTOKENS);
1366 :
1367 7 : if (nLUTItemCount)
1368 : {
1369 0 : if (padfLUTInputs)
1370 : {
1371 0 : VSIFree( padfLUTInputs );
1372 0 : padfLUTInputs = NULL;
1373 : }
1374 0 : if (padfLUTOutputs)
1375 : {
1376 0 : VSIFree( padfLUTOutputs );
1377 0 : padfLUTOutputs = NULL;
1378 : }
1379 0 : nLUTItemCount = 0;
1380 : }
1381 :
1382 7 : nLUTItemCount = CSLCount(papszValues) / 2;
1383 :
1384 7 : padfLUTInputs = (double *) VSIMalloc2(nLUTItemCount, sizeof(double));
1385 7 : if ( !padfLUTInputs )
1386 : {
1387 0 : CSLDestroy(papszValues);
1388 0 : nLUTItemCount = 0;
1389 0 : return CE_Failure;
1390 : }
1391 :
1392 7 : padfLUTOutputs = (double *) VSIMalloc2(nLUTItemCount, sizeof(double));
1393 7 : if ( !padfLUTOutputs )
1394 : {
1395 0 : CSLDestroy(papszValues);
1396 0 : VSIFree( padfLUTInputs );
1397 0 : padfLUTInputs = NULL;
1398 0 : nLUTItemCount = 0;
1399 0 : return CE_Failure;
1400 : }
1401 :
1402 71 : for ( nIndex = 0; nIndex < nLUTItemCount; nIndex++ )
1403 : {
1404 64 : padfLUTInputs[nIndex] = atof( papszValues[nIndex * 2] );
1405 64 : padfLUTOutputs[nIndex] = atof( papszValues[nIndex * 2 + 1] );
1406 :
1407 : // Enforce the requirement that the LUT input array is monotonically non-decreasing.
1408 64 : if ( nIndex > 0 && padfLUTInputs[nIndex] < padfLUTInputs[nIndex - 1] )
1409 : {
1410 0 : CSLDestroy(papszValues);
1411 0 : VSIFree( padfLUTInputs );
1412 0 : VSIFree( padfLUTOutputs );
1413 0 : padfLUTInputs = NULL;
1414 0 : padfLUTOutputs = NULL;
1415 0 : nLUTItemCount = 0;
1416 0 : return CE_Failure;
1417 : }
1418 : }
1419 :
1420 7 : CSLDestroy(papszValues);
1421 : }
1422 :
1423 37 : if( CPLGetXMLValue(psSrc, "ColorTableComponent", NULL) != NULL )
1424 : {
1425 14 : nColorTableComponent = atoi(CPLGetXMLValue(psSrc, "ColorTableComponent", "0"));
1426 : }
1427 :
1428 37 : return CE_None;
1429 : }
1430 :
1431 : /************************************************************************/
1432 : /* LookupValue() */
1433 : /************************************************************************/
1434 :
1435 : double
1436 58964 : VRTComplexSource::LookupValue( double dfInput )
1437 : {
1438 : // Find the index of the first element in the LUT input array that
1439 : // is not smaller than the input value.
1440 58964 : int i = std::lower_bound(padfLUTInputs, padfLUTInputs + nLUTItemCount, dfInput) - padfLUTInputs;
1441 :
1442 58964 : if (i == 0)
1443 0 : return padfLUTOutputs[0];
1444 :
1445 : // If the index is beyond the end of the LUT input array, the input
1446 : // value is larger than all the values in the array.
1447 58964 : if (i == nLUTItemCount)
1448 4 : return padfLUTOutputs[nLUTItemCount - 1];
1449 :
1450 58960 : if (padfLUTInputs[i] == dfInput)
1451 4859 : return padfLUTOutputs[i];
1452 :
1453 : // Otherwise, interpolate.
1454 108202 : return padfLUTOutputs[i - 1] + (dfInput - padfLUTInputs[i - 1]) *
1455 108202 : ((padfLUTOutputs[i] - padfLUTOutputs[i - 1]) / (padfLUTInputs[i] - padfLUTInputs[i - 1]));
1456 : }
1457 :
1458 : /************************************************************************/
1459 : /* RasterIO() */
1460 : /************************************************************************/
1461 :
1462 : CPLErr
1463 2097 : VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
1464 : void *pData, int nBufXSize, int nBufYSize,
1465 : GDALDataType eBufType,
1466 : int nPixelSpace, int nLineSpace )
1467 :
1468 : {
1469 : // The window we will actually request from the source raster band.
1470 : int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
1471 :
1472 : // The window we will actual set _within_ the pData buffer.
1473 : int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
1474 :
1475 2097 : if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
1476 : &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
1477 : &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
1478 0 : return CE_None;
1479 :
1480 : return RasterIOInternal(nReqXOff, nReqYOff, nReqXSize, nReqYSize,
1481 : ((GByte *)pData)
1482 : + nPixelSpace * nOutXOff
1483 : + nLineSpace * nOutYOff,
1484 : nOutXSize, nOutYSize,
1485 : eBufType,
1486 2097 : nPixelSpace, nLineSpace );
1487 : }
1488 :
1489 : /************************************************************************/
1490 : /* RasterIOInternal() */
1491 : /************************************************************************/
1492 :
1493 : /* nReqXOff, nReqYOff, nReqXSize, nReqYSize are expressed in source band */
1494 : /* referential */
1495 2317 : CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
1496 : int nReqXSize, int nReqYSize,
1497 : void *pData, int nOutXSize, int nOutYSize,
1498 : GDALDataType eBufType,
1499 : int nPixelSpace, int nLineSpace )
1500 : {
1501 : /* -------------------------------------------------------------------- */
1502 : /* Read into a temporary buffer. */
1503 : /* -------------------------------------------------------------------- */
1504 : float *pafData;
1505 : CPLErr eErr;
1506 2317 : GDALColorTable* poColorTable = NULL;
1507 2317 : int bIsComplex = GDALDataTypeIsComplex(eBufType);
1508 2317 : GDALDataType eWrkDataType = (bIsComplex) ? GDT_CFloat32 : GDT_Float32;
1509 2317 : int nWordSize = GDALGetDataTypeSize(eWrkDataType) / 8;
1510 2317 : int bNoDataSetAndNotNan = bNoDataSet && !CPLIsNan(dfNoDataValue);
1511 :
1512 2317 : if( bDoScaling && bNoDataSet == FALSE && dfScaleRatio == 0)
1513 : {
1514 : /* -------------------------------------------------------------------- */
1515 : /* Optimization when outputing a constant value */
1516 : /* (used by the -addalpha option of gdalbuildvrt) */
1517 : /* -------------------------------------------------------------------- */
1518 0 : pafData = NULL;
1519 : }
1520 : else
1521 : {
1522 2317 : pafData = (float *) VSIMalloc3(nOutXSize,nOutYSize,nWordSize);
1523 2317 : if (pafData == NULL)
1524 : {
1525 0 : CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
1526 0 : return CE_Failure;
1527 : }
1528 : eErr = poRasterBand->RasterIO( GF_Read,
1529 : nReqXOff, nReqYOff, nReqXSize, nReqYSize,
1530 : pafData, nOutXSize, nOutYSize, eWrkDataType,
1531 2317 : nWordSize, nWordSize * nOutXSize );
1532 2317 : if( eErr != CE_None )
1533 : {
1534 0 : CPLFree( pafData );
1535 0 : return eErr;
1536 : }
1537 :
1538 2317 : if (nColorTableComponent != 0)
1539 : {
1540 1610 : poColorTable = poRasterBand->GetColorTable();
1541 1610 : if (poColorTable == NULL)
1542 : {
1543 : CPLError(CE_Failure, CPLE_AppDefined,
1544 0 : "Source band has no color table.");
1545 0 : CPLFree( pafData );
1546 0 : return CE_Failure;
1547 : }
1548 : }
1549 : }
1550 :
1551 : /* -------------------------------------------------------------------- */
1552 : /* Selectively copy into output buffer with nodata masking, */
1553 : /* and/or scaling. */
1554 : /* -------------------------------------------------------------------- */
1555 : int iX, iY;
1556 :
1557 6867 : for( iY = 0; iY < nOutYSize; iY++ )
1558 : {
1559 1381656 : for( iX = 0; iX < nOutXSize; iX++ )
1560 : {
1561 : GByte *pDstLocation;
1562 :
1563 : pDstLocation = ((GByte *)pData)
1564 : + nPixelSpace * iX
1565 1377106 : + nLineSpace * iY;
1566 :
1567 2753409 : if (pafData && !bIsComplex)
1568 : {
1569 1377105 : float fResult = pafData[iX + iY * nOutXSize];
1570 1377105 : if( CPLIsNan(dfNoDataValue) && CPLIsNan(fResult) )
1571 20 : continue;
1572 1377085 : if( bNoDataSetAndNotNan && ARE_REAL_EQUAL(fResult, dfNoDataValue) )
1573 782 : continue;
1574 :
1575 1376303 : if (nColorTableComponent)
1576 : {
1577 1275780 : const GDALColorEntry* poEntry = poColorTable->GetColorEntry((int)fResult);
1578 1275780 : if (poEntry)
1579 : {
1580 1275780 : if (nColorTableComponent == 1)
1581 474978 : fResult = poEntry->c1;
1582 800802 : else if (nColorTableComponent == 2)
1583 320401 : fResult = poEntry->c2;
1584 480401 : else if (nColorTableComponent == 3)
1585 320401 : fResult = poEntry->c3;
1586 160000 : else if (nColorTableComponent == 4)
1587 160000 : fResult = poEntry->c4;
1588 : }
1589 : else
1590 : {
1591 : static int bHasWarned = FALSE;
1592 0 : if (!bHasWarned)
1593 : {
1594 0 : bHasWarned = TRUE;
1595 : CPLError(CE_Failure, CPLE_AppDefined,
1596 0 : "No entry %d.", (int)fResult);
1597 : }
1598 0 : continue;
1599 : }
1600 : }
1601 :
1602 1376303 : if( bDoScaling )
1603 10000 : fResult = (float) (fResult * dfScaleRatio + dfScaleOff);
1604 :
1605 1376303 : if (nLUTItemCount)
1606 58964 : fResult = (float) LookupValue( fResult );
1607 :
1608 1376303 : if( eBufType == GDT_Byte )
1609 660422 : *pDstLocation = (GByte) MIN(255,MAX(0,fResult + 0.5));
1610 : else
1611 : GDALCopyWords( &fResult, GDT_Float32, 0,
1612 715881 : pDstLocation, eBufType, 0, 1 );
1613 : }
1614 2 : else if (pafData && bIsComplex)
1615 : {
1616 : float afResult[2];
1617 1 : afResult[0] = pafData[2 * (iX + iY * nOutXSize)];
1618 1 : afResult[1] = pafData[2 * (iX + iY * nOutXSize) + 1];
1619 :
1620 : /* Do not use color table */
1621 :
1622 1 : if( bDoScaling )
1623 : {
1624 1 : afResult[0] = (float) (afResult[0] * dfScaleRatio + dfScaleOff);
1625 1 : afResult[1] = (float) (afResult[1] * dfScaleRatio + dfScaleOff);
1626 : }
1627 :
1628 : /* Do not use LUT */
1629 :
1630 1 : if( eBufType == GDT_Byte )
1631 0 : *pDstLocation = (GByte) MIN(255,MAX(0,afResult[0] + 0.5));
1632 : else
1633 : GDALCopyWords( afResult, GDT_CFloat32, 0,
1634 1 : pDstLocation, eBufType, 0, 1 );
1635 : }
1636 : else
1637 : {
1638 0 : float fResult = (float) dfScaleOff;
1639 :
1640 0 : if (nLUTItemCount)
1641 0 : fResult = (float) LookupValue( fResult );
1642 :
1643 0 : if( eBufType == GDT_Byte )
1644 0 : *pDstLocation = (GByte) MIN(255,MAX(0,fResult + 0.5));
1645 : else
1646 : GDALCopyWords( &fResult, GDT_Float32, 0,
1647 0 : pDstLocation, eBufType, 0, 1 );
1648 : }
1649 :
1650 : }
1651 : }
1652 :
1653 2317 : CPLFree( pafData );
1654 :
1655 2317 : return CE_None;
1656 : }
1657 :
1658 : /************************************************************************/
1659 : /* GetMinimum() */
1660 : /************************************************************************/
1661 :
1662 0 : double VRTComplexSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
1663 : {
1664 0 : if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
1665 : nLUTItemCount == 0 && nColorTableComponent == 0)
1666 : {
1667 0 : return VRTSimpleSource::GetMinimum(nXSize, nYSize, pbSuccess);
1668 : }
1669 :
1670 0 : *pbSuccess = FALSE;
1671 0 : return 0;
1672 : }
1673 :
1674 : /************************************************************************/
1675 : /* GetMaximum() */
1676 : /************************************************************************/
1677 :
1678 0 : double VRTComplexSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
1679 : {
1680 0 : if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
1681 : nLUTItemCount == 0 && nColorTableComponent == 0)
1682 : {
1683 0 : return VRTSimpleSource::GetMaximum(nXSize, nYSize, pbSuccess);
1684 : }
1685 :
1686 0 : *pbSuccess = FALSE;
1687 0 : return 0;
1688 : }
1689 :
1690 : /************************************************************************/
1691 : /* ComputeRasterMinMax() */
1692 : /************************************************************************/
1693 :
1694 0 : CPLErr VRTComplexSource::ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax )
1695 : {
1696 0 : if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
1697 : nLUTItemCount == 0 && nColorTableComponent == 0)
1698 : {
1699 0 : return VRTSimpleSource::ComputeRasterMinMax(nXSize, nYSize, bApproxOK, adfMinMax);
1700 : }
1701 :
1702 0 : return CE_Failure;
1703 : }
1704 :
1705 : /************************************************************************/
1706 : /* GetHistogram() */
1707 : /************************************************************************/
1708 :
1709 0 : CPLErr VRTComplexSource::GetHistogram( int nXSize, int nYSize,
1710 : double dfMin, double dfMax,
1711 : int nBuckets, int * panHistogram,
1712 : int bIncludeOutOfRange, int bApproxOK,
1713 : GDALProgressFunc pfnProgress, void *pProgressData )
1714 : {
1715 0 : if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
1716 : nLUTItemCount == 0 && nColorTableComponent == 0)
1717 : {
1718 : return VRTSimpleSource::GetHistogram(nXSize, nYSize,
1719 : dfMin, dfMax, nBuckets,
1720 : panHistogram,
1721 : bIncludeOutOfRange, bApproxOK,
1722 0 : pfnProgress, pProgressData);
1723 : }
1724 :
1725 0 : return CE_Failure;
1726 : }
1727 :
1728 : /************************************************************************/
1729 : /* ComputeStatistics() */
1730 : /************************************************************************/
1731 :
1732 0 : CPLErr VRTComplexSource::ComputeStatistics( int nXSize, int nYSize,
1733 : int bApproxOK,
1734 : double *pdfMin, double *pdfMax,
1735 : double *pdfMean, double *pdfStdDev,
1736 : GDALProgressFunc pfnProgress, void *pProgressData )
1737 : {
1738 0 : if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
1739 : nLUTItemCount == 0 && nColorTableComponent == 0)
1740 : {
1741 : return VRTSimpleSource::ComputeStatistics(nXSize, nYSize, bApproxOK, pdfMin, pdfMax,
1742 : pdfMean, pdfStdDev,
1743 0 : pfnProgress, pProgressData);
1744 : }
1745 :
1746 0 : return CE_Failure;
1747 : }
1748 :
1749 : /************************************************************************/
1750 : /* ==================================================================== */
1751 : /* VRTFuncSource */
1752 : /* ==================================================================== */
1753 : /************************************************************************/
1754 :
1755 : /************************************************************************/
1756 : /* VRTFuncSource() */
1757 : /************************************************************************/
1758 :
1759 0 : VRTFuncSource::VRTFuncSource()
1760 :
1761 : {
1762 0 : pfnReadFunc = NULL;
1763 0 : pCBData = NULL;
1764 0 : fNoDataValue = (float) VRT_NODATA_UNSET;
1765 0 : eType = GDT_Byte;
1766 0 : }
1767 :
1768 : /************************************************************************/
1769 : /* ~VRTFuncSource() */
1770 : /************************************************************************/
1771 :
1772 0 : VRTFuncSource::~VRTFuncSource()
1773 :
1774 : {
1775 0 : }
1776 :
1777 : /************************************************************************/
1778 : /* SerializeToXML() */
1779 : /************************************************************************/
1780 :
1781 0 : CPLXMLNode *VRTFuncSource::SerializeToXML( const char * pszVRTPath )
1782 :
1783 : {
1784 0 : return NULL;
1785 : }
1786 :
1787 : /************************************************************************/
1788 : /* RasterIO() */
1789 : /************************************************************************/
1790 :
1791 : CPLErr
1792 0 : VRTFuncSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
1793 : void *pData, int nBufXSize, int nBufYSize,
1794 : GDALDataType eBufType,
1795 : int nPixelSpace, int nLineSpace )
1796 :
1797 : {
1798 0 : if( nPixelSpace*8 == GDALGetDataTypeSize( eBufType )
1799 : && nLineSpace == nPixelSpace * nXSize
1800 : && nBufXSize == nXSize && nBufYSize == nYSize
1801 : && eBufType == eType )
1802 : {
1803 : return pfnReadFunc( pCBData,
1804 : nXOff, nYOff, nXSize, nYSize,
1805 0 : pData );
1806 : }
1807 : else
1808 : {
1809 : printf( "%d,%d %d,%d, %d,%d %d,%d %d,%d\n",
1810 : nPixelSpace*8, GDALGetDataTypeSize(eBufType),
1811 : nLineSpace, nPixelSpace * nXSize,
1812 : nBufXSize, nXSize,
1813 : nBufYSize, nYSize,
1814 0 : (int) eBufType, (int) eType );
1815 : CPLError( CE_Failure, CPLE_AppDefined,
1816 0 : "VRTFuncSource::RasterIO() - Irregular request." );
1817 0 : return CE_Failure;
1818 : }
1819 : }
1820 :
1821 : /************************************************************************/
1822 : /* GetMinimum() */
1823 : /************************************************************************/
1824 :
1825 0 : double VRTFuncSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
1826 : {
1827 0 : *pbSuccess = FALSE;
1828 0 : return 0;
1829 : }
1830 :
1831 : /************************************************************************/
1832 : /* GetMaximum() */
1833 : /************************************************************************/
1834 :
1835 0 : double VRTFuncSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
1836 : {
1837 0 : *pbSuccess = FALSE;
1838 0 : return 0;
1839 : }
1840 :
1841 : /************************************************************************/
1842 : /* ComputeRasterMinMax() */
1843 : /************************************************************************/
1844 :
1845 0 : CPLErr VRTFuncSource::ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax )
1846 : {
1847 0 : return CE_Failure;
1848 : }
1849 :
1850 : /************************************************************************/
1851 : /* ComputeStatistics() */
1852 : /************************************************************************/
1853 :
1854 0 : CPLErr VRTFuncSource::ComputeStatistics( int nXSize, int nYSize,
1855 : int bApproxOK,
1856 : double *pdfMin, double *pdfMax,
1857 : double *pdfMean, double *pdfStdDev,
1858 : GDALProgressFunc pfnProgress, void *pProgressData )
1859 : {
1860 0 : return CE_Failure;
1861 : }
1862 :
1863 : /************************************************************************/
1864 : /* GetHistogram() */
1865 : /************************************************************************/
1866 :
1867 0 : CPLErr VRTFuncSource::GetHistogram( int nXSize, int nYSize,
1868 : double dfMin, double dfMax,
1869 : int nBuckets, int * panHistogram,
1870 : int bIncludeOutOfRange, int bApproxOK,
1871 : GDALProgressFunc pfnProgress, void *pProgressData )
1872 : {
1873 0 : return CE_Failure;
1874 : }
1875 :
1876 : /************************************************************************/
1877 : /* VRTParseCoreSources() */
1878 : /************************************************************************/
1879 :
1880 456 : VRTSource *VRTParseCoreSources( CPLXMLNode *psChild, const char *pszVRTPath )
1881 :
1882 : {
1883 : VRTSource * poSource;
1884 :
1885 456 : if( EQUAL(psChild->pszValue,"AveragedSource")
1886 : || (EQUAL(psChild->pszValue,"SimpleSource")
1887 : && EQUALN(CPLGetXMLValue(psChild, "Resampling", "Nearest"),
1888 : "Aver",4)) )
1889 : {
1890 2 : poSource = new VRTAveragedSource();
1891 : }
1892 454 : else if( EQUAL(psChild->pszValue,"SimpleSource") )
1893 : {
1894 422 : poSource = new VRTSimpleSource();
1895 : }
1896 32 : else if( EQUAL(psChild->pszValue,"ComplexSource") )
1897 : {
1898 32 : poSource = new VRTComplexSource();
1899 : }
1900 : else
1901 : {
1902 : CPLError( CE_Failure, CPLE_AppDefined,
1903 0 : "VRTParseCoreSources() - Unknown source : %s", psChild->pszValue );
1904 0 : return NULL;
1905 : }
1906 :
1907 456 : if ( poSource->XMLInit( psChild, pszVRTPath ) == CE_None )
1908 355 : return poSource;
1909 :
1910 101 : delete poSource;
1911 101 : return NULL;
1912 : }
1913 :
|