1 : /******************************************************************************
2 : * $Id: gdalwarper.cpp 18092 2009-11-24 20:48:51Z rouault $
3 : *
4 : * Project: High Performance Image Reprojector
5 : * Purpose: Implementation of high level convenience APIs for warper.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "gdalwarper.h"
31 : #include "cpl_string.h"
32 : #include "cpl_minixml.h"
33 : #include "ogr_api.h"
34 :
35 : CPL_CVSID("$Id: gdalwarper.cpp 18092 2009-11-24 20:48:51Z rouault $");
36 :
37 : /************************************************************************/
38 : /* GDALReprojectImage() */
39 : /************************************************************************/
40 :
41 : /**
42 : * Reproject image.
43 : *
44 : * This is a convenience function utilizing the GDALWarpOperation class to
45 : * reproject an image from a source to a destination. In particular, this
46 : * function takes care of establishing the transformation function to
47 : * implement the reprojection, and will default a variety of other
48 : * warp options.
49 : *
50 : * By default all bands are transferred, with no masking or nodata values
51 : * in effect. No metadata, projection info, or color tables are transferred
52 : * to the output file.
53 : *
54 : * @param hSrcDS the source image file.
55 : * @param pszSrcWKT the source projection. If NULL the source projection
56 : * is read from from hSrcDS.
57 : * @param hDstDS the destination image file.
58 : * @param pszDstWKT the destination projection. If NULL the destination
59 : * projection will be read from hDstDS.
60 : * @param eResampleAlg the type of resampling to use.
61 : * @param dfWarpMemoryLimit the amount of memory (in bytes) that the warp
62 : * API is allowed to use for caching. This is in addition to the memory
63 : * already allocated to the GDAL caching (as per GDALSetCacheMax()). May be
64 : * 0.0 to use default memory settings.
65 : * @param dfMaxError maximum error measured in input pixels that is allowed
66 : * in approximating the transformation (0.0 for exact calculations).
67 : * @param pfnProgress a GDALProgressFunc() compatible callback function for
68 : * reporting progress or NULL.
69 : * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
70 : * @param psOptions warp options, normally NULL.
71 : *
72 : * @return CE_None on success or CE_Failure if something goes wrong.
73 : */
74 :
75 : CPLErr CPL_STDCALL
76 18 : GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
77 : GDALDatasetH hDstDS, const char *pszDstWKT,
78 : GDALResampleAlg eResampleAlg,
79 : double dfWarpMemoryLimit,
80 : double dfMaxError,
81 : GDALProgressFunc pfnProgress, void *pProgressArg,
82 : GDALWarpOptions *psOptions )
83 :
84 : {
85 : GDALWarpOptions *psWOptions;
86 :
87 : /* -------------------------------------------------------------------- */
88 : /* Setup a reprojection based transformer. */
89 : /* -------------------------------------------------------------------- */
90 : void *hTransformArg;
91 :
92 : hTransformArg =
93 : GDALCreateGenImgProjTransformer( hSrcDS, pszSrcWKT, hDstDS, pszDstWKT,
94 18 : TRUE, 1000.0, 0 );
95 :
96 18 : if( hTransformArg == NULL )
97 0 : return CE_Failure;
98 :
99 : /* -------------------------------------------------------------------- */
100 : /* Create a copy of the user provided options, or a defaulted */
101 : /* options structure. */
102 : /* -------------------------------------------------------------------- */
103 18 : if( psOptions == NULL )
104 18 : psWOptions = GDALCreateWarpOptions();
105 : else
106 0 : psWOptions = GDALCloneWarpOptions( psOptions );
107 :
108 18 : psWOptions->eResampleAlg = eResampleAlg;
109 :
110 : /* -------------------------------------------------------------------- */
111 : /* Set transform. */
112 : /* -------------------------------------------------------------------- */
113 18 : if( dfMaxError > 0.0 )
114 : {
115 : psWOptions->pTransformerArg =
116 : GDALCreateApproxTransformer( GDALGenImgProjTransform,
117 0 : hTransformArg, dfMaxError );
118 :
119 0 : psWOptions->pfnTransformer = GDALApproxTransform;
120 : }
121 : else
122 : {
123 18 : psWOptions->pfnTransformer = GDALGenImgProjTransform;
124 18 : psWOptions->pTransformerArg = hTransformArg;
125 : }
126 :
127 : /* -------------------------------------------------------------------- */
128 : /* Set file and band mapping. */
129 : /* -------------------------------------------------------------------- */
130 : int iBand;
131 :
132 18 : psWOptions->hSrcDS = hSrcDS;
133 18 : psWOptions->hDstDS = hDstDS;
134 :
135 18 : if( psWOptions->nBandCount == 0 )
136 : {
137 : psWOptions->nBandCount = MIN(GDALGetRasterCount(hSrcDS),
138 18 : GDALGetRasterCount(hDstDS));
139 :
140 : psWOptions->panSrcBands = (int *)
141 18 : CPLMalloc(sizeof(int) * psWOptions->nBandCount);
142 : psWOptions->panDstBands = (int *)
143 18 : CPLMalloc(sizeof(int) * psWOptions->nBandCount);
144 :
145 36 : for( iBand = 0; iBand < psWOptions->nBandCount; iBand++ )
146 : {
147 18 : psWOptions->panSrcBands[iBand] = iBand+1;
148 18 : psWOptions->panDstBands[iBand] = iBand+1;
149 : }
150 : }
151 :
152 : /* -------------------------------------------------------------------- */
153 : /* Set source nodata values if the source dataset seems to have */
154 : /* any. */
155 : /* -------------------------------------------------------------------- */
156 36 : for( iBand = 0; iBand < psWOptions->nBandCount; iBand++ )
157 : {
158 18 : GDALRasterBandH hBand = GDALGetRasterBand( hSrcDS, iBand+1 );
159 18 : int bGotNoData = FALSE;
160 : double dfNoDataValue;
161 :
162 18 : dfNoDataValue = GDALGetRasterNoDataValue( hBand, &bGotNoData );
163 18 : if( bGotNoData )
164 : {
165 5 : if( psWOptions->padfSrcNoDataReal == NULL )
166 : {
167 : int ii;
168 :
169 : psWOptions->padfSrcNoDataReal = (double *)
170 5 : CPLMalloc(sizeof(double) * psWOptions->nBandCount);
171 : psWOptions->padfSrcNoDataImag = (double *)
172 5 : CPLMalloc(sizeof(double) * psWOptions->nBandCount);
173 :
174 10 : for( ii = 0; ii < psWOptions->nBandCount; ii++ )
175 : {
176 5 : psWOptions->padfSrcNoDataReal[ii] = -1.1e20;
177 5 : psWOptions->padfSrcNoDataImag[ii] = 0.0;
178 : }
179 : }
180 :
181 5 : psWOptions->padfSrcNoDataReal[iBand] = dfNoDataValue;
182 : }
183 : }
184 :
185 : /* -------------------------------------------------------------------- */
186 : /* Set the progress function. */
187 : /* -------------------------------------------------------------------- */
188 18 : if( pfnProgress != NULL )
189 : {
190 0 : psWOptions->pfnProgress = pfnProgress;
191 0 : psWOptions->pProgressArg = pProgressArg;
192 : }
193 :
194 : /* -------------------------------------------------------------------- */
195 : /* Create a warp options based on the options. */
196 : /* -------------------------------------------------------------------- */
197 18 : GDALWarpOperation oWarper;
198 : CPLErr eErr;
199 :
200 18 : eErr = oWarper.Initialize( psWOptions );
201 :
202 18 : if( eErr == CE_None )
203 : eErr = oWarper.ChunkAndWarpImage( 0, 0,
204 : GDALGetRasterXSize(hDstDS),
205 18 : GDALGetRasterYSize(hDstDS) );
206 :
207 : /* -------------------------------------------------------------------- */
208 : /* Cleanup. */
209 : /* -------------------------------------------------------------------- */
210 18 : GDALDestroyGenImgProjTransformer( hTransformArg );
211 :
212 18 : if( dfMaxError > 0.0 )
213 0 : GDALDestroyApproxTransformer( psWOptions->pTransformerArg );
214 :
215 18 : GDALDestroyWarpOptions( psWOptions );
216 :
217 18 : return eErr;
218 : }
219 :
220 : /************************************************************************/
221 : /* GDALCreateAndReprojectImage() */
222 : /* */
223 : /* This is a "quicky" reprojection API. */
224 : /************************************************************************/
225 :
226 0 : CPLErr CPL_STDCALL GDALCreateAndReprojectImage(
227 : GDALDatasetH hSrcDS, const char *pszSrcWKT,
228 : const char *pszDstFilename, const char *pszDstWKT,
229 : GDALDriverH hDstDriver, char **papszCreateOptions,
230 : GDALResampleAlg eResampleAlg, double dfWarpMemoryLimit, double dfMaxError,
231 : GDALProgressFunc pfnProgress, void *pProgressArg,
232 : GDALWarpOptions *psOptions )
233 :
234 : {
235 0 : VALIDATE_POINTER1( hSrcDS, "GDALCreateAndReprojectImage", CE_Failure );
236 :
237 : /* -------------------------------------------------------------------- */
238 : /* Default a few parameters. */
239 : /* -------------------------------------------------------------------- */
240 0 : if( hDstDriver == NULL )
241 : {
242 0 : hDstDriver = GDALGetDriverByName( "GTiff" );
243 0 : if (hDstDriver == NULL)
244 : {
245 : CPLError(CE_Failure, CPLE_AppDefined,
246 0 : "GDALCreateAndReprojectImage needs GTiff driver");
247 0 : return CE_Failure;
248 : }
249 : }
250 :
251 0 : if( pszSrcWKT == NULL )
252 0 : pszSrcWKT = GDALGetProjectionRef( hSrcDS );
253 :
254 0 : if( pszDstWKT == NULL )
255 0 : pszDstWKT = pszSrcWKT;
256 :
257 : /* -------------------------------------------------------------------- */
258 : /* Create a transformation object from the source to */
259 : /* destination coordinate system. */
260 : /* -------------------------------------------------------------------- */
261 : void *hTransformArg;
262 :
263 : hTransformArg =
264 : GDALCreateGenImgProjTransformer( hSrcDS, pszSrcWKT, NULL, pszDstWKT,
265 0 : TRUE, 1000.0, 0 );
266 :
267 0 : if( hTransformArg == NULL )
268 0 : return CE_Failure;
269 :
270 : /* -------------------------------------------------------------------- */
271 : /* Get approximate output definition. */
272 : /* -------------------------------------------------------------------- */
273 : double adfDstGeoTransform[6];
274 : int nPixels, nLines;
275 :
276 0 : if( GDALSuggestedWarpOutput( hSrcDS,
277 : GDALGenImgProjTransform, hTransformArg,
278 : adfDstGeoTransform, &nPixels, &nLines )
279 : != CE_None )
280 0 : return CE_Failure;
281 :
282 0 : GDALDestroyGenImgProjTransformer( hTransformArg );
283 :
284 : /* -------------------------------------------------------------------- */
285 : /* Create the output file. */
286 : /* -------------------------------------------------------------------- */
287 : GDALDatasetH hDstDS;
288 :
289 : hDstDS = GDALCreate( hDstDriver, pszDstFilename, nPixels, nLines,
290 : GDALGetRasterCount(hSrcDS),
291 : GDALGetRasterDataType(GDALGetRasterBand(hSrcDS,1)),
292 0 : papszCreateOptions );
293 :
294 0 : if( hDstDS == NULL )
295 0 : return CE_Failure;
296 :
297 : /* -------------------------------------------------------------------- */
298 : /* Write out the projection definition. */
299 : /* -------------------------------------------------------------------- */
300 0 : GDALSetProjection( hDstDS, pszDstWKT );
301 0 : GDALSetGeoTransform( hDstDS, adfDstGeoTransform );
302 :
303 : /* -------------------------------------------------------------------- */
304 : /* Perform the reprojection. */
305 : /* -------------------------------------------------------------------- */
306 : CPLErr eErr ;
307 :
308 : eErr =
309 : GDALReprojectImage( hSrcDS, pszSrcWKT, hDstDS, pszDstWKT,
310 : eResampleAlg, dfWarpMemoryLimit, dfMaxError,
311 0 : pfnProgress, pProgressArg, psOptions );
312 :
313 0 : GDALClose( hDstDS );
314 :
315 0 : return eErr;
316 : }
317 :
318 : /************************************************************************/
319 : /* GDALWarpNoDataMasker() */
320 : /* */
321 : /* GDALMaskFunc for establishing a validity mask for a source */
322 : /* band based on a provided NODATA value. */
323 : /************************************************************************/
324 :
325 : CPLErr
326 8 : GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
327 : int /* nXOff */, int /* nYOff */, int nXSize, int nYSize,
328 : GByte **ppImageData,
329 : int bMaskIsFloat, void *pValidityMask )
330 :
331 : {
332 8 : double *padfNoData = (double *) pMaskFuncArg;
333 8 : GUInt32 *panValidityMask = (GUInt32 *) pValidityMask;
334 :
335 8 : if( nBandCount != 1 || bMaskIsFloat )
336 : {
337 : CPLError( CE_Failure, CPLE_AppDefined,
338 0 : "Invalid nBandCount or bMaskIsFloat argument in SourceNoDataMask" );
339 0 : return CE_Failure;
340 : }
341 :
342 8 : switch( eType )
343 : {
344 : case GDT_Byte:
345 : {
346 3 : int nNoData = (int) padfNoData[0];
347 3 : GByte *pabyData = (GByte *) *ppImageData;
348 : int iOffset;
349 :
350 : // nothing to do if value is out of range.
351 6 : if( padfNoData[0] < 0.0 || padfNoData[0] > 255.000001
352 3 : || padfNoData[1] != 0.0 )
353 0 : return CE_None;
354 :
355 66380 : for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
356 : {
357 66377 : if( pabyData[iOffset] == nNoData )
358 : {
359 66077 : panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
360 : }
361 : }
362 : }
363 3 : break;
364 :
365 : case GDT_Int16:
366 : {
367 5 : int nNoData = (int) padfNoData[0];
368 5 : GInt16 *panData = (GInt16 *) *ppImageData;
369 : int iOffset;
370 :
371 : // nothing to do if value is out of range.
372 10 : if( padfNoData[0] < -32768 || padfNoData[0] > 32767
373 5 : || padfNoData[1] != 0.0 )
374 0 : return CE_None;
375 :
376 45829 : for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
377 : {
378 45824 : if( panData[iOffset] == nNoData )
379 : {
380 715 : panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
381 : }
382 : }
383 : }
384 5 : break;
385 :
386 : case GDT_UInt16:
387 : {
388 0 : int nNoData = (int) padfNoData[0];
389 0 : GUInt16 *panData = (GUInt16 *) *ppImageData;
390 : int iOffset;
391 :
392 : // nothing to do if value is out of range.
393 0 : if( padfNoData[0] < 0 || padfNoData[0] > 65535
394 0 : || padfNoData[1] != 0.0 )
395 0 : return CE_None;
396 :
397 0 : for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
398 : {
399 0 : if( panData[iOffset] == nNoData )
400 : {
401 0 : panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
402 : }
403 : }
404 : }
405 0 : break;
406 :
407 : case GDT_Float32:
408 : {
409 0 : float fNoData = (float) padfNoData[0];
410 0 : float *pafData = (float *) *ppImageData;
411 : int iOffset;
412 :
413 : // nothing to do if value is out of range.
414 0 : if( padfNoData[1] != 0.0 )
415 0 : return CE_None;
416 :
417 0 : for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
418 : {
419 0 : if( pafData[iOffset] == fNoData )
420 : {
421 0 : panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
422 : }
423 : }
424 : }
425 0 : break;
426 :
427 : default:
428 : {
429 : double *padfWrk;
430 : int iLine, iPixel;
431 0 : int nWordSize = GDALGetDataTypeSize(eType)/8;
432 :
433 0 : padfWrk = (double *) CPLMalloc(nXSize * sizeof(double) * 2);
434 0 : for( iLine = 0; iLine < nYSize; iLine++ )
435 : {
436 : GDALCopyWords( ((GByte *) *ppImageData)+nWordSize*iLine*nXSize,
437 : eType, nWordSize,
438 0 : padfWrk, GDT_CFloat64, 16, nXSize );
439 :
440 0 : for( iPixel = 0; iPixel < nXSize; iPixel++ )
441 : {
442 0 : if( padfWrk[iPixel*2] == padfNoData[0]
443 0 : && padfWrk[iPixel*2+1] == padfNoData[1] )
444 : {
445 0 : int iOffset = iPixel + iLine * nXSize;
446 :
447 : panValidityMask[iOffset>>5] &=
448 0 : ~(0x01 << (iOffset & 0x1f));
449 : }
450 : }
451 :
452 : }
453 :
454 0 : CPLFree( padfWrk );
455 : }
456 : break;
457 : }
458 :
459 8 : return CE_None;
460 : }
461 :
462 : /************************************************************************/
463 : /* GDALWarpSrcAlphaMasker() */
464 : /* */
465 : /* GDALMaskFunc for reading source simple 8bit alpha mask */
466 : /* information and building a floating point density mask from */
467 : /* it. */
468 : /************************************************************************/
469 :
470 : CPLErr
471 7 : GDALWarpSrcAlphaMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
472 : int nXOff, int nYOff, int nXSize, int nYSize,
473 : GByte ** /*ppImageData */,
474 : int bMaskIsFloat, void *pValidityMask )
475 :
476 : {
477 7 : GDALWarpOptions *psWO = (GDALWarpOptions *) pMaskFuncArg;
478 7 : float *pafMask = (float *) pValidityMask;
479 :
480 : /* -------------------------------------------------------------------- */
481 : /* Do some minimal checking. */
482 : /* -------------------------------------------------------------------- */
483 7 : if( !bMaskIsFloat )
484 : {
485 : CPLAssert( FALSE );
486 0 : return CE_Failure;
487 : }
488 :
489 7 : if( psWO == NULL || psWO->nSrcAlphaBand < 1 )
490 : {
491 : CPLAssert( FALSE );
492 0 : return CE_Failure;
493 : }
494 :
495 : /* -------------------------------------------------------------------- */
496 : /* Read the alpha band. */
497 : /* -------------------------------------------------------------------- */
498 : CPLErr eErr;
499 : GDALRasterBandH hAlphaBand = GDALGetRasterBand( psWO->hSrcDS,
500 7 : psWO->nSrcAlphaBand );
501 7 : if (hAlphaBand == NULL)
502 0 : return CE_Failure;
503 :
504 : eErr = GDALRasterIO( hAlphaBand, GF_Read, nXOff, nYOff, nXSize, nYSize,
505 7 : pafMask, nXSize, nYSize, GDT_Float32, 0, 0 );
506 :
507 7 : if( eErr != CE_None )
508 0 : return eErr;
509 :
510 : /* -------------------------------------------------------------------- */
511 : /* Rescale from 0-255 to 0.0-1.0. */
512 : /* -------------------------------------------------------------------- */
513 2807 : for( int iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
514 : { // (1/255)
515 2800 : pafMask[iPixel] = (float)( pafMask[iPixel] * 0.00392157 );
516 2800 : pafMask[iPixel] = MIN( 1.0F, pafMask[iPixel] );
517 : }
518 :
519 7 : return CE_None;
520 : }
521 :
522 : /************************************************************************/
523 : /* GDALWarpDstAlphaMasker() */
524 : /* */
525 : /* GDALMaskFunc for reading or writing the destination simple */
526 : /* 8bit alpha mask information and building a floating point */
527 : /* density mask from it. Note, writing is distinguished */
528 : /* negative bandcount. */
529 : /************************************************************************/
530 :
531 : CPLErr
532 18 : GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
533 : int nXOff, int nYOff, int nXSize, int nYSize,
534 : GByte ** /*ppImageData */,
535 : int bMaskIsFloat, void *pValidityMask )
536 :
537 : {
538 18 : GDALWarpOptions *psWO = (GDALWarpOptions *) pMaskFuncArg;
539 18 : float *pafMask = (float *) pValidityMask;
540 : int iPixel;
541 : CPLErr eErr;
542 :
543 : /* -------------------------------------------------------------------- */
544 : /* Do some minimal checking. */
545 : /* -------------------------------------------------------------------- */
546 18 : if( !bMaskIsFloat )
547 : {
548 : CPLAssert( FALSE );
549 0 : return CE_Failure;
550 : }
551 :
552 18 : if( psWO == NULL || psWO->nDstAlphaBand < 1 )
553 : {
554 : CPLAssert( FALSE );
555 0 : return CE_Failure;
556 : }
557 :
558 : GDALRasterBandH hAlphaBand =
559 18 : GDALGetRasterBand( psWO->hDstDS, psWO->nDstAlphaBand );
560 18 : if (hAlphaBand == NULL)
561 0 : return CE_Failure;
562 :
563 : /* -------------------------------------------------------------------- */
564 : /* Read alpha case. */
565 : /* -------------------------------------------------------------------- */
566 18 : if( nBandCount >= 0 )
567 : {
568 : const char *pszInitDest =
569 9 : CSLFetchNameValue( psWO->papszWarpOptions, "INIT_DEST" );
570 :
571 : // Special logic for destinations being initialized on the fly.
572 9 : if( pszInitDest != NULL )
573 : {
574 526797 : for( iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
575 526788 : pafMask[iPixel] = 0.0;
576 9 : return CE_None;
577 : }
578 :
579 : // Read data.
580 : eErr = GDALRasterIO( hAlphaBand, GF_Read, nXOff, nYOff, nXSize, nYSize,
581 0 : pafMask, nXSize, nYSize, GDT_Float32, 0, 0 );
582 :
583 0 : if( eErr != CE_None )
584 0 : return eErr;
585 :
586 : // rescale.
587 0 : for( iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
588 : {
589 0 : pafMask[iPixel] = (float) (pafMask[iPixel] * 0.00392157);
590 0 : pafMask[iPixel] = MIN( 1.0F, pafMask[iPixel] );
591 : }
592 :
593 0 : return CE_None;
594 : }
595 :
596 : /* -------------------------------------------------------------------- */
597 : /* Write alpha case. */
598 : /* -------------------------------------------------------------------- */
599 : else
600 : {
601 526797 : for( iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
602 526788 : pafMask[iPixel] = (int) ( pafMask[iPixel] * 255.1 );
603 :
604 : // Write data.
605 :
606 : /* The VRT warper will pass destination sizes that may exceed */
607 : /* the size of the raster for the partial blocks at the right */
608 : /* and bottom of the band. So let's adjust the size */
609 9 : int nDstXSize = nXSize;
610 9 : if (nXOff + nXSize > GDALGetRasterXSize(hAlphaBand))
611 8 : nDstXSize = GDALGetRasterXSize(hAlphaBand) - nXOff;
612 9 : int nDstYSize = nYSize;
613 9 : if (nYOff + nYSize > GDALGetRasterYSize(hAlphaBand))
614 8 : nDstYSize = GDALGetRasterYSize(hAlphaBand) - nYOff;
615 :
616 : eErr = GDALRasterIO( hAlphaBand, GF_Write,
617 : nXOff, nYOff, nDstXSize, nDstYSize,
618 : pafMask, nDstXSize, nDstYSize, GDT_Float32,
619 9 : 0, sizeof(float) * nXSize );
620 9 : return eErr;
621 : }
622 : }
623 :
624 : /************************************************************************/
625 : /* ==================================================================== */
626 : /* GDALWarpOptions */
627 : /* ==================================================================== */
628 : /************************************************************************/
629 :
630 : /**
631 : * \var char **GDALWarpOptions::papszWarpOptions;
632 : *
633 : * A string list of additional options controlling the warp operation in
634 : * name=value format. A suitable string list can be prepared with
635 : * CSLSetNameValue().
636 : *
637 : * The following values are currently supported:
638 : *
639 : * - INIT_DEST=[value] or INIT_DEST=NO_DATA: This option forces the
640 : * destination image to be initialized to the indicated value (for all bands)
641 : * or indicates that it should be initialized to the NO_DATA value in
642 : * padfDstNoDataReal/padfDstNoDataImag. If this value isn't set the
643 : * destination image will be read and overlayed.
644 : *
645 : * - WRITE_FLUSH=YES/NO: This option forces a flush to disk of data after
646 : * each chunk is processed. In some cases this helps ensure a serial
647 : * writing of the output data otherwise a block of data may be written to disk
648 : * each time a block of data is read for the input buffer resulting in alot
649 : * of extra seeking around the disk, and reduced IO throughput. The default
650 : * at this time is NO.
651 : *
652 : * - SKIP_NOSOURCE=YES/NO: Skip all processing for chunks for which there
653 : * is no corresponding input data. This will disable initializing the
654 : * destination (INIT_DEST) and all other processing, and so should be used
655 : * careful. Mostly useful to short circuit a lot of extra work in mosaicing
656 : * situations.
657 : *
658 : * - UNIFIED_SRC_NODATA=YES/[NO]: By default nodata masking values considered
659 : * independently for each band. However, sometimes it is desired to treat all
660 : * bands as nodata if and only if, all bands match the corresponding nodata
661 : * values. To get this behavior set this option to YES.
662 : *
663 : * Normally when computing the source raster data to
664 : * load to generate a particular output area, the warper samples transforms
665 : * 21 points along each edge of the destination region back onto the source
666 : * file, and uses this to compute a bounding window on the source image that
667 : * is sufficient. Depending on the transformation in effect, the source
668 : * window may be a bit too small, or even missing large areas. Problem
669 : * situations are those where the transformation is very non-linear or
670 : * "inside out". Examples are transforming from WGS84 to Polar Steregraphic
671 : * for areas around the pole, or transformations where some of the image is
672 : * untransformable. The following options provide some additional control
673 : * to deal with errors in computing the source window:
674 : *
675 : * - SAMPLE_GRID=YES/NO: Setting this option to YES will force the sampling to
676 : * include internal points as well as edge points which can be important if
677 : * the transformation is esoteric inside out, or if large sections of the
678 : * destination image are not transformable into the source coordinate system.
679 : *
680 : * - SAMPLE_STEPS: Modifies the density of the sampling grid. The default
681 : * number of steps is 21. Increasing this can increase the computational
682 : * cost, but improves the accuracy with which the source region is computed.
683 : *
684 : * - SOURCE_EXTRA: This is a number of extra pixels added around the source
685 : * window for a given request, and by default it is 1 to take care of rounding
686 : * error. Setting this larger will incease the amount of data that needs to
687 : * be read, but can avoid missing source data.
688 : *
689 : * - CUTLINE: This may contain the WKT geometry for a cutline. It will
690 : * be converted into a geometry by GDALWarpOperation::Initialize() and assigned
691 : * to the GDALWarpOptions hCutline field.
692 : *
693 : * - CUTLINE_BLEND_DIST: This may be set with a distance in pixels which
694 : * will be assigned to the dfCutlineBlendDist field in the GDALWarpOptions.
695 : *
696 : * - CUTLINE_ALL_TOUCHED: This defaults to FALSE, but may be set to TRUE
697 : * to enable ALL_TOUCHEd mode when rasterizing cutline polygons. This is
698 : * useful to ensure that that all pixels overlapping the cutline polygon
699 : * will be selected, not just those whose center point falls within the
700 : * polygon.
701 : */
702 :
703 : /************************************************************************/
704 : /* GDALCreateWarpOptions() */
705 : /************************************************************************/
706 :
707 606 : GDALWarpOptions * CPL_STDCALL GDALCreateWarpOptions()
708 :
709 : {
710 : GDALWarpOptions *psOptions;
711 :
712 606 : psOptions = (GDALWarpOptions *) CPLCalloc(sizeof(GDALWarpOptions),1);
713 :
714 606 : psOptions->eResampleAlg = GRA_NearestNeighbour;
715 606 : psOptions->pfnProgress = GDALDummyProgress;
716 606 : psOptions->eWorkingDataType = GDT_Unknown;
717 :
718 606 : return psOptions;
719 : }
720 :
721 : /************************************************************************/
722 : /* GDALDestroyWarpOptions() */
723 : /************************************************************************/
724 :
725 606 : void CPL_STDCALL GDALDestroyWarpOptions( GDALWarpOptions *psOptions )
726 :
727 : {
728 606 : VALIDATE_POINTER0( psOptions, "GDALDestroyWarpOptions" );
729 :
730 606 : CSLDestroy( psOptions->papszWarpOptions );
731 606 : CPLFree( psOptions->panSrcBands );
732 606 : CPLFree( psOptions->panDstBands );
733 606 : CPLFree( psOptions->padfSrcNoDataReal );
734 606 : CPLFree( psOptions->padfSrcNoDataImag );
735 606 : CPLFree( psOptions->padfDstNoDataReal );
736 606 : CPLFree( psOptions->padfDstNoDataImag );
737 606 : CPLFree( psOptions->papfnSrcPerBandValidityMaskFunc );
738 606 : CPLFree( psOptions->papSrcPerBandValidityMaskFuncArg );
739 :
740 606 : if( psOptions->hCutline != NULL )
741 9 : OGR_G_DestroyGeometry( (OGRGeometryH) psOptions->hCutline );
742 :
743 606 : CPLFree( psOptions );
744 : }
745 :
746 :
747 : #define COPY_MEM(target,type,count) \
748 : if( (psSrcOptions->target) != NULL && (count) != 0 ) \
749 : { \
750 : (psDstOptions->target) = (type *) CPLMalloc(sizeof(type)*count); \
751 : memcpy( (psDstOptions->target), (psSrcOptions->target), \
752 : sizeof(type) * count ); \
753 : }
754 :
755 : /************************************************************************/
756 : /* GDALCloneWarpOptions() */
757 : /************************************************************************/
758 :
759 : GDALWarpOptions * CPL_STDCALL
760 304 : GDALCloneWarpOptions( const GDALWarpOptions *psSrcOptions )
761 :
762 : {
763 304 : GDALWarpOptions *psDstOptions = GDALCreateWarpOptions();
764 :
765 304 : memcpy( psDstOptions, psSrcOptions, sizeof(GDALWarpOptions) );
766 :
767 304 : if( psSrcOptions->papszWarpOptions != NULL )
768 : psDstOptions->papszWarpOptions =
769 264 : CSLDuplicate( psSrcOptions->papszWarpOptions );
770 :
771 304 : COPY_MEM( panSrcBands, int, psSrcOptions->nBandCount );
772 304 : COPY_MEM( panDstBands, int, psSrcOptions->nBandCount );
773 304 : COPY_MEM( padfSrcNoDataReal, double, psSrcOptions->nBandCount );
774 304 : COPY_MEM( padfSrcNoDataImag, double, psSrcOptions->nBandCount );
775 304 : COPY_MEM( padfDstNoDataReal, double, psSrcOptions->nBandCount );
776 304 : COPY_MEM( padfDstNoDataImag, double, psSrcOptions->nBandCount );
777 304 : COPY_MEM( papfnSrcPerBandValidityMaskFunc, GDALMaskFunc,
778 : psSrcOptions->nBandCount );
779 :
780 304 : if( psSrcOptions->hCutline != NULL )
781 : psDstOptions->hCutline =
782 3 : OGR_G_Clone( (OGRGeometryH) psSrcOptions->hCutline );
783 304 : psDstOptions->dfCutlineBlendDist = psSrcOptions->dfCutlineBlendDist;
784 :
785 304 : return psDstOptions;
786 : }
787 :
788 : /************************************************************************/
789 : /* GDALSerializeWarpOptions() */
790 : /************************************************************************/
791 :
792 : CPLXMLNode * CPL_STDCALL
793 4 : GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
794 :
795 : {
796 : CPLXMLNode *psTree;
797 :
798 : /* -------------------------------------------------------------------- */
799 : /* Create root. */
800 : /* -------------------------------------------------------------------- */
801 4 : psTree = CPLCreateXMLNode( NULL, CXT_Element, "GDALWarpOptions" );
802 :
803 : /* -------------------------------------------------------------------- */
804 : /* WarpMemoryLimit */
805 : /* -------------------------------------------------------------------- */
806 : CPLCreateXMLElementAndValue(
807 : psTree, "WarpMemoryLimit",
808 4 : CPLString().Printf("%g", psWO->dfWarpMemoryLimit ) );
809 :
810 : /* -------------------------------------------------------------------- */
811 : /* ResampleAlg */
812 : /* -------------------------------------------------------------------- */
813 : const char *pszAlgName;
814 :
815 4 : if( psWO->eResampleAlg == GRA_NearestNeighbour )
816 4 : pszAlgName = "NearestNeighbour";
817 0 : else if( psWO->eResampleAlg == GRA_Bilinear )
818 0 : pszAlgName = "Bilinear";
819 0 : else if( psWO->eResampleAlg == GRA_Cubic )
820 0 : pszAlgName = "Cubic";
821 0 : else if( psWO->eResampleAlg == GRA_CubicSpline )
822 0 : pszAlgName = "CubicSpline";
823 0 : else if( psWO->eResampleAlg == GRA_Lanczos )
824 0 : pszAlgName = "Lanczos";
825 : else
826 0 : pszAlgName = "Unknown";
827 :
828 : CPLCreateXMLElementAndValue(
829 4 : psTree, "ResampleAlg", pszAlgName );
830 :
831 : /* -------------------------------------------------------------------- */
832 : /* Working Data Type */
833 : /* -------------------------------------------------------------------- */
834 :
835 : CPLCreateXMLElementAndValue(
836 : psTree, "WorkingDataType",
837 4 : GDALGetDataTypeName( psWO->eWorkingDataType ) );
838 :
839 : /* -------------------------------------------------------------------- */
840 : /* Name/value warp options. */
841 : /* -------------------------------------------------------------------- */
842 : int iWO;
843 :
844 10 : for( iWO = 0; psWO->papszWarpOptions != NULL
845 4 : && psWO->papszWarpOptions[iWO] != NULL; iWO++ )
846 : {
847 2 : char *pszName = NULL;
848 : const char *pszValue =
849 2 : CPLParseNameValue( psWO->papszWarpOptions[iWO], &pszName );
850 :
851 : CPLXMLNode *psOption =
852 : CPLCreateXMLElementAndValue(
853 2 : psTree, "Option", pszValue );
854 :
855 : CPLCreateXMLNode(
856 : CPLCreateXMLNode( psOption, CXT_Attribute, "name" ),
857 2 : CXT_Text, pszName );
858 :
859 2 : CPLFree(pszName);
860 : }
861 :
862 : /* -------------------------------------------------------------------- */
863 : /* Source and Destination Data Source */
864 : /* -------------------------------------------------------------------- */
865 4 : if( psWO->hSrcDS != NULL )
866 : {
867 : CPLCreateXMLElementAndValue(
868 : psTree, "SourceDataset",
869 4 : GDALGetDescription( psWO->hSrcDS ) );
870 : }
871 :
872 4 : if( psWO->hDstDS != NULL && strlen(GDALGetDescription(psWO->hDstDS)) != 0 )
873 : {
874 : CPLCreateXMLElementAndValue(
875 : psTree, "DestinationDataset",
876 0 : GDALGetDescription( psWO->hDstDS ) );
877 : }
878 :
879 : /* -------------------------------------------------------------------- */
880 : /* Serialize transformer. */
881 : /* -------------------------------------------------------------------- */
882 4 : if( psWO->pfnTransformer != NULL )
883 : {
884 : CPLXMLNode *psTransformerContainer;
885 : CPLXMLNode *psTransformerTree;
886 :
887 : psTransformerContainer =
888 4 : CPLCreateXMLNode( psTree, CXT_Element, "Transformer" );
889 :
890 : psTransformerTree =
891 : GDALSerializeTransformer( psWO->pfnTransformer,
892 4 : psWO->pTransformerArg );
893 :
894 4 : if( psTransformerTree != NULL )
895 4 : CPLAddXMLChild( psTransformerContainer, psTransformerTree );
896 : }
897 :
898 : /* -------------------------------------------------------------------- */
899 : /* Band count and lists. */
900 : /* -------------------------------------------------------------------- */
901 4 : CPLXMLNode *psBandList = NULL;
902 : int i;
903 :
904 4 : if( psWO->nBandCount != 0 )
905 4 : psBandList = CPLCreateXMLNode( psTree, CXT_Element, "BandList" );
906 :
907 10 : for( i = 0; i < psWO->nBandCount; i++ )
908 : {
909 : CPLXMLNode *psBand;
910 :
911 6 : psBand = CPLCreateXMLNode( psBandList, CXT_Element, "BandMapping" );
912 6 : if( psWO->panSrcBands != NULL )
913 : CPLCreateXMLNode(
914 : CPLCreateXMLNode( psBand, CXT_Attribute, "src" ),
915 6 : CXT_Text, CPLString().Printf( "%d", psWO->panSrcBands[i] ) );
916 6 : if( psWO->panDstBands != NULL )
917 : CPLCreateXMLNode(
918 : CPLCreateXMLNode( psBand, CXT_Attribute, "dst" ),
919 6 : CXT_Text, CPLString().Printf( "%d", psWO->panDstBands[i] ) );
920 :
921 6 : if( psWO->padfSrcNoDataReal != NULL )
922 : CPLCreateXMLElementAndValue(
923 : psBand, "SrcNoDataReal",
924 0 : CPLString().Printf( "%.16g", psWO->padfSrcNoDataReal[i] ) );
925 :
926 6 : if( psWO->padfSrcNoDataImag != NULL )
927 : CPLCreateXMLElementAndValue(
928 : psBand, "SrcNoDataImag",
929 0 : CPLString().Printf( "%.16g", psWO->padfSrcNoDataImag[i] ) );
930 :
931 6 : if( psWO->padfDstNoDataReal != NULL )
932 : CPLCreateXMLElementAndValue(
933 : psBand, "DstNoDataReal",
934 0 : CPLString().Printf( "%.16g", psWO->padfDstNoDataReal[i] ) );
935 :
936 6 : if( psWO->padfDstNoDataImag != NULL )
937 : CPLCreateXMLElementAndValue(
938 : psBand, "DstNoDataImag",
939 0 : CPLString().Printf( "%.16g", psWO->padfDstNoDataImag[i] ) );
940 : }
941 :
942 : /* -------------------------------------------------------------------- */
943 : /* Alpha bands. */
944 : /* -------------------------------------------------------------------- */
945 4 : if( psWO->nSrcAlphaBand > 0 )
946 : CPLCreateXMLElementAndValue(
947 : psTree, "SrcAlphaBand",
948 0 : CPLString().Printf( "%d", psWO->nSrcAlphaBand ) );
949 :
950 4 : if( psWO->nDstAlphaBand > 0 )
951 : CPLCreateXMLElementAndValue(
952 : psTree, "DstAlphaBand",
953 0 : CPLString().Printf( "%d", psWO->nDstAlphaBand ) );
954 :
955 : /* -------------------------------------------------------------------- */
956 : /* Cutline. */
957 : /* -------------------------------------------------------------------- */
958 4 : if( psWO->hCutline != NULL )
959 : {
960 0 : char *pszWKT = NULL;
961 0 : if( OGR_G_ExportToWkt( (OGRGeometryH) psWO->hCutline, &pszWKT )
962 : == OGRERR_NONE )
963 : {
964 0 : CPLCreateXMLElementAndValue( psTree, "Cutline", pszWKT );
965 0 : CPLFree( pszWKT );
966 : }
967 : }
968 :
969 4 : if( psWO->dfCutlineBlendDist != 0.0 )
970 : CPLCreateXMLElementAndValue(
971 : psTree, "CutlineBlendDist",
972 0 : CPLString().Printf( "%.5g", psWO->dfCutlineBlendDist ) );
973 :
974 4 : return psTree;
975 : }
976 :
977 : /************************************************************************/
978 : /* GDALDeserializeWarpOptions() */
979 : /************************************************************************/
980 :
981 34 : GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
982 :
983 : {
984 34 : CPLErrorReset();
985 :
986 : /* -------------------------------------------------------------------- */
987 : /* Verify this is the right kind of object. */
988 : /* -------------------------------------------------------------------- */
989 34 : if( psTree == NULL || psTree->eType != CXT_Element
990 : || !EQUAL(psTree->pszValue,"GDALWarpOptions") )
991 : {
992 : CPLError( CE_Failure, CPLE_AppDefined,
993 0 : "Wrong node, unable to deserialize GDALWarpOptions." );
994 0 : return NULL;
995 : }
996 :
997 : /* -------------------------------------------------------------------- */
998 : /* Create pre-initialized warp options. */
999 : /* -------------------------------------------------------------------- */
1000 34 : GDALWarpOptions *psWO = GDALCreateWarpOptions();
1001 :
1002 : /* -------------------------------------------------------------------- */
1003 : /* Warp memory limit. */
1004 : /* -------------------------------------------------------------------- */
1005 : psWO->dfWarpMemoryLimit =
1006 34 : atof(CPLGetXMLValue(psTree,"WarpMemoryLimit","0.0"));
1007 :
1008 : /* -------------------------------------------------------------------- */
1009 : /* resample algorithm */
1010 : /* -------------------------------------------------------------------- */
1011 : const char *pszValue =
1012 34 : CPLGetXMLValue(psTree,"ResampleAlg","Default");
1013 :
1014 34 : if( EQUAL(pszValue,"NearestNeighbour") )
1015 20 : psWO->eResampleAlg = GRA_NearestNeighbour;
1016 14 : else if( EQUAL(pszValue,"Bilinear") )
1017 4 : psWO->eResampleAlg = GRA_Bilinear;
1018 10 : else if( EQUAL(pszValue,"Cubic") )
1019 4 : psWO->eResampleAlg = GRA_Cubic;
1020 6 : else if( EQUAL(pszValue,"CubicSpline") )
1021 4 : psWO->eResampleAlg = GRA_CubicSpline;
1022 2 : else if( EQUAL(pszValue,"Lanczos") )
1023 2 : psWO->eResampleAlg = GRA_Lanczos;
1024 0 : else if( EQUAL(pszValue,"Default") )
1025 : /* leave as is */;
1026 : else
1027 : {
1028 : CPLError( CE_Failure, CPLE_AppDefined,
1029 : "Unrecognise ResampleAlg value '%s'.",
1030 0 : pszValue );
1031 : }
1032 :
1033 : /* -------------------------------------------------------------------- */
1034 : /* Working data type. */
1035 : /* -------------------------------------------------------------------- */
1036 : psWO->eWorkingDataType =
1037 : GDALGetDataTypeByName(
1038 34 : CPLGetXMLValue(psTree,"WorkingDataType","Unknown"));
1039 :
1040 : /* -------------------------------------------------------------------- */
1041 : /* Name/value warp options. */
1042 : /* -------------------------------------------------------------------- */
1043 : CPLXMLNode *psItem;
1044 :
1045 273 : for( psItem = psTree->psChild; psItem != NULL; psItem = psItem->psNext )
1046 : {
1047 239 : if( psItem->eType == CXT_Element
1048 : && EQUAL(psItem->pszValue,"Option") )
1049 : {
1050 16 : const char *pszName = CPLGetXMLValue(psItem, "Name", NULL );
1051 16 : const char *pszValue = CPLGetXMLValue(psItem, "", NULL );
1052 :
1053 16 : if( pszName != NULL && pszValue != NULL )
1054 : {
1055 : psWO->papszWarpOptions =
1056 : CSLSetNameValue( psWO->papszWarpOptions,
1057 16 : pszName, pszValue );
1058 : }
1059 : }
1060 : }
1061 :
1062 : /* -------------------------------------------------------------------- */
1063 : /* Source Dataset. */
1064 : /* -------------------------------------------------------------------- */
1065 34 : pszValue = CPLGetXMLValue(psTree,"SourceDataset",NULL);
1066 :
1067 34 : if( pszValue != NULL )
1068 34 : psWO->hSrcDS = GDALOpenShared( pszValue, GA_ReadOnly );
1069 :
1070 : /* -------------------------------------------------------------------- */
1071 : /* Destination Dataset. */
1072 : /* -------------------------------------------------------------------- */
1073 34 : pszValue = CPLGetXMLValue(psTree,"DestinationDataset",NULL);
1074 :
1075 34 : if( pszValue != NULL )
1076 0 : psWO->hDstDS = GDALOpenShared( pszValue, GA_Update );
1077 :
1078 : /* -------------------------------------------------------------------- */
1079 : /* First, count band mappings so we can establish the bandcount. */
1080 : /* -------------------------------------------------------------------- */
1081 34 : CPLXMLNode *psBandTree = CPLGetXMLNode( psTree, "BandList" );
1082 34 : CPLXMLNode *psBand = NULL;
1083 :
1084 34 : psWO->nBandCount = 0;
1085 :
1086 88 : for( psBand=psBandTree->psChild; psBand != NULL; psBand = psBand->psNext )
1087 : {
1088 54 : if( psBand->eType != CXT_Element
1089 : || !EQUAL(psBand->pszValue,"BandMapping") )
1090 0 : continue;
1091 :
1092 54 : psWO->nBandCount++;
1093 : }
1094 :
1095 : /* ==================================================================== */
1096 : /* Now actually process each bandmapping. */
1097 : /* ==================================================================== */
1098 34 : int iBand = 0;
1099 :
1100 88 : for( psBand=psBandTree->psChild; psBand != NULL; psBand = psBand->psNext )
1101 : {
1102 54 : if( psBand->eType != CXT_Element
1103 : || !EQUAL(psBand->pszValue,"BandMapping") )
1104 0 : continue;
1105 :
1106 : /* -------------------------------------------------------------------- */
1107 : /* Source band */
1108 : /* -------------------------------------------------------------------- */
1109 54 : if( psWO->panSrcBands == NULL )
1110 34 : psWO->panSrcBands = (int *)CPLMalloc(sizeof(int)*psWO->nBandCount);
1111 :
1112 54 : pszValue = CPLGetXMLValue(psBand,"src",NULL);
1113 54 : if( pszValue == NULL )
1114 0 : psWO->panSrcBands[iBand] = iBand+1;
1115 : else
1116 54 : psWO->panSrcBands[iBand] = atoi(pszValue);
1117 :
1118 : /* -------------------------------------------------------------------- */
1119 : /* Destination band. */
1120 : /* -------------------------------------------------------------------- */
1121 54 : pszValue = CPLGetXMLValue(psBand,"dst",NULL);
1122 54 : if( pszValue != NULL )
1123 : {
1124 54 : if( psWO->panDstBands == NULL )
1125 : psWO->panDstBands =
1126 34 : (int *) CPLMalloc(sizeof(int)*psWO->nBandCount);
1127 :
1128 54 : psWO->panDstBands[iBand] = atoi(pszValue);
1129 : }
1130 :
1131 : /* -------------------------------------------------------------------- */
1132 : /* Source nodata. */
1133 : /* -------------------------------------------------------------------- */
1134 54 : pszValue = CPLGetXMLValue(psBand,"SrcNoDataReal",NULL);
1135 54 : if( pszValue != NULL )
1136 : {
1137 1 : if( psWO->padfSrcNoDataReal == NULL )
1138 : psWO->padfSrcNoDataReal =
1139 1 : (double *) CPLCalloc(sizeof(double),psWO->nBandCount);
1140 :
1141 1 : psWO->padfSrcNoDataReal[iBand] = atof(pszValue);
1142 : }
1143 :
1144 54 : pszValue = CPLGetXMLValue(psBand,"SrcNoDataImag",NULL);
1145 54 : if( pszValue != NULL )
1146 : {
1147 1 : if( psWO->padfSrcNoDataImag == NULL )
1148 : psWO->padfSrcNoDataImag =
1149 1 : (double *) CPLCalloc(sizeof(double),psWO->nBandCount);
1150 :
1151 1 : psWO->padfSrcNoDataImag[iBand] = atof(pszValue);
1152 : }
1153 :
1154 : /* -------------------------------------------------------------------- */
1155 : /* Destination nodata. */
1156 : /* -------------------------------------------------------------------- */
1157 54 : pszValue = CPLGetXMLValue(psBand,"DstNoDataReal",NULL);
1158 54 : if( pszValue != NULL )
1159 : {
1160 1 : if( psWO->padfDstNoDataReal == NULL )
1161 : psWO->padfDstNoDataReal =
1162 1 : (double *) CPLCalloc(sizeof(double),psWO->nBandCount);
1163 :
1164 1 : psWO->padfDstNoDataReal[iBand] = atof(pszValue);
1165 : }
1166 :
1167 54 : pszValue = CPLGetXMLValue(psBand,"DstNoDataImag",NULL);
1168 54 : if( pszValue != NULL )
1169 : {
1170 1 : if( psWO->padfDstNoDataImag == NULL )
1171 : psWO->padfDstNoDataImag =
1172 1 : (double *) CPLCalloc(sizeof(double),psWO->nBandCount);
1173 :
1174 1 : psWO->padfDstNoDataImag[iBand] = atof(pszValue);
1175 : }
1176 :
1177 54 : iBand++;
1178 : }
1179 :
1180 : /* -------------------------------------------------------------------- */
1181 : /* Alpha bands. */
1182 : /* -------------------------------------------------------------------- */
1183 : psWO->nSrcAlphaBand =
1184 34 : atoi( CPLGetXMLValue( psTree, "SrcAlphaBand", "0" ) );
1185 : psWO->nDstAlphaBand =
1186 34 : atoi( CPLGetXMLValue( psTree, "DstAlphaBand", "0" ) );
1187 :
1188 : /* -------------------------------------------------------------------- */
1189 : /* Cutline. */
1190 : /* -------------------------------------------------------------------- */
1191 34 : const char *pszWKT = CPLGetXMLValue( psTree, "Cutline", NULL );
1192 34 : if( pszWKT )
1193 : {
1194 : OGR_G_CreateFromWkt( (char **) &pszWKT, NULL,
1195 3 : (OGRGeometryH *) (&psWO->hCutline) );
1196 : }
1197 :
1198 : psWO->dfCutlineBlendDist =
1199 34 : atof( CPLGetXMLValue( psTree, "CutlineBlendDist", "0" ) );
1200 :
1201 : /* -------------------------------------------------------------------- */
1202 : /* Transformation. */
1203 : /* -------------------------------------------------------------------- */
1204 34 : CPLXMLNode *psTransformer = CPLGetXMLNode( psTree, "Transformer" );
1205 :
1206 34 : if( psTransformer != NULL && psTransformer->psChild != NULL )
1207 : {
1208 : GDALDeserializeTransformer( psTransformer->psChild,
1209 : &(psWO->pfnTransformer),
1210 34 : &(psWO->pTransformerArg) );
1211 : }
1212 :
1213 : /* -------------------------------------------------------------------- */
1214 : /* If any error has occured, cleanup else return success. */
1215 : /* -------------------------------------------------------------------- */
1216 34 : if( CPLGetLastErrorNo() != CE_None )
1217 : {
1218 0 : if ( psWO->pTransformerArg )
1219 : {
1220 0 : GDALDestroyTransformer( psWO->pTransformerArg );
1221 0 : psWO->pTransformerArg = NULL;
1222 : }
1223 0 : if( psWO->hSrcDS != NULL )
1224 : {
1225 0 : GDALClose( psWO->hSrcDS );
1226 0 : psWO->hSrcDS = NULL;
1227 : }
1228 0 : if( psWO->hDstDS != NULL )
1229 : {
1230 0 : GDALClose( psWO->hDstDS );
1231 0 : psWO->hDstDS = NULL;
1232 : }
1233 0 : GDALDestroyWarpOptions( psWO );
1234 0 : return NULL;
1235 : }
1236 : else
1237 34 : return psWO;
1238 : }
|