1 : /******************************************************************************
2 : * $Id: vrtsources.cpp 17852 2009-10-18 11:15:09Z 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 <algorithm>
32 :
33 : #include "vrtdataset.h"
34 : #include "gdal_proxy.h"
35 : #include "cpl_minixml.h"
36 : #include "cpl_string.h"
37 :
38 : CPL_CVSID("$Id: vrtsources.cpp 17852 2009-10-18 11:15:09Z rouault $");
39 :
40 : /************************************************************************/
41 : /* ==================================================================== */
42 : /* VRTSource */
43 : /* ==================================================================== */
44 : /************************************************************************/
45 :
46 299 : VRTSource::~VRTSource()
47 : {
48 299 : }
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 299 : VRTSimpleSource::VRTSimpleSource()
70 :
71 : {
72 299 : poRasterBand = NULL;
73 299 : bNoDataSet = FALSE;
74 299 : }
75 :
76 : /************************************************************************/
77 : /* ~VRTSimpleSource() */
78 : /************************************************************************/
79 :
80 550 : VRTSimpleSource::~VRTSimpleSource()
81 :
82 : {
83 299 : if( poRasterBand != NULL && poRasterBand->GetDataset() != NULL )
84 : {
85 298 : if( poRasterBand->GetDataset()->GetShared() )
86 270 : GDALClose( (GDALDatasetH) poRasterBand->GetDataset() );
87 : else
88 28 : poRasterBand->GetDataset()->Dereference();
89 : }
90 550 : }
91 :
92 : /************************************************************************/
93 : /* SetSrcBand() */
94 : /************************************************************************/
95 :
96 112 : void VRTSimpleSource::SetSrcBand( GDALRasterBand *poNewSrcBand )
97 :
98 : {
99 112 : poRasterBand = poNewSrcBand;
100 112 : }
101 :
102 : /************************************************************************/
103 : /* SetSrcWindow() */
104 : /************************************************************************/
105 :
106 112 : void VRTSimpleSource::SetSrcWindow( int nNewXOff, int nNewYOff,
107 : int nNewXSize, int nNewYSize )
108 :
109 : {
110 112 : nSrcXOff = nNewXOff;
111 112 : nSrcYOff = nNewYOff;
112 112 : nSrcXSize = nNewXSize;
113 112 : nSrcYSize = nNewYSize;
114 112 : }
115 :
116 : /************************************************************************/
117 : /* SetDstWindow() */
118 : /************************************************************************/
119 :
120 112 : void VRTSimpleSource::SetDstWindow( int nNewXOff, int nNewYOff,
121 : int nNewXSize, int nNewYSize )
122 :
123 : {
124 112 : nDstXOff = nNewXOff;
125 112 : nDstYOff = nNewYOff;
126 112 : nDstXSize = nNewXSize;
127 112 : nDstYSize = nNewYSize;
128 112 : }
129 :
130 : /************************************************************************/
131 : /* SetNoDataValue() */
132 : /************************************************************************/
133 :
134 8 : void VRTSimpleSource::SetNoDataValue( double dfNewNoDataValue )
135 :
136 : {
137 8 : if( dfNewNoDataValue == VRT_NODATA_UNSET )
138 : {
139 0 : bNoDataSet = FALSE;
140 0 : dfNoDataValue = VRT_NODATA_UNSET;
141 : }
142 : else
143 : {
144 8 : bNoDataSet = TRUE;
145 8 : dfNoDataValue = dfNewNoDataValue;
146 : }
147 8 : }
148 :
149 : /************************************************************************/
150 : /* SerializeToXML() */
151 : /************************************************************************/
152 :
153 76 : CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
154 :
155 : {
156 : CPLXMLNode *psSrc;
157 : int bRelativeToVRT;
158 : const char *pszRelativePath;
159 : int nBlockXSize, nBlockYSize;
160 :
161 76 : if( poRasterBand == NULL )
162 0 : return NULL;
163 :
164 76 : GDALDataset *poDS = poRasterBand->GetDataset();
165 :
166 76 : if( poDS == NULL || poRasterBand->GetBand() < 1 )
167 0 : return NULL;
168 :
169 76 : psSrc = CPLCreateXMLNode( NULL, CXT_Element, "SimpleSource" );
170 :
171 : pszRelativePath =
172 76 : CPLExtractRelativePath( pszVRTPath, poDS->GetDescription(),
173 152 : &bRelativeToVRT );
174 :
175 76 : CPLSetXMLValue( psSrc, "SourceFilename", pszRelativePath );
176 :
177 : CPLCreateXMLNode(
178 : CPLCreateXMLNode( CPLGetXMLNode( psSrc, "SourceFilename" ),
179 : CXT_Attribute, "relativeToVRT" ),
180 76 : CXT_Text, bRelativeToVRT ? "1" : "0" );
181 :
182 : CPLSetXMLValue( psSrc, "SourceBand",
183 76 : CPLSPrintf("%d",poRasterBand->GetBand()) );
184 :
185 : /* Write a few additional useful properties of the dataset */
186 : /* so that we can use a proxy dataset when re-opening. See XMLInit() */
187 : /* below */
188 : CPLSetXMLValue( psSrc, "SourceProperties.#RasterXSize",
189 76 : CPLSPrintf("%d",poRasterBand->GetXSize()) );
190 : CPLSetXMLValue( psSrc, "SourceProperties.#RasterYSize",
191 76 : CPLSPrintf("%d",poRasterBand->GetYSize()) );
192 : CPLSetXMLValue( psSrc, "SourceProperties.#DataType",
193 76 : GDALGetDataTypeName( poRasterBand->GetRasterDataType() ) );
194 76 : poRasterBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
195 : CPLSetXMLValue( psSrc, "SourceProperties.#BlockXSize",
196 76 : CPLSPrintf("%d",nBlockXSize) );
197 : CPLSetXMLValue( psSrc, "SourceProperties.#BlockYSize",
198 76 : CPLSPrintf("%d",nBlockYSize) );
199 :
200 76 : if( nSrcXOff != -1
201 : || nSrcYOff != -1
202 : || nSrcXSize != -1
203 : || nSrcYSize != -1 )
204 : {
205 : CPLSetXMLValue( psSrc, "SrcRect.#xOff",
206 76 : CPLSPrintf( "%d", nSrcXOff ) );
207 : CPLSetXMLValue( psSrc, "SrcRect.#yOff",
208 76 : CPLSPrintf( "%d", nSrcYOff ) );
209 : CPLSetXMLValue( psSrc, "SrcRect.#xSize",
210 76 : CPLSPrintf( "%d", nSrcXSize ) );
211 : CPLSetXMLValue( psSrc, "SrcRect.#ySize",
212 76 : CPLSPrintf( "%d", nSrcYSize ) );
213 : }
214 :
215 76 : if( nDstXOff != -1
216 : || nDstYOff != -1
217 : || nDstXSize != -1
218 : || nDstYSize != -1 )
219 : {
220 76 : CPLSetXMLValue( psSrc, "DstRect.#xOff", CPLSPrintf( "%d", nDstXOff ) );
221 76 : CPLSetXMLValue( psSrc, "DstRect.#yOff", CPLSPrintf( "%d", nDstYOff ) );
222 76 : CPLSetXMLValue( psSrc, "DstRect.#xSize",CPLSPrintf( "%d", nDstXSize ));
223 76 : CPLSetXMLValue( psSrc, "DstRect.#ySize",CPLSPrintf( "%d", nDstYSize ));
224 : }
225 :
226 76 : return psSrc;
227 : }
228 :
229 : /************************************************************************/
230 : /* XMLInit() */
231 : /************************************************************************/
232 :
233 187 : CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
234 :
235 : {
236 : /* -------------------------------------------------------------------- */
237 : /* Prepare filename. */
238 : /* -------------------------------------------------------------------- */
239 187 : char *pszSrcDSName = NULL;
240 187 : CPLXMLNode* psSourceFileNameNode = CPLGetXMLNode(psSrc,"SourceFilename");
241 : const char *pszFilename =
242 187 : psSourceFileNameNode ? CPLGetXMLValue(psSourceFileNameNode,NULL, NULL) : NULL;
243 :
244 187 : if( pszFilename == NULL )
245 : {
246 : CPLError( CE_Warning, CPLE_AppDefined,
247 0 : "Missing <SourceFilename> element in VRTRasterBand." );
248 0 : return CE_Failure;
249 : }
250 :
251 187 : if( pszVRTPath != NULL
252 : && atoi(CPLGetXMLValue( psSourceFileNameNode, "relativetoVRT", "0")) )
253 : {
254 : pszSrcDSName = CPLStrdup(
255 171 : CPLProjectRelativeFilename( pszVRTPath, pszFilename ) );
256 : }
257 : else
258 16 : pszSrcDSName = CPLStrdup( pszFilename );
259 :
260 :
261 187 : int nSrcBand = atoi(CPLGetXMLValue(psSrc,"SourceBand","1"));
262 :
263 : /* Newly generated VRT will have RasterXSize, RasterYSize, DataType, */
264 : /* BlockXSize, BlockYSize tags, so that we don't have actually to */
265 : /* open the real dataset immediately, but we can use a proxy dataset */
266 : /* instead. This is particularly usefull when dealing with huge VRT */
267 : /* For example, a VRT with the world coverage of DTED0 (25594 files) */
268 187 : CPLXMLNode* psSrcProperties = CPLGetXMLNode(psSrc,"SourceProperties");
269 187 : int nRasterXSize = 0, nRasterYSize =0;
270 187 : GDALDataType eDataType = (GDALDataType)-1;
271 187 : int nBlockXSize = 0, nBlockYSize = 0;
272 187 : if (psSrcProperties)
273 : {
274 84 : nRasterXSize = atoi(CPLGetXMLValue(psSrcProperties,"RasterXSize","0"));
275 84 : nRasterYSize = atoi(CPLGetXMLValue(psSrcProperties,"RasterYSize","0"));
276 84 : const char *pszDataType = CPLGetXMLValue(psSrcProperties, "DataType", NULL);
277 84 : if( pszDataType != NULL )
278 : {
279 174 : for( int iType = 0; iType < GDT_TypeCount; iType++ )
280 : {
281 174 : const char *pszThisName = GDALGetDataTypeName((GDALDataType)iType);
282 :
283 174 : if( pszThisName != NULL && EQUAL(pszDataType,pszThisName) )
284 : {
285 84 : eDataType = (GDALDataType) iType;
286 84 : break;
287 : }
288 : }
289 : }
290 84 : nBlockXSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockXSize","0"));
291 84 : nBlockYSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockYSize","0"));
292 : }
293 :
294 : GDALDataset *poSrcDS;
295 290 : if (nRasterXSize == 0 || nRasterYSize == 0 || eDataType == (GDALDataType)-1 ||
296 : nBlockXSize == 0 || nBlockYSize == 0)
297 : {
298 : /* -------------------------------------------------------------------- */
299 : /* Open the file (shared). */
300 : /* -------------------------------------------------------------------- */
301 103 : poSrcDS = (GDALDataset *) GDALOpenShared( pszSrcDSName, GA_ReadOnly );
302 : }
303 : else
304 : {
305 : /* -------------------------------------------------------------------- */
306 : /* Create a proxy dataset */
307 : /* -------------------------------------------------------------------- */
308 : int i;
309 84 : GDALProxyPoolDataset* proxyDS = new GDALProxyPoolDataset(pszSrcDSName, nRasterXSize, nRasterYSize, GA_ReadOnly, TRUE);
310 84 : poSrcDS = proxyDS;
311 :
312 : /* Only the information of rasterBand nSrcBand will be accurate */
313 : /* but that's OK since we only use that band afterwards */
314 174 : for(i=1;i<=nSrcBand;i++)
315 90 : proxyDS->AddSrcBandDescription(eDataType, nBlockXSize, nBlockYSize);
316 : }
317 :
318 187 : CPLFree( pszSrcDSName );
319 :
320 187 : if( poSrcDS == NULL )
321 1 : return CE_Failure;
322 :
323 : /* -------------------------------------------------------------------- */
324 : /* Get the raster band. */
325 : /* -------------------------------------------------------------------- */
326 :
327 186 : poRasterBand = poSrcDS->GetRasterBand(nSrcBand);
328 186 : if( poRasterBand == NULL )
329 0 : return CE_Failure;
330 :
331 : /* -------------------------------------------------------------------- */
332 : /* Set characteristics. */
333 : /* -------------------------------------------------------------------- */
334 186 : CPLXMLNode* psSrcRect = CPLGetXMLNode(psSrc,"SrcRect");
335 186 : if (psSrcRect)
336 : {
337 182 : nSrcXOff = atoi(CPLGetXMLValue(psSrcRect,"xOff","-1"));
338 182 : nSrcYOff = atoi(CPLGetXMLValue(psSrcRect,"yOff","-1"));
339 182 : nSrcXSize = atoi(CPLGetXMLValue(psSrcRect,"xSize","-1"));
340 182 : nSrcYSize = atoi(CPLGetXMLValue(psSrcRect,"ySize","-1"));
341 : }
342 : else
343 : {
344 4 : nSrcXOff = nSrcYOff = nSrcXSize = nSrcYSize = -1;
345 : }
346 :
347 186 : CPLXMLNode* psDstRect = CPLGetXMLNode(psSrc,"DstRect");
348 186 : if (psDstRect)
349 : {
350 182 : nDstXOff = atoi(CPLGetXMLValue(psDstRect,"xOff","-1"));
351 182 : nDstYOff = atoi(CPLGetXMLValue(psDstRect,"yOff","-1"));
352 182 : nDstXSize = atoi(CPLGetXMLValue(psDstRect,"xSize","-1"));
353 182 : nDstYSize = atoi(CPLGetXMLValue(psDstRect,"ySize","-1"));
354 : }
355 : else
356 : {
357 4 : nDstXOff = nDstYOff = nDstXSize = nDstYSize = -1;
358 : }
359 :
360 186 : return CE_None;
361 : }
362 :
363 : /************************************************************************/
364 : /* GetFileList() */
365 : /************************************************************************/
366 :
367 0 : void VRTSimpleSource::GetFileList(char*** ppapszFileList, int *pnSize,
368 : int *pnMaxSize, CPLHashSet* hSetFiles)
369 : {
370 : const char* pszFilename;
371 0 : if (poRasterBand != NULL && poRasterBand->GetDataset() != NULL &&
372 0 : (pszFilename = poRasterBand->GetDataset()->GetDescription()) != NULL)
373 : {
374 : /* -------------------------------------------------------------------- */
375 : /* Is the filename even a real filesystem object? */
376 : /* -------------------------------------------------------------------- */
377 : VSIStatBufL sStat;
378 0 : if( VSIStatL( pszFilename, &sStat ) != 0 )
379 0 : return;
380 :
381 : /* -------------------------------------------------------------------- */
382 : /* Is it already in the list ? */
383 : /* -------------------------------------------------------------------- */
384 0 : if( CPLHashSetLookup(hSetFiles, pszFilename) != NULL )
385 0 : return;
386 :
387 : /* -------------------------------------------------------------------- */
388 : /* Grow array if necessary */
389 : /* -------------------------------------------------------------------- */
390 0 : if (*pnSize + 1 >= *pnMaxSize)
391 : {
392 0 : *pnMaxSize = 2 + 2 * (*pnMaxSize);
393 : *ppapszFileList = (char **) CPLRealloc(
394 0 : *ppapszFileList, sizeof(char*) * (*pnMaxSize) );
395 : }
396 :
397 : /* -------------------------------------------------------------------- */
398 : /* Add the string to the list */
399 : /* -------------------------------------------------------------------- */
400 0 : (*ppapszFileList)[*pnSize] = CPLStrdup(pszFilename);
401 0 : (*ppapszFileList)[(*pnSize + 1)] = NULL;
402 0 : CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
403 :
404 0 : (*pnSize) ++;
405 : }
406 : }
407 :
408 : /************************************************************************/
409 : /* SrcToDst() */
410 : /* */
411 : /* Note: this is a no-op if the dst window is -1,-1,-1,-1. */
412 : /************************************************************************/
413 :
414 770 : void VRTSimpleSource::SrcToDst( double dfX, double dfY,
415 : double &dfXOut, double &dfYOut )
416 :
417 : {
418 770 : dfXOut = ((dfX - nSrcXOff) / nSrcXSize) * nDstXSize + nDstXOff;
419 770 : dfYOut = ((dfY - nSrcYOff) / nSrcYSize) * nDstYSize + nDstYOff;
420 770 : }
421 :
422 : /************************************************************************/
423 : /* DstToSrc() */
424 : /* */
425 : /* Note: this is a no-op if the dst window is -1,-1,-1,-1. */
426 : /************************************************************************/
427 :
428 3400 : void VRTSimpleSource::DstToSrc( double dfX, double dfY,
429 : double &dfXOut, double &dfYOut )
430 :
431 : {
432 3400 : dfXOut = ((dfX - nDstXOff) / nDstXSize) * nSrcXSize + nSrcXOff;
433 3400 : dfYOut = ((dfY - nDstYOff) / nDstYSize) * nSrcYSize + nSrcYOff;
434 3400 : }
435 :
436 : /************************************************************************/
437 : /* GetSrcDstWindow() */
438 : /************************************************************************/
439 :
440 : int
441 6562 : VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
442 : int nBufXSize, int nBufYSize,
443 : int *pnReqXOff, int *pnReqYOff,
444 : int *pnReqXSize, int *pnReqYSize,
445 : int *pnOutXOff, int *pnOutYOff,
446 : int *pnOutXSize, int *pnOutYSize )
447 :
448 : {
449 : int bDstWinSet = nDstXOff != -1 || nDstXSize != -1
450 6562 : || nDstYOff != -1 || nDstYSize != -1;
451 :
452 : #ifdef DEBUG
453 : int bSrcWinSet = nSrcXOff != -1 || nSrcXSize != -1
454 : || nSrcYOff != -1 || nSrcYSize != -1;
455 :
456 : if( bSrcWinSet != bDstWinSet )
457 : {
458 : return FALSE;
459 : }
460 : #endif
461 :
462 : /* -------------------------------------------------------------------- */
463 : /* If the input window completely misses the portion of the */
464 : /* virtual dataset provided by this source we have nothing to do. */
465 : /* -------------------------------------------------------------------- */
466 6562 : if( bDstWinSet )
467 : {
468 6540 : if( nXOff >= nDstXOff + nDstXSize
469 : || nYOff >= nDstYOff + nDstYSize
470 : || nXOff + nXSize < nDstXOff
471 : || nYOff + nYSize < nDstYOff )
472 400 : return FALSE;
473 : }
474 :
475 : /* -------------------------------------------------------------------- */
476 : /* This request window corresponds to the whole output buffer. */
477 : /* -------------------------------------------------------------------- */
478 6162 : *pnOutXOff = 0;
479 6162 : *pnOutYOff = 0;
480 6162 : *pnOutXSize = nBufXSize;
481 6162 : *pnOutYSize = nBufYSize;
482 :
483 : /* -------------------------------------------------------------------- */
484 : /* If the input window extents outside the portion of the on */
485 : /* the virtual file that this source can set, then clip down */
486 : /* the requested window. */
487 : /* -------------------------------------------------------------------- */
488 6162 : int bModifiedX = FALSE, bModifiedY = FALSE;
489 6162 : int nRXOff = nXOff;
490 6162 : int nRYOff = nYOff;
491 6162 : int nRXSize = nXSize;
492 6162 : int nRYSize = nYSize;
493 :
494 :
495 6162 : if( bDstWinSet )
496 : {
497 6140 : if( nRXOff < nDstXOff )
498 : {
499 174 : nRXSize = nRXSize + nRXOff - nDstXOff;
500 174 : nRXOff = nDstXOff;
501 174 : bModifiedX = TRUE;
502 : }
503 :
504 6140 : if( nRYOff < nDstYOff )
505 : {
506 16 : nRYSize = nRYSize + nRYOff - nDstYOff;
507 16 : nRYOff = nDstYOff;
508 16 : bModifiedY = TRUE;
509 : }
510 :
511 6140 : if( nRXOff + nRXSize > nDstXOff + nDstXSize )
512 : {
513 235 : nRXSize = nDstXOff + nDstXSize - nRXOff;
514 235 : bModifiedX = TRUE;
515 : }
516 :
517 6140 : if( nRYOff + nRYSize > nDstYOff + nDstYSize )
518 : {
519 0 : nRYSize = nDstYOff + nDstYSize - nRYOff;
520 0 : bModifiedY = TRUE;
521 : }
522 : }
523 :
524 : /* -------------------------------------------------------------------- */
525 : /* Translate requested region in virtual file into the source */
526 : /* band coordinates. */
527 : /* -------------------------------------------------------------------- */
528 6162 : double dfScaleX = nSrcXSize / (double) nDstXSize;
529 6162 : double dfScaleY = nSrcYSize / (double) nDstYSize;
530 :
531 6162 : *pnReqXOff = (int) floor((nRXOff - nDstXOff) * dfScaleX + nSrcXOff);
532 6162 : *pnReqYOff = (int) floor((nRYOff - nDstYOff) * dfScaleY + nSrcYOff);
533 :
534 6162 : *pnReqXSize = (int) floor(nRXSize * dfScaleX + 0.5);
535 6162 : *pnReqYSize = (int) floor(nRYSize * dfScaleY + 0.5);
536 :
537 : /* -------------------------------------------------------------------- */
538 : /* Clamp within the bounds of the available source data. */
539 : /* -------------------------------------------------------------------- */
540 6162 : if( *pnReqXOff < 0 )
541 : {
542 0 : *pnReqXSize += *pnReqXOff;
543 0 : *pnReqXOff = 0;
544 :
545 0 : bModifiedX = TRUE;
546 : }
547 :
548 6162 : if( *pnReqYOff < 0 )
549 : {
550 0 : *pnReqYSize += *pnReqYOff;
551 0 : *pnReqYOff = 0;
552 0 : bModifiedY = TRUE;
553 : }
554 :
555 6162 : if( *pnReqXSize == 0 )
556 0 : *pnReqXSize = 1;
557 6162 : if( *pnReqYSize == 0 )
558 16 : *pnReqYSize = 1;
559 :
560 6162 : if( *pnReqXOff + *pnReqXSize > poRasterBand->GetXSize() )
561 : {
562 2 : *pnReqXSize = poRasterBand->GetXSize() - *pnReqXOff;
563 2 : bModifiedX = TRUE;
564 : }
565 :
566 6162 : if( *pnReqYOff + *pnReqYSize > poRasterBand->GetYSize() )
567 : {
568 2 : *pnReqYSize = poRasterBand->GetYSize() - *pnReqYOff;
569 2 : bModifiedY = TRUE;
570 : }
571 :
572 : /* -------------------------------------------------------------------- */
573 : /* Don't do anything if the requesting region is completely off */
574 : /* the source image. */
575 : /* -------------------------------------------------------------------- */
576 6162 : if( *pnReqXOff >= poRasterBand->GetXSize()
577 : || *pnReqYOff >= poRasterBand->GetYSize()
578 : || *pnReqXSize <= 0 || *pnReqYSize <= 0 )
579 : {
580 0 : return FALSE;
581 : }
582 :
583 : /* -------------------------------------------------------------------- */
584 : /* If we haven't had to modify the source rectangle, then the */
585 : /* destination rectangle must be the whole region. */
586 : /* -------------------------------------------------------------------- */
587 6162 : if( !bModifiedX && !bModifiedY )
588 5777 : return TRUE;
589 :
590 : /* -------------------------------------------------------------------- */
591 : /* Now transform this possibly reduced request back into the */
592 : /* destination buffer coordinates in case the output region is */
593 : /* less than the whole buffer. */
594 : /* -------------------------------------------------------------------- */
595 : double dfDstULX, dfDstULY, dfDstLRX, dfDstLRY;
596 : double dfScaleWinToBufX, dfScaleWinToBufY;
597 :
598 385 : SrcToDst( (double) *pnReqXOff, (double) *pnReqYOff, dfDstULX, dfDstULY );
599 : SrcToDst( *pnReqXOff + *pnReqXSize, *pnReqYOff + *pnReqYSize,
600 385 : dfDstLRX, dfDstLRY );
601 :
602 385 : if( bModifiedX )
603 : {
604 385 : dfScaleWinToBufX = nBufXSize / (double) nXSize;
605 :
606 385 : *pnOutXOff = (int) ((dfDstULX - nXOff) * dfScaleWinToBufX+0.001);
607 : *pnOutXSize = (int) ((dfDstLRX - nXOff) * dfScaleWinToBufX+0.001)
608 385 : - *pnOutXOff;
609 :
610 385 : *pnOutXOff = MAX(0,*pnOutXOff);
611 385 : if( *pnOutXOff + *pnOutXSize > nBufXSize )
612 0 : *pnOutXSize = nBufXSize - *pnOutXOff;
613 : }
614 :
615 385 : if( bModifiedY )
616 : {
617 18 : dfScaleWinToBufY = nBufYSize / (double) nYSize;
618 :
619 18 : *pnOutYOff = (int) ((dfDstULY - nYOff) * dfScaleWinToBufY+0.001);
620 : *pnOutYSize = (int) ((dfDstLRY - nYOff) * dfScaleWinToBufY+0.001)
621 18 : - *pnOutYOff;
622 :
623 18 : *pnOutYOff = MAX(0,*pnOutYOff);
624 18 : if( *pnOutYOff + *pnOutYSize > nBufYSize )
625 16 : *pnOutYSize = nBufYSize - *pnOutYOff;
626 : }
627 :
628 385 : if( *pnOutXSize < 1 || *pnOutYSize < 1 )
629 16 : return FALSE;
630 : else
631 369 : return TRUE;
632 : }
633 :
634 : /************************************************************************/
635 : /* RasterIO() */
636 : /************************************************************************/
637 :
638 : CPLErr
639 4586 : VRTSimpleSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
640 : void *pData, int nBufXSize, int nBufYSize,
641 : GDALDataType eBufType,
642 : int nPixelSpace, int nLineSpace )
643 :
644 : {
645 : // The window we will actually request from the source raster band.
646 : int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
647 :
648 : // The window we will actual set _within_ the pData buffer.
649 : int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
650 :
651 4586 : if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize,
652 : nBufXSize, nBufYSize,
653 : &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
654 : &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
655 : {
656 416 : return CE_None;
657 : }
658 :
659 : /* -------------------------------------------------------------------- */
660 : /* Actually perform the IO request. */
661 : /* -------------------------------------------------------------------- */
662 : CPLErr eErr;
663 :
664 : eErr =
665 : poRasterBand->RasterIO( GF_Read,
666 : nReqXOff, nReqYOff, nReqXSize, nReqYSize,
667 : ((unsigned char *) pData)
668 : + nOutXOff * nPixelSpace
669 : + nOutYOff * nLineSpace,
670 : nOutXSize, nOutYSize,
671 4170 : eBufType, nPixelSpace, nLineSpace );
672 :
673 4170 : return eErr;
674 : }
675 :
676 : /************************************************************************/
677 : /* ==================================================================== */
678 : /* VRTAveragedSource */
679 : /* ==================================================================== */
680 : /************************************************************************/
681 :
682 : /************************************************************************/
683 : /* VRTAveragedSource() */
684 : /************************************************************************/
685 :
686 2 : VRTAveragedSource::VRTAveragedSource()
687 : {
688 2 : }
689 :
690 : /************************************************************************/
691 : /* SerializeToXML() */
692 : /************************************************************************/
693 :
694 0 : CPLXMLNode *VRTAveragedSource::SerializeToXML( const char *pszVRTPath )
695 :
696 : {
697 0 : CPLXMLNode *psSrc = VRTSimpleSource::SerializeToXML( pszVRTPath );
698 :
699 0 : if( psSrc == NULL )
700 0 : return NULL;
701 :
702 0 : CPLFree( psSrc->pszValue );
703 0 : psSrc->pszValue = CPLStrdup( "AveragedSource" );
704 :
705 0 : return psSrc;
706 : }
707 :
708 : /************************************************************************/
709 : /* RasterIO() */
710 : /************************************************************************/
711 :
712 : CPLErr
713 50 : VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
714 : void *pData, int nBufXSize, int nBufYSize,
715 : GDALDataType eBufType,
716 : int nPixelSpace, int nLineSpace )
717 :
718 : {
719 : // The window we will actually request from the source raster band.
720 : int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
721 :
722 : // The window we will actual set _within_ the pData buffer.
723 : int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
724 :
725 50 : if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
726 : &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
727 : &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
728 0 : return CE_None;
729 :
730 : /* -------------------------------------------------------------------- */
731 : /* Allocate a temporary buffer to whole the full resolution */
732 : /* data from the area of interest. */
733 : /* -------------------------------------------------------------------- */
734 : float *pafSrc;
735 :
736 50 : pafSrc = (float *) VSIMalloc3(sizeof(float), nReqXSize, nReqYSize);
737 50 : if( pafSrc == NULL )
738 : {
739 : CPLError( CE_Failure, CPLE_OutOfMemory,
740 0 : "Out of memory allocating working buffer in VRTAveragedSource::RasterIO()." );
741 0 : return CE_Failure;
742 : }
743 :
744 : /* -------------------------------------------------------------------- */
745 : /* Load it. */
746 : /* -------------------------------------------------------------------- */
747 : CPLErr eErr;
748 :
749 : eErr = poRasterBand->RasterIO( GF_Read,
750 : nReqXOff, nReqYOff, nReqXSize, nReqYSize,
751 : pafSrc, nReqXSize, nReqYSize, GDT_Float32,
752 50 : 0, 0 );
753 :
754 50 : if( eErr != CE_None )
755 : {
756 0 : VSIFree( pafSrc );
757 0 : return eErr;
758 : }
759 :
760 : /* -------------------------------------------------------------------- */
761 : /* Do the averaging. */
762 : /* -------------------------------------------------------------------- */
763 100 : for( int iBufLine = nOutYOff; iBufLine < nOutYOff + nOutYSize; iBufLine++ )
764 : {
765 : double dfYDst;
766 :
767 50 : dfYDst = (iBufLine / (double) nBufYSize) * nYSize + nYOff;
768 :
769 1750 : for( int iBufPixel = nOutXOff;
770 : iBufPixel < nOutXOff + nOutXSize;
771 : iBufPixel++ )
772 : {
773 : double dfXDst;
774 : double dfXSrcStart, dfXSrcEnd, dfYSrcStart, dfYSrcEnd;
775 : int iXSrcStart, iYSrcStart, iXSrcEnd, iYSrcEnd;
776 :
777 1700 : dfXDst = (iBufPixel / (double) nBufXSize) * nXSize + nXOff;
778 :
779 : // Compute the source image rectangle needed for this pixel.
780 1700 : DstToSrc( dfXDst, dfYDst, dfXSrcStart, dfYSrcStart );
781 1700 : DstToSrc( dfXDst+1.0, dfYDst+1.0, dfXSrcEnd, dfYSrcEnd );
782 :
783 : // Convert to integers, assuming that the center of the source
784 : // pixel must be in our rect to get included.
785 1700 : if (dfXSrcEnd >= dfXSrcStart + 1)
786 : {
787 100 : iXSrcStart = (int) floor(dfXSrcStart+0.5);
788 100 : iXSrcEnd = (int) floor(dfXSrcEnd+0.5);
789 : }
790 : else
791 : {
792 : /* If the resampling factor is less than 100%, the distance */
793 : /* between the source pixel is < 1, so we stick to nearest */
794 : /* neighbour */
795 1600 : iXSrcStart = (int) floor(dfXSrcStart);
796 1600 : iXSrcEnd = iXSrcStart + 1;
797 : }
798 1700 : if (dfYSrcEnd >= dfYSrcStart + 1)
799 : {
800 100 : iYSrcStart = (int) floor(dfYSrcStart+0.5);
801 100 : iYSrcEnd = (int) floor(dfYSrcEnd+0.5);
802 : }
803 : else
804 : {
805 1600 : iYSrcStart = (int) floor(dfYSrcStart);
806 1600 : iYSrcEnd = iYSrcStart + 1;
807 : }
808 :
809 : // Transform into the coordinate system of the source *buffer*
810 1700 : iXSrcStart -= nReqXOff;
811 1700 : iYSrcStart -= nReqYOff;
812 1700 : iXSrcEnd -= nReqXOff;
813 1700 : iYSrcEnd -= nReqYOff;
814 :
815 1700 : double dfSum = 0.0;
816 1700 : int nPixelCount = 0;
817 :
818 3500 : for( int iY = iYSrcStart; iY < iYSrcEnd; iY++ )
819 : {
820 1800 : if( iY < 0 || iY >= nReqYSize )
821 0 : continue;
822 :
823 3800 : for( int iX = iXSrcStart; iX < iXSrcEnd; iX++ )
824 : {
825 2000 : if( iX < 0 || iX >= nReqXSize )
826 0 : continue;
827 :
828 2000 : float fSampledValue = pafSrc[iX + iY * nReqXSize];
829 :
830 2000 : if( bNoDataSet
831 : && ABS(fSampledValue-dfNoDataValue) < 0.0001 )
832 0 : continue;
833 :
834 2000 : nPixelCount++;
835 2000 : dfSum += pafSrc[iX + iY * nReqXSize];
836 : }
837 : }
838 :
839 1700 : if( nPixelCount == 0 )
840 0 : continue;
841 :
842 : // Compute output value.
843 1700 : float dfOutputValue = (float) (dfSum / nPixelCount);
844 :
845 : // Put it in the output buffer.
846 : GByte *pDstLocation;
847 :
848 : pDstLocation = ((GByte *)pData)
849 : + nPixelSpace * iBufPixel
850 1700 : + nLineSpace * iBufLine;
851 :
852 1700 : if( eBufType == GDT_Byte )
853 0 : *pDstLocation = (GByte) MIN(255,MAX(0,dfOutputValue + 0.5));
854 : else
855 : GDALCopyWords( &dfOutputValue, GDT_Float32, 4,
856 1700 : pDstLocation, eBufType, 8, 1 );
857 : }
858 : }
859 :
860 50 : VSIFree( pafSrc );
861 :
862 50 : return CE_None;
863 : }
864 :
865 : /************************************************************************/
866 : /* ==================================================================== */
867 : /* VRTComplexSource */
868 : /* ==================================================================== */
869 : /************************************************************************/
870 :
871 : /************************************************************************/
872 : /* VRTComplexSource() */
873 : /************************************************************************/
874 :
875 46 : VRTComplexSource::VRTComplexSource()
876 :
877 : {
878 46 : bDoScaling = FALSE;
879 46 : dfScaleOff = 0.0;
880 46 : dfScaleRatio = 1.0;
881 :
882 46 : bNoDataSet = FALSE;
883 46 : dfNoDataValue = 0.0;
884 :
885 46 : padfLUTInputs = NULL;
886 46 : padfLUTOutputs = NULL;
887 46 : nLUTItemCount = 0;
888 46 : nColorTableComponent = 0;
889 46 : }
890 :
891 87 : VRTComplexSource::~VRTComplexSource()
892 : {
893 46 : if (padfLUTInputs)
894 1 : VSIFree( padfLUTInputs );
895 46 : if (padfLUTOutputs)
896 1 : VSIFree( padfLUTOutputs );
897 87 : }
898 :
899 : /************************************************************************/
900 : /* SerializeToXML() */
901 : /************************************************************************/
902 :
903 15 : CPLXMLNode *VRTComplexSource::SerializeToXML( const char *pszVRTPath )
904 :
905 : {
906 15 : CPLXMLNode *psSrc = VRTSimpleSource::SerializeToXML( pszVRTPath );
907 :
908 15 : if( psSrc == NULL )
909 0 : return NULL;
910 :
911 15 : CPLFree( psSrc->pszValue );
912 15 : psSrc->pszValue = CPLStrdup( "ComplexSource" );
913 :
914 15 : if( bNoDataSet )
915 : {
916 : CPLSetXMLValue( psSrc, "NODATA",
917 8 : CPLSPrintf("%g", dfNoDataValue) );
918 : }
919 :
920 15 : if( bDoScaling )
921 : {
922 : CPLSetXMLValue( psSrc, "ScaleOffset",
923 0 : CPLSPrintf("%g", dfScaleOff) );
924 : CPLSetXMLValue( psSrc, "ScaleRatio",
925 0 : CPLSPrintf("%g", dfScaleRatio) );
926 : }
927 :
928 15 : if ( nLUTItemCount )
929 : {
930 0 : CPLString osLUT = CPLString().Printf("%g:%g", padfLUTInputs[0], padfLUTOutputs[0]);
931 : int i;
932 0 : for ( i = 1; i < nLUTItemCount; i++ )
933 0 : osLUT += CPLString().Printf(",%g:%g", padfLUTInputs[i], padfLUTOutputs[i]);
934 0 : CPLSetXMLValue( psSrc, "LUT", osLUT );
935 : }
936 :
937 15 : if ( nColorTableComponent )
938 : {
939 : CPLSetXMLValue( psSrc, "ColorTableComponent",
940 7 : CPLSPrintf("%d", nColorTableComponent) );
941 : }
942 :
943 15 : return psSrc;
944 : }
945 :
946 : /************************************************************************/
947 : /* XMLInit() */
948 : /************************************************************************/
949 :
950 28 : CPLErr VRTComplexSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
951 :
952 : {
953 : CPLErr eErr;
954 :
955 : /* -------------------------------------------------------------------- */
956 : /* Do base initialization. */
957 : /* -------------------------------------------------------------------- */
958 28 : eErr = VRTSimpleSource::XMLInit( psSrc, pszVRTPath );
959 28 : if( eErr != CE_None )
960 0 : return eErr;
961 :
962 : /* -------------------------------------------------------------------- */
963 : /* Complex parameters. */
964 : /* -------------------------------------------------------------------- */
965 28 : if( CPLGetXMLValue(psSrc, "ScaleOffset", NULL) != NULL
966 : || CPLGetXMLValue(psSrc, "ScaleRatio", NULL) != NULL )
967 : {
968 0 : bDoScaling = TRUE;
969 0 : dfScaleOff = atof(CPLGetXMLValue(psSrc, "ScaleOffset", "0") );
970 0 : dfScaleRatio = atof(CPLGetXMLValue(psSrc, "ScaleRatio", "1") );
971 : }
972 :
973 28 : if( CPLGetXMLValue(psSrc, "NODATA", NULL) != NULL )
974 : {
975 8 : bNoDataSet = TRUE;
976 8 : dfNoDataValue = atof(CPLGetXMLValue(psSrc, "NODATA", "0"));
977 : }
978 :
979 28 : if( CPLGetXMLValue(psSrc, "LUT", NULL) != NULL )
980 : {
981 : int nIndex;
982 1 : char **papszValues = CSLTokenizeString2(CPLGetXMLValue(psSrc, "LUT", ""), ",:", CSLT_ALLOWEMPTYTOKENS);
983 :
984 1 : if (nLUTItemCount)
985 : {
986 0 : if (padfLUTInputs)
987 : {
988 0 : VSIFree( padfLUTInputs );
989 0 : padfLUTInputs = NULL;
990 : }
991 0 : if (padfLUTOutputs)
992 : {
993 0 : VSIFree( padfLUTOutputs );
994 0 : padfLUTOutputs = NULL;
995 : }
996 0 : nLUTItemCount = 0;
997 : }
998 :
999 1 : nLUTItemCount = CSLCount(papszValues) / 2;
1000 :
1001 1 : padfLUTInputs = (double *) VSIMalloc2(nLUTItemCount, sizeof(double));
1002 1 : if ( !padfLUTInputs )
1003 : {
1004 0 : CSLDestroy(papszValues);
1005 0 : nLUTItemCount = 0;
1006 0 : return CE_Failure;
1007 : }
1008 :
1009 1 : padfLUTOutputs = (double *) VSIMalloc2(nLUTItemCount, sizeof(double));
1010 1 : if ( !padfLUTOutputs )
1011 : {
1012 0 : CSLDestroy(papszValues);
1013 0 : VSIFree( padfLUTInputs );
1014 0 : padfLUTInputs = NULL;
1015 0 : nLUTItemCount = 0;
1016 0 : return CE_Failure;
1017 : }
1018 :
1019 8 : for ( nIndex = 0; nIndex < nLUTItemCount; nIndex++ )
1020 : {
1021 7 : padfLUTInputs[nIndex] = atof( papszValues[nIndex * 2] );
1022 7 : padfLUTOutputs[nIndex] = atof( papszValues[nIndex * 2 + 1] );
1023 :
1024 : // Enforce the requirement that the LUT input array is monotonically non-decreasing.
1025 7 : if ( nIndex > 0 && padfLUTInputs[nIndex] < padfLUTInputs[nIndex - 1] )
1026 : {
1027 0 : CSLDestroy(papszValues);
1028 0 : VSIFree( padfLUTInputs );
1029 0 : VSIFree( padfLUTOutputs );
1030 0 : padfLUTInputs = NULL;
1031 0 : padfLUTOutputs = NULL;
1032 0 : nLUTItemCount = 0;
1033 0 : return CE_Failure;
1034 : }
1035 : }
1036 :
1037 1 : CSLDestroy(papszValues);
1038 : }
1039 :
1040 28 : if( CPLGetXMLValue(psSrc, "ColorTableComponent", NULL) != NULL )
1041 : {
1042 14 : nColorTableComponent = atoi(CPLGetXMLValue(psSrc, "ColorTableComponent", "0"));
1043 : }
1044 :
1045 28 : return CE_None;
1046 : }
1047 :
1048 : /************************************************************************/
1049 : /* LookupValue() */
1050 : /************************************************************************/
1051 :
1052 : double
1053 400 : VRTComplexSource::LookupValue( double dfInput )
1054 : {
1055 : // Find the index of the first element in the LUT input array that
1056 : // is not smaller than the input value.
1057 400 : int i = std::lower_bound(padfLUTInputs, padfLUTInputs + nLUTItemCount, dfInput) - padfLUTInputs;
1058 :
1059 400 : if (i == 0)
1060 0 : return padfLUTOutputs[0];
1061 :
1062 : // If the index is beyond the end of the LUT input array, the input
1063 : // value is larger than all the values in the array.
1064 400 : if (i == nLUTItemCount)
1065 4 : return padfLUTOutputs[nLUTItemCount - 1];
1066 :
1067 396 : if (padfLUTInputs[i] == dfInput)
1068 0 : return padfLUTOutputs[i];
1069 :
1070 : // Otherwise, interpolate.
1071 792 : return padfLUTOutputs[i - 1] + (dfInput - padfLUTInputs[i - 1]) *
1072 792 : ((padfLUTOutputs[i] - padfLUTOutputs[i - 1]) / (padfLUTInputs[i] - padfLUTInputs[i - 1]));
1073 : }
1074 :
1075 : /************************************************************************/
1076 : /* RasterIO() */
1077 : /************************************************************************/
1078 :
1079 : CPLErr
1080 1926 : VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
1081 : void *pData, int nBufXSize, int nBufYSize,
1082 : GDALDataType eBufType,
1083 : int nPixelSpace, int nLineSpace )
1084 :
1085 : {
1086 : // The window we will actually request from the source raster band.
1087 : int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
1088 :
1089 : // The window we will actual set _within_ the pData buffer.
1090 : int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
1091 :
1092 1926 : if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
1093 : &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
1094 : &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
1095 0 : return CE_None;
1096 :
1097 :
1098 : /* -------------------------------------------------------------------- */
1099 : /* Read into a temporary buffer. */
1100 : /* -------------------------------------------------------------------- */
1101 : float *pafData;
1102 : CPLErr eErr;
1103 1926 : GDALColorTable* poColorTable = NULL;
1104 :
1105 1926 : if( bDoScaling && bNoDataSet == FALSE && dfScaleRatio == 0)
1106 : {
1107 : /* -------------------------------------------------------------------- */
1108 : /* Optimization when outputing a constant value */
1109 : /* (used by the -addalpha option of gdalbuildvrt) */
1110 : /* -------------------------------------------------------------------- */
1111 0 : pafData = NULL;
1112 : }
1113 : else
1114 : {
1115 1926 : pafData = (float *) CPLMalloc(nOutXSize*nOutYSize*sizeof(float));
1116 : eErr = poRasterBand->RasterIO( GF_Read,
1117 : nReqXOff, nReqYOff, nReqXSize, nReqYSize,
1118 : pafData, nOutXSize, nOutYSize, GDT_Float32,
1119 1926 : sizeof(float), sizeof(float) * nOutXSize );
1120 1926 : if( eErr != CE_None )
1121 : {
1122 0 : CPLFree( pafData );
1123 0 : return eErr;
1124 : }
1125 :
1126 1926 : if (nColorTableComponent != 0)
1127 : {
1128 1606 : poColorTable = poRasterBand->GetColorTable();
1129 1606 : if (poColorTable == NULL)
1130 : {
1131 : CPLError(CE_Failure, CPLE_AppDefined,
1132 0 : "Source band has no color table.");
1133 0 : return CE_Failure;
1134 : }
1135 : }
1136 : }
1137 :
1138 : /* -------------------------------------------------------------------- */
1139 : /* Selectively copy into output buffer with nodata masking, */
1140 : /* and/or scaling. */
1141 : /* -------------------------------------------------------------------- */
1142 : int iX, iY;
1143 :
1144 5536 : for( iY = 0; iY < nOutYSize; iY++ )
1145 : {
1146 1157370 : for( iX = 0; iX < nOutXSize; iX++ )
1147 : {
1148 : float fResult;
1149 :
1150 1153760 : if (pafData)
1151 : {
1152 1153760 : fResult = pafData[iX + iY * nOutXSize];
1153 1153760 : if( bNoDataSet && fResult == dfNoDataValue )
1154 782 : continue;
1155 :
1156 1152978 : if (nColorTableComponent)
1157 : {
1158 1121200 : const GDALColorEntry* poEntry = poColorTable->GetColorEntry((int)fResult);
1159 1121200 : if (poEntry)
1160 : {
1161 1121200 : if (nColorTableComponent == 1)
1162 320400 : fResult = poEntry->c1;
1163 800800 : else if (nColorTableComponent == 2)
1164 320400 : fResult = poEntry->c2;
1165 480400 : else if (nColorTableComponent == 3)
1166 320400 : fResult = poEntry->c3;
1167 160000 : else if (nColorTableComponent == 4)
1168 160000 : fResult = poEntry->c4;
1169 : }
1170 : else
1171 : {
1172 : CPLError(CE_Failure, CPLE_AppDefined,
1173 0 : "No entry %d.", (int)fResult);
1174 0 : return CE_Failure;
1175 : }
1176 : }
1177 :
1178 1152978 : if( bDoScaling )
1179 0 : fResult = (float) (fResult * dfScaleRatio + dfScaleOff);
1180 : }
1181 : else
1182 : {
1183 0 : fResult = (float) dfScaleOff;
1184 : }
1185 :
1186 1152978 : if (nLUTItemCount)
1187 400 : fResult = (float) LookupValue( fResult );
1188 :
1189 : GByte *pDstLocation;
1190 :
1191 : pDstLocation = ((GByte *)pData)
1192 : + nPixelSpace * (iX + nOutXOff)
1193 1152978 : + nLineSpace * (iY + nOutYOff);
1194 :
1195 1152978 : if( eBufType == GDT_Byte )
1196 481200 : *pDstLocation = (GByte) MIN(255,MAX(0,fResult + 0.5));
1197 : else
1198 : GDALCopyWords( &fResult, GDT_Float32, 4,
1199 671778 : pDstLocation, eBufType, 8, 1 );
1200 :
1201 : }
1202 : }
1203 :
1204 1926 : CPLFree( pafData );
1205 :
1206 1926 : return CE_None;
1207 : }
1208 :
1209 : /************************************************************************/
1210 : /* ==================================================================== */
1211 : /* VRTFuncSource */
1212 : /* ==================================================================== */
1213 : /************************************************************************/
1214 :
1215 : /************************************************************************/
1216 : /* VRTFuncSource() */
1217 : /************************************************************************/
1218 :
1219 0 : VRTFuncSource::VRTFuncSource()
1220 :
1221 : {
1222 0 : pfnReadFunc = NULL;
1223 0 : pCBData = NULL;
1224 0 : fNoDataValue = (float) VRT_NODATA_UNSET;
1225 0 : eType = GDT_Byte;
1226 0 : }
1227 :
1228 : /************************************************************************/
1229 : /* ~VRTFuncSource() */
1230 : /************************************************************************/
1231 :
1232 0 : VRTFuncSource::~VRTFuncSource()
1233 :
1234 : {
1235 0 : }
1236 :
1237 : /************************************************************************/
1238 : /* SerializeToXML() */
1239 : /************************************************************************/
1240 :
1241 0 : CPLXMLNode *VRTFuncSource::SerializeToXML( const char * pszVRTPath )
1242 :
1243 : {
1244 0 : return NULL;
1245 : }
1246 :
1247 : /************************************************************************/
1248 : /* RasterIO() */
1249 : /************************************************************************/
1250 :
1251 : CPLErr
1252 0 : VRTFuncSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
1253 : void *pData, int nBufXSize, int nBufYSize,
1254 : GDALDataType eBufType,
1255 : int nPixelSpace, int nLineSpace )
1256 :
1257 : {
1258 0 : if( nPixelSpace*8 == GDALGetDataTypeSize( eBufType )
1259 : && nLineSpace == nPixelSpace * nXSize
1260 : && nBufXSize == nXSize && nBufYSize == nYSize
1261 : && eBufType == eType )
1262 : {
1263 : return pfnReadFunc( pCBData,
1264 : nXOff, nYOff, nXSize, nYSize,
1265 0 : pData );
1266 : }
1267 : else
1268 : {
1269 : printf( "%d,%d %d,%d, %d,%d %d,%d %d,%d\n",
1270 : nPixelSpace*8, GDALGetDataTypeSize(eBufType),
1271 : nLineSpace, nPixelSpace * nXSize,
1272 : nBufXSize, nXSize,
1273 : nBufYSize, nYSize,
1274 0 : (int) eBufType, (int) eType );
1275 : CPLError( CE_Failure, CPLE_AppDefined,
1276 0 : "VRTFuncSource::RasterIO() - Irregular request." );
1277 0 : return CE_Failure;
1278 : }
1279 : }
1280 :
1281 : /************************************************************************/
1282 : /* VRTParseCoreSources() */
1283 : /************************************************************************/
1284 :
1285 182 : VRTSource *VRTParseCoreSources( CPLXMLNode *psChild, const char *pszVRTPath )
1286 :
1287 : {
1288 : VRTSource * poSource;
1289 :
1290 182 : if( EQUAL(psChild->pszValue,"AveragedSource")
1291 : || (EQUAL(psChild->pszValue,"SimpleSource")
1292 : && EQUALN(CPLGetXMLValue(psChild, "Resampling", "Nearest"),
1293 : "Aver",4)) )
1294 : {
1295 2 : poSource = new VRTAveragedSource();
1296 : }
1297 180 : else if( EQUAL(psChild->pszValue,"SimpleSource") )
1298 : {
1299 157 : poSource = new VRTSimpleSource();
1300 : }
1301 23 : else if( EQUAL(psChild->pszValue,"ComplexSource") )
1302 : {
1303 23 : poSource = new VRTComplexSource();
1304 : }
1305 : else
1306 : {
1307 : CPLError( CE_Failure, CPLE_AppDefined,
1308 0 : "VRTParseCoreSources() - Unknown source : %s", psChild->pszValue );
1309 0 : return NULL;
1310 : }
1311 :
1312 182 : if ( poSource->XMLInit( psChild, pszVRTPath ) == CE_None )
1313 181 : return poSource;
1314 :
1315 1 : delete poSource;
1316 1 : return NULL;
1317 : }
1318 :
|