1 : /******************************************************************************
2 : * $Id: vrtsources.cpp 19692 2010-05-13 17:16:55Z 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 19692 2010-05-13 17:16:55Z rouault $");
39 :
40 : /************************************************************************/
41 : /* ==================================================================== */
42 : /* VRTSource */
43 : /* ==================================================================== */
44 : /************************************************************************/
45 :
46 339 : VRTSource::~VRTSource()
47 : {
48 339 : }
49 :
50 : /************************************************************************/
51 : /* GetFileList() */
52 : /************************************************************************/
53 :
54 : void VRTSource::GetFileList(char*** ppapszFileList, int *pnSize,
55 0 : int *pnMaxSize, CPLHashSet* hSetFiles)
56 : {
57 0 : }
58 :
59 : /************************************************************************/
60 : /* ==================================================================== */
61 : /* VRTSimpleSource */
62 : /* ==================================================================== */
63 : /************************************************************************/
64 :
65 : /************************************************************************/
66 : /* VRTSimpleSource() */
67 : /************************************************************************/
68 :
69 339 : VRTSimpleSource::VRTSimpleSource()
70 :
71 : {
72 339 : poRasterBand = NULL;
73 339 : bNoDataSet = FALSE;
74 339 : }
75 :
76 : /************************************************************************/
77 : /* ~VRTSimpleSource() */
78 : /************************************************************************/
79 :
80 339 : VRTSimpleSource::~VRTSimpleSource()
81 :
82 : {
83 339 : if( poRasterBand != NULL && poRasterBand->GetDataset() != NULL )
84 : {
85 338 : if( poRasterBand->GetDataset()->GetShared() )
86 312 : GDALClose( (GDALDatasetH) poRasterBand->GetDataset() );
87 : else
88 26 : poRasterBand->GetDataset()->Dereference();
89 : }
90 339 : }
91 :
92 : /************************************************************************/
93 : /* SetSrcBand() */
94 : /************************************************************************/
95 :
96 137 : void VRTSimpleSource::SetSrcBand( GDALRasterBand *poNewSrcBand )
97 :
98 : {
99 137 : poRasterBand = poNewSrcBand;
100 137 : }
101 :
102 : /************************************************************************/
103 : /* SetSrcWindow() */
104 : /************************************************************************/
105 :
106 : void VRTSimpleSource::SetSrcWindow( int nNewXOff, int nNewYOff,
107 137 : int nNewXSize, int nNewYSize )
108 :
109 : {
110 137 : nSrcXOff = nNewXOff;
111 137 : nSrcYOff = nNewYOff;
112 137 : nSrcXSize = nNewXSize;
113 137 : nSrcYSize = nNewYSize;
114 137 : }
115 :
116 : /************************************************************************/
117 : /* SetDstWindow() */
118 : /************************************************************************/
119 :
120 : void VRTSimpleSource::SetDstWindow( int nNewXOff, int nNewYOff,
121 137 : int nNewXSize, int nNewYSize )
122 :
123 : {
124 137 : nDstXOff = nNewXOff;
125 137 : nDstYOff = nNewYOff;
126 137 : nDstXSize = nNewXSize;
127 137 : nDstYSize = nNewYSize;
128 137 : }
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 78 : CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
154 :
155 : {
156 : CPLXMLNode *psSrc;
157 : int bRelativeToVRT;
158 : const char *pszRelativePath;
159 : int nBlockXSize, nBlockYSize;
160 :
161 78 : if( poRasterBand == NULL )
162 0 : return NULL;
163 :
164 78 : GDALDataset *poDS = poRasterBand->GetDataset();
165 :
166 78 : if( poDS == NULL || poRasterBand->GetBand() < 1 )
167 0 : return NULL;
168 :
169 78 : psSrc = CPLCreateXMLNode( NULL, CXT_Element, "SimpleSource" );
170 :
171 : pszRelativePath =
172 : CPLExtractRelativePath( pszVRTPath, poDS->GetDescription(),
173 78 : &bRelativeToVRT );
174 :
175 78 : CPLSetXMLValue( psSrc, "SourceFilename", pszRelativePath );
176 :
177 : CPLCreateXMLNode(
178 : CPLCreateXMLNode( CPLGetXMLNode( psSrc, "SourceFilename" ),
179 : CXT_Attribute, "relativeToVRT" ),
180 78 : CXT_Text, bRelativeToVRT ? "1" : "0" );
181 :
182 : CPLSetXMLValue( psSrc, "SourceBand",
183 78 : 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 78 : CPLSPrintf("%d",poRasterBand->GetXSize()) );
190 : CPLSetXMLValue( psSrc, "SourceProperties.#RasterYSize",
191 78 : CPLSPrintf("%d",poRasterBand->GetYSize()) );
192 : CPLSetXMLValue( psSrc, "SourceProperties.#DataType",
193 78 : GDALGetDataTypeName( poRasterBand->GetRasterDataType() ) );
194 78 : poRasterBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
195 : CPLSetXMLValue( psSrc, "SourceProperties.#BlockXSize",
196 78 : CPLSPrintf("%d",nBlockXSize) );
197 : CPLSetXMLValue( psSrc, "SourceProperties.#BlockYSize",
198 78 : CPLSPrintf("%d",nBlockYSize) );
199 :
200 78 : if( nSrcXOff != -1
201 : || nSrcYOff != -1
202 : || nSrcXSize != -1
203 : || nSrcYSize != -1 )
204 : {
205 : CPLSetXMLValue( psSrc, "SrcRect.#xOff",
206 78 : CPLSPrintf( "%d", nSrcXOff ) );
207 : CPLSetXMLValue( psSrc, "SrcRect.#yOff",
208 78 : CPLSPrintf( "%d", nSrcYOff ) );
209 : CPLSetXMLValue( psSrc, "SrcRect.#xSize",
210 78 : CPLSPrintf( "%d", nSrcXSize ) );
211 : CPLSetXMLValue( psSrc, "SrcRect.#ySize",
212 78 : CPLSPrintf( "%d", nSrcYSize ) );
213 : }
214 :
215 78 : if( nDstXOff != -1
216 : || nDstYOff != -1
217 : || nDstXSize != -1
218 : || nDstYSize != -1 )
219 : {
220 78 : CPLSetXMLValue( psSrc, "DstRect.#xOff", CPLSPrintf( "%d", nDstXOff ) );
221 78 : CPLSetXMLValue( psSrc, "DstRect.#yOff", CPLSPrintf( "%d", nDstYOff ) );
222 78 : CPLSetXMLValue( psSrc, "DstRect.#xSize",CPLSPrintf( "%d", nDstXSize ));
223 78 : CPLSetXMLValue( psSrc, "DstRect.#ySize",CPLSPrintf( "%d", nDstYSize ));
224 : }
225 :
226 78 : return psSrc;
227 : }
228 :
229 : /************************************************************************/
230 : /* XMLInit() */
231 : /************************************************************************/
232 :
233 202 : CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
234 :
235 : {
236 : /* -------------------------------------------------------------------- */
237 : /* Prepare filename. */
238 : /* -------------------------------------------------------------------- */
239 202 : char *pszSrcDSName = NULL;
240 202 : CPLXMLNode* psSourceFileNameNode = CPLGetXMLNode(psSrc,"SourceFilename");
241 : const char *pszFilename =
242 202 : psSourceFileNameNode ? CPLGetXMLValue(psSourceFileNameNode,NULL, NULL) : NULL;
243 :
244 202 : 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 202 : if( pszVRTPath != NULL
252 : && atoi(CPLGetXMLValue( psSourceFileNameNode, "relativetoVRT", "0")) )
253 : {
254 : pszSrcDSName = CPLStrdup(
255 177 : CPLProjectRelativeFilename( pszVRTPath, pszFilename ) );
256 : }
257 : else
258 25 : pszSrcDSName = CPLStrdup( pszFilename );
259 :
260 :
261 202 : 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 202 : CPLXMLNode* psSrcProperties = CPLGetXMLNode(psSrc,"SourceProperties");
269 202 : int nRasterXSize = 0, nRasterYSize =0;
270 202 : GDALDataType eDataType = (GDALDataType)-1;
271 202 : int nBlockXSize = 0, nBlockYSize = 0;
272 202 : if (psSrcProperties)
273 : {
274 95 : nRasterXSize = atoi(CPLGetXMLValue(psSrcProperties,"RasterXSize","0"));
275 95 : nRasterYSize = atoi(CPLGetXMLValue(psSrcProperties,"RasterYSize","0"));
276 95 : const char *pszDataType = CPLGetXMLValue(psSrcProperties, "DataType", NULL);
277 95 : if( pszDataType != NULL )
278 : {
279 218 : for( int iType = 0; iType < GDT_TypeCount; iType++ )
280 : {
281 218 : const char *pszThisName = GDALGetDataTypeName((GDALDataType)iType);
282 :
283 218 : if( pszThisName != NULL && EQUAL(pszDataType,pszThisName) )
284 : {
285 95 : eDataType = (GDALDataType) iType;
286 95 : break;
287 : }
288 : }
289 : }
290 95 : nBlockXSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockXSize","0"));
291 95 : nBlockYSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockYSize","0"));
292 : }
293 :
294 : GDALDataset *poSrcDS;
295 309 : if (nRasterXSize == 0 || nRasterYSize == 0 || eDataType == (GDALDataType)-1 ||
296 : nBlockXSize == 0 || nBlockYSize == 0)
297 : {
298 : /* -------------------------------------------------------------------- */
299 : /* Open the file (shared). */
300 : /* -------------------------------------------------------------------- */
301 107 : poSrcDS = (GDALDataset *) GDALOpenShared( pszSrcDSName, GA_ReadOnly );
302 : }
303 : else
304 : {
305 : /* -------------------------------------------------------------------- */
306 : /* Create a proxy dataset */
307 : /* -------------------------------------------------------------------- */
308 : int i;
309 95 : GDALProxyPoolDataset* proxyDS = new GDALProxyPoolDataset(pszSrcDSName, nRasterXSize, nRasterYSize, GA_ReadOnly, TRUE);
310 95 : 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 196 : for(i=1;i<=nSrcBand;i++)
315 101 : proxyDS->AddSrcBandDescription(eDataType, nBlockXSize, nBlockYSize);
316 : }
317 :
318 202 : CPLFree( pszSrcDSName );
319 :
320 202 : if( poSrcDS == NULL )
321 1 : return CE_Failure;
322 :
323 : /* -------------------------------------------------------------------- */
324 : /* Get the raster band. */
325 : /* -------------------------------------------------------------------- */
326 :
327 201 : poRasterBand = poSrcDS->GetRasterBand(nSrcBand);
328 201 : if( poRasterBand == NULL )
329 0 : return CE_Failure;
330 :
331 : /* -------------------------------------------------------------------- */
332 : /* Set characteristics. */
333 : /* -------------------------------------------------------------------- */
334 201 : CPLXMLNode* psSrcRect = CPLGetXMLNode(psSrc,"SrcRect");
335 201 : if (psSrcRect)
336 : {
337 194 : nSrcXOff = atoi(CPLGetXMLValue(psSrcRect,"xOff","-1"));
338 194 : nSrcYOff = atoi(CPLGetXMLValue(psSrcRect,"yOff","-1"));
339 194 : nSrcXSize = atoi(CPLGetXMLValue(psSrcRect,"xSize","-1"));
340 194 : nSrcYSize = atoi(CPLGetXMLValue(psSrcRect,"ySize","-1"));
341 : }
342 : else
343 : {
344 7 : nSrcXOff = nSrcYOff = nSrcXSize = nSrcYSize = -1;
345 : }
346 :
347 201 : CPLXMLNode* psDstRect = CPLGetXMLNode(psSrc,"DstRect");
348 201 : if (psDstRect)
349 : {
350 194 : nDstXOff = atoi(CPLGetXMLValue(psDstRect,"xOff","-1"));
351 194 : nDstYOff = atoi(CPLGetXMLValue(psDstRect,"yOff","-1"));
352 194 : nDstXSize = atoi(CPLGetXMLValue(psDstRect,"xSize","-1"));
353 194 : nDstYSize = atoi(CPLGetXMLValue(psDstRect,"ySize","-1"));
354 : }
355 : else
356 : {
357 7 : nDstXOff = nDstYOff = nDstXSize = nDstYSize = -1;
358 : }
359 :
360 201 : return CE_None;
361 : }
362 :
363 : /************************************************************************/
364 : /* GetFileList() */
365 : /************************************************************************/
366 :
367 : void VRTSimpleSource::GetFileList(char*** ppapszFileList, int *pnSize,
368 4 : int *pnMaxSize, CPLHashSet* hSetFiles)
369 : {
370 : const char* pszFilename;
371 4 : if (poRasterBand != NULL && poRasterBand->GetDataset() != NULL &&
372 : (pszFilename = poRasterBand->GetDataset()->GetDescription()) != NULL)
373 : {
374 : /* -------------------------------------------------------------------- */
375 : /* Is the filename even a real filesystem object? */
376 : /* -------------------------------------------------------------------- */
377 : VSIStatBufL sStat;
378 4 : if( VSIStatL( pszFilename, &sStat ) != 0 )
379 0 : return;
380 :
381 : /* -------------------------------------------------------------------- */
382 : /* Is it already in the list ? */
383 : /* -------------------------------------------------------------------- */
384 4 : if( CPLHashSetLookup(hSetFiles, pszFilename) != NULL )
385 0 : return;
386 :
387 : /* -------------------------------------------------------------------- */
388 : /* Grow array if necessary */
389 : /* -------------------------------------------------------------------- */
390 4 : if (*pnSize + 1 >= *pnMaxSize)
391 : {
392 4 : *pnMaxSize = 2 + 2 * (*pnMaxSize);
393 : *ppapszFileList = (char **) CPLRealloc(
394 4 : *ppapszFileList, sizeof(char*) * (*pnMaxSize) );
395 : }
396 :
397 : /* -------------------------------------------------------------------- */
398 : /* Add the string to the list */
399 : /* -------------------------------------------------------------------- */
400 4 : (*ppapszFileList)[*pnSize] = CPLStrdup(pszFilename);
401 4 : (*ppapszFileList)[(*pnSize + 1)] = NULL;
402 4 : CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
403 :
404 4 : (*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 : void VRTSimpleSource::SrcToDst( double dfX, double dfY,
415 770 : 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 : void VRTSimpleSource::DstToSrc( double dfX, double dfY,
429 3400 : 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 : 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 6859 : int *pnOutXSize, int *pnOutYSize )
447 :
448 : {
449 : int bDstWinSet = nDstXOff != -1 || nDstXSize != -1
450 6859 : || nDstYOff != -1 || nDstYSize != -1;
451 :
452 : #ifdef DEBUG
453 : int bSrcWinSet = nSrcXOff != -1 || nSrcXSize != -1
454 6859 : || nSrcYOff != -1 || nSrcYSize != -1;
455 :
456 6859 : if( bSrcWinSet != bDstWinSet )
457 : {
458 0 : 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 6859 : if( bDstWinSet )
467 : {
468 6837 : 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 6459 : *pnOutXOff = 0;
479 6459 : *pnOutYOff = 0;
480 6459 : *pnOutXSize = nBufXSize;
481 6459 : *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 6459 : int bModifiedX = FALSE, bModifiedY = FALSE;
489 6459 : int nRXOff = nXOff;
490 6459 : int nRYOff = nYOff;
491 6459 : int nRXSize = nXSize;
492 6459 : int nRYSize = nYSize;
493 :
494 :
495 6459 : if( bDstWinSet )
496 : {
497 6437 : if( nRXOff < nDstXOff )
498 : {
499 174 : nRXSize = nRXSize + nRXOff - nDstXOff;
500 174 : nRXOff = nDstXOff;
501 174 : bModifiedX = TRUE;
502 : }
503 :
504 6437 : if( nRYOff < nDstYOff )
505 : {
506 16 : nRYSize = nRYSize + nRYOff - nDstYOff;
507 16 : nRYOff = nDstYOff;
508 16 : bModifiedY = TRUE;
509 : }
510 :
511 6437 : if( nRXOff + nRXSize > nDstXOff + nDstXSize )
512 : {
513 235 : nRXSize = nDstXOff + nDstXSize - nRXOff;
514 235 : bModifiedX = TRUE;
515 : }
516 :
517 6437 : 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 6459 : double dfScaleX = nSrcXSize / (double) nDstXSize;
529 6459 : double dfScaleY = nSrcYSize / (double) nDstYSize;
530 :
531 6459 : *pnReqXOff = (int) floor((nRXOff - nDstXOff) * dfScaleX + nSrcXOff);
532 6459 : *pnReqYOff = (int) floor((nRYOff - nDstYOff) * dfScaleY + nSrcYOff);
533 :
534 6459 : *pnReqXSize = (int) floor(nRXSize * dfScaleX + 0.5);
535 6459 : *pnReqYSize = (int) floor(nRYSize * dfScaleY + 0.5);
536 :
537 : /* -------------------------------------------------------------------- */
538 : /* Clamp within the bounds of the available source data. */
539 : /* -------------------------------------------------------------------- */
540 6459 : if( *pnReqXOff < 0 )
541 : {
542 0 : *pnReqXSize += *pnReqXOff;
543 0 : *pnReqXOff = 0;
544 :
545 0 : bModifiedX = TRUE;
546 : }
547 :
548 6459 : if( *pnReqYOff < 0 )
549 : {
550 0 : *pnReqYSize += *pnReqYOff;
551 0 : *pnReqYOff = 0;
552 0 : bModifiedY = TRUE;
553 : }
554 :
555 6459 : if( *pnReqXSize == 0 )
556 0 : *pnReqXSize = 1;
557 6459 : if( *pnReqYSize == 0 )
558 16 : *pnReqYSize = 1;
559 :
560 6459 : if( *pnReqXOff + *pnReqXSize > poRasterBand->GetXSize() )
561 : {
562 2 : *pnReqXSize = poRasterBand->GetXSize() - *pnReqXOff;
563 2 : bModifiedX = TRUE;
564 : }
565 :
566 6459 : 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 6459 : 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 6459 : if( !bModifiedX && !bModifiedY )
588 6074 : 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 : VRTSimpleSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
640 : void *pData, int nBufXSize, int nBufYSize,
641 : GDALDataType eBufType,
642 4499 : 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 4499 : 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 4083 : eBufType, nPixelSpace, nLineSpace );
672 :
673 4083 : 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 : VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
714 : void *pData, int nBufXSize, int nBufYSize,
715 : GDALDataType eBufType,
716 50 : 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 2000 : if (CPLIsNan(fSampledValue))
830 0 : continue;
831 :
832 2000 : if( bNoDataSet && EQUAL_TO_NODATA(fSampledValue, dfNoDataValue))
833 0 : continue;
834 :
835 2000 : nPixelCount++;
836 2000 : dfSum += pafSrc[iX + iY * nReqXSize];
837 : }
838 : }
839 :
840 1700 : if( nPixelCount == 0 )
841 0 : continue;
842 :
843 : // Compute output value.
844 1700 : float dfOutputValue = (float) (dfSum / nPixelCount);
845 :
846 : // Put it in the output buffer.
847 : GByte *pDstLocation;
848 :
849 : pDstLocation = ((GByte *)pData)
850 : + nPixelSpace * iBufPixel
851 1700 : + nLineSpace * iBufLine;
852 :
853 1700 : if( eBufType == GDT_Byte )
854 0 : *pDstLocation = (GByte) MIN(255,MAX(0,dfOutputValue + 0.5));
855 : else
856 : GDALCopyWords( &dfOutputValue, GDT_Float32, 4,
857 1700 : pDstLocation, eBufType, 8, 1 );
858 : }
859 : }
860 :
861 50 : VSIFree( pafSrc );
862 :
863 50 : return CE_None;
864 : }
865 :
866 : /************************************************************************/
867 : /* ==================================================================== */
868 : /* VRTComplexSource */
869 : /* ==================================================================== */
870 : /************************************************************************/
871 :
872 : /************************************************************************/
873 : /* VRTComplexSource() */
874 : /************************************************************************/
875 :
876 54 : VRTComplexSource::VRTComplexSource()
877 :
878 : {
879 54 : bDoScaling = FALSE;
880 54 : dfScaleOff = 0.0;
881 54 : dfScaleRatio = 1.0;
882 :
883 54 : bNoDataSet = FALSE;
884 54 : dfNoDataValue = 0.0;
885 :
886 54 : padfLUTInputs = NULL;
887 54 : padfLUTOutputs = NULL;
888 54 : nLUTItemCount = 0;
889 54 : nColorTableComponent = 0;
890 54 : }
891 :
892 54 : VRTComplexSource::~VRTComplexSource()
893 : {
894 54 : if (padfLUTInputs)
895 7 : VSIFree( padfLUTInputs );
896 54 : if (padfLUTOutputs)
897 7 : VSIFree( padfLUTOutputs );
898 54 : }
899 :
900 : /************************************************************************/
901 : /* SerializeToXML() */
902 : /************************************************************************/
903 :
904 15 : CPLXMLNode *VRTComplexSource::SerializeToXML( const char *pszVRTPath )
905 :
906 : {
907 15 : CPLXMLNode *psSrc = VRTSimpleSource::SerializeToXML( pszVRTPath );
908 :
909 15 : if( psSrc == NULL )
910 0 : return NULL;
911 :
912 15 : CPLFree( psSrc->pszValue );
913 15 : psSrc->pszValue = CPLStrdup( "ComplexSource" );
914 :
915 15 : if( bNoDataSet )
916 : {
917 8 : if (CPLIsNan(dfNoDataValue))
918 0 : CPLSetXMLValue( psSrc, "NODATA", "nan");
919 : else
920 : CPLSetXMLValue( psSrc, "NODATA",
921 8 : CPLSPrintf("%g", dfNoDataValue) );
922 : }
923 :
924 15 : if( bDoScaling )
925 : {
926 : CPLSetXMLValue( psSrc, "ScaleOffset",
927 0 : CPLSPrintf("%g", dfScaleOff) );
928 : CPLSetXMLValue( psSrc, "ScaleRatio",
929 0 : CPLSPrintf("%g", dfScaleRatio) );
930 : }
931 :
932 15 : if ( nLUTItemCount )
933 : {
934 0 : CPLString osLUT = CPLString().Printf("%g:%g", padfLUTInputs[0], padfLUTOutputs[0]);
935 : int i;
936 0 : for ( i = 1; i < nLUTItemCount; i++ )
937 0 : osLUT += CPLString().Printf(",%g:%g", padfLUTInputs[i], padfLUTOutputs[i]);
938 0 : CPLSetXMLValue( psSrc, "LUT", osLUT );
939 : }
940 :
941 15 : if ( nColorTableComponent )
942 : {
943 : CPLSetXMLValue( psSrc, "ColorTableComponent",
944 7 : CPLSPrintf("%d", nColorTableComponent) );
945 : }
946 :
947 15 : return psSrc;
948 : }
949 :
950 : /************************************************************************/
951 : /* XMLInit() */
952 : /************************************************************************/
953 :
954 36 : CPLErr VRTComplexSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
955 :
956 : {
957 : CPLErr eErr;
958 :
959 : /* -------------------------------------------------------------------- */
960 : /* Do base initialization. */
961 : /* -------------------------------------------------------------------- */
962 36 : eErr = VRTSimpleSource::XMLInit( psSrc, pszVRTPath );
963 36 : if( eErr != CE_None )
964 0 : return eErr;
965 :
966 : /* -------------------------------------------------------------------- */
967 : /* Complex parameters. */
968 : /* -------------------------------------------------------------------- */
969 36 : if( CPLGetXMLValue(psSrc, "ScaleOffset", NULL) != NULL
970 : || CPLGetXMLValue(psSrc, "ScaleRatio", NULL) != NULL )
971 : {
972 0 : bDoScaling = TRUE;
973 0 : dfScaleOff = atof(CPLGetXMLValue(psSrc, "ScaleOffset", "0") );
974 0 : dfScaleRatio = atof(CPLGetXMLValue(psSrc, "ScaleRatio", "1") );
975 : }
976 :
977 36 : if( CPLGetXMLValue(psSrc, "NODATA", NULL) != NULL )
978 : {
979 10 : bNoDataSet = TRUE;
980 10 : dfNoDataValue = CPLAtofM(CPLGetXMLValue(psSrc, "NODATA", "0"));
981 : }
982 :
983 36 : if( CPLGetXMLValue(psSrc, "LUT", NULL) != NULL )
984 : {
985 : int nIndex;
986 7 : char **papszValues = CSLTokenizeString2(CPLGetXMLValue(psSrc, "LUT", ""), ",:", CSLT_ALLOWEMPTYTOKENS);
987 :
988 7 : if (nLUTItemCount)
989 : {
990 0 : if (padfLUTInputs)
991 : {
992 0 : VSIFree( padfLUTInputs );
993 0 : padfLUTInputs = NULL;
994 : }
995 0 : if (padfLUTOutputs)
996 : {
997 0 : VSIFree( padfLUTOutputs );
998 0 : padfLUTOutputs = NULL;
999 : }
1000 0 : nLUTItemCount = 0;
1001 : }
1002 :
1003 7 : nLUTItemCount = CSLCount(papszValues) / 2;
1004 :
1005 7 : padfLUTInputs = (double *) VSIMalloc2(nLUTItemCount, sizeof(double));
1006 7 : if ( !padfLUTInputs )
1007 : {
1008 0 : CSLDestroy(papszValues);
1009 0 : nLUTItemCount = 0;
1010 0 : return CE_Failure;
1011 : }
1012 :
1013 7 : padfLUTOutputs = (double *) VSIMalloc2(nLUTItemCount, sizeof(double));
1014 7 : if ( !padfLUTOutputs )
1015 : {
1016 0 : CSLDestroy(papszValues);
1017 0 : VSIFree( padfLUTInputs );
1018 0 : padfLUTInputs = NULL;
1019 0 : nLUTItemCount = 0;
1020 0 : return CE_Failure;
1021 : }
1022 :
1023 71 : for ( nIndex = 0; nIndex < nLUTItemCount; nIndex++ )
1024 : {
1025 64 : padfLUTInputs[nIndex] = atof( papszValues[nIndex * 2] );
1026 64 : padfLUTOutputs[nIndex] = atof( papszValues[nIndex * 2 + 1] );
1027 :
1028 : // Enforce the requirement that the LUT input array is monotonically non-decreasing.
1029 64 : if ( nIndex > 0 && padfLUTInputs[nIndex] < padfLUTInputs[nIndex - 1] )
1030 : {
1031 0 : CSLDestroy(papszValues);
1032 0 : VSIFree( padfLUTInputs );
1033 0 : VSIFree( padfLUTOutputs );
1034 0 : padfLUTInputs = NULL;
1035 0 : padfLUTOutputs = NULL;
1036 0 : nLUTItemCount = 0;
1037 0 : return CE_Failure;
1038 : }
1039 : }
1040 :
1041 7 : CSLDestroy(papszValues);
1042 : }
1043 :
1044 36 : if( CPLGetXMLValue(psSrc, "ColorTableComponent", NULL) != NULL )
1045 : {
1046 14 : nColorTableComponent = atoi(CPLGetXMLValue(psSrc, "ColorTableComponent", "0"));
1047 : }
1048 :
1049 36 : return CE_None;
1050 : }
1051 :
1052 : /************************************************************************/
1053 : /* LookupValue() */
1054 : /************************************************************************/
1055 :
1056 : double
1057 58964 : VRTComplexSource::LookupValue( double dfInput )
1058 : {
1059 : // Find the index of the first element in the LUT input array that
1060 : // is not smaller than the input value.
1061 58964 : int i = std::lower_bound(padfLUTInputs, padfLUTInputs + nLUTItemCount, dfInput) - padfLUTInputs;
1062 :
1063 58964 : if (i == 0)
1064 0 : return padfLUTOutputs[0];
1065 :
1066 : // If the index is beyond the end of the LUT input array, the input
1067 : // value is larger than all the values in the array.
1068 58964 : if (i == nLUTItemCount)
1069 4 : return padfLUTOutputs[nLUTItemCount - 1];
1070 :
1071 58960 : if (padfLUTInputs[i] == dfInput)
1072 4859 : return padfLUTOutputs[i];
1073 :
1074 : // Otherwise, interpolate.
1075 : return padfLUTOutputs[i - 1] + (dfInput - padfLUTInputs[i - 1]) *
1076 54101 : ((padfLUTOutputs[i] - padfLUTOutputs[i - 1]) / (padfLUTInputs[i] - padfLUTInputs[i - 1]));
1077 : }
1078 :
1079 : /************************************************************************/
1080 : /* RasterIO() */
1081 : /************************************************************************/
1082 :
1083 : CPLErr
1084 : VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
1085 : void *pData, int nBufXSize, int nBufYSize,
1086 : GDALDataType eBufType,
1087 2310 : int nPixelSpace, int nLineSpace )
1088 :
1089 : {
1090 : // The window we will actually request from the source raster band.
1091 : int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
1092 :
1093 : // The window we will actual set _within_ the pData buffer.
1094 : int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
1095 :
1096 2310 : if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
1097 : &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
1098 : &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
1099 0 : return CE_None;
1100 :
1101 :
1102 : /* -------------------------------------------------------------------- */
1103 : /* Read into a temporary buffer. */
1104 : /* -------------------------------------------------------------------- */
1105 : float *pafData;
1106 : CPLErr eErr;
1107 2310 : GDALColorTable* poColorTable = NULL;
1108 :
1109 2310 : if( bDoScaling && bNoDataSet == FALSE && dfScaleRatio == 0)
1110 : {
1111 : /* -------------------------------------------------------------------- */
1112 : /* Optimization when outputing a constant value */
1113 : /* (used by the -addalpha option of gdalbuildvrt) */
1114 : /* -------------------------------------------------------------------- */
1115 0 : pafData = NULL;
1116 : }
1117 : else
1118 : {
1119 2310 : pafData = (float *) CPLMalloc(nOutXSize*nOutYSize*sizeof(float));
1120 : eErr = poRasterBand->RasterIO( GF_Read,
1121 : nReqXOff, nReqYOff, nReqXSize, nReqYSize,
1122 : pafData, nOutXSize, nOutYSize, GDT_Float32,
1123 2310 : sizeof(float), sizeof(float) * nOutXSize );
1124 2310 : if( eErr != CE_None )
1125 : {
1126 0 : CPLFree( pafData );
1127 0 : return eErr;
1128 : }
1129 :
1130 2310 : if (nColorTableComponent != 0)
1131 : {
1132 1606 : poColorTable = poRasterBand->GetColorTable();
1133 1606 : if (poColorTable == NULL)
1134 : {
1135 : CPLError(CE_Failure, CPLE_AppDefined,
1136 0 : "Source band has no color table.");
1137 0 : return CE_Failure;
1138 : }
1139 : }
1140 : }
1141 :
1142 : /* -------------------------------------------------------------------- */
1143 : /* Selectively copy into output buffer with nodata masking, */
1144 : /* and/or scaling. */
1145 : /* -------------------------------------------------------------------- */
1146 : int iX, iY;
1147 :
1148 6424 : for( iY = 0; iY < nOutYSize; iY++ )
1149 : {
1150 1216638 : for( iX = 0; iX < nOutXSize; iX++ )
1151 : {
1152 : float fResult;
1153 :
1154 1212524 : if (pafData)
1155 : {
1156 1212524 : fResult = pafData[iX + iY * nOutXSize];
1157 1212524 : if( CPLIsNan(dfNoDataValue) && CPLIsNan(fResult) )
1158 20 : continue;
1159 1212504 : if( bNoDataSet && EQUAL_TO_NODATA(fResult, dfNoDataValue) )
1160 782 : continue;
1161 :
1162 1211722 : if (nColorTableComponent)
1163 : {
1164 1121200 : const GDALColorEntry* poEntry = poColorTable->GetColorEntry((int)fResult);
1165 1121200 : if (poEntry)
1166 : {
1167 1121200 : if (nColorTableComponent == 1)
1168 320400 : fResult = poEntry->c1;
1169 800800 : else if (nColorTableComponent == 2)
1170 320400 : fResult = poEntry->c2;
1171 480400 : else if (nColorTableComponent == 3)
1172 320400 : fResult = poEntry->c3;
1173 160000 : else if (nColorTableComponent == 4)
1174 160000 : fResult = poEntry->c4;
1175 : }
1176 : else
1177 : {
1178 : static int bHasWarned = FALSE;
1179 0 : if (!bHasWarned)
1180 : {
1181 0 : bHasWarned = TRUE;
1182 : CPLError(CE_Failure, CPLE_AppDefined,
1183 0 : "No entry %d.", (int)fResult);
1184 : }
1185 0 : continue;
1186 : }
1187 : }
1188 :
1189 1211722 : if( bDoScaling )
1190 0 : fResult = (float) (fResult * dfScaleRatio + dfScaleOff);
1191 : }
1192 : else
1193 : {
1194 0 : fResult = (float) dfScaleOff;
1195 : }
1196 :
1197 1211722 : if (nLUTItemCount)
1198 58964 : fResult = (float) LookupValue( fResult );
1199 :
1200 : GByte *pDstLocation;
1201 :
1202 : pDstLocation = ((GByte *)pData)
1203 : + nPixelSpace * (iX + nOutXOff)
1204 1211722 : + nLineSpace * (iY + nOutYOff);
1205 :
1206 1211722 : if( eBufType == GDT_Byte )
1207 495841 : *pDstLocation = (GByte) MIN(255,MAX(0,fResult + 0.5));
1208 : else
1209 : GDALCopyWords( &fResult, GDT_Float32, 4,
1210 715881 : pDstLocation, eBufType, 8, 1 );
1211 :
1212 : }
1213 : }
1214 :
1215 2310 : CPLFree( pafData );
1216 :
1217 2310 : return CE_None;
1218 : }
1219 :
1220 : /************************************************************************/
1221 : /* ==================================================================== */
1222 : /* VRTFuncSource */
1223 : /* ==================================================================== */
1224 : /************************************************************************/
1225 :
1226 : /************************************************************************/
1227 : /* VRTFuncSource() */
1228 : /************************************************************************/
1229 :
1230 0 : VRTFuncSource::VRTFuncSource()
1231 :
1232 : {
1233 0 : pfnReadFunc = NULL;
1234 0 : pCBData = NULL;
1235 0 : fNoDataValue = (float) VRT_NODATA_UNSET;
1236 0 : eType = GDT_Byte;
1237 0 : }
1238 :
1239 : /************************************************************************/
1240 : /* ~VRTFuncSource() */
1241 : /************************************************************************/
1242 :
1243 0 : VRTFuncSource::~VRTFuncSource()
1244 :
1245 : {
1246 0 : }
1247 :
1248 : /************************************************************************/
1249 : /* SerializeToXML() */
1250 : /************************************************************************/
1251 :
1252 0 : CPLXMLNode *VRTFuncSource::SerializeToXML( const char * pszVRTPath )
1253 :
1254 : {
1255 0 : return NULL;
1256 : }
1257 :
1258 : /************************************************************************/
1259 : /* RasterIO() */
1260 : /************************************************************************/
1261 :
1262 : CPLErr
1263 : VRTFuncSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
1264 : void *pData, int nBufXSize, int nBufYSize,
1265 : GDALDataType eBufType,
1266 0 : int nPixelSpace, int nLineSpace )
1267 :
1268 : {
1269 0 : if( nPixelSpace*8 == GDALGetDataTypeSize( eBufType )
1270 : && nLineSpace == nPixelSpace * nXSize
1271 : && nBufXSize == nXSize && nBufYSize == nYSize
1272 : && eBufType == eType )
1273 : {
1274 : return pfnReadFunc( pCBData,
1275 : nXOff, nYOff, nXSize, nYSize,
1276 0 : pData );
1277 : }
1278 : else
1279 : {
1280 : printf( "%d,%d %d,%d, %d,%d %d,%d %d,%d\n",
1281 : nPixelSpace*8, GDALGetDataTypeSize(eBufType),
1282 : nLineSpace, nPixelSpace * nXSize,
1283 : nBufXSize, nXSize,
1284 : nBufYSize, nYSize,
1285 0 : (int) eBufType, (int) eType );
1286 : CPLError( CE_Failure, CPLE_AppDefined,
1287 0 : "VRTFuncSource::RasterIO() - Irregular request." );
1288 0 : return CE_Failure;
1289 : }
1290 : }
1291 :
1292 : /************************************************************************/
1293 : /* VRTParseCoreSources() */
1294 : /************************************************************************/
1295 :
1296 197 : VRTSource *VRTParseCoreSources( CPLXMLNode *psChild, const char *pszVRTPath )
1297 :
1298 : {
1299 : VRTSource * poSource;
1300 :
1301 197 : if( EQUAL(psChild->pszValue,"AveragedSource")
1302 : || (EQUAL(psChild->pszValue,"SimpleSource")
1303 : && EQUALN(CPLGetXMLValue(psChild, "Resampling", "Nearest"),
1304 : "Aver",4)) )
1305 : {
1306 2 : poSource = new VRTAveragedSource();
1307 : }
1308 195 : else if( EQUAL(psChild->pszValue,"SimpleSource") )
1309 : {
1310 164 : poSource = new VRTSimpleSource();
1311 : }
1312 31 : else if( EQUAL(psChild->pszValue,"ComplexSource") )
1313 : {
1314 31 : poSource = new VRTComplexSource();
1315 : }
1316 : else
1317 : {
1318 : CPLError( CE_Failure, CPLE_AppDefined,
1319 0 : "VRTParseCoreSources() - Unknown source : %s", psChild->pszValue );
1320 0 : return NULL;
1321 : }
1322 :
1323 197 : if ( poSource->XMLInit( psChild, pszVRTPath ) == CE_None )
1324 196 : return poSource;
1325 :
1326 1 : delete poSource;
1327 1 : return NULL;
1328 : }
1329 :
|