1 : /******************************************************************************
2 : * $Id: gdalwarpkernel.cpp 18012 2009-11-13 06:20:52Z warmerdam $
3 : *
4 : * Project: High Performance Image Reprojector
5 : * Purpose: Implementation of the GDALWarpKernel class. Implements the actual
6 : * image warping for a "chunk" of input and output imagery already
7 : * loaded into memory.
8 : * Author: Frank Warmerdam, warmerdam@pobox.com
9 : *
10 : ******************************************************************************
11 : * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
12 : *
13 : * Permission is hereby granted, free of charge, to any person obtaining a
14 : * copy of this software and associated documentation files (the "Software"),
15 : * to deal in the Software without restriction, including without limitation
16 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 : * and/or sell copies of the Software, and to permit persons to whom the
18 : * Software is furnished to do so, subject to the following conditions:
19 : *
20 : * The above copyright notice and this permission notice shall be included
21 : * in all copies or substantial portions of the Software.
22 : *
23 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 : * DEALINGS IN THE SOFTWARE.
30 : ****************************************************************************/
31 :
32 : #include "gdalwarper.h"
33 : #include "cpl_string.h"
34 :
35 : CPL_CVSID("$Id: gdalwarpkernel.cpp 18012 2009-11-13 06:20:52Z warmerdam $");
36 :
37 : static const int anGWKFilterRadius[] =
38 : {
39 : 0, // Nearest neighbour
40 : 1, // Bilinear
41 : 2, // Cubic Convolution
42 : 2, // Cubic B-Spline
43 : 3 // Lanczos windowed sinc
44 : };
45 :
46 : /* Used in gdalwarpoperation.cpp */
47 330 : int GWKGetFilterRadius(GDALResampleAlg eResampleAlg)
48 : {
49 330 : return anGWKFilterRadius[eResampleAlg];
50 : }
51 :
52 : static CPLErr GWKGeneralCase( GDALWarpKernel * );
53 : static CPLErr GWKNearestNoMasksByte( GDALWarpKernel *poWK );
54 : static CPLErr GWKBilinearNoMasksByte( GDALWarpKernel *poWK );
55 : static CPLErr GWKCubicNoMasksByte( GDALWarpKernel *poWK );
56 : static CPLErr GWKCubicSplineNoMasksByte( GDALWarpKernel *poWK );
57 : static CPLErr GWKNearestByte( GDALWarpKernel *poWK );
58 : static CPLErr GWKNearestNoMasksShort( GDALWarpKernel *poWK );
59 : static CPLErr GWKBilinearNoMasksShort( GDALWarpKernel *poWK );
60 : static CPLErr GWKCubicNoMasksShort( GDALWarpKernel *poWK );
61 : static CPLErr GWKCubicSplineNoMasksShort( GDALWarpKernel *poWK );
62 : static CPLErr GWKNearestShort( GDALWarpKernel *poWK );
63 : static CPLErr GWKNearestNoMasksFloat( GDALWarpKernel *poWK );
64 : static CPLErr GWKNearestFloat( GDALWarpKernel *poWK );
65 :
66 : /************************************************************************/
67 : /* ==================================================================== */
68 : /* GDALWarpKernel */
69 : /* ==================================================================== */
70 : /************************************************************************/
71 :
72 : /**
73 : * \class GDALWarpKernel "gdalwarper.h"
74 : *
75 : * Low level image warping class.
76 : *
77 : * This class is responsible for low level image warping for one
78 : * "chunk" of imagery. The class is essentially a structure with all
79 : * data members public - primarily so that new special-case functions
80 : * can be added without changing the class declaration.
81 : *
82 : * Applications are normally intended to interactive with warping facilities
83 : * through the GDALWarpOperation class, though the GDALWarpKernel can in
84 : * theory be used directly if great care is taken in setting up the
85 : * control data.
86 : *
87 : * <h3>Design Issues</h3>
88 : *
89 : * My intention is that PerformWarp() would analyse the setup in terms
90 : * of the datatype, resampling type, and validity/density mask usage and
91 : * pick one of many specific implementations of the warping algorithm over
92 : * a continuim of optimization vs. generality. At one end there will be a
93 : * reference general purpose implementation of the algorithm that supports
94 : * any data type (working internally in double precision complex), all three
95 : * resampling types, and any or all of the validity/density masks. At the
96 : * other end would be highly optimized algorithms for common cases like
97 : * nearest neighbour resampling on GDT_Byte data with no masks.
98 : *
99 : * The full set of optimized versions have not been decided but we should
100 : * expect to have at least:
101 : * - One for each resampling algorithm for 8bit data with no masks.
102 : * - One for each resampling algorithm for float data with no masks.
103 : * - One for each resampling algorithm for float data with any/all masks
104 : * (essentially the generic case for just float data).
105 : * - One for each resampling algorithm for 8bit data with support for
106 : * input validity masks (per band or per pixel). This handles the common
107 : * case of nodata masking.
108 : * - One for each resampling algorithm for float data with support for
109 : * input validity masks (per band or per pixel). This handles the common
110 : * case of nodata masking.
111 : *
112 : * Some of the specializations would operate on all bands in one pass
113 : * (especially the ones without masking would do this), while others might
114 : * process each band individually to reduce code complexity.
115 : *
116 : * <h3>Masking Semantics</h3>
117 : *
118 : * A detailed explanation of the semantics of the validity and density masks,
119 : * and their effects on resampling kernels is needed here.
120 : */
121 :
122 : /************************************************************************/
123 : /* GDALWarpKernel Data Members */
124 : /************************************************************************/
125 :
126 : /**
127 : * \var GDALResampleAlg GDALWarpKernel::eResample;
128 : *
129 : * Resampling algorithm.
130 : *
131 : * The resampling algorithm to use. One of GRA_NearestNeighbour,
132 : * GRA_Bilinear, or GRA_Cubic.
133 : *
134 : * This field is required. GDT_NearestNeighbour may be used as a default
135 : * value.
136 : */
137 :
138 : /**
139 : * \var GDALDataType GDALWarpKernel::eWorkingDataType;
140 : *
141 : * Working pixel data type.
142 : *
143 : * The datatype of pixels in the source image (papabySrcimage) and
144 : * destination image (papabyDstImage) buffers. Note that operations on
145 : * some data types (such as GDT_Byte) may be much better optimized than other
146 : * less common cases.
147 : *
148 : * This field is required. It may not be GDT_Unknown.
149 : */
150 :
151 : /**
152 : * \var int GDALWarpKernel::nBands;
153 : *
154 : * Number of bands.
155 : *
156 : * The number of bands (layers) of imagery being warped. Determines the
157 : * number of entries in the papabySrcImage, papanBandSrcValid,
158 : * and papabyDstImage arrays.
159 : *
160 : * This field is required.
161 : */
162 :
163 : /**
164 : * \var int GDALWarpKernel::nSrcXSize;
165 : *
166 : * Source image width in pixels.
167 : *
168 : * This field is required.
169 : */
170 :
171 : /**
172 : * \var int GDALWarpKernel::nSrcYSize;
173 : *
174 : * Source image height in pixels.
175 : *
176 : * This field is required.
177 : */
178 :
179 : /**
180 : * \var int GDALWarpKernel::papabySrcImage;
181 : *
182 : * Array of source image band data.
183 : *
184 : * This is an array of pointers (of size GDALWarpKernel::nBands) pointers
185 : * to image data. Each individual band of image data is organized as a single
186 : * block of image data in left to right, then bottom to top order. The actual
187 : * type of the image data is determined by GDALWarpKernel::eWorkingDataType.
188 : *
189 : * To access the the pixel value for the (x=3,y=4) pixel (zero based) of
190 : * the second band with eWorkingDataType set to GDT_Float32 use code like
191 : * this:
192 : *
193 : * \code
194 : * float dfPixelValue;
195 : * int nBand = 1; // band indexes are zero based.
196 : * int nPixel = 3; // zero based
197 : * int nLine = 4; // zero based
198 : *
199 : * assert( nPixel >= 0 && nPixel < poKern->nSrcXSize );
200 : * assert( nLine >= 0 && nLine < poKern->nSrcYSize );
201 : * assert( nBand >= 0 && nBand < poKern->nBands );
202 : * dfPixelValue = ((float *) poKern->papabySrcImage[nBand-1])
203 : * [nPixel + nLine * poKern->nSrcXSize];
204 : * \endcode
205 : *
206 : * This field is required.
207 : */
208 :
209 : /**
210 : * \var GUInt32 **GDALWarpKernel::papanBandSrcValid;
211 : *
212 : * Per band validity mask for source pixels.
213 : *
214 : * Array of pixel validity mask layers for each source band. Each of
215 : * the mask layers is the same size (in pixels) as the source image with
216 : * one bit per pixel. Note that it is legal (and common) for this to be
217 : * NULL indicating that none of the pixels are invalidated, or for some
218 : * band validity masks to be NULL in which case all pixels of the band are
219 : * valid. The following code can be used to test the validity of a particular
220 : * pixel.
221 : *
222 : * \code
223 : * int bIsValid = TRUE;
224 : * int nBand = 1; // band indexes are zero based.
225 : * int nPixel = 3; // zero based
226 : * int nLine = 4; // zero based
227 : *
228 : * assert( nPixel >= 0 && nPixel < poKern->nSrcXSize );
229 : * assert( nLine >= 0 && nLine < poKern->nSrcYSize );
230 : * assert( nBand >= 0 && nBand < poKern->nBands );
231 : *
232 : * if( poKern->papanBandSrcValid != NULL
233 : * && poKern->papanBandSrcValid[nBand] != NULL )
234 : * {
235 : * GUInt32 *panBandMask = poKern->papanBandSrcValid[nBand];
236 : * int iPixelOffset = nPixel + nLine * poKern->nSrcXSize;
237 : *
238 : * bIsValid = panBandMask[iPixelOffset>>5]
239 : * & (0x01 << (iPixelOffset & 0x1f));
240 : * }
241 : * \endcode
242 : */
243 :
244 : /**
245 : * \var GUInt32 *GDALWarpKernel::panUnifiedSrcValid;
246 : *
247 : * Per pixel validity mask for source pixels.
248 : *
249 : * A single validity mask layer that applies to the pixels of all source
250 : * bands. It is accessed similarly to papanBandSrcValid, but without the
251 : * extra level of band indirection.
252 : *
253 : * This pointer may be NULL indicating that all pixels are valid.
254 : *
255 : * Note that if both panUnifiedSrcValid, and papanBandSrcValid are available,
256 : * the pixel isn't considered to be valid unless both arrays indicate it is
257 : * valid.
258 : */
259 :
260 : /**
261 : * \var float *GDALWarpKernel::pafUnifiedSrcDensity;
262 : *
263 : * Per pixel density mask for source pixels.
264 : *
265 : * A single density mask layer that applies to the pixels of all source
266 : * bands. It contains values between 0.0 and 1.0 indicating the degree to
267 : * which this pixel should be allowed to contribute to the output result.
268 : *
269 : * This pointer may be NULL indicating that all pixels have a density of 1.0.
270 : *
271 : * The density for a pixel may be accessed like this:
272 : *
273 : * \code
274 : * float fDensity = 1.0;
275 : * int nPixel = 3; // zero based
276 : * int nLine = 4; // zero based
277 : *
278 : * assert( nPixel >= 0 && nPixel < poKern->nSrcXSize );
279 : * assert( nLine >= 0 && nLine < poKern->nSrcYSize );
280 : * if( poKern->pafUnifiedSrcDensity != NULL )
281 : * fDensity = poKern->pafUnifiedSrcDensity
282 : * [nPixel + nLine * poKern->nSrcXSize];
283 : * \endcode
284 : */
285 :
286 : /**
287 : * \var int GDALWarpKernel::nDstXSize;
288 : *
289 : * Width of destination image in pixels.
290 : *
291 : * This field is required.
292 : */
293 :
294 : /**
295 : * \var int GDALWarpKernel::nDstYSize;
296 : *
297 : * Height of destination image in pixels.
298 : *
299 : * This field is required.
300 : */
301 :
302 : /**
303 : * \var GByte **GDALWarpKernel::papabyDstImage;
304 : *
305 : * Array of destination image band data.
306 : *
307 : * This is an array of pointers (of size GDALWarpKernel::nBands) pointers
308 : * to image data. Each individual band of image data is organized as a single
309 : * block of image data in left to right, then bottom to top order. The actual
310 : * type of the image data is determined by GDALWarpKernel::eWorkingDataType.
311 : *
312 : * To access the the pixel value for the (x=3,y=4) pixel (zero based) of
313 : * the second band with eWorkingDataType set to GDT_Float32 use code like
314 : * this:
315 : *
316 : * \code
317 : * float dfPixelValue;
318 : * int nBand = 1; // band indexes are zero based.
319 : * int nPixel = 3; // zero based
320 : * int nLine = 4; // zero based
321 : *
322 : * assert( nPixel >= 0 && nPixel < poKern->nDstXSize );
323 : * assert( nLine >= 0 && nLine < poKern->nDstYSize );
324 : * assert( nBand >= 0 && nBand < poKern->nBands );
325 : * dfPixelValue = ((float *) poKern->papabyDstImage[nBand-1])
326 : * [nPixel + nLine * poKern->nSrcYSize];
327 : * \endcode
328 : *
329 : * This field is required.
330 : */
331 :
332 : /**
333 : * \var GUInt32 *GDALWarpKernel::panDstValid;
334 : *
335 : * Per pixel validity mask for destination pixels.
336 : *
337 : * A single validity mask layer that applies to the pixels of all destination
338 : * bands. It is accessed similarly to papanUnitifiedSrcValid, but based
339 : * on the size of the destination image.
340 : *
341 : * This pointer may be NULL indicating that all pixels are valid.
342 : */
343 :
344 : /**
345 : * \var float *GDALWarpKernel::pafDstDensity;
346 : *
347 : * Per pixel density mask for destination pixels.
348 : *
349 : * A single density mask layer that applies to the pixels of all destination
350 : * bands. It contains values between 0.0 and 1.0.
351 : *
352 : * This pointer may be NULL indicating that all pixels have a density of 1.0.
353 : *
354 : * The density for a pixel may be accessed like this:
355 : *
356 : * \code
357 : * float fDensity = 1.0;
358 : * int nPixel = 3; // zero based
359 : * int nLine = 4; // zero based
360 : *
361 : * assert( nPixel >= 0 && nPixel < poKern->nDstXSize );
362 : * assert( nLine >= 0 && nLine < poKern->nDstYSize );
363 : * if( poKern->pafDstDensity != NULL )
364 : * fDensity = poKern->pafDstDensity[nPixel + nLine * poKern->nDstXSize];
365 : * \endcode
366 : */
367 :
368 : /**
369 : * \var int GDALWarpKernel::nSrcXOff;
370 : *
371 : * X offset to source pixel coordinates for transformation.
372 : *
373 : * See pfnTransformer.
374 : *
375 : * This field is required.
376 : */
377 :
378 : /**
379 : * \var int GDALWarpKernel::nSrcYOff;
380 : *
381 : * Y offset to source pixel coordinates for transformation.
382 : *
383 : * See pfnTransformer.
384 : *
385 : * This field is required.
386 : */
387 :
388 : /**
389 : * \var int GDALWarpKernel::nDstXOff;
390 : *
391 : * X offset to destination pixel coordinates for transformation.
392 : *
393 : * See pfnTransformer.
394 : *
395 : * This field is required.
396 : */
397 :
398 : /**
399 : * \var int GDALWarpKernel::nDstYOff;
400 : *
401 : * Y offset to destination pixel coordinates for transformation.
402 : *
403 : * See pfnTransformer.
404 : *
405 : * This field is required.
406 : */
407 :
408 : /**
409 : * \var GDALTransformerFunc GDALWarpKernel::pfnTransformer;
410 : *
411 : * Source/destination location transformer.
412 : *
413 : * The function to call to transform coordinates between source image
414 : * pixel/line coordinates and destination image pixel/line coordinates.
415 : * See GDALTransformerFunc() for details of the semantics of this function.
416 : *
417 : * The GDALWarpKern algorithm will only ever use this transformer in
418 : * "destination to source" mode (bDstToSrc=TRUE), and will always pass
419 : * partial or complete scanlines of points in the destination image as
420 : * input. This means, amoung other things, that it is safe to the the
421 : * approximating transform GDALApproxTransform() as the transformation
422 : * function.
423 : *
424 : * Source and destination images may be subsets of a larger overall image.
425 : * The transformation algorithms will expect and return pixel/line coordinates
426 : * in terms of this larger image, so coordinates need to be offset by
427 : * the offsets specified in nSrcXOff, nSrcYOff, nDstXOff, and nDstYOff before
428 : * passing to pfnTransformer, and after return from it.
429 : *
430 : * The GDALWarpKernel::pfnTransformerArg value will be passed as the callback
431 : * data to this function when it is called.
432 : *
433 : * This field is required.
434 : */
435 :
436 : /**
437 : * \var void *GDALWarpKernel::pTransformerArg;
438 : *
439 : * Callback data for pfnTransformer.
440 : *
441 : * This field may be NULL if not required for the pfnTransformer being used.
442 : */
443 :
444 : /**
445 : * \var GDALProgressFunc GDALWarpKernel::pfnProgress;
446 : *
447 : * The function to call to report progress of the algorithm, and to check
448 : * for a requested termination of the operation. It operates according to
449 : * GDALProgressFunc() semantics.
450 : *
451 : * Generally speaking the progress function will be invoked for each
452 : * scanline of the destination buffer that has been processed.
453 : *
454 : * This field may be NULL (internally set to GDALDummyProgress()).
455 : */
456 :
457 : /**
458 : * \var void *GDALWarpKernel::pProgress;
459 : *
460 : * Callback data for pfnProgress.
461 : *
462 : * This field may be NULL if not required for the pfnProgress being used.
463 : */
464 :
465 :
466 : /************************************************************************/
467 : /* GDALWarpKernel() */
468 : /************************************************************************/
469 :
470 330 : GDALWarpKernel::GDALWarpKernel()
471 :
472 : {
473 330 : eResample = GRA_NearestNeighbour;
474 330 : eWorkingDataType = GDT_Unknown;
475 330 : nBands = 0;
476 330 : nDstXOff = 0;
477 330 : nDstYOff = 0;
478 330 : nDstXSize = 0;
479 330 : nDstYSize = 0;
480 330 : nSrcXOff = 0;
481 330 : nSrcYOff = 0;
482 330 : nSrcXSize = 0;
483 330 : nSrcYSize = 0;
484 330 : dfXScale = 1.0;
485 330 : dfYScale = 1.0;
486 330 : dfXFilter = 0.0;
487 330 : dfYFilter = 0.0;
488 330 : nXRadius = 0;
489 330 : nYRadius = 0;
490 330 : nFiltInitX = 0;
491 330 : nFiltInitY = 0;
492 330 : pafDstDensity = NULL;
493 330 : pafUnifiedSrcDensity = NULL;
494 330 : panDstValid = NULL;
495 330 : panUnifiedSrcValid = NULL;
496 330 : papabyDstImage = NULL;
497 330 : papabySrcImage = NULL;
498 330 : papanBandSrcValid = NULL;
499 330 : pfnProgress = GDALDummyProgress;
500 330 : pProgress = NULL;
501 330 : dfProgressBase = 0.0;
502 330 : dfProgressScale = 1.0;
503 330 : pfnTransformer = NULL;
504 330 : pTransformerArg = NULL;
505 330 : papszWarpOptions = NULL;
506 330 : }
507 :
508 : /************************************************************************/
509 : /* ~GDALWarpKernel() */
510 : /************************************************************************/
511 :
512 330 : GDALWarpKernel::~GDALWarpKernel()
513 :
514 : {
515 330 : }
516 :
517 : /************************************************************************/
518 : /* PerformWarp() */
519 : /************************************************************************/
520 :
521 : /**
522 : * \fn CPLErr GDALWarpKernel::PerformWarp();
523 : *
524 : * This method performs the warp described in the GDALWarpKernel.
525 : *
526 : * @return CE_None on success or CE_Failure if an error occurs.
527 : */
528 :
529 330 : CPLErr GDALWarpKernel::PerformWarp()
530 :
531 : {
532 : CPLErr eErr;
533 :
534 330 : if( (eErr = Validate()) != CE_None )
535 0 : return eErr;
536 :
537 : // See #2445 and #3079
538 330 : if (nSrcXSize <= 0 || nSrcYSize <= 0)
539 : {
540 : pfnProgress( dfProgressBase + dfProgressScale,
541 0 : "", pProgress );
542 0 : return CE_None;
543 : }
544 :
545 : /* -------------------------------------------------------------------- */
546 : /* Pre-calculate resampling scales and window sizes for filtering. */
547 : /* -------------------------------------------------------------------- */
548 :
549 330 : dfXScale = (double)nDstXSize / nSrcXSize;
550 330 : dfYScale = (double)nDstYSize / nSrcYSize;
551 :
552 330 : dfXFilter = anGWKFilterRadius[eResample];
553 330 : dfYFilter = anGWKFilterRadius[eResample];
554 :
555 : nXRadius = ( dfXScale < 1.0 ) ?
556 330 : (int)ceil( dfXFilter / dfXScale ) :(int)dfXFilter;
557 : nYRadius = ( dfYScale < 1.0 ) ?
558 330 : (int)ceil( dfYFilter / dfYScale ) : (int)dfYFilter;
559 :
560 : // Filter window offset depends on the parity of the kernel radius
561 330 : nFiltInitX = ((anGWKFilterRadius[eResample] + 1) % 2) - nXRadius;
562 330 : nFiltInitY = ((anGWKFilterRadius[eResample] + 1) % 2) - nYRadius;
563 :
564 : /* -------------------------------------------------------------------- */
565 : /* Set up resampling functions. */
566 : /* -------------------------------------------------------------------- */
567 330 : if( CSLFetchBoolean( papszWarpOptions, "USE_GENERAL_CASE", FALSE ) )
568 0 : return GWKGeneralCase( this );
569 :
570 330 : if( eWorkingDataType == GDT_Byte
571 : && eResample == GRA_NearestNeighbour
572 : && papanBandSrcValid == NULL
573 : && panUnifiedSrcValid == NULL
574 : && pafUnifiedSrcDensity == NULL
575 : && panDstValid == NULL
576 : && pafDstDensity == NULL )
577 35 : return GWKNearestNoMasksByte( this );
578 :
579 295 : if( eWorkingDataType == GDT_Byte
580 : && eResample == GRA_Bilinear
581 : && papanBandSrcValid == NULL
582 : && panUnifiedSrcValid == NULL
583 : && pafUnifiedSrcDensity == NULL
584 : && panDstValid == NULL
585 : && pafDstDensity == NULL )
586 10 : return GWKBilinearNoMasksByte( this );
587 :
588 285 : if( eWorkingDataType == GDT_Byte
589 : && eResample == GRA_Cubic
590 : && papanBandSrcValid == NULL
591 : && panUnifiedSrcValid == NULL
592 : && pafUnifiedSrcDensity == NULL
593 : && panDstValid == NULL
594 : && pafDstDensity == NULL )
595 10 : return GWKCubicNoMasksByte( this );
596 :
597 275 : if( eWorkingDataType == GDT_Byte
598 : && eResample == GRA_CubicSpline
599 : && papanBandSrcValid == NULL
600 : && panUnifiedSrcValid == NULL
601 : && pafUnifiedSrcDensity == NULL
602 : && panDstValid == NULL
603 : && pafDstDensity == NULL )
604 10 : return GWKCubicSplineNoMasksByte( this );
605 :
606 265 : if( eWorkingDataType == GDT_Byte
607 : && eResample == GRA_NearestNeighbour )
608 10 : return GWKNearestByte( this );
609 :
610 255 : if( (eWorkingDataType == GDT_Int16 || eWorkingDataType == GDT_UInt16)
611 : && eResample == GRA_NearestNeighbour
612 : && papanBandSrcValid == NULL
613 : && panUnifiedSrcValid == NULL
614 : && pafUnifiedSrcDensity == NULL
615 : && panDstValid == NULL
616 : && pafDstDensity == NULL )
617 14 : return GWKNearestNoMasksShort( this );
618 :
619 241 : if( (eWorkingDataType == GDT_Int16 )
620 : && eResample == GRA_Cubic
621 : && papanBandSrcValid == NULL
622 : && panUnifiedSrcValid == NULL
623 : && pafUnifiedSrcDensity == NULL
624 : && panDstValid == NULL
625 : && pafDstDensity == NULL )
626 8 : return GWKCubicNoMasksShort( this );
627 :
628 233 : if( (eWorkingDataType == GDT_Int16 )
629 : && eResample == GRA_CubicSpline
630 : && papanBandSrcValid == NULL
631 : && panUnifiedSrcValid == NULL
632 : && pafUnifiedSrcDensity == NULL
633 : && panDstValid == NULL
634 : && pafDstDensity == NULL )
635 8 : return GWKCubicSplineNoMasksShort( this );
636 :
637 225 : if( (eWorkingDataType == GDT_Int16 )
638 : && eResample == GRA_Bilinear
639 : && papanBandSrcValid == NULL
640 : && panUnifiedSrcValid == NULL
641 : && pafUnifiedSrcDensity == NULL
642 : && panDstValid == NULL
643 : && pafDstDensity == NULL )
644 19 : return GWKBilinearNoMasksShort( this );
645 :
646 206 : if( (eWorkingDataType == GDT_Int16 || eWorkingDataType == GDT_UInt16)
647 : && eResample == GRA_NearestNeighbour )
648 7 : return GWKNearestShort( this );
649 :
650 199 : if( eWorkingDataType == GDT_Float32
651 : && eResample == GRA_NearestNeighbour
652 : && papanBandSrcValid == NULL
653 : && panUnifiedSrcValid == NULL
654 : && pafUnifiedSrcDensity == NULL
655 : && panDstValid == NULL
656 : && pafDstDensity == NULL )
657 8 : return GWKNearestNoMasksFloat( this );
658 :
659 191 : if( eWorkingDataType == GDT_Float32
660 : && eResample == GRA_NearestNeighbour )
661 2 : return GWKNearestFloat( this );
662 :
663 189 : return GWKGeneralCase( this );
664 : }
665 :
666 : /************************************************************************/
667 : /* Validate() */
668 : /************************************************************************/
669 :
670 : /**
671 : * \fn CPLErr GDALWarpKernel::Validate()
672 : *
673 : * Check the settings in the GDALWarpKernel, and issue a CPLError()
674 : * (and return CE_Failure) if the configuration is considered to be
675 : * invalid for some reason.
676 : *
677 : * This method will also do some standard defaulting such as setting
678 : * pfnProgress to GDALDummyProgress() if it is NULL.
679 : *
680 : * @return CE_None on success or CE_Failure if an error is detected.
681 : */
682 :
683 330 : CPLErr GDALWarpKernel::Validate()
684 :
685 : {
686 330 : if ( (size_t)eResample >=
687 : (sizeof(anGWKFilterRadius) / sizeof(anGWKFilterRadius[0])) )
688 : {
689 : CPLError( CE_Failure, CPLE_AppDefined,
690 0 : "Unsupported resampling method %d.", (int) eResample );
691 0 : return CE_Failure;
692 : }
693 :
694 330 : return CE_None;
695 : }
696 :
697 : /************************************************************************/
698 : /* GWKOverlayDensity() */
699 : /* */
700 : /* Compute the final density for the destination pixel. This */
701 : /* is a function of the overlay density (passed in) and the */
702 : /* original density. */
703 : /************************************************************************/
704 :
705 1789850 : static void GWKOverlayDensity( GDALWarpKernel *poWK, int iDstOffset,
706 : double dfDensity )
707 : {
708 1789850 : if( dfDensity < 0.0001 || poWK->pafDstDensity == NULL )
709 1784048 : return;
710 :
711 5802 : poWK->pafDstDensity[iDstOffset] = (float)
712 5802 : ( 1.0 - (1.0 - dfDensity) * (1.0 - poWK->pafDstDensity[iDstOffset]) );
713 : }
714 :
715 : /************************************************************************/
716 : /* GWKSetPixelValue() */
717 : /************************************************************************/
718 :
719 282451 : static int GWKSetPixelValue( GDALWarpKernel *poWK, int iBand,
720 : int iDstOffset, double dfDensity,
721 : double dfReal, double dfImag )
722 :
723 : {
724 282451 : GByte *pabyDst = poWK->papabyDstImage[iBand];
725 :
726 : /* -------------------------------------------------------------------- */
727 : /* If the source density is less than 100% we need to fetch the */
728 : /* existing destination value, and mix it with the source to */
729 : /* get the new "to apply" value. Also compute composite */
730 : /* density. */
731 : /* */
732 : /* We avoid mixing if density is very near one or risk mixing */
733 : /* in very extreme nodata values and causing odd results (#1610) */
734 : /* -------------------------------------------------------------------- */
735 282451 : if( dfDensity < 0.9999 )
736 : {
737 1472 : double dfDstReal, dfDstImag, dfDstDensity = 1.0;
738 :
739 1472 : if( dfDensity < 0.0001 )
740 0 : return TRUE;
741 :
742 1472 : if( poWK->pafDstDensity != NULL )
743 0 : dfDstDensity = poWK->pafDstDensity[iDstOffset];
744 1472 : else if( poWK->panDstValid != NULL
745 0 : && !((poWK->panDstValid[iDstOffset>>5]
746 : & (0x01 << (iDstOffset & 0x1f))) ) )
747 0 : dfDstDensity = 0.0;
748 :
749 : // It seems like we also ought to be testing panDstValid[] here!
750 :
751 1472 : switch( poWK->eWorkingDataType )
752 : {
753 : case GDT_Byte:
754 1472 : dfDstReal = pabyDst[iDstOffset];
755 1472 : dfDstImag = 0.0;
756 1472 : break;
757 :
758 : case GDT_Int16:
759 0 : dfDstReal = ((GInt16 *) pabyDst)[iDstOffset];
760 0 : dfDstImag = 0.0;
761 0 : break;
762 :
763 : case GDT_UInt16:
764 0 : dfDstReal = ((GUInt16 *) pabyDst)[iDstOffset];
765 0 : dfDstImag = 0.0;
766 0 : break;
767 :
768 : case GDT_Int32:
769 0 : dfDstReal = ((GInt32 *) pabyDst)[iDstOffset];
770 0 : dfDstImag = 0.0;
771 0 : break;
772 :
773 : case GDT_UInt32:
774 0 : dfDstReal = ((GUInt32 *) pabyDst)[iDstOffset];
775 0 : dfDstImag = 0.0;
776 0 : break;
777 :
778 : case GDT_Float32:
779 0 : dfDstReal = ((float *) pabyDst)[iDstOffset];
780 0 : dfDstImag = 0.0;
781 0 : break;
782 :
783 : case GDT_Float64:
784 0 : dfDstReal = ((double *) pabyDst)[iDstOffset];
785 0 : dfDstImag = 0.0;
786 0 : break;
787 :
788 : case GDT_CInt16:
789 0 : dfDstReal = ((GInt16 *) pabyDst)[iDstOffset*2];
790 0 : dfDstImag = ((GInt16 *) pabyDst)[iDstOffset*2+1];
791 0 : break;
792 :
793 : case GDT_CInt32:
794 0 : dfDstReal = ((GInt32 *) pabyDst)[iDstOffset*2];
795 0 : dfDstImag = ((GInt32 *) pabyDst)[iDstOffset*2+1];
796 0 : break;
797 :
798 : case GDT_CFloat32:
799 0 : dfDstReal = ((float *) pabyDst)[iDstOffset*2];
800 0 : dfDstImag = ((float *) pabyDst)[iDstOffset*2+1];
801 0 : break;
802 :
803 : case GDT_CFloat64:
804 0 : dfDstReal = ((double *) pabyDst)[iDstOffset*2];
805 0 : dfDstImag = ((double *) pabyDst)[iDstOffset*2+1];
806 0 : break;
807 :
808 : default:
809 : CPLAssert( FALSE );
810 0 : dfDstDensity = 0.0;
811 0 : return FALSE;
812 : }
813 :
814 : // the destination density is really only relative to the portion
815 : // not occluded by the overlay.
816 1472 : double dfDstInfluence = (1.0 - dfDensity) * dfDstDensity;
817 :
818 : dfReal = (dfReal * dfDensity + dfDstReal * dfDstInfluence)
819 1472 : / (dfDensity + dfDstInfluence);
820 :
821 : dfImag = (dfImag * dfDensity + dfDstImag * dfDstInfluence)
822 1472 : / (dfDensity + dfDstInfluence);
823 : }
824 :
825 : /* -------------------------------------------------------------------- */
826 : /* Actually apply the destination value. */
827 : /* */
828 : /* Avoid using the destination nodata value for integer datatypes */
829 : /* if by chance it is equal to the computed pixel value. */
830 : /* -------------------------------------------------------------------- */
831 :
832 : #define CLAMP(type,minval,maxval) \
833 : do { \
834 : if (dfReal < minval) ((type *) pabyDst)[iDstOffset] = (type)minval; \
835 : else if (dfReal > maxval) ((type *) pabyDst)[iDstOffset] = (type)maxval; \
836 : else ((type *) pabyDst)[iDstOffset] = (minval < 0) ? (type)floor(dfReal + 0.5) : (type)(dfReal + 0.5); \
837 : if (poWK->padfDstNoDataReal != NULL && \
838 : poWK->padfDstNoDataReal[iBand] == (double)((type *) pabyDst)[iDstOffset]) \
839 : { \
840 : if (((type *) pabyDst)[iDstOffset] == minval) \
841 : ((type *) pabyDst)[iDstOffset] = minval + 1; \
842 : else \
843 : ((type *) pabyDst)[iDstOffset] --; \
844 : } } while(0)
845 :
846 282451 : switch( poWK->eWorkingDataType )
847 : {
848 : case GDT_Byte:
849 279679 : CLAMP(GByte, 0.0, 255.0);
850 279679 : break;
851 :
852 : case GDT_Int16:
853 63 : CLAMP(GInt16, -32768.0, 32767.0);
854 63 : break;
855 :
856 : case GDT_UInt16:
857 252 : CLAMP(GUInt16, 0.0, 65535.0);
858 252 : break;
859 :
860 : case GDT_UInt32:
861 315 : CLAMP(GUInt32, 0.0, 4294967295.0);
862 315 : break;
863 :
864 : case GDT_Int32:
865 315 : CLAMP(GInt32, -2147483648.0, 2147483647.0);
866 315 : break;
867 :
868 : case GDT_Float32:
869 252 : ((float *) pabyDst)[iDstOffset] = (float) dfReal;
870 252 : break;
871 :
872 : case GDT_Float64:
873 315 : ((double *) pabyDst)[iDstOffset] = dfReal;
874 315 : break;
875 :
876 : case GDT_CInt16:
877 315 : if( dfReal < -32768 )
878 0 : ((GInt16 *) pabyDst)[iDstOffset*2] = -32768;
879 315 : else if( dfReal > 32767 )
880 0 : ((GInt16 *) pabyDst)[iDstOffset*2] = 32767;
881 : else
882 315 : ((GInt16 *) pabyDst)[iDstOffset*2] = (GInt16) floor(dfReal+0.5);
883 315 : if( dfImag < -32768 )
884 0 : ((GInt16 *) pabyDst)[iDstOffset*2+1] = -32768;
885 315 : else if( dfImag > 32767 )
886 0 : ((GInt16 *) pabyDst)[iDstOffset*2+1] = 32767;
887 : else
888 315 : ((GInt16 *) pabyDst)[iDstOffset*2+1] = (GInt16) floor(dfImag+0.5);
889 315 : break;
890 :
891 : case GDT_CInt32:
892 315 : if( dfReal < -2147483648.0 )
893 0 : ((GInt32 *) pabyDst)[iDstOffset*2] = (GInt32) -2147483648.0;
894 315 : else if( dfReal > 2147483647.0 )
895 0 : ((GInt32 *) pabyDst)[iDstOffset*2] = (GInt32) 2147483647.0;
896 : else
897 315 : ((GInt32 *) pabyDst)[iDstOffset*2] = (GInt32) floor(dfReal+0.5);
898 315 : if( dfImag < -2147483648.0 )
899 0 : ((GInt32 *) pabyDst)[iDstOffset*2+1] = (GInt32) -2147483648.0;
900 315 : else if( dfImag > 2147483647.0 )
901 0 : ((GInt32 *) pabyDst)[iDstOffset*2+1] = (GInt32) 2147483647.0;
902 : else
903 315 : ((GInt32 *) pabyDst)[iDstOffset*2+1] = (GInt32) floor(dfImag+0.5);
904 315 : break;
905 :
906 : case GDT_CFloat32:
907 315 : ((float *) pabyDst)[iDstOffset*2] = (float) dfReal;
908 315 : ((float *) pabyDst)[iDstOffset*2+1] = (float) dfImag;
909 315 : break;
910 :
911 : case GDT_CFloat64:
912 315 : ((double *) pabyDst)[iDstOffset*2] = (double) dfReal;
913 315 : ((double *) pabyDst)[iDstOffset*2+1] = (double) dfImag;
914 315 : break;
915 :
916 : default:
917 0 : return FALSE;
918 : }
919 :
920 282451 : return TRUE;
921 : }
922 :
923 : /************************************************************************/
924 : /* GWKGetPixelValue() */
925 : /************************************************************************/
926 :
927 479 : static int GWKGetPixelValue( GDALWarpKernel *poWK, int iBand,
928 : int iSrcOffset, double *pdfDensity,
929 : double *pdfReal, double *pdfImag )
930 :
931 : {
932 479 : GByte *pabySrc = poWK->papabySrcImage[iBand];
933 :
934 479 : if( poWK->panUnifiedSrcValid != NULL
935 0 : && !((poWK->panUnifiedSrcValid[iSrcOffset>>5]
936 : & (0x01 << (iSrcOffset & 0x1f))) ) )
937 : {
938 0 : *pdfDensity = 0.0;
939 0 : return FALSE;
940 : }
941 :
942 479 : if( poWK->papanBandSrcValid != NULL
943 0 : && poWK->papanBandSrcValid[iBand] != NULL
944 0 : && !((poWK->papanBandSrcValid[iBand][iSrcOffset>>5]
945 : & (0x01 << (iSrcOffset & 0x1f)))) )
946 : {
947 0 : *pdfDensity = 0.0;
948 0 : return FALSE;
949 : }
950 :
951 479 : switch( poWK->eWorkingDataType )
952 : {
953 : case GDT_Byte:
954 1 : *pdfReal = pabySrc[iSrcOffset];
955 1 : *pdfImag = 0.0;
956 1 : break;
957 :
958 : case GDT_Int16:
959 1 : *pdfReal = ((GInt16 *) pabySrc)[iSrcOffset];
960 1 : *pdfImag = 0.0;
961 1 : break;
962 :
963 : case GDT_UInt16:
964 4 : *pdfReal = ((GUInt16 *) pabySrc)[iSrcOffset];
965 4 : *pdfImag = 0.0;
966 4 : break;
967 :
968 : case GDT_Int32:
969 67 : *pdfReal = ((GInt32 *) pabySrc)[iSrcOffset];
970 67 : *pdfImag = 0.0;
971 67 : break;
972 :
973 : case GDT_UInt32:
974 67 : *pdfReal = ((GUInt32 *) pabySrc)[iSrcOffset];
975 67 : *pdfImag = 0.0;
976 67 : break;
977 :
978 : case GDT_Float32:
979 4 : *pdfReal = ((float *) pabySrc)[iSrcOffset];
980 4 : *pdfImag = 0.0;
981 4 : break;
982 :
983 : case GDT_Float64:
984 67 : *pdfReal = ((double *) pabySrc)[iSrcOffset];
985 67 : *pdfImag = 0.0;
986 67 : break;
987 :
988 : case GDT_CInt16:
989 67 : *pdfReal = ((GInt16 *) pabySrc)[iSrcOffset*2];
990 67 : *pdfImag = ((GInt16 *) pabySrc)[iSrcOffset*2+1];
991 67 : break;
992 :
993 : case GDT_CInt32:
994 67 : *pdfReal = ((GInt32 *) pabySrc)[iSrcOffset*2];
995 67 : *pdfImag = ((GInt32 *) pabySrc)[iSrcOffset*2+1];
996 67 : break;
997 :
998 : case GDT_CFloat32:
999 67 : *pdfReal = ((float *) pabySrc)[iSrcOffset*2];
1000 67 : *pdfImag = ((float *) pabySrc)[iSrcOffset*2+1];
1001 67 : break;
1002 :
1003 : case GDT_CFloat64:
1004 67 : *pdfReal = ((double *) pabySrc)[iSrcOffset*2];
1005 67 : *pdfImag = ((double *) pabySrc)[iSrcOffset*2+1];
1006 67 : break;
1007 :
1008 : default:
1009 0 : *pdfDensity = 0.0;
1010 0 : return FALSE;
1011 : }
1012 :
1013 479 : if( poWK->pafUnifiedSrcDensity != NULL )
1014 0 : *pdfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
1015 : else
1016 479 : *pdfDensity = 1.0;
1017 :
1018 479 : return *pdfDensity != 0.0;
1019 : }
1020 :
1021 : /************************************************************************/
1022 : /* GWKGetPixelRow() */
1023 : /************************************************************************/
1024 :
1025 1925779 : static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
1026 : int iSrcOffset, int nHalfSrcLen,
1027 : double adfDensity[],
1028 : double adfReal[], double adfImag[] )
1029 : {
1030 : // We know that nSrcLen is even, so we can *always* unroll loops 2x
1031 1925779 : int nSrcLen = nHalfSrcLen * 2;
1032 1925779 : int bHasValid = FALSE;
1033 : int i;
1034 :
1035 : // Init the density
1036 9617385 : for ( i = 0; i < nSrcLen; i += 2 )
1037 : {
1038 7691606 : adfDensity[i] = 1.0;
1039 7691606 : adfDensity[i+1] = 1.0;
1040 : }
1041 :
1042 1925779 : if ( poWK->panUnifiedSrcValid != NULL )
1043 : {
1044 0 : for ( i = 0; i < nSrcLen; i += 2 )
1045 : {
1046 0 : if(poWK->panUnifiedSrcValid[(iSrcOffset+i)>>5]
1047 : & (0x01 << ((iSrcOffset+i) & 0x1f)))
1048 0 : bHasValid = TRUE;
1049 : else
1050 0 : adfDensity[i] = 0.0;
1051 :
1052 0 : if(poWK->panUnifiedSrcValid[(iSrcOffset+i+1)>>5]
1053 : & (0x01 << ((iSrcOffset+i+1) & 0x1f)))
1054 0 : bHasValid = TRUE;
1055 : else
1056 0 : adfDensity[i+1] = 0.0;
1057 : }
1058 :
1059 : // Reset or fail as needed
1060 0 : if ( bHasValid )
1061 0 : bHasValid = FALSE;
1062 : else
1063 0 : return FALSE;
1064 : }
1065 :
1066 1925779 : if ( poWK->papanBandSrcValid != NULL
1067 0 : && poWK->papanBandSrcValid[iBand] != NULL)
1068 : {
1069 0 : for ( i = 0; i < nSrcLen; i += 2 )
1070 : {
1071 0 : if(poWK->papanBandSrcValid[iBand][(iSrcOffset+i)>>5]
1072 : & (0x01 << ((iSrcOffset+i) & 0x1f)))
1073 0 : bHasValid = TRUE;
1074 : else
1075 0 : adfDensity[i] = 0.0;
1076 :
1077 0 : if(poWK->papanBandSrcValid[iBand][(iSrcOffset+i+1)>>5]
1078 : & (0x01 << ((iSrcOffset+i+1) & 0x1f)))
1079 0 : bHasValid = TRUE;
1080 : else
1081 0 : adfDensity[i+1] = 0.0;
1082 : }
1083 :
1084 : // Reset or fail as needed
1085 0 : if ( bHasValid )
1086 0 : bHasValid = FALSE;
1087 : else
1088 0 : return FALSE;
1089 : }
1090 :
1091 : // Fetch data
1092 1925779 : switch( poWK->eWorkingDataType )
1093 : {
1094 : case GDT_Byte:
1095 : {
1096 1919280 : GByte* pSrc = (GByte*) poWK->papabySrcImage[iBand];
1097 1919280 : pSrc += iSrcOffset;
1098 9594840 : for ( i = 0; i < nSrcLen; i += 2 )
1099 : {
1100 7675560 : adfReal[i] = pSrc[i];
1101 7675560 : adfReal[i+1] = pSrc[i+1];
1102 : }
1103 1919280 : memset( adfImag, 0, nSrcLen * sizeof(double) );
1104 1919280 : break;
1105 : }
1106 :
1107 : case GDT_Int16:
1108 : {
1109 280 : GInt16* pSrc = (GInt16*) poWK->papabySrcImage[iBand];
1110 280 : pSrc += iSrcOffset;
1111 1314 : for ( i = 0; i < nSrcLen; i += 2 )
1112 : {
1113 1034 : adfReal[i] = pSrc[i];
1114 1034 : adfReal[i+1] = pSrc[i+1];
1115 : }
1116 280 : memset( adfImag, 0, nSrcLen * sizeof(double) );
1117 280 : break;
1118 : }
1119 :
1120 : case GDT_UInt16:
1121 : {
1122 691 : GUInt16* pSrc = (GUInt16*) poWK->papabySrcImage[iBand];
1123 691 : pSrc += iSrcOffset;
1124 2359 : for ( i = 0; i < nSrcLen; i += 2 )
1125 : {
1126 1668 : adfReal[i] = pSrc[i];
1127 1668 : adfReal[i+1] = pSrc[i+1];
1128 : }
1129 691 : memset( adfImag, 0, nSrcLen * sizeof(double) );
1130 691 : break;
1131 : }
1132 :
1133 : case GDT_Int32:
1134 : {
1135 691 : GInt32* pSrc = (GInt32*) poWK->papabySrcImage[iBand];
1136 691 : pSrc += iSrcOffset;
1137 2359 : for ( i = 0; i < nSrcLen; i += 2 )
1138 : {
1139 1668 : adfReal[i] = pSrc[i];
1140 1668 : adfReal[i+1] = pSrc[i+1];
1141 : }
1142 691 : memset( adfImag, 0, nSrcLen * sizeof(double) );
1143 691 : break;
1144 : }
1145 :
1146 : case GDT_UInt32:
1147 : {
1148 691 : GUInt32* pSrc = (GUInt32*) poWK->papabySrcImage[iBand];
1149 691 : pSrc += iSrcOffset;
1150 2359 : for ( i = 0; i < nSrcLen; i += 2 )
1151 : {
1152 1668 : adfReal[i] = pSrc[i];
1153 1668 : adfReal[i+1] = pSrc[i+1];
1154 : }
1155 691 : memset( adfImag, 0, nSrcLen * sizeof(double) );
1156 691 : break;
1157 : }
1158 :
1159 : case GDT_Float32:
1160 : {
1161 691 : float* pSrc = (float*) poWK->papabySrcImage[iBand];
1162 691 : pSrc += iSrcOffset;
1163 2359 : for ( i = 0; i < nSrcLen; i += 2 )
1164 : {
1165 1668 : adfReal[i] = pSrc[i];
1166 1668 : adfReal[i+1] = pSrc[i+1];
1167 : }
1168 691 : memset( adfImag, 0, nSrcLen * sizeof(double) );
1169 691 : break;
1170 : }
1171 :
1172 : case GDT_Float64:
1173 : {
1174 691 : double* pSrc = (double*) poWK->papabySrcImage[iBand];
1175 691 : pSrc += iSrcOffset;
1176 2359 : for ( i = 0; i < nSrcLen; i += 2 )
1177 : {
1178 1668 : adfReal[i] = pSrc[i];
1179 1668 : adfReal[i+1] = pSrc[i+1];
1180 : }
1181 691 : memset( adfImag, 0, nSrcLen * sizeof(double) );
1182 691 : break;
1183 : }
1184 :
1185 : case GDT_CInt16:
1186 : {
1187 691 : GInt16* pSrc = (GInt16*) poWK->papabySrcImage[iBand];
1188 691 : pSrc += 2 * iSrcOffset;
1189 2359 : for ( i = 0; i < nSrcLen; i += 2 )
1190 : {
1191 1668 : adfReal[i] = pSrc[2*i];
1192 1668 : adfImag[i] = pSrc[2*i+1];
1193 :
1194 1668 : adfReal[i+1] = pSrc[2*i+2];
1195 1668 : adfImag[i+1] = pSrc[2*i+3];
1196 : }
1197 691 : break;
1198 : }
1199 :
1200 : case GDT_CInt32:
1201 : {
1202 691 : GInt32* pSrc = (GInt32*) poWK->papabySrcImage[iBand];
1203 691 : pSrc += 2 * iSrcOffset;
1204 2359 : for ( i = 0; i < nSrcLen; i += 2 )
1205 : {
1206 1668 : adfReal[i] = pSrc[2*i];
1207 1668 : adfImag[i] = pSrc[2*i+1];
1208 :
1209 1668 : adfReal[i+1] = pSrc[2*i+2];
1210 1668 : adfImag[i+1] = pSrc[2*i+3];
1211 : }
1212 691 : break;
1213 : }
1214 :
1215 : case GDT_CFloat32:
1216 : {
1217 691 : float* pSrc = (float*) poWK->papabySrcImage[iBand];
1218 691 : pSrc += 2 * iSrcOffset;
1219 2359 : for ( i = 0; i < nSrcLen; i += 2 )
1220 : {
1221 1668 : adfReal[i] = pSrc[2*i];
1222 1668 : adfImag[i] = pSrc[2*i+1];
1223 :
1224 1668 : adfReal[i+1] = pSrc[2*i+2];
1225 1668 : adfImag[i+1] = pSrc[2*i+3];
1226 : }
1227 691 : break;
1228 : }
1229 :
1230 :
1231 : case GDT_CFloat64:
1232 : {
1233 691 : double* pSrc = (double*) poWK->papabySrcImage[iBand];
1234 691 : pSrc += 2 * iSrcOffset;
1235 2359 : for ( i = 0; i < nSrcLen; i += 2 )
1236 : {
1237 1668 : adfReal[i] = pSrc[2*i];
1238 1668 : adfImag[i] = pSrc[2*i+1];
1239 :
1240 1668 : adfReal[i+1] = pSrc[2*i+2];
1241 1668 : adfImag[i+1] = pSrc[2*i+3];
1242 : }
1243 691 : break;
1244 : }
1245 :
1246 : default:
1247 : CPLAssert(FALSE);
1248 0 : memset( adfDensity, 0, nSrcLen * sizeof(double) );
1249 0 : return FALSE;
1250 : }
1251 :
1252 1925779 : if( poWK->pafUnifiedSrcDensity == NULL )
1253 : {
1254 9617385 : for ( i = 0; i < nSrcLen; i += 2 )
1255 : {
1256 : // Take into account earlier calcs
1257 7691606 : if(adfDensity[i] > 0.000000001)
1258 : {
1259 7691606 : adfDensity[i] = 1.0;
1260 7691606 : bHasValid = TRUE;
1261 : }
1262 :
1263 7691606 : if(adfDensity[i+1] > 0.000000001)
1264 : {
1265 7691606 : adfDensity[i+1] = 1.0;
1266 7691606 : bHasValid = TRUE;
1267 : }
1268 : }
1269 : }
1270 : else
1271 : {
1272 0 : for ( i = 0; i < nSrcLen; i += 2 )
1273 : {
1274 0 : if(adfDensity[i] > 0.000000001)
1275 0 : adfDensity[i] = poWK->pafUnifiedSrcDensity[iSrcOffset+i];
1276 0 : if(adfDensity[i] > 0.000000001)
1277 0 : bHasValid = TRUE;
1278 :
1279 0 : if(adfDensity[i+1] > 0.000000001)
1280 0 : adfDensity[i+1] = poWK->pafUnifiedSrcDensity[iSrcOffset+i+1];
1281 0 : if(adfDensity[i+1] > 0.000000001)
1282 0 : bHasValid = TRUE;
1283 : }
1284 : }
1285 :
1286 1925779 : return bHasValid;
1287 : }
1288 :
1289 : /************************************************************************/
1290 : /* GWKGetPixelByte() */
1291 : /************************************************************************/
1292 :
1293 30805 : static int GWKGetPixelByte( GDALWarpKernel *poWK, int iBand,
1294 : int iSrcOffset, double *pdfDensity,
1295 : GByte *pbValue )
1296 :
1297 : {
1298 30805 : GByte *pabySrc = poWK->papabySrcImage[iBand];
1299 :
1300 31106 : if ( ( poWK->panUnifiedSrcValid != NULL
1301 301 : && !((poWK->panUnifiedSrcValid[iSrcOffset>>5]
1302 : & (0x01 << (iSrcOffset & 0x1f))) ) )
1303 : || ( poWK->papanBandSrcValid != NULL
1304 0 : && poWK->papanBandSrcValid[iBand] != NULL
1305 0 : && !((poWK->papanBandSrcValid[iBand][iSrcOffset>>5]
1306 : & (0x01 << (iSrcOffset & 0x1f)))) ) )
1307 : {
1308 0 : *pdfDensity = 0.0;
1309 0 : return FALSE;
1310 : }
1311 :
1312 30805 : *pbValue = pabySrc[iSrcOffset];
1313 :
1314 30805 : if ( poWK->pafUnifiedSrcDensity == NULL )
1315 15702 : *pdfDensity = 1.0;
1316 : else
1317 15103 : *pdfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
1318 :
1319 30805 : return *pdfDensity != 0.0;
1320 : }
1321 :
1322 : /************************************************************************/
1323 : /* GWKGetPixelShort() */
1324 : /************************************************************************/
1325 :
1326 1488467 : static int GWKGetPixelShort( GDALWarpKernel *poWK, int iBand,
1327 : int iSrcOffset, double *pdfDensity,
1328 : GInt16 *piValue )
1329 :
1330 : {
1331 1488467 : GInt16 *pabySrc = (GInt16 *)poWK->papabySrcImage[iBand];
1332 :
1333 4462995 : if ( ( poWK->panUnifiedSrcValid != NULL
1334 0 : && !((poWK->panUnifiedSrcValid[iSrcOffset>>5]
1335 : & (0x01 << (iSrcOffset & 0x1f))) ) )
1336 : || ( poWK->papanBandSrcValid != NULL
1337 1487264 : && poWK->papanBandSrcValid[iBand] != NULL
1338 1487264 : && !((poWK->papanBandSrcValid[iBand][iSrcOffset>>5]
1339 : & (0x01 << (iSrcOffset & 0x1f)))) ) )
1340 : {
1341 715 : *pdfDensity = 0.0;
1342 715 : return FALSE;
1343 : }
1344 :
1345 1487752 : *piValue = pabySrc[iSrcOffset];
1346 :
1347 1487752 : if ( poWK->pafUnifiedSrcDensity == NULL )
1348 1486549 : *pdfDensity = 1.0;
1349 : else
1350 1203 : *pdfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
1351 :
1352 1487752 : return *pdfDensity != 0.0;
1353 : }
1354 :
1355 : /************************************************************************/
1356 : /* GWKGetPixelFloat() */
1357 : /************************************************************************/
1358 :
1359 1203 : static int GWKGetPixelFloat( GDALWarpKernel *poWK, int iBand,
1360 : int iSrcOffset, double *pdfDensity,
1361 : float *pfValue )
1362 :
1363 : {
1364 1203 : float *pabySrc = (float *)poWK->papabySrcImage[iBand];
1365 :
1366 1203 : if ( ( poWK->panUnifiedSrcValid != NULL
1367 0 : && !((poWK->panUnifiedSrcValid[iSrcOffset>>5]
1368 : & (0x01 << (iSrcOffset & 0x1f))) ) )
1369 : || ( poWK->papanBandSrcValid != NULL
1370 0 : && poWK->papanBandSrcValid[iBand] != NULL
1371 0 : && !((poWK->papanBandSrcValid[iBand][iSrcOffset>>5]
1372 : & (0x01 << (iSrcOffset & 0x1f)))) ) )
1373 : {
1374 0 : *pdfDensity = 0.0;
1375 0 : return FALSE;
1376 : }
1377 :
1378 1203 : *pfValue = pabySrc[iSrcOffset];
1379 :
1380 1203 : if ( poWK->pafUnifiedSrcDensity == NULL )
1381 0 : *pdfDensity = 1.0;
1382 : else
1383 1203 : *pdfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
1384 :
1385 1203 : return *pdfDensity != 0.0;
1386 : }
1387 :
1388 : /************************************************************************/
1389 : /* GWKBilinearResample() */
1390 : /* Set of bilinear interpolators */
1391 : /************************************************************************/
1392 :
1393 1008 : static int GWKBilinearResample( GDALWarpKernel *poWK, int iBand,
1394 : double dfSrcX, double dfSrcY,
1395 : double *pdfDensity,
1396 : double *pdfReal, double *pdfImag )
1397 :
1398 : {
1399 : // Save as local variables to avoid following pointers
1400 1008 : int nSrcXSize = poWK->nSrcXSize;
1401 1008 : int nSrcYSize = poWK->nSrcYSize;
1402 :
1403 1008 : int iSrcX = (int) floor(dfSrcX - 0.5);
1404 1008 : int iSrcY = (int) floor(dfSrcY - 0.5);
1405 1008 : int iSrcOffset = iSrcX + iSrcY * nSrcXSize;
1406 1008 : double dfRatioX = 1.5 - (dfSrcX - iSrcX);
1407 1008 : double dfRatioY = 1.5 - (dfSrcY - iSrcY);
1408 : double adfDensity[2], adfReal[2], adfImag[2];
1409 1008 : double dfAccumulatorReal = 0.0, dfAccumulatorImag = 0.0;
1410 1008 : double dfAccumulatorDensity = 0.0;
1411 1008 : double dfAccumulatorDivisor = 0.0;
1412 1008 : int bShifted = FALSE;
1413 :
1414 : // Shift so we don't overrun the array
1415 1008 : if( nSrcXSize * nSrcYSize == iSrcOffset + 1
1416 : || nSrcXSize * nSrcYSize == iSrcOffset + nSrcXSize + 1 )
1417 : {
1418 72 : bShifted = TRUE;
1419 72 : --iSrcOffset;
1420 : }
1421 :
1422 : // Get pixel row
1423 1008 : if ( iSrcY >= 0 && iSrcY < nSrcYSize
1424 : && iSrcOffset >= 0 && iSrcOffset < nSrcXSize * nSrcYSize
1425 : && GWKGetPixelRow( poWK, iBand, iSrcOffset, 1,
1426 : adfDensity, adfReal, adfImag ) )
1427 : {
1428 792 : double dfMult1 = dfRatioX * dfRatioY;
1429 792 : double dfMult2 = (1.0-dfRatioX) * dfRatioY;
1430 :
1431 : // Shifting corrected
1432 792 : if ( bShifted )
1433 : {
1434 72 : adfReal[0] = adfReal[1];
1435 72 : adfImag[0] = adfImag[1];
1436 72 : adfDensity[0] = adfDensity[1];
1437 : }
1438 :
1439 : // Upper Left Pixel
1440 1584 : if ( iSrcX >= 0 && iSrcX < nSrcXSize
1441 792 : && adfDensity[0] > 0.000000001 )
1442 : {
1443 792 : dfAccumulatorDivisor += dfMult1;
1444 :
1445 792 : dfAccumulatorReal += adfReal[0] * dfMult1;
1446 792 : dfAccumulatorImag += adfImag[0] * dfMult1;
1447 792 : dfAccumulatorDensity += adfDensity[0] * dfMult1;
1448 : }
1449 :
1450 : // Upper Right Pixel
1451 1422 : if ( iSrcX+1 >= 0 && iSrcX+1 < nSrcXSize
1452 630 : && adfDensity[1] > 0.000000001 )
1453 : {
1454 630 : dfAccumulatorDivisor += dfMult2;
1455 :
1456 630 : dfAccumulatorReal += adfReal[1] * dfMult2;
1457 630 : dfAccumulatorImag += adfImag[1] * dfMult2;
1458 630 : dfAccumulatorDensity += adfDensity[1] * dfMult2;
1459 : }
1460 : }
1461 :
1462 : // Get pixel row
1463 1008 : if ( iSrcY+1 >= 0 && iSrcY+1 < nSrcYSize
1464 : && iSrcOffset+nSrcXSize >= 0
1465 : && iSrcOffset+nSrcXSize < nSrcXSize * nSrcYSize
1466 : && GWKGetPixelRow( poWK, iBand, iSrcOffset+nSrcXSize, 1,
1467 : adfDensity, adfReal, adfImag ) )
1468 : {
1469 828 : double dfMult1 = dfRatioX * (1.0-dfRatioY);
1470 828 : double dfMult2 = (1.0-dfRatioX) * (1.0-dfRatioY);
1471 :
1472 : // Shifting corrected
1473 828 : if ( bShifted )
1474 : {
1475 36 : adfReal[0] = adfReal[1];
1476 36 : adfImag[0] = adfImag[1];
1477 36 : adfDensity[0] = adfDensity[1];
1478 : }
1479 :
1480 : // Lower Left Pixel
1481 1656 : if ( iSrcX >= 0 && iSrcX < nSrcXSize
1482 828 : && adfDensity[0] > 0.000000001 )
1483 : {
1484 828 : dfAccumulatorDivisor += dfMult1;
1485 :
1486 828 : dfAccumulatorReal += adfReal[0] * dfMult1;
1487 828 : dfAccumulatorImag += adfImag[0] * dfMult1;
1488 828 : dfAccumulatorDensity += adfDensity[0] * dfMult1;
1489 : }
1490 :
1491 : // Lower Right Pixel
1492 1476 : if ( iSrcX+1 >= 0 && iSrcX+1 < nSrcXSize
1493 648 : && adfDensity[1] > 0.000000001 )
1494 : {
1495 648 : dfAccumulatorDivisor += dfMult2;
1496 :
1497 648 : dfAccumulatorReal += adfReal[1] * dfMult2;
1498 648 : dfAccumulatorImag += adfImag[1] * dfMult2;
1499 648 : dfAccumulatorDensity += adfDensity[1] * dfMult2;
1500 : }
1501 : }
1502 :
1503 : /* -------------------------------------------------------------------- */
1504 : /* Return result. */
1505 : /* -------------------------------------------------------------------- */
1506 1008 : if ( dfAccumulatorDivisor == 1.0 )
1507 : {
1508 594 : *pdfReal = dfAccumulatorReal;
1509 594 : *pdfImag = dfAccumulatorImag;
1510 594 : *pdfDensity = dfAccumulatorDensity;
1511 594 : return TRUE;
1512 : }
1513 414 : else if ( dfAccumulatorDivisor < 0.00001 )
1514 : {
1515 0 : *pdfReal = 0.0;
1516 0 : *pdfImag = 0.0;
1517 0 : *pdfDensity = 0.0;
1518 0 : return FALSE;
1519 : }
1520 : else
1521 : {
1522 414 : *pdfReal = dfAccumulatorReal / dfAccumulatorDivisor;
1523 414 : *pdfImag = dfAccumulatorImag / dfAccumulatorDivisor;
1524 414 : *pdfDensity = dfAccumulatorDensity / dfAccumulatorDivisor;
1525 414 : return TRUE;
1526 : }
1527 : }
1528 :
1529 288782 : static int GWKBilinearResampleNoMasksByte( GDALWarpKernel *poWK, int iBand,
1530 : double dfSrcX, double dfSrcY,
1531 : GByte *pbValue )
1532 :
1533 : {
1534 288782 : double dfAccumulator = 0.0;
1535 288782 : double dfAccumulatorDivisor = 0.0;
1536 :
1537 288782 : int iSrcX = (int) floor(dfSrcX - 0.5);
1538 288782 : int iSrcY = (int) floor(dfSrcY - 0.5);
1539 288782 : int iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
1540 288782 : double dfRatioX = 1.5 - (dfSrcX - iSrcX);
1541 288782 : double dfRatioY = 1.5 - (dfSrcY - iSrcY);
1542 :
1543 : // Upper Left Pixel
1544 288782 : if( iSrcX >= 0 && iSrcX < poWK->nSrcXSize
1545 : && iSrcY >= 0 && iSrcY < poWK->nSrcYSize )
1546 : {
1547 281993 : double dfMult = dfRatioX * dfRatioY;
1548 :
1549 281993 : dfAccumulatorDivisor += dfMult;
1550 :
1551 : dfAccumulator +=
1552 281993 : (double)poWK->papabySrcImage[iBand][iSrcOffset] * dfMult;
1553 : }
1554 :
1555 : // Upper Right Pixel
1556 288782 : if( iSrcX+1 >= 0 && iSrcX+1 < poWK->nSrcXSize
1557 : && iSrcY >= 0 && iSrcY < poWK->nSrcYSize )
1558 : {
1559 285029 : double dfMult = (1.0-dfRatioX) * dfRatioY;
1560 :
1561 285029 : dfAccumulatorDivisor += dfMult;
1562 :
1563 : dfAccumulator +=
1564 285029 : (double)poWK->papabySrcImage[iBand][iSrcOffset+1] * dfMult;
1565 : }
1566 :
1567 : // Lower Right Pixel
1568 288782 : if( iSrcX+1 >= 0 && iSrcX+1 < poWK->nSrcXSize
1569 : && iSrcY+1 >= 0 && iSrcY+1 < poWK->nSrcYSize )
1570 : {
1571 288103 : double dfMult = (1.0-dfRatioX) * (1.0-dfRatioY);
1572 :
1573 288103 : dfAccumulatorDivisor += dfMult;
1574 :
1575 : dfAccumulator +=
1576 288103 : (double)poWK->papabySrcImage[iBand][iSrcOffset+1+poWK->nSrcXSize]
1577 288103 : * dfMult;
1578 : }
1579 :
1580 : // Lower Left Pixel
1581 288782 : if( iSrcX >= 0 && iSrcX < poWK->nSrcXSize
1582 : && iSrcY+1 >= 0 && iSrcY+1 < poWK->nSrcYSize )
1583 : {
1584 285054 : double dfMult = dfRatioX * (1.0-dfRatioY);
1585 :
1586 285054 : dfAccumulatorDivisor += dfMult;
1587 :
1588 : dfAccumulator +=
1589 285054 : (double)poWK->papabySrcImage[iBand][iSrcOffset+poWK->nSrcXSize]
1590 285054 : * dfMult;
1591 : }
1592 :
1593 : /* -------------------------------------------------------------------- */
1594 : /* Return result. */
1595 : /* -------------------------------------------------------------------- */
1596 : double dfValue;
1597 :
1598 288782 : if( dfAccumulatorDivisor < 0.00001 )
1599 : {
1600 0 : *pbValue = 0;
1601 0 : return FALSE;
1602 : }
1603 288782 : else if( dfAccumulatorDivisor == 1.0 )
1604 : {
1605 276809 : dfValue = dfAccumulator;
1606 : }
1607 : else
1608 : {
1609 11973 : dfValue = dfAccumulator / dfAccumulatorDivisor;
1610 : }
1611 :
1612 288782 : if ( dfValue < 0.0 )
1613 0 : *pbValue = 0;
1614 288782 : else if ( dfValue > 255.0 )
1615 925 : *pbValue = 255;
1616 : else
1617 287857 : *pbValue = (GByte)(0.5 + dfValue);
1618 :
1619 288782 : return TRUE;
1620 : }
1621 :
1622 272494 : static int GWKBilinearResampleNoMasksShort( GDALWarpKernel *poWK, int iBand,
1623 : double dfSrcX, double dfSrcY,
1624 : GInt16 *piValue )
1625 :
1626 : {
1627 272494 : double dfAccumulator = 0.0;
1628 272494 : double dfAccumulatorDivisor = 0.0;
1629 :
1630 272494 : int iSrcX = (int) floor(dfSrcX - 0.5);
1631 272494 : int iSrcY = (int) floor(dfSrcY - 0.5);
1632 272494 : int iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
1633 272494 : double dfRatioX = 1.5 - (dfSrcX - iSrcX);
1634 272494 : double dfRatioY = 1.5 - (dfSrcY - iSrcY);
1635 :
1636 : // Upper Left Pixel
1637 272494 : if( iSrcX >= 0 && iSrcX < poWK->nSrcXSize
1638 : && iSrcY >= 0 && iSrcY < poWK->nSrcYSize )
1639 : {
1640 266132 : double dfMult = dfRatioX * dfRatioY;
1641 :
1642 266132 : dfAccumulatorDivisor += dfMult;
1643 :
1644 : dfAccumulator +=
1645 266132 : (double)((GInt16 *)poWK->papabySrcImage[iBand])[iSrcOffset]
1646 266132 : * dfMult;
1647 : }
1648 :
1649 : // Upper Right Pixel
1650 272494 : if( iSrcX+1 >= 0 && iSrcX+1 < poWK->nSrcXSize
1651 : && iSrcY >= 0 && iSrcY < poWK->nSrcYSize )
1652 : {
1653 269168 : double dfMult = (1.0-dfRatioX) * dfRatioY;
1654 :
1655 269168 : dfAccumulatorDivisor += dfMult;
1656 :
1657 : dfAccumulator +=
1658 269168 : (double)((GInt16 *)poWK->papabySrcImage[iBand])[iSrcOffset+1] * dfMult;
1659 : }
1660 :
1661 : // Lower Right Pixel
1662 272494 : if( iSrcX+1 >= 0 && iSrcX+1 < poWK->nSrcXSize
1663 : && iSrcY+1 >= 0 && iSrcY+1 < poWK->nSrcYSize )
1664 : {
1665 272341 : double dfMult = (1.0-dfRatioX) * (1.0-dfRatioY);
1666 :
1667 272341 : dfAccumulatorDivisor += dfMult;
1668 :
1669 : dfAccumulator +=
1670 272341 : (double)((GInt16 *)poWK->papabySrcImage[iBand])[iSrcOffset+1+poWK->nSrcXSize]
1671 272341 : * dfMult;
1672 : }
1673 :
1674 : // Lower Left Pixel
1675 272494 : if( iSrcX >= 0 && iSrcX < poWK->nSrcXSize
1676 : && iSrcY+1 >= 0 && iSrcY+1 < poWK->nSrcYSize )
1677 : {
1678 269292 : double dfMult = dfRatioX * (1.0-dfRatioY);
1679 :
1680 269292 : dfAccumulatorDivisor += dfMult;
1681 :
1682 : dfAccumulator +=
1683 269292 : (double)((GInt16 *)poWK->papabySrcImage[iBand])[iSrcOffset+poWK->nSrcXSize]
1684 269292 : * dfMult;
1685 : }
1686 :
1687 : /* -------------------------------------------------------------------- */
1688 : /* Return result. */
1689 : /* -------------------------------------------------------------------- */
1690 272494 : if( dfAccumulatorDivisor == 1.0 )
1691 : {
1692 261669 : *piValue = (GInt16)(0.5 + dfAccumulator);
1693 261669 : return TRUE;
1694 : }
1695 10825 : else if( dfAccumulatorDivisor < 0.00001 )
1696 : {
1697 0 : *piValue = 0;
1698 0 : return FALSE;
1699 : }
1700 : else
1701 : {
1702 10825 : *piValue = (GInt16)(0.5 + dfAccumulator / dfAccumulatorDivisor);
1703 10825 : return TRUE;
1704 : }
1705 : }
1706 :
1707 : /************************************************************************/
1708 : /* GWKCubicResample() */
1709 : /* Set of bicubic interpolators using cubic convolution. */
1710 : /************************************************************************/
1711 :
1712 : #define CubicConvolution(distance1,distance2,distance3,f0,f1,f2,f3) \
1713 : ( ( -f0 + f1 - f2 + f3) * distance3 \
1714 : + (2.0*(f0 - f1) + f2 - f3) * distance2 \
1715 : + ( -f0 + f2 ) * distance1 \
1716 : + f1 )
1717 :
1718 558 : static int GWKCubicResample( GDALWarpKernel *poWK, int iBand,
1719 : double dfSrcX, double dfSrcY,
1720 : double *pdfDensity,
1721 : double *pdfReal, double *pdfImag )
1722 :
1723 : {
1724 558 : int iSrcX = (int) floor( dfSrcX - 0.5 );
1725 558 : int iSrcY = (int) floor( dfSrcY - 0.5 );
1726 558 : int iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
1727 558 : double dfDeltaX = dfSrcX - 0.5 - iSrcX;
1728 558 : double dfDeltaY = dfSrcY - 0.5 - iSrcY;
1729 558 : double dfDeltaX2 = dfDeltaX * dfDeltaX;
1730 558 : double dfDeltaY2 = dfDeltaY * dfDeltaY;
1731 558 : double dfDeltaX3 = dfDeltaX2 * dfDeltaX;
1732 558 : double dfDeltaY3 = dfDeltaY2 * dfDeltaY;
1733 : double adfValueDens[4], adfValueReal[4], adfValueImag[4];
1734 : double adfDensity[4], adfReal[4], adfImag[4];
1735 : int i;
1736 :
1737 : // Get the bilinear interpolation at the image borders
1738 558 : if ( iSrcX - 1 < 0 || iSrcX + 2 >= poWK->nSrcXSize
1739 : || iSrcY - 1 < 0 || iSrcY + 2 >= poWK->nSrcYSize )
1740 : return GWKBilinearResample( poWK, iBand, dfSrcX, dfSrcY,
1741 450 : pdfDensity, pdfReal, pdfImag );
1742 :
1743 540 : for ( i = -1; i < 3; i++ )
1744 : {
1745 2160 : if ( !GWKGetPixelRow(poWK, iBand, iSrcOffset + i * poWK->nSrcXSize - 1,
1746 : 2, adfDensity, adfReal, adfImag)
1747 432 : || adfDensity[0] < 0.000000001
1748 432 : || adfDensity[1] < 0.000000001
1749 432 : || adfDensity[2] < 0.000000001
1750 432 : || adfDensity[3] < 0.000000001 )
1751 : {
1752 : return GWKBilinearResample( poWK, iBand, dfSrcX, dfSrcY,
1753 0 : pdfDensity, pdfReal, pdfImag );
1754 : }
1755 :
1756 3456 : adfValueDens[i + 1] = CubicConvolution(dfDeltaX, dfDeltaX2, dfDeltaX3,
1757 3456 : adfDensity[0], adfDensity[1], adfDensity[2], adfDensity[3]);
1758 3456 : adfValueReal[i + 1] = CubicConvolution(dfDeltaX, dfDeltaX2, dfDeltaX3,
1759 3456 : adfReal[0], adfReal[1], adfReal[2], adfReal[3]);
1760 3456 : adfValueImag[i + 1] = CubicConvolution(dfDeltaX, dfDeltaX2, dfDeltaX3,
1761 3456 : adfImag[0], adfImag[1], adfImag[2], adfImag[3]);
1762 : }
1763 :
1764 :
1765 : /* -------------------------------------------------------------------- */
1766 : /* For now, if we have any pixels missing in the kernel area, */
1767 : /* we fallback on using bilinear interpolation. Ideally we */
1768 : /* should do "weight adjustment" of our results similarly to */
1769 : /* what is done for the cubic spline and lanc. interpolators. */
1770 : /* -------------------------------------------------------------------- */
1771 864 : *pdfDensity = CubicConvolution(dfDeltaY, dfDeltaY2, dfDeltaY3,
1772 : adfValueDens[0], adfValueDens[1],
1773 864 : adfValueDens[2], adfValueDens[3]);
1774 864 : *pdfReal = CubicConvolution(dfDeltaY, dfDeltaY2, dfDeltaY3,
1775 : adfValueReal[0], adfValueReal[1],
1776 864 : adfValueReal[2], adfValueReal[3]);
1777 864 : *pdfImag = CubicConvolution(dfDeltaY, dfDeltaY2, dfDeltaY3,
1778 : adfValueImag[0], adfValueImag[1],
1779 864 : adfValueImag[2], adfValueImag[3]);
1780 :
1781 108 : return TRUE;
1782 : }
1783 :
1784 278207 : static int GWKCubicResampleNoMasksByte( GDALWarpKernel *poWK, int iBand,
1785 : double dfSrcX, double dfSrcY,
1786 : GByte *pbValue )
1787 :
1788 : {
1789 278207 : int iSrcX = (int) floor( dfSrcX - 0.5 );
1790 278207 : int iSrcY = (int) floor( dfSrcY - 0.5 );
1791 278207 : int iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
1792 278207 : double dfDeltaX = dfSrcX - 0.5 - iSrcX;
1793 278207 : double dfDeltaY = dfSrcY - 0.5 - iSrcY;
1794 278207 : double dfDeltaX2 = dfDeltaX * dfDeltaX;
1795 278207 : double dfDeltaY2 = dfDeltaY * dfDeltaY;
1796 278207 : double dfDeltaX3 = dfDeltaX2 * dfDeltaX;
1797 278207 : double dfDeltaY3 = dfDeltaY2 * dfDeltaY;
1798 : double adfValue[4];
1799 : int i;
1800 :
1801 : // Get the bilinear interpolation at the image borders
1802 278207 : if ( iSrcX - 1 < 0 || iSrcX + 2 >= poWK->nSrcXSize
1803 : || iSrcY - 1 < 0 || iSrcY + 2 >= poWK->nSrcYSize )
1804 : return GWKBilinearResampleNoMasksByte( poWK, iBand, dfSrcX, dfSrcY,
1805 10574 : pbValue);
1806 :
1807 1338165 : for ( i = -1; i < 3; i++ )
1808 : {
1809 1070532 : int iOffset = iSrcOffset + i * poWK->nSrcXSize;
1810 :
1811 11775852 : adfValue[i + 1] = CubicConvolution(dfDeltaX, dfDeltaX2, dfDeltaX3,
1812 : (double)poWK->papabySrcImage[iBand][iOffset - 1],
1813 : (double)poWK->papabySrcImage[iBand][iOffset],
1814 : (double)poWK->papabySrcImage[iBand][iOffset + 1],
1815 11775852 : (double)poWK->papabySrcImage[iBand][iOffset + 2]);
1816 : }
1817 :
1818 267633 : double dfValue = CubicConvolution(dfDeltaY, dfDeltaY2, dfDeltaY3,
1819 : adfValue[0], adfValue[1], adfValue[2], adfValue[3]);
1820 :
1821 267633 : if ( dfValue < 0.0 )
1822 8 : *pbValue = 0;
1823 267625 : else if ( dfValue > 255.0 )
1824 11506 : *pbValue = 255;
1825 : else
1826 256119 : *pbValue = (GByte)(0.5 + dfValue);
1827 :
1828 267633 : return TRUE;
1829 : }
1830 :
1831 262207 : static int GWKCubicResampleNoMasksShort( GDALWarpKernel *poWK, int iBand,
1832 : double dfSrcX, double dfSrcY,
1833 : GInt16 *piValue )
1834 :
1835 : {
1836 262207 : int iSrcX = (int) floor( dfSrcX - 0.5 );
1837 262207 : int iSrcY = (int) floor( dfSrcY - 0.5 );
1838 262207 : int iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
1839 262207 : double dfDeltaX = dfSrcX - 0.5 - iSrcX;
1840 262207 : double dfDeltaY = dfSrcY - 0.5 - iSrcY;
1841 262207 : double dfDeltaX2 = dfDeltaX * dfDeltaX;
1842 262207 : double dfDeltaY2 = dfDeltaY * dfDeltaY;
1843 262207 : double dfDeltaX3 = dfDeltaX2 * dfDeltaX;
1844 262207 : double dfDeltaY3 = dfDeltaY2 * dfDeltaY;
1845 : double adfValue[4];
1846 : int i;
1847 :
1848 : // Get the bilinear interpolation at the image borders
1849 262207 : if ( iSrcX - 1 < 0 || iSrcX + 2 >= poWK->nSrcXSize
1850 : || iSrcY - 1 < 0 || iSrcY + 2 >= poWK->nSrcYSize )
1851 : return GWKBilinearResampleNoMasksShort( poWK, iBand, dfSrcX, dfSrcY,
1852 9186 : piValue);
1853 :
1854 1265105 : for ( i = -1; i < 3; i++ )
1855 : {
1856 1012084 : int iOffset = iSrcOffset + i * poWK->nSrcXSize;
1857 :
1858 11132924 : adfValue[i + 1] =CubicConvolution(dfDeltaX, dfDeltaX2, dfDeltaX3,
1859 : (double)((GInt16 *)poWK->papabySrcImage[iBand])[iOffset - 1],
1860 : (double)((GInt16 *)poWK->papabySrcImage[iBand])[iOffset],
1861 : (double)((GInt16 *)poWK->papabySrcImage[iBand])[iOffset + 1],
1862 11132924 : (double)((GInt16 *)poWK->papabySrcImage[iBand])[iOffset + 2]);
1863 : }
1864 :
1865 2024168 : *piValue = (GInt16)CubicConvolution(dfDeltaY, dfDeltaY2, dfDeltaY3,
1866 2024168 : adfValue[0], adfValue[1], adfValue[2], adfValue[3]);
1867 :
1868 253021 : return TRUE;
1869 : }
1870 :
1871 :
1872 : /************************************************************************/
1873 : /* GWKLanczosSinc() */
1874 : /************************************************************************/
1875 :
1876 : /*
1877 : * Lanczos windowed sinc interpolation kernel with radius r.
1878 : * /
1879 : * | sinc(x) * sinc(x/r), if |x| < r
1880 : * L(x) = | 1, if x = 0 ,
1881 : * | 0, otherwise
1882 : * \
1883 : *
1884 : * where sinc(x) = sin(PI * x) / (PI * x).
1885 : */
1886 :
1887 : #define GWK_PI 3.14159265358979323846
1888 3844908 : static double GWKLanczosSinc( double dfX, double dfR )
1889 : {
1890 3844908 : if ( fabs(dfX) > dfR )
1891 533142 : return 0.0;
1892 3311766 : if ( dfX == 0.0 )
1893 385 : return 1.0;
1894 :
1895 3311381 : double dfPIX = GWK_PI * dfX;
1896 3311381 : return ( sin(dfPIX) / dfPIX ) * ( sin(dfPIX / dfR) * dfR / dfPIX );
1897 : }
1898 : #undef GWK_PI
1899 :
1900 : /************************************************************************/
1901 : /* GWKBSpline() */
1902 : /************************************************************************/
1903 :
1904 4326797 : static double GWKBSpline( double x )
1905 : {
1906 4326797 : double xp2 = x + 2.0;
1907 4326797 : double xp1 = x + 1.0;
1908 4326797 : double xm1 = x - 1.0;
1909 :
1910 : // This will most likely be used, so we'll compute it ahead of time to
1911 : // avoid stalling the processor
1912 4326797 : double xp2c = xp2 * xp2 * xp2;
1913 :
1914 : // Note that the test is computed only if it is needed
1915 : return (((xp2 > 0.0)?((xp1 > 0.0)?((x > 0.0)?((xm1 > 0.0)?
1916 : -4.0 * xm1*xm1*xm1:0.0) +
1917 : 6.0 * x*x*x:0.0) +
1918 : -4.0 * xp1*xp1*xp1:0.0) +
1919 4326797 : xp2c:0.0) ) * 0.166666666666666666666;
1920 : }
1921 :
1922 :
1923 : typedef struct
1924 : {
1925 : // Space for saved X weights
1926 : double *padfWeightsX;
1927 : char *panCalcX;
1928 :
1929 : // Space for saving a row of pixels
1930 : double *padfRowDensity;
1931 : double *padfRowReal;
1932 : double *padfRowImag;
1933 : } GWKResampleWrkStruct;
1934 :
1935 87 : static GWKResampleWrkStruct* GWKResampleCreateWrkStruct(GDALWarpKernel *poWK)
1936 : {
1937 87 : int nXDist = ( poWK->nXRadius + 1 ) * 2;
1938 :
1939 : GWKResampleWrkStruct* psWrkStruct =
1940 87 : (GWKResampleWrkStruct*)CPLMalloc(sizeof(GWKResampleWrkStruct));
1941 :
1942 : // Alloc space for saved X weights
1943 87 : psWrkStruct->padfWeightsX = (double *)CPLCalloc( nXDist, sizeof(double) );
1944 87 : psWrkStruct->panCalcX = (char *)CPLMalloc( nXDist * sizeof(char) );
1945 :
1946 : // Alloc space for saving a row of pixels
1947 87 : psWrkStruct->padfRowDensity = (double *)CPLCalloc( nXDist, sizeof(double) );
1948 87 : psWrkStruct->padfRowReal = (double *)CPLCalloc( nXDist, sizeof(double) );
1949 87 : psWrkStruct->padfRowImag = (double *)CPLCalloc( nXDist, sizeof(double) );
1950 :
1951 87 : return psWrkStruct;
1952 : }
1953 :
1954 87 : static void GWKResampleDeleteWrkStruct(GWKResampleWrkStruct* psWrkStruct)
1955 : {
1956 87 : CPLFree( psWrkStruct->padfWeightsX );
1957 87 : CPLFree( psWrkStruct->panCalcX );
1958 87 : CPLFree( psWrkStruct->padfRowDensity );
1959 87 : CPLFree( psWrkStruct->padfRowReal );
1960 87 : CPLFree( psWrkStruct->padfRowImag );
1961 87 : CPLFree( psWrkStruct );
1962 87 : }
1963 :
1964 : /************************************************************************/
1965 : /* GWKResample() */
1966 : /************************************************************************/
1967 :
1968 279384 : static int GWKResample( GDALWarpKernel *poWK, int iBand,
1969 : double dfSrcX, double dfSrcY,
1970 : double *pdfDensity,
1971 : double *pdfReal, double *pdfImag,
1972 : const GWKResampleWrkStruct* psWrkStruct )
1973 :
1974 : {
1975 : // Save as local variables to avoid following pointers in loops
1976 279384 : int nSrcXSize = poWK->nSrcXSize;
1977 279384 : int nSrcYSize = poWK->nSrcYSize;
1978 :
1979 279384 : double dfAccumulatorReal = 0.0, dfAccumulatorImag = 0.0;
1980 279384 : double dfAccumulatorDensity = 0.0;
1981 279384 : double dfAccumulatorWeight = 0.0;
1982 279384 : int iSrcX = (int) floor( dfSrcX - 0.5 );
1983 279384 : int iSrcY = (int) floor( dfSrcY - 0.5 );
1984 279384 : int iSrcOffset = iSrcX + iSrcY * nSrcXSize;
1985 279384 : double dfDeltaX = dfSrcX - 0.5 - iSrcX;
1986 279384 : double dfDeltaY = dfSrcY - 0.5 - iSrcY;
1987 279384 : int eResample = poWK->eResample;
1988 :
1989 : double dfXScale, dfYScale;
1990 : double dfXFilter, dfYFilter;
1991 : int nXRadius, nFiltInitX;
1992 : int nYRadius, nFiltInitY;
1993 :
1994 279384 : dfXScale = poWK->dfXScale;
1995 279384 : dfYScale = poWK->dfYScale;
1996 279384 : nXRadius = poWK->nXRadius;
1997 279384 : nYRadius = poWK->nYRadius;
1998 279384 : nFiltInitX = poWK->nFiltInitX;
1999 279384 : nFiltInitY = poWK->nFiltInitY;
2000 279384 : dfXFilter = poWK->dfXFilter;
2001 279384 : dfYFilter = poWK->dfYFilter;
2002 :
2003 : int i, j;
2004 279384 : int nXDist = ( nXRadius + 1 ) * 2;
2005 :
2006 : // Space for saved X weights
2007 279384 : double *padfWeightsX = psWrkStruct->padfWeightsX;
2008 279384 : char *panCalcX = psWrkStruct->panCalcX;
2009 :
2010 : // Space for saving a row of pixels
2011 279384 : double *padfRowDensity = psWrkStruct->padfRowDensity;
2012 279384 : double *padfRowReal = psWrkStruct->padfRowReal;
2013 279384 : double *padfRowImag = psWrkStruct->padfRowImag;
2014 :
2015 : // Mark as needing calculation (don't calculate the weights yet,
2016 : // because a mask may render it unnecessary)
2017 279384 : memset( panCalcX, FALSE, nXDist * sizeof(char) );
2018 :
2019 : // Loop over pixel rows in the kernel
2020 2233398 : for ( j = nFiltInitY; j <= nYRadius; ++j )
2021 : {
2022 1954014 : int iRowOffset, nXMin = nFiltInitX, nXMax = nXRadius;
2023 : double dfWeight1;
2024 :
2025 : // Skip sampling over edge of image
2026 1954014 : if ( iSrcY + j < 0 || iSrcY + j >= nSrcYSize )
2027 30287 : continue;
2028 :
2029 : // Invariant; needs calculation only once per row
2030 1923727 : iRowOffset = iSrcOffset + j * nSrcXSize + nFiltInitX;
2031 :
2032 : // Make sure we don't read before or after the source array.
2033 1923727 : if ( iRowOffset < 0 )
2034 : {
2035 1316 : nXMin = nXMin - iRowOffset;
2036 1316 : iRowOffset = 0;
2037 : }
2038 1923727 : if ( iRowOffset + nXDist >= nSrcXSize*nSrcYSize )
2039 : {
2040 891 : nXMax = nSrcXSize*nSrcYSize - iRowOffset + nXMin - 1;
2041 891 : nXMax -= (nXMax-nXMin+1) % 2;
2042 : }
2043 :
2044 : // Get pixel values
2045 1923727 : if ( !GWKGetPixelRow( poWK, iBand, iRowOffset, (nXMax-nXMin+2)/2,
2046 : padfRowDensity, padfRowReal, padfRowImag ) )
2047 0 : continue;
2048 :
2049 : // Select the resampling algorithm
2050 1923727 : if ( eResample == GRA_CubicSpline )
2051 : // Calculate the Y weight
2052 : dfWeight1 = ( dfYScale < 1.0 ) ?
2053 : GWKBSpline(((double)j) * dfYScale) * dfYScale :
2054 1647 : GWKBSpline(((double)j) - dfDeltaY);
2055 1922080 : else if ( eResample == GRA_Lanczos )
2056 : dfWeight1 = ( dfYScale < 1.0 ) ?
2057 : GWKLanczosSinc(j * dfYScale, dfYFilter) * dfYScale :
2058 1922080 : GWKLanczosSinc(j - dfDeltaY, dfYFilter);
2059 : else
2060 0 : return FALSE;
2061 :
2062 : // Iterate over pixels in row
2063 15381135 : for (i = nXMin; i <= nXMax; ++i )
2064 : {
2065 : double dfWeight2;
2066 :
2067 : // Skip sampling at edge of image OR if pixel has zero density
2068 26721797 : if ( iSrcX + i < 0 || iSrcX + i >= nSrcXSize
2069 13264389 : || padfRowDensity[i-nXMin] < 0.000000001 )
2070 193019 : continue;
2071 :
2072 : // Make or use a cached set of weights for this row
2073 13264389 : if ( panCalcX[i-nFiltInitX] )
2074 : // Use saved weight value instead of recomputing it
2075 11339707 : dfWeight2 = dfWeight1 * padfWeightsX[i-nFiltInitX];
2076 : else
2077 : {
2078 : // Choose among possible algorithms
2079 1924682 : if ( eResample == GRA_CubicSpline )
2080 : // Calculate & save the X weight
2081 1854 : padfWeightsX[i-nFiltInitX] = dfWeight2 = (dfXScale < 1.0 ) ?
2082 : GWKBSpline((double)i * dfXScale) * dfXScale :
2083 1854 : GWKBSpline(dfDeltaX - (double)i);
2084 1922828 : else if ( eResample == GRA_Lanczos )
2085 : // Calculate & save the X weight
2086 1922828 : padfWeightsX[i-nFiltInitX] = dfWeight2 = (dfXScale < 1.0 ) ?
2087 : GWKLanczosSinc(i * dfXScale, dfXFilter) * dfXScale :
2088 1922828 : GWKLanczosSinc(i - dfDeltaX, dfXFilter);
2089 : else
2090 0 : return FALSE;
2091 :
2092 1924682 : dfWeight2 *= dfWeight1;
2093 1924682 : panCalcX[i-nFiltInitX] = TRUE;
2094 : }
2095 :
2096 : // Accumulate!
2097 13264389 : dfAccumulatorReal += padfRowReal[i-nXMin] * dfWeight2;
2098 13264389 : dfAccumulatorImag += padfRowImag[i-nXMin] * dfWeight2;
2099 13264389 : dfAccumulatorDensity += padfRowDensity[i-nXMin] * dfWeight2;
2100 13264389 : dfAccumulatorWeight += dfWeight2;
2101 : }
2102 : }
2103 :
2104 279384 : if ( dfAccumulatorWeight < 0.000001 || dfAccumulatorDensity < 0.000001 )
2105 : {
2106 0 : *pdfDensity = 0.0;
2107 0 : return FALSE;
2108 : }
2109 :
2110 : // Calculate the output taking into account weighting
2111 557870 : if ( dfAccumulatorWeight < 0.99999 || dfAccumulatorWeight > 1.00001 )
2112 : {
2113 278486 : *pdfReal = dfAccumulatorReal / dfAccumulatorWeight;
2114 278486 : *pdfImag = dfAccumulatorImag / dfAccumulatorWeight;
2115 278486 : *pdfDensity = dfAccumulatorDensity / dfAccumulatorWeight;
2116 : }
2117 : else
2118 : {
2119 898 : *pdfReal = dfAccumulatorReal;
2120 898 : *pdfImag = dfAccumulatorImag;
2121 898 : *pdfDensity = dfAccumulatorDensity;
2122 : }
2123 :
2124 279384 : return TRUE;
2125 : }
2126 :
2127 278207 : static int GWKCubicSplineResampleNoMasksByte( GDALWarpKernel *poWK, int iBand,
2128 : double dfSrcX, double dfSrcY,
2129 : GByte *pbValue, double *padfBSpline )
2130 :
2131 : {
2132 : // Commonly used; save locally
2133 278207 : int nSrcXSize = poWK->nSrcXSize;
2134 278207 : int nSrcYSize = poWK->nSrcYSize;
2135 :
2136 278207 : double dfAccumulator = 0.0;
2137 278207 : int iSrcX = (int) floor( dfSrcX - 0.5 );
2138 278207 : int iSrcY = (int) floor( dfSrcY - 0.5 );
2139 278207 : int iSrcOffset = iSrcX + iSrcY * nSrcXSize;
2140 278207 : double dfDeltaX = dfSrcX - 0.5 - iSrcX;
2141 278207 : double dfDeltaY = dfSrcY - 0.5 - iSrcY;
2142 :
2143 278207 : double dfXScale = poWK->dfXScale;
2144 278207 : double dfYScale = poWK->dfYScale;
2145 278207 : int nXRadius = poWK->nXRadius;
2146 278207 : int nYRadius = poWK->nYRadius;
2147 :
2148 278207 : GByte* pabySrcBand = poWK->papabySrcImage[iBand];
2149 :
2150 : // Politely refusing to process invalid coordinates or obscenely small image
2151 278207 : if ( iSrcX >= nSrcXSize || iSrcY >= nSrcYSize
2152 : || nXRadius > nSrcXSize || nYRadius > nSrcYSize )
2153 1 : return GWKBilinearResampleNoMasksByte( poWK, iBand, dfSrcX, dfSrcY, pbValue);
2154 :
2155 : // Loop over all rows in the kernel
2156 : int j, jC;
2157 1391030 : for ( jC = 0, j = 1 - nYRadius; j <= nYRadius; ++j, ++jC )
2158 : {
2159 : int iSampJ;
2160 : // Calculate the Y weight
2161 : double dfWeight1 = ( dfYScale < 1.0 ) ?
2162 : GWKBSpline((double)j * dfYScale) * dfYScale :
2163 1112824 : GWKBSpline((double)j - dfDeltaY);
2164 :
2165 : // Flip sampling over edge of image
2166 1112824 : if ( iSrcY + j < 0 )
2167 6700 : iSampJ = iSrcOffset - (iSrcY + j) * nSrcXSize;
2168 1106124 : else if ( iSrcY + j >= nSrcYSize )
2169 549 : iSampJ = iSrcOffset + (2*nSrcYSize - 2*iSrcY - j - 1) * nSrcXSize;
2170 : else
2171 1105575 : iSampJ = iSrcOffset + j * nSrcXSize;
2172 :
2173 : // Loop over all pixels in the row
2174 : int i, iC;
2175 5564120 : for ( iC = 0, i = 1 - nXRadius; i <= nXRadius; ++i, ++iC )
2176 : {
2177 : int iSampI;
2178 : double dfWeight2;
2179 :
2180 : // Flip sampling over edge of image
2181 4451296 : if ( iSrcX + i < 0 )
2182 26704 : iSampI = -iSrcX - i;
2183 4424592 : else if ( iSrcX + i >= nSrcXSize )
2184 2224 : iSampI = 2*nSrcXSize - 2*iSrcX - i - 1;
2185 : else
2186 4422368 : iSampI = i;
2187 :
2188 : // Make a cached set of GWKBSpline values
2189 4451296 : if( jC == 0 )
2190 : {
2191 : // Calculate & save the X weight
2192 1112824 : dfWeight2 = padfBSpline[iC] = ((dfXScale < 1.0 ) ?
2193 : GWKBSpline((double)i * dfXScale) * dfXScale :
2194 1112824 : GWKBSpline(dfDeltaX - (double)i));
2195 1112824 : dfWeight2 *= dfWeight1;
2196 : }
2197 : else
2198 3338472 : dfWeight2 = dfWeight1 * padfBSpline[iC];
2199 :
2200 : // Retrieve the pixel & accumulate
2201 4451296 : dfAccumulator += (double)pabySrcBand[iSampI+iSampJ] * dfWeight2;
2202 : }
2203 : }
2204 :
2205 278206 : if ( dfAccumulator < 0.0 )
2206 0 : *pbValue = 0;
2207 278206 : else if ( dfAccumulator > 255.0 )
2208 23 : *pbValue = 255;
2209 : else
2210 278183 : *pbValue = (GByte)(0.5 + dfAccumulator);
2211 :
2212 278206 : return TRUE;
2213 : }
2214 :
2215 262207 : static int GWKCubicSplineResampleNoMasksShort( GDALWarpKernel *poWK, int iBand,
2216 : double dfSrcX, double dfSrcY,
2217 : GInt16 *piValue, double *padfBSpline )
2218 :
2219 : {
2220 : //Save src size to local var
2221 262207 : int nSrcXSize = poWK->nSrcXSize;
2222 262207 : int nSrcYSize = poWK->nSrcYSize;
2223 :
2224 262207 : double dfAccumulator = 0.0;
2225 262207 : int iSrcX = (int) floor( dfSrcX - 0.5 );
2226 262207 : int iSrcY = (int) floor( dfSrcY - 0.5 );
2227 262207 : int iSrcOffset = iSrcX + iSrcY * nSrcXSize;
2228 262207 : double dfDeltaX = dfSrcX - 0.5 - iSrcX;
2229 262207 : double dfDeltaY = dfSrcY - 0.5 - iSrcY;
2230 :
2231 262207 : double dfXScale = poWK->dfXScale;
2232 262207 : double dfYScale = poWK->dfYScale;
2233 262207 : int nXRadius = poWK->nXRadius;
2234 262207 : int nYRadius = poWK->nYRadius;
2235 :
2236 : // Save band array pointer to local var; cast here instead of later
2237 262207 : GInt16* pabySrcBand = ((GInt16 *)poWK->papabySrcImage[iBand]);
2238 :
2239 : // Politely refusing to process invalid coordinates or obscenely small image
2240 262207 : if ( iSrcX >= nSrcXSize || iSrcY >= nSrcYSize
2241 : || nXRadius > nSrcXSize || nYRadius > nSrcYSize )
2242 1 : return GWKBilinearResampleNoMasksShort( poWK, iBand, dfSrcX, dfSrcY, piValue);
2243 :
2244 : // Loop over all pixels in the kernel
2245 : int j, jC;
2246 1311030 : for ( jC = 0, j = 1 - nYRadius; j <= nYRadius; ++j, ++jC )
2247 : {
2248 : int iSampJ;
2249 :
2250 : // Calculate the Y weight
2251 : double dfWeight1 = ( dfYScale < 1.0 ) ?
2252 : GWKBSpline((double)j * dfYScale) * dfYScale :
2253 1048824 : GWKBSpline((double)j - dfDeltaY);
2254 :
2255 : // Flip sampling over edge of image
2256 1048824 : if ( iSrcY + j < 0 )
2257 6180 : iSampJ = iSrcOffset - (iSrcY + j) * nSrcXSize;
2258 1042644 : else if ( iSrcY + j >= nSrcYSize )
2259 29 : iSampJ = iSrcOffset + (2*nSrcYSize - 2*iSrcY - j - 1) * nSrcXSize;
2260 : else
2261 1042615 : iSampJ = iSrcOffset + j * nSrcXSize;
2262 :
2263 : // Loop over all pixels in row
2264 : int i, iC;
2265 5244120 : for ( iC = 0, i = 1 - nXRadius; i <= nXRadius; ++i, ++iC )
2266 : {
2267 : int iSampI;
2268 : double dfWeight2;
2269 :
2270 : // Flip sampling over edge of image
2271 4195296 : if ( iSrcX + i < 0 )
2272 24624 : iSampI = -iSrcX - i;
2273 4170672 : else if(iSrcX + i >= nSrcXSize)
2274 144 : iSampI = 2*nSrcXSize - 2*iSrcX - i - 1;
2275 : else
2276 4170528 : iSampI = i;
2277 :
2278 : // Make a cached set of GWKBSpline values
2279 4195296 : if ( jC == 0 )
2280 : {
2281 : // Calculate & save the X weight
2282 1048824 : dfWeight2 = padfBSpline[iC] = ((dfXScale < 1.0 ) ?
2283 : GWKBSpline((double)i * dfXScale) * dfXScale :
2284 1048824 : GWKBSpline(dfDeltaX - (double)i));
2285 1048824 : dfWeight2 *= dfWeight1;
2286 : } else
2287 3146472 : dfWeight2 = dfWeight1 * padfBSpline[iC];
2288 :
2289 4195296 : dfAccumulator += (double)pabySrcBand[iSampI + iSampJ] * dfWeight2;
2290 : }
2291 : }
2292 :
2293 262206 : *piValue = (GInt16)(0.5 + dfAccumulator);
2294 :
2295 262206 : return TRUE;
2296 : }
2297 :
2298 : /************************************************************************/
2299 : /* GWKGeneralCase() */
2300 : /* */
2301 : /* This is the most general case. It attempts to handle all */
2302 : /* possible features with relatively little concern for */
2303 : /* efficiency. */
2304 : /************************************************************************/
2305 :
2306 189 : static CPLErr GWKGeneralCase( GDALWarpKernel *poWK )
2307 :
2308 : {
2309 : int iDstY;
2310 189 : int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
2311 189 : int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
2312 189 : CPLErr eErr = CE_None;
2313 :
2314 : CPLDebug( "GDAL", "GDALWarpKernel()::GWKGeneralCase()\n"
2315 : "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
2316 : poWK->nSrcXOff, poWK->nSrcYOff,
2317 : poWK->nSrcXSize, poWK->nSrcYSize,
2318 : poWK->nDstXOff, poWK->nDstYOff,
2319 189 : poWK->nDstXSize, poWK->nDstYSize );
2320 :
2321 189 : if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
2322 : {
2323 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
2324 0 : return CE_Failure;
2325 : }
2326 :
2327 : /* -------------------------------------------------------------------- */
2328 : /* Allocate x,y,z coordinate arrays for transformation ... one */
2329 : /* scanlines worth of positions. */
2330 : /* -------------------------------------------------------------------- */
2331 : double *padfX, *padfY, *padfZ;
2332 : int *pabSuccess;
2333 :
2334 189 : padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
2335 189 : padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
2336 189 : padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
2337 189 : pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
2338 :
2339 189 : GWKResampleWrkStruct* psWrkStruct = NULL;
2340 189 : if (poWK->eResample == GRA_CubicSpline
2341 : || poWK->eResample == GRA_Lanczos )
2342 : {
2343 87 : psWrkStruct = GWKResampleCreateWrkStruct(poWK);
2344 : }
2345 :
2346 : /* ==================================================================== */
2347 : /* Loop over output lines. */
2348 : /* ==================================================================== */
2349 1838 : for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
2350 : {
2351 : int iDstX;
2352 :
2353 : /* -------------------------------------------------------------------- */
2354 : /* Setup points to transform to source image space. */
2355 : /* -------------------------------------------------------------------- */
2356 530372 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
2357 : {
2358 528723 : padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
2359 528723 : padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
2360 528723 : padfZ[iDstX] = 0.0;
2361 : }
2362 :
2363 : /* -------------------------------------------------------------------- */
2364 : /* Transform the points from destination pixel/line coordinates */
2365 : /* to source pixel/line coordinates. */
2366 : /* -------------------------------------------------------------------- */
2367 : poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize,
2368 1649 : padfX, padfY, padfZ, pabSuccess );
2369 :
2370 : /* ==================================================================== */
2371 : /* Loop over pixels in output scanline. */
2372 : /* ==================================================================== */
2373 530372 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
2374 : {
2375 : int iDstOffset;
2376 :
2377 528723 : if( !pabSuccess[iDstX] )
2378 0 : continue;
2379 :
2380 : /* -------------------------------------------------------------------- */
2381 : /* Figure out what pixel we want in our source raster, and skip */
2382 : /* further processing if it is well off the source image. */
2383 : /* -------------------------------------------------------------------- */
2384 : // We test against the value before casting to avoid the
2385 : // problem of asymmetric truncation effects around zero. That is
2386 : // -0.5 will be 0 when cast to an int.
2387 1057407 : if( padfX[iDstX] < poWK->nSrcXOff
2388 528684 : || padfY[iDstX] < poWK->nSrcYOff )
2389 29292 : continue;
2390 :
2391 : int iSrcX, iSrcY, iSrcOffset;
2392 :
2393 499431 : iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
2394 499431 : iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
2395 :
2396 : // If operating outside natural projection area, padfX/Y can be
2397 : // a very huge positive number, that becomes -2147483648 in the
2398 : // int trucation. So it is necessary to test now for non negativeness.
2399 499431 : if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
2400 217249 : continue;
2401 :
2402 282182 : iSrcOffset = iSrcX + iSrcY * nSrcXSize;
2403 :
2404 : /* -------------------------------------------------------------------- */
2405 : /* Do not try to apply transparent/invalid source pixels to the */
2406 : /* destination. This currently ignores the multi-pixel input */
2407 : /* of bilinear and cubic resamples. */
2408 : /* -------------------------------------------------------------------- */
2409 282182 : double dfDensity = 1.0;
2410 :
2411 282182 : if( poWK->pafUnifiedSrcDensity != NULL
2412 : && iSrcX >= 0 && iSrcY >= 0
2413 : && iSrcX < nSrcXSize && iSrcY < nSrcYSize )
2414 : {
2415 1203 : dfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
2416 1203 : if( dfDensity < 0.00001 )
2417 1203 : continue;
2418 : }
2419 :
2420 280979 : if( poWK->panUnifiedSrcValid != NULL
2421 : && iSrcX >= 0 && iSrcY >= 0
2422 : && iSrcX < nSrcXSize && iSrcY < nSrcYSize
2423 0 : && !(poWK->panUnifiedSrcValid[iSrcOffset>>5]
2424 : & (0x01 << (iSrcOffset & 0x1f))) )
2425 0 : continue;
2426 :
2427 : /* ==================================================================== */
2428 : /* Loop processing each band. */
2429 : /* ==================================================================== */
2430 : int iBand;
2431 280979 : int bHasFoundDensity = FALSE;
2432 :
2433 280979 : iDstOffset = iDstX + iDstY * nDstXSize;
2434 561958 : for( iBand = 0; iBand < poWK->nBands; iBand++ )
2435 : {
2436 280979 : double dfBandDensity = 0.0;
2437 280979 : double dfValueReal = 0.0;
2438 280979 : double dfValueImag = 0.0;
2439 :
2440 : /* -------------------------------------------------------------------- */
2441 : /* Collect the source value. */
2442 : /* -------------------------------------------------------------------- */
2443 281458 : if ( poWK->eResample == GRA_NearestNeighbour ||
2444 : nSrcXSize == 1 || nSrcYSize == 1)
2445 : {
2446 : GWKGetPixelValue( poWK, iBand, iSrcOffset,
2447 479 : &dfBandDensity, &dfValueReal, &dfValueImag );
2448 : }
2449 280500 : else if ( poWK->eResample == GRA_Bilinear )
2450 : {
2451 : GWKBilinearResample( poWK, iBand,
2452 558 : padfX[iDstX]-poWK->nSrcXOff,
2453 558 : padfY[iDstX]-poWK->nSrcYOff,
2454 : &dfBandDensity,
2455 1116 : &dfValueReal, &dfValueImag );
2456 : }
2457 279942 : else if ( poWK->eResample == GRA_Cubic )
2458 : {
2459 : GWKCubicResample( poWK, iBand,
2460 558 : padfX[iDstX]-poWK->nSrcXOff,
2461 558 : padfY[iDstX]-poWK->nSrcYOff,
2462 : &dfBandDensity,
2463 1116 : &dfValueReal, &dfValueImag );
2464 : }
2465 279384 : else if ( poWK->eResample == GRA_CubicSpline
2466 : || poWK->eResample == GRA_Lanczos )
2467 : {
2468 : GWKResample( poWK, iBand,
2469 279384 : padfX[iDstX]-poWK->nSrcXOff,
2470 279384 : padfY[iDstX]-poWK->nSrcYOff,
2471 : &dfBandDensity,
2472 558768 : &dfValueReal, &dfValueImag, psWrkStruct );
2473 : }
2474 :
2475 :
2476 : // If we didn't find any valid inputs skip to next band.
2477 280979 : if ( dfBandDensity < 0.0000000001 )
2478 0 : continue;
2479 :
2480 280979 : bHasFoundDensity = TRUE;
2481 :
2482 : /* -------------------------------------------------------------------- */
2483 : /* We have a computed value from the source. Now apply it to */
2484 : /* the destination pixel. */
2485 : /* -------------------------------------------------------------------- */
2486 : GWKSetPixelValue( poWK, iBand, iDstOffset,
2487 : dfBandDensity,
2488 280979 : dfValueReal, dfValueImag );
2489 :
2490 : }
2491 :
2492 280979 : if (!bHasFoundDensity)
2493 0 : continue;
2494 :
2495 : /* -------------------------------------------------------------------- */
2496 : /* Update destination density/validity masks. */
2497 : /* -------------------------------------------------------------------- */
2498 280979 : GWKOverlayDensity( poWK, iDstOffset, dfDensity );
2499 :
2500 280979 : if( poWK->panDstValid != NULL )
2501 : {
2502 : poWK->panDstValid[iDstOffset>>5] |=
2503 0 : 0x01 << (iDstOffset & 0x1f);
2504 : }
2505 :
2506 : } /* Next iDstX */
2507 :
2508 : /* -------------------------------------------------------------------- */
2509 : /* Report progress to the user, and optionally cancel out. */
2510 : /* -------------------------------------------------------------------- */
2511 1649 : if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
2512 : ((iDstY+1) / (double) nDstYSize),
2513 : "", poWK->pProgress ) )
2514 : {
2515 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
2516 0 : eErr = CE_Failure;
2517 : }
2518 : }
2519 :
2520 : /* -------------------------------------------------------------------- */
2521 : /* Cleanup and return. */
2522 : /* -------------------------------------------------------------------- */
2523 189 : CPLFree( padfX );
2524 189 : CPLFree( padfY );
2525 189 : CPLFree( padfZ );
2526 189 : CPLFree( pabSuccess );
2527 189 : if (psWrkStruct)
2528 87 : GWKResampleDeleteWrkStruct(psWrkStruct);
2529 :
2530 189 : return eErr;
2531 : }
2532 :
2533 : /************************************************************************/
2534 : /* GWKNearestNoMasksByte() */
2535 : /* */
2536 : /* Case for 8bit input data with nearest neighbour resampling */
2537 : /* without concerning about masking. Should be as fast as */
2538 : /* possible for this particular transformation type. */
2539 : /************************************************************************/
2540 :
2541 35 : static CPLErr GWKNearestNoMasksByte( GDALWarpKernel *poWK )
2542 :
2543 : {
2544 : int iDstY;
2545 35 : int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
2546 35 : int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
2547 35 : CPLErr eErr = CE_None;
2548 :
2549 : CPLDebug( "GDAL", "GDALWarpKernel()::GWKNearestNoMasksByte()\n"
2550 : "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
2551 : poWK->nSrcXOff, poWK->nSrcYOff,
2552 : poWK->nSrcXSize, poWK->nSrcYSize,
2553 : poWK->nDstXOff, poWK->nDstYOff,
2554 35 : poWK->nDstXSize, poWK->nDstYSize );
2555 :
2556 35 : if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
2557 : {
2558 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
2559 0 : return CE_Failure;
2560 : }
2561 :
2562 : /* -------------------------------------------------------------------- */
2563 : /* Allocate x,y,z coordinate arrays for transformation ... one */
2564 : /* scanlines worth of positions. */
2565 : /* -------------------------------------------------------------------- */
2566 : double *padfX, *padfY, *padfZ;
2567 : int *pabSuccess;
2568 :
2569 35 : padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
2570 35 : padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
2571 35 : padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
2572 35 : pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
2573 :
2574 : /* ==================================================================== */
2575 : /* Loop over output lines. */
2576 : /* ==================================================================== */
2577 3729 : for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
2578 : {
2579 : int iDstX;
2580 :
2581 : /* -------------------------------------------------------------------- */
2582 : /* Setup points to transform to source image space. */
2583 : /* -------------------------------------------------------------------- */
2584 1746574 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
2585 : {
2586 1742880 : padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
2587 1742880 : padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
2588 1742880 : padfZ[iDstX] = 0.0;
2589 : }
2590 :
2591 : /* -------------------------------------------------------------------- */
2592 : /* Transform the points from destination pixel/line coordinates */
2593 : /* to source pixel/line coordinates. */
2594 : /* -------------------------------------------------------------------- */
2595 : poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize,
2596 3694 : padfX, padfY, padfZ, pabSuccess );
2597 :
2598 : /* ==================================================================== */
2599 : /* Loop over pixels in output scanline. */
2600 : /* ==================================================================== */
2601 1746574 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
2602 : {
2603 1742880 : if( !pabSuccess[iDstX] )
2604 153669 : continue;
2605 :
2606 : /* -------------------------------------------------------------------- */
2607 : /* Figure out what pixel we want in our source raster, and skip */
2608 : /* further processing if it is well off the source image. */
2609 : /* -------------------------------------------------------------------- */
2610 : // We test against the value before casting to avoid the
2611 : // problem of asymmetric truncation effects around zero. That is
2612 : // -0.5 will be 0 when cast to an int.
2613 3178222 : if( padfX[iDstX] < poWK->nSrcXOff
2614 1589011 : || padfY[iDstX] < poWK->nSrcYOff )
2615 120136 : continue;
2616 :
2617 : int iSrcX, iSrcY, iSrcOffset;
2618 :
2619 1469075 : iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
2620 1469075 : iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
2621 :
2622 : // If operating outside natural projection area, padfX/Y can be
2623 : // a very huge positive number, that becomes -2147483648 in the
2624 : // int trucation. So it is necessary to test now for non negativeness.
2625 1469075 : if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
2626 305331 : continue;
2627 :
2628 1163744 : iSrcOffset = iSrcX + iSrcY * nSrcXSize;
2629 :
2630 : /* ==================================================================== */
2631 : /* Loop processing each band. */
2632 : /* ==================================================================== */
2633 : int iBand;
2634 : int iDstOffset;
2635 :
2636 1163744 : iDstOffset = iDstX + iDstY * nDstXSize;
2637 :
2638 3916032 : for( iBand = 0; iBand < poWK->nBands; iBand++ )
2639 : {
2640 2752288 : poWK->papabyDstImage[iBand][iDstOffset] =
2641 2752288 : poWK->papabySrcImage[iBand][iSrcOffset];
2642 : }
2643 : }
2644 :
2645 : /* -------------------------------------------------------------------- */
2646 : /* Report progress to the user, and optionally cancel out. */
2647 : /* -------------------------------------------------------------------- */
2648 3694 : if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
2649 : ((iDstY+1) / (double) nDstYSize),
2650 : "", poWK->pProgress ) )
2651 : {
2652 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
2653 0 : eErr = CE_Failure;
2654 : }
2655 : }
2656 :
2657 : /* -------------------------------------------------------------------- */
2658 : /* Cleanup and return. */
2659 : /* -------------------------------------------------------------------- */
2660 35 : CPLFree( padfX );
2661 35 : CPLFree( padfY );
2662 35 : CPLFree( padfZ );
2663 35 : CPLFree( pabSuccess );
2664 :
2665 35 : return eErr;
2666 : }
2667 :
2668 : /************************************************************************/
2669 : /* GWKBilinearNoMasksByte() */
2670 : /* */
2671 : /* Case for 8bit input data with bilinear resampling without */
2672 : /* concerning about masking. Should be as fast as possible */
2673 : /* for this particular transformation type. */
2674 : /************************************************************************/
2675 :
2676 10 : static CPLErr GWKBilinearNoMasksByte( GDALWarpKernel *poWK )
2677 :
2678 : {
2679 : int iDstY;
2680 10 : int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
2681 10 : int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
2682 10 : CPLErr eErr = CE_None;
2683 :
2684 : CPLDebug( "GDAL", "GDALWarpKernel()::GWKBilinearNoMasksByte()\n"
2685 : "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
2686 : poWK->nSrcXOff, poWK->nSrcYOff,
2687 : poWK->nSrcXSize, poWK->nSrcYSize,
2688 : poWK->nDstXOff, poWK->nDstYOff,
2689 10 : poWK->nDstXSize, poWK->nDstYSize );
2690 :
2691 10 : if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
2692 : {
2693 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
2694 0 : return CE_Failure;
2695 : }
2696 :
2697 : /* -------------------------------------------------------------------- */
2698 : /* Allocate x,y,z coordinate arrays for transformation ... one */
2699 : /* scanlines worth of positions. */
2700 : /* -------------------------------------------------------------------- */
2701 : double *padfX, *padfY, *padfZ;
2702 : int *pabSuccess;
2703 :
2704 10 : padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
2705 10 : padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
2706 10 : padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
2707 10 : pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
2708 :
2709 : /* ==================================================================== */
2710 : /* Loop over output lines. */
2711 : /* ==================================================================== */
2712 703 : for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
2713 : {
2714 : int iDstX;
2715 :
2716 : /* -------------------------------------------------------------------- */
2717 : /* Setup points to transform to source image space. */
2718 : /* -------------------------------------------------------------------- */
2719 330036 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
2720 : {
2721 329343 : padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
2722 329343 : padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
2723 329343 : padfZ[iDstX] = 0.0;
2724 : }
2725 :
2726 : /* -------------------------------------------------------------------- */
2727 : /* Transform the points from destination pixel/line coordinates */
2728 : /* to source pixel/line coordinates. */
2729 : /* -------------------------------------------------------------------- */
2730 : poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize,
2731 693 : padfX, padfY, padfZ, pabSuccess );
2732 :
2733 : /* ==================================================================== */
2734 : /* Loop over pixels in output scanline. */
2735 : /* ==================================================================== */
2736 330036 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
2737 : {
2738 329343 : if( !pabSuccess[iDstX] )
2739 0 : continue;
2740 :
2741 : /* -------------------------------------------------------------------- */
2742 : /* Figure out what pixel we want in our source raster, and skip */
2743 : /* further processing if it is well off the source image. */
2744 : /* -------------------------------------------------------------------- */
2745 : // We test against the value before casting to avoid the
2746 : // problem of asymmetric truncation effects around zero. That is
2747 : // -0.5 will be 0 when cast to an int.
2748 658686 : if( padfX[iDstX] < poWK->nSrcXOff
2749 329343 : || padfY[iDstX] < poWK->nSrcYOff )
2750 0 : continue;
2751 :
2752 : int iSrcX, iSrcY, iSrcOffset;
2753 :
2754 329343 : iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
2755 329343 : iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
2756 :
2757 : // If operating outside natural projection area, padfX/Y can be
2758 : // a very huge positive number, that becomes -2147483648 in the
2759 : // int trucation. So it is necessary to test now for non negativeness.
2760 329343 : if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
2761 51136 : continue;
2762 :
2763 278207 : iSrcOffset = iSrcX + iSrcY * nSrcXSize;
2764 :
2765 : /* ==================================================================== */
2766 : /* Loop processing each band. */
2767 : /* ==================================================================== */
2768 : int iBand;
2769 : int iDstOffset;
2770 :
2771 278207 : iDstOffset = iDstX + iDstY * nDstXSize;
2772 :
2773 556414 : for( iBand = 0; iBand < poWK->nBands; iBand++ )
2774 : {
2775 : GWKBilinearResampleNoMasksByte( poWK, iBand,
2776 278207 : padfX[iDstX]-poWK->nSrcXOff,
2777 278207 : padfY[iDstX]-poWK->nSrcYOff,
2778 834621 : &poWK->papabyDstImage[iBand][iDstOffset] );
2779 : }
2780 : }
2781 :
2782 : /* -------------------------------------------------------------------- */
2783 : /* Report progress to the user, and optionally cancel out. */
2784 : /* -------------------------------------------------------------------- */
2785 693 : if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
2786 : ((iDstY+1) / (double) nDstYSize),
2787 : "", poWK->pProgress ) )
2788 : {
2789 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
2790 0 : eErr = CE_Failure;
2791 : }
2792 : }
2793 :
2794 : /* -------------------------------------------------------------------- */
2795 : /* Cleanup and return. */
2796 : /* -------------------------------------------------------------------- */
2797 10 : CPLFree( padfX );
2798 10 : CPLFree( padfY );
2799 10 : CPLFree( padfZ );
2800 10 : CPLFree( pabSuccess );
2801 :
2802 10 : return eErr;
2803 : }
2804 :
2805 : /************************************************************************/
2806 : /* GWKCubicNoMasksByte() */
2807 : /* */
2808 : /* Case for 8bit input data with cubic resampling without */
2809 : /* concerning about masking. Should be as fast as possible */
2810 : /* for this particular transformation type. */
2811 : /************************************************************************/
2812 :
2813 10 : static CPLErr GWKCubicNoMasksByte( GDALWarpKernel *poWK )
2814 :
2815 : {
2816 : int iDstY;
2817 10 : int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
2818 10 : int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
2819 10 : CPLErr eErr = CE_None;
2820 :
2821 : CPLDebug( "GDAL", "GDALWarpKernel()::GWKCubicNoMasksByte()\n"
2822 : "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
2823 : poWK->nSrcXOff, poWK->nSrcYOff,
2824 : poWK->nSrcXSize, poWK->nSrcYSize,
2825 : poWK->nDstXOff, poWK->nDstYOff,
2826 10 : poWK->nDstXSize, poWK->nDstYSize );
2827 :
2828 10 : if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
2829 : {
2830 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
2831 0 : return CE_Failure;
2832 : }
2833 :
2834 : /* -------------------------------------------------------------------- */
2835 : /* Allocate x,y,z coordinate arrays for transformation ... one */
2836 : /* scanlines worth of positions. */
2837 : /* -------------------------------------------------------------------- */
2838 : double *padfX, *padfY, *padfZ;
2839 : int *pabSuccess;
2840 :
2841 10 : padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
2842 10 : padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
2843 10 : padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
2844 10 : pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
2845 :
2846 : /* ==================================================================== */
2847 : /* Loop over output lines. */
2848 : /* ==================================================================== */
2849 703 : for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
2850 : {
2851 : int iDstX;
2852 :
2853 : /* -------------------------------------------------------------------- */
2854 : /* Setup points to transform to source image space. */
2855 : /* -------------------------------------------------------------------- */
2856 330036 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
2857 : {
2858 329343 : padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
2859 329343 : padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
2860 329343 : padfZ[iDstX] = 0.0;
2861 : }
2862 :
2863 : /* -------------------------------------------------------------------- */
2864 : /* Transform the points from destination pixel/line coordinates */
2865 : /* to source pixel/line coordinates. */
2866 : /* -------------------------------------------------------------------- */
2867 : poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize,
2868 693 : padfX, padfY, padfZ, pabSuccess );
2869 :
2870 : /* ==================================================================== */
2871 : /* Loop over pixels in output scanline. */
2872 : /* ==================================================================== */
2873 330036 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
2874 : {
2875 329343 : if( !pabSuccess[iDstX] )
2876 0 : continue;
2877 :
2878 : /* -------------------------------------------------------------------- */
2879 : /* Figure out what pixel we want in our source raster, and skip */
2880 : /* further processing if it is well off the source image. */
2881 : /* -------------------------------------------------------------------- */
2882 : // We test against the value before casting to avoid the
2883 : // problem of asymmetric truncation effects around zero. That is
2884 : // -0.5 will be 0 when cast to an int.
2885 658686 : if( padfX[iDstX] < poWK->nSrcXOff
2886 329343 : || padfY[iDstX] < poWK->nSrcYOff )
2887 0 : continue;
2888 :
2889 : int iSrcX, iSrcY, iSrcOffset;
2890 :
2891 329343 : iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
2892 329343 : iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
2893 :
2894 : // If operating outside natural projection area, padfX/Y can be
2895 : // a very huge positive number, that becomes -2147483648 in the
2896 : // int trucation. So it is necessary to test now for non negativeness.
2897 329343 : if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
2898 51136 : continue;
2899 :
2900 278207 : iSrcOffset = iSrcX + iSrcY * nSrcXSize;
2901 :
2902 : /* ==================================================================== */
2903 : /* Loop processing each band. */
2904 : /* ==================================================================== */
2905 : int iBand;
2906 : int iDstOffset;
2907 :
2908 278207 : iDstOffset = iDstX + iDstY * nDstXSize;
2909 :
2910 556414 : for( iBand = 0; iBand < poWK->nBands; iBand++ )
2911 : {
2912 : GWKCubicResampleNoMasksByte( poWK, iBand,
2913 278207 : padfX[iDstX]-poWK->nSrcXOff,
2914 278207 : padfY[iDstX]-poWK->nSrcYOff,
2915 834621 : &poWK->papabyDstImage[iBand][iDstOffset] );
2916 : }
2917 : }
2918 :
2919 : /* -------------------------------------------------------------------- */
2920 : /* Report progress to the user, and optionally cancel out. */
2921 : /* -------------------------------------------------------------------- */
2922 693 : if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
2923 : ((iDstY+1) / (double) nDstYSize),
2924 : "", poWK->pProgress ) )
2925 : {
2926 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
2927 0 : eErr = CE_Failure;
2928 : }
2929 : }
2930 :
2931 : /* -------------------------------------------------------------------- */
2932 : /* Cleanup and return. */
2933 : /* -------------------------------------------------------------------- */
2934 10 : CPLFree( padfX );
2935 10 : CPLFree( padfY );
2936 10 : CPLFree( padfZ );
2937 10 : CPLFree( pabSuccess );
2938 :
2939 10 : return eErr;
2940 : }
2941 :
2942 : /************************************************************************/
2943 : /* GWKCubicSplineNoMasksByte() */
2944 : /* */
2945 : /* Case for 8bit input data with cubic spline resampling without */
2946 : /* concerning about masking. Should be as fast as possible */
2947 : /* for this particular transformation type. */
2948 : /************************************************************************/
2949 :
2950 10 : static CPLErr GWKCubicSplineNoMasksByte( GDALWarpKernel *poWK )
2951 :
2952 : {
2953 : int iDstY;
2954 10 : int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
2955 10 : int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
2956 10 : CPLErr eErr = CE_None;
2957 :
2958 : CPLDebug( "GDAL", "GDALWarpKernel()::GWKCubicSplineNoMasksByte()\n"
2959 : "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
2960 : poWK->nSrcXOff, poWK->nSrcYOff,
2961 : poWK->nSrcXSize, poWK->nSrcYSize,
2962 : poWK->nDstXOff, poWK->nDstYOff,
2963 10 : poWK->nDstXSize, poWK->nDstYSize );
2964 :
2965 10 : if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
2966 : {
2967 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
2968 0 : return CE_Failure;
2969 : }
2970 :
2971 : /* -------------------------------------------------------------------- */
2972 : /* Allocate x,y,z coordinate arrays for transformation ... one */
2973 : /* scanlines worth of positions. */
2974 : /* -------------------------------------------------------------------- */
2975 : double *padfX, *padfY, *padfZ;
2976 : int *pabSuccess;
2977 :
2978 10 : padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
2979 10 : padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
2980 10 : padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
2981 10 : pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
2982 :
2983 10 : int nXRadius = poWK->nXRadius;
2984 10 : double *padfBSpline = (double *)CPLCalloc( nXRadius * 2, sizeof(double) );
2985 :
2986 : /* ==================================================================== */
2987 : /* Loop over output lines. */
2988 : /* ==================================================================== */
2989 703 : for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
2990 : {
2991 : int iDstX;
2992 :
2993 : /* -------------------------------------------------------------------- */
2994 : /* Setup points to transform to source image space. */
2995 : /* -------------------------------------------------------------------- */
2996 330036 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
2997 : {
2998 329343 : padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
2999 329343 : padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
3000 329343 : padfZ[iDstX] = 0.0;
3001 : }
3002 :
3003 : /* -------------------------------------------------------------------- */
3004 : /* Transform the points from destination pixel/line coordinates */
3005 : /* to source pixel/line coordinates. */
3006 : /* -------------------------------------------------------------------- */
3007 : poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize,
3008 693 : padfX, padfY, padfZ, pabSuccess );
3009 :
3010 : /* ==================================================================== */
3011 : /* Loop over pixels in output scanline. */
3012 : /* ==================================================================== */
3013 330036 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
3014 : {
3015 329343 : if( !pabSuccess[iDstX] )
3016 0 : continue;
3017 :
3018 : /* -------------------------------------------------------------------- */
3019 : /* Figure out what pixel we want in our source raster, and skip */
3020 : /* further processing if it is well off the source image. */
3021 : /* -------------------------------------------------------------------- */
3022 : // We test against the value before casting to avoid the
3023 : // problem of asymmetric truncation effects around zero. That is
3024 : // -0.5 will be 0 when cast to an int.
3025 658686 : if( padfX[iDstX] < poWK->nSrcXOff
3026 329343 : || padfY[iDstX] < poWK->nSrcYOff )
3027 0 : continue;
3028 :
3029 : int iSrcX, iSrcY, iSrcOffset;
3030 :
3031 329343 : iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
3032 329343 : iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
3033 :
3034 : // If operating outside natural projection area, padfX/Y can be
3035 : // a very huge positive number, that becomes -2147483648 in the
3036 : // int trucation. So it is necessary to test now for non negativeness.
3037 329343 : if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
3038 51136 : continue;
3039 :
3040 278207 : iSrcOffset = iSrcX + iSrcY * nSrcXSize;
3041 :
3042 : /* ==================================================================== */
3043 : /* Loop processing each band. */
3044 : /* ==================================================================== */
3045 : int iBand;
3046 : int iDstOffset;
3047 :
3048 278207 : iDstOffset = iDstX + iDstY * nDstXSize;
3049 :
3050 556414 : for( iBand = 0; iBand < poWK->nBands; iBand++ )
3051 : {
3052 : GWKCubicSplineResampleNoMasksByte( poWK, iBand,
3053 278207 : padfX[iDstX]-poWK->nSrcXOff,
3054 278207 : padfY[iDstX]-poWK->nSrcYOff,
3055 278207 : &poWK->papabyDstImage[iBand][iDstOffset],
3056 834621 : padfBSpline);
3057 : }
3058 : }
3059 :
3060 : /* -------------------------------------------------------------------- */
3061 : /* Report progress to the user, and optionally cancel out. */
3062 : /* -------------------------------------------------------------------- */
3063 693 : if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
3064 : ((iDstY+1) / (double) nDstYSize),
3065 : "", poWK->pProgress ) )
3066 : {
3067 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
3068 0 : eErr = CE_Failure;
3069 : }
3070 : }
3071 :
3072 : /* -------------------------------------------------------------------- */
3073 : /* Cleanup and return. */
3074 : /* -------------------------------------------------------------------- */
3075 10 : CPLFree( padfX );
3076 10 : CPLFree( padfY );
3077 10 : CPLFree( padfZ );
3078 10 : CPLFree( pabSuccess );
3079 10 : CPLFree( padfBSpline );
3080 :
3081 10 : return eErr;
3082 : }
3083 :
3084 : /************************************************************************/
3085 : /* GWKNearestByte() */
3086 : /* */
3087 : /* Case for 8bit input data with nearest neighbour resampling */
3088 : /* using valid flags. Should be as fast as possible for this */
3089 : /* particular transformation type. */
3090 : /************************************************************************/
3091 :
3092 10 : static CPLErr GWKNearestByte( GDALWarpKernel *poWK )
3093 :
3094 : {
3095 : int iDstY;
3096 10 : int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
3097 10 : int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
3098 10 : CPLErr eErr = CE_None;
3099 :
3100 : CPLDebug( "GDAL", "GDALWarpKernel()::GWKNearestByte()\n"
3101 : "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
3102 : poWK->nSrcXOff, poWK->nSrcYOff,
3103 : poWK->nSrcXSize, poWK->nSrcYSize,
3104 : poWK->nDstXOff, poWK->nDstYOff,
3105 10 : poWK->nDstXSize, poWK->nDstYSize );
3106 :
3107 10 : if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
3108 : {
3109 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
3110 0 : return CE_Failure;
3111 : }
3112 :
3113 : /* -------------------------------------------------------------------- */
3114 : /* Allocate x,y,z coordinate arrays for transformation ... one */
3115 : /* scanlines worth of positions. */
3116 : /* -------------------------------------------------------------------- */
3117 : double *padfX, *padfY, *padfZ;
3118 : int *pabSuccess;
3119 :
3120 10 : padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3121 10 : padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3122 10 : padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3123 10 : pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
3124 :
3125 : /* ==================================================================== */
3126 : /* Loop over output lines. */
3127 : /* ==================================================================== */
3128 1121 : for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
3129 : {
3130 : int iDstX;
3131 :
3132 : /* -------------------------------------------------------------------- */
3133 : /* Setup points to transform to source image space. */
3134 : /* -------------------------------------------------------------------- */
3135 391732 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
3136 : {
3137 390621 : padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
3138 390621 : padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
3139 390621 : padfZ[iDstX] = 0.0;
3140 : }
3141 :
3142 : /* -------------------------------------------------------------------- */
3143 : /* Transform the points from destination pixel/line coordinates */
3144 : /* to source pixel/line coordinates. */
3145 : /* -------------------------------------------------------------------- */
3146 : poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize,
3147 1111 : padfX, padfY, padfZ, pabSuccess );
3148 :
3149 : /* ==================================================================== */
3150 : /* Loop over pixels in output scanline. */
3151 : /* ==================================================================== */
3152 391732 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
3153 : {
3154 : int iDstOffset;
3155 :
3156 390621 : if( !pabSuccess[iDstX] )
3157 0 : continue;
3158 :
3159 : /* -------------------------------------------------------------------- */
3160 : /* Figure out what pixel we want in our source raster, and skip */
3161 : /* further processing if it is well off the source image. */
3162 : /* -------------------------------------------------------------------- */
3163 : // We test against the value before casting to avoid the
3164 : // problem of asymmetric truncation effects around zero. That is
3165 : // -0.5 will be 0 when cast to an int.
3166 781218 : if( padfX[iDstX] < poWK->nSrcXOff
3167 390597 : || padfY[iDstX] < poWK->nSrcYOff )
3168 9740 : continue;
3169 :
3170 : int iSrcX, iSrcY, iSrcOffset;
3171 :
3172 380881 : iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
3173 380881 : iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
3174 :
3175 : // If operating outside natural projection area, padfX/Y can be
3176 : // a very huge positive number, that becomes -2147483648 in the
3177 : // int trucation. So it is necessary to test now for non negativeness.
3178 380881 : if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
3179 285079 : continue;
3180 :
3181 95802 : iSrcOffset = iSrcX + iSrcY * nSrcXSize;
3182 :
3183 : /* -------------------------------------------------------------------- */
3184 : /* Do not try to apply invalid source pixels to the dest. */
3185 : /* -------------------------------------------------------------------- */
3186 96203 : if( poWK->panUnifiedSrcValid != NULL
3187 401 : && !(poWK->panUnifiedSrcValid[iSrcOffset>>5]
3188 : & (0x01 << (iSrcOffset & 0x1f))) )
3189 100 : continue;
3190 :
3191 : /* -------------------------------------------------------------------- */
3192 : /* Do not try to apply transparent source pixels to the destination.*/
3193 : /* -------------------------------------------------------------------- */
3194 95702 : double dfDensity = 1.0;
3195 :
3196 95702 : if( poWK->pafUnifiedSrcDensity != NULL )
3197 : {
3198 90000 : dfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
3199 90000 : if( dfDensity < 0.00001 )
3200 74897 : continue;
3201 : }
3202 :
3203 : /* ==================================================================== */
3204 : /* Loop processing each band. */
3205 : /* ==================================================================== */
3206 : int iBand;
3207 :
3208 20805 : iDstOffset = iDstX + iDstY * nDstXSize;
3209 :
3210 51610 : for( iBand = 0; iBand < poWK->nBands; iBand++ )
3211 : {
3212 30805 : GByte bValue = 0;
3213 30805 : double dfBandDensity = 0.0;
3214 :
3215 : /* -------------------------------------------------------------------- */
3216 : /* Collect the source value. */
3217 : /* -------------------------------------------------------------------- */
3218 30805 : if ( GWKGetPixelByte( poWK, iBand, iSrcOffset, &dfBandDensity,
3219 : &bValue ) )
3220 : {
3221 30805 : if( dfBandDensity < 1.0 )
3222 : {
3223 1472 : if( dfBandDensity == 0.0 )
3224 : /* do nothing */;
3225 : else
3226 : {
3227 : /* let the general code take care of mixing */
3228 : GWKSetPixelValue( poWK, iBand, iDstOffset,
3229 : dfBandDensity, (double) bValue,
3230 1472 : 0.0 );
3231 : }
3232 : }
3233 : else
3234 : {
3235 29333 : poWK->papabyDstImage[iBand][iDstOffset] = bValue;
3236 : }
3237 : }
3238 : }
3239 :
3240 : /* -------------------------------------------------------------------- */
3241 : /* Mark this pixel valid/opaque in the output. */
3242 : /* -------------------------------------------------------------------- */
3243 20805 : GWKOverlayDensity( poWK, iDstOffset, dfDensity );
3244 :
3245 20805 : if( poWK->panDstValid != NULL )
3246 : {
3247 : poWK->panDstValid[iDstOffset>>5] |=
3248 702 : 0x01 << (iDstOffset & 0x1f);
3249 : }
3250 : } /* Next iDstX */
3251 :
3252 : /* -------------------------------------------------------------------- */
3253 : /* Report progress to the user, and optionally cancel out. */
3254 : /* -------------------------------------------------------------------- */
3255 1111 : if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
3256 : ((iDstY+1) / (double) nDstYSize),
3257 : "", poWK->pProgress ) )
3258 : {
3259 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
3260 0 : eErr = CE_Failure;
3261 : }
3262 : } /* Next iDstY */
3263 :
3264 : /* -------------------------------------------------------------------- */
3265 : /* Cleanup and return. */
3266 : /* -------------------------------------------------------------------- */
3267 10 : CPLFree( padfX );
3268 10 : CPLFree( padfY );
3269 10 : CPLFree( padfZ );
3270 10 : CPLFree( pabSuccess );
3271 :
3272 10 : return eErr;
3273 : }
3274 :
3275 : /************************************************************************/
3276 : /* GWKNearestNoMasksShort() */
3277 : /* */
3278 : /* Case for 16bit signed and unsigned integer input data with */
3279 : /* nearest neighbour resampling without concerning about masking. */
3280 : /* Should be as fast as possible for this particular */
3281 : /* transformation type. */
3282 : /************************************************************************/
3283 :
3284 14 : static CPLErr GWKNearestNoMasksShort( GDALWarpKernel *poWK )
3285 :
3286 : {
3287 : int iDstY;
3288 14 : int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
3289 14 : int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
3290 14 : CPLErr eErr = CE_None;
3291 :
3292 : CPLDebug( "GDAL", "GDALWarpKernel()::GWKNearestNoMasksShort()\n"
3293 : "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
3294 : poWK->nSrcXOff, poWK->nSrcYOff,
3295 : poWK->nSrcXSize, poWK->nSrcYSize,
3296 : poWK->nDstXOff, poWK->nDstYOff,
3297 14 : poWK->nDstXSize, poWK->nDstYSize );
3298 :
3299 14 : if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
3300 : {
3301 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
3302 0 : return CE_Failure;
3303 : }
3304 :
3305 : /* -------------------------------------------------------------------- */
3306 : /* Allocate x,y,z coordinate arrays for transformation ... one */
3307 : /* scanlines worth of positions. */
3308 : /* -------------------------------------------------------------------- */
3309 : double *padfX, *padfY, *padfZ;
3310 : int *pabSuccess;
3311 :
3312 14 : padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3313 14 : padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3314 14 : padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3315 14 : pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
3316 :
3317 : /* ==================================================================== */
3318 : /* Loop over output lines. */
3319 : /* ==================================================================== */
3320 700 : for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
3321 : {
3322 : int iDstX;
3323 :
3324 : /* -------------------------------------------------------------------- */
3325 : /* Setup points to transform to source image space. */
3326 : /* -------------------------------------------------------------------- */
3327 328892 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
3328 : {
3329 328206 : padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
3330 328206 : padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
3331 328206 : padfZ[iDstX] = 0.0;
3332 : }
3333 :
3334 : /* -------------------------------------------------------------------- */
3335 : /* Transform the points from destination pixel/line coordinates */
3336 : /* to source pixel/line coordinates. */
3337 : /* -------------------------------------------------------------------- */
3338 : poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize,
3339 686 : padfX, padfY, padfZ, pabSuccess );
3340 :
3341 : /* ==================================================================== */
3342 : /* Loop over pixels in output scanline. */
3343 : /* ==================================================================== */
3344 328892 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
3345 : {
3346 : int iDstOffset;
3347 :
3348 328206 : if( !pabSuccess[iDstX] )
3349 63072 : continue;
3350 :
3351 : /* -------------------------------------------------------------------- */
3352 : /* Figure out what pixel we want in our source raster, and skip */
3353 : /* further processing if it is well off the source image. */
3354 : /* -------------------------------------------------------------------- */
3355 : // We test against the value before casting to avoid the
3356 : // problem of asymmetric truncation effects around zero. That is
3357 : // -0.5 will be 0 when cast to an int.
3358 530082 : if( padfX[iDstX] < poWK->nSrcXOff
3359 264948 : || padfY[iDstX] < poWK->nSrcYOff )
3360 186 : continue;
3361 :
3362 : int iSrcX, iSrcY, iSrcOffset;
3363 :
3364 264948 : iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
3365 264948 : iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
3366 :
3367 : // If operating outside natural projection area, padfX/Y can be
3368 : // a very huge positive number, that becomes -2147483648 in the
3369 : // int trucation. So it is necessary to test now for non negativeness.
3370 264948 : if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
3371 0 : continue;
3372 :
3373 264948 : iSrcOffset = iSrcX + iSrcY * nSrcXSize;
3374 :
3375 : /* ==================================================================== */
3376 : /* Loop processing each band. */
3377 : /* ==================================================================== */
3378 : int iBand;
3379 :
3380 264948 : iDstOffset = iDstX + iDstY * nDstXSize;
3381 :
3382 529896 : for( iBand = 0; iBand < poWK->nBands; iBand++ )
3383 : {
3384 264948 : ((GInt16 *)poWK->papabyDstImage[iBand])[iDstOffset] =
3385 264948 : ((GInt16 *)poWK->papabySrcImage[iBand])[iSrcOffset];
3386 : }
3387 : }
3388 :
3389 : /* -------------------------------------------------------------------- */
3390 : /* Report progress to the user, and optionally cancel out. */
3391 : /* -------------------------------------------------------------------- */
3392 686 : if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
3393 : ((iDstY+1) / (double) nDstYSize),
3394 : "", poWK->pProgress ) )
3395 : {
3396 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
3397 0 : eErr = CE_Failure;
3398 : }
3399 : }
3400 :
3401 : /* -------------------------------------------------------------------- */
3402 : /* Cleanup and return. */
3403 : /* -------------------------------------------------------------------- */
3404 14 : CPLFree( padfX );
3405 14 : CPLFree( padfY );
3406 14 : CPLFree( padfZ );
3407 14 : CPLFree( pabSuccess );
3408 :
3409 14 : return eErr;
3410 : }
3411 :
3412 : /************************************************************************/
3413 : /* GWKBilinearNoMasksShort() */
3414 : /* */
3415 : /* Case for 16bit input data with cubic resampling without */
3416 : /* concerning about masking. Should be as fast as possible */
3417 : /* for this particular transformation type. */
3418 : /************************************************************************/
3419 :
3420 19 : static CPLErr GWKBilinearNoMasksShort( GDALWarpKernel *poWK )
3421 :
3422 : {
3423 : int iDstY;
3424 19 : int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
3425 19 : int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
3426 19 : CPLErr eErr = CE_None;
3427 :
3428 : CPLDebug( "GDAL", "GDALWarpKernel()::GWKBilinearNoMasksShort()\n"
3429 : "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
3430 : poWK->nSrcXOff, poWK->nSrcYOff,
3431 : poWK->nSrcXSize, poWK->nSrcYSize,
3432 : poWK->nDstXOff, poWK->nDstYOff,
3433 19 : poWK->nDstXSize, poWK->nDstYSize );
3434 :
3435 19 : if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
3436 : {
3437 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
3438 0 : return CE_Failure;
3439 : }
3440 :
3441 : /* -------------------------------------------------------------------- */
3442 : /* Allocate x,y,z coordinate arrays for transformation ... one */
3443 : /* scanlines worth of positions. */
3444 : /* -------------------------------------------------------------------- */
3445 : double *padfX, *padfY, *padfZ;
3446 : int *pabSuccess;
3447 :
3448 19 : padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3449 19 : padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3450 19 : padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3451 19 : pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
3452 :
3453 : /* ==================================================================== */
3454 : /* Loop over output lines. */
3455 : /* ==================================================================== */
3456 654 : for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
3457 : {
3458 : int iDstX;
3459 :
3460 : /* -------------------------------------------------------------------- */
3461 : /* Setup points to transform to source image space. */
3462 : /* -------------------------------------------------------------------- */
3463 263942 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
3464 : {
3465 263307 : padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
3466 263307 : padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
3467 263307 : padfZ[iDstX] = 0.0;
3468 : }
3469 :
3470 : /* -------------------------------------------------------------------- */
3471 : /* Transform the points from destination pixel/line coordinates */
3472 : /* to source pixel/line coordinates. */
3473 : /* -------------------------------------------------------------------- */
3474 : poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize,
3475 635 : padfX, padfY, padfZ, pabSuccess );
3476 :
3477 : /* ==================================================================== */
3478 : /* Loop over pixels in output scanline. */
3479 : /* ==================================================================== */
3480 263942 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
3481 : {
3482 263307 : if( !pabSuccess[iDstX] )
3483 0 : continue;
3484 :
3485 : /* -------------------------------------------------------------------- */
3486 : /* Figure out what pixel we want in our source raster, and skip */
3487 : /* further processing if it is well off the source image. */
3488 : /* -------------------------------------------------------------------- */
3489 : // We test against the value before casting to avoid the
3490 : // problem of asymmetric truncation effects around zero. That is
3491 : // -0.5 will be 0 when cast to an int.
3492 526614 : if( padfX[iDstX] < poWK->nSrcXOff
3493 263307 : || padfY[iDstX] < poWK->nSrcYOff )
3494 0 : continue;
3495 :
3496 : int iSrcX, iSrcY, iSrcOffset;
3497 :
3498 263307 : iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
3499 263307 : iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
3500 :
3501 : // If operating outside natural projection area, padfX/Y can be
3502 : // a very huge positive number, that becomes -2147483648 in the
3503 : // int trucation. So it is necessary to test now for non negativeness.
3504 263307 : if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
3505 0 : continue;
3506 :
3507 263307 : iSrcOffset = iSrcX + iSrcY * nSrcXSize;
3508 :
3509 : /* ==================================================================== */
3510 : /* Loop processing each band. */
3511 : /* ==================================================================== */
3512 : int iBand;
3513 : int iDstOffset;
3514 :
3515 263307 : iDstOffset = iDstX + iDstY * nDstXSize;
3516 :
3517 526614 : for( iBand = 0; iBand < poWK->nBands; iBand++ )
3518 : {
3519 263307 : GInt16 iValue = 0;
3520 : GWKBilinearResampleNoMasksShort( poWK, iBand,
3521 263307 : padfX[iDstX]-poWK->nSrcXOff,
3522 263307 : padfY[iDstX]-poWK->nSrcYOff,
3523 526614 : &iValue );
3524 263307 : ((GInt16 *)poWK->papabyDstImage[iBand])[iDstOffset] = iValue;
3525 : }
3526 : }
3527 :
3528 : /* -------------------------------------------------------------------- */
3529 : /* Report progress to the user, and optionally cancel out. */
3530 : /* -------------------------------------------------------------------- */
3531 635 : if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
3532 : ((iDstY+1) / (double) nDstYSize),
3533 : "", poWK->pProgress ) )
3534 : {
3535 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
3536 0 : eErr = CE_Failure;
3537 : }
3538 : }
3539 :
3540 : /* -------------------------------------------------------------------- */
3541 : /* Cleanup and return. */
3542 : /* -------------------------------------------------------------------- */
3543 19 : CPLFree( padfX );
3544 19 : CPLFree( padfY );
3545 19 : CPLFree( padfZ );
3546 19 : CPLFree( pabSuccess );
3547 :
3548 19 : return eErr;
3549 : }
3550 :
3551 : /************************************************************************/
3552 : /* GWKCubicNoMasksShort() */
3553 : /* */
3554 : /* Case for 16bit input data with cubic resampling without */
3555 : /* concerning about masking. Should be as fast as possible */
3556 : /* for this particular transformation type. */
3557 : /************************************************************************/
3558 :
3559 8 : static CPLErr GWKCubicNoMasksShort( GDALWarpKernel *poWK )
3560 :
3561 : {
3562 : int iDstY;
3563 8 : int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
3564 8 : int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
3565 8 : CPLErr eErr = CE_None;
3566 :
3567 : CPLDebug( "GDAL", "GDALWarpKernel()::GWKCubicNoMasksShort()\n"
3568 : "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
3569 : poWK->nSrcXOff, poWK->nSrcYOff,
3570 : poWK->nSrcXSize, poWK->nSrcYSize,
3571 : poWK->nDstXOff, poWK->nDstYOff,
3572 8 : poWK->nDstXSize, poWK->nDstYSize );
3573 :
3574 8 : if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
3575 : {
3576 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
3577 0 : return CE_Failure;
3578 : }
3579 :
3580 : /* -------------------------------------------------------------------- */
3581 : /* Allocate x,y,z coordinate arrays for transformation ... one */
3582 : /* scanlines worth of positions. */
3583 : /* -------------------------------------------------------------------- */
3584 : double *padfX, *padfY, *padfZ;
3585 : int *pabSuccess;
3586 :
3587 8 : padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3588 8 : padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3589 8 : padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3590 8 : pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
3591 :
3592 : /* ==================================================================== */
3593 : /* Loop over output lines. */
3594 : /* ==================================================================== */
3595 533 : for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
3596 : {
3597 : int iDstX;
3598 :
3599 : /* -------------------------------------------------------------------- */
3600 : /* Setup points to transform to source image space. */
3601 : /* -------------------------------------------------------------------- */
3602 262732 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
3603 : {
3604 262207 : padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
3605 262207 : padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
3606 262207 : padfZ[iDstX] = 0.0;
3607 : }
3608 :
3609 : /* -------------------------------------------------------------------- */
3610 : /* Transform the points from destination pixel/line coordinates */
3611 : /* to source pixel/line coordinates. */
3612 : /* -------------------------------------------------------------------- */
3613 : poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize,
3614 525 : padfX, padfY, padfZ, pabSuccess );
3615 :
3616 : /* ==================================================================== */
3617 : /* Loop over pixels in output scanline. */
3618 : /* ==================================================================== */
3619 262732 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
3620 : {
3621 262207 : if( !pabSuccess[iDstX] )
3622 0 : continue;
3623 :
3624 : /* -------------------------------------------------------------------- */
3625 : /* Figure out what pixel we want in our source raster, and skip */
3626 : /* further processing if it is well off the source image. */
3627 : /* -------------------------------------------------------------------- */
3628 : // We test against the value before casting to avoid the
3629 : // problem of asymmetric truncation effects around zero. That is
3630 : // -0.5 will be 0 when cast to an int.
3631 524414 : if( padfX[iDstX] < poWK->nSrcXOff
3632 262207 : || padfY[iDstX] < poWK->nSrcYOff )
3633 0 : continue;
3634 :
3635 : int iSrcX, iSrcY, iSrcOffset;
3636 :
3637 262207 : iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
3638 262207 : iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
3639 :
3640 : // If operating outside natural projection area, padfX/Y can be
3641 : // a very huge positive number, that becomes -2147483648 in the
3642 : // int trucation. So it is necessary to test now for non negativeness.
3643 262207 : if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
3644 0 : continue;
3645 :
3646 262207 : iSrcOffset = iSrcX + iSrcY * nSrcXSize;
3647 :
3648 : /* ==================================================================== */
3649 : /* Loop processing each band. */
3650 : /* ==================================================================== */
3651 : int iBand;
3652 : int iDstOffset;
3653 :
3654 262207 : iDstOffset = iDstX + iDstY * nDstXSize;
3655 :
3656 524414 : for( iBand = 0; iBand < poWK->nBands; iBand++ )
3657 : {
3658 262207 : GInt16 iValue = 0;
3659 : GWKCubicResampleNoMasksShort( poWK, iBand,
3660 262207 : padfX[iDstX]-poWK->nSrcXOff,
3661 262207 : padfY[iDstX]-poWK->nSrcYOff,
3662 524414 : &iValue );
3663 262207 : ((GInt16 *)poWK->papabyDstImage[iBand])[iDstOffset] = iValue;
3664 : }
3665 : }
3666 :
3667 : /* -------------------------------------------------------------------- */
3668 : /* Report progress to the user, and optionally cancel out. */
3669 : /* -------------------------------------------------------------------- */
3670 525 : if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
3671 : ((iDstY+1) / (double) nDstYSize),
3672 : "", poWK->pProgress ) )
3673 : {
3674 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
3675 0 : eErr = CE_Failure;
3676 : }
3677 : }
3678 :
3679 : /* -------------------------------------------------------------------- */
3680 : /* Cleanup and return. */
3681 : /* -------------------------------------------------------------------- */
3682 8 : CPLFree( padfX );
3683 8 : CPLFree( padfY );
3684 8 : CPLFree( padfZ );
3685 8 : CPLFree( pabSuccess );
3686 :
3687 8 : return eErr;
3688 : }
3689 :
3690 : /************************************************************************/
3691 : /* GWKCubicSplineNoMasksShort() */
3692 : /* */
3693 : /* Case for 16bit input data with cubic resampling without */
3694 : /* concerning about masking. Should be as fast as possible */
3695 : /* for this particular transformation type. */
3696 : /************************************************************************/
3697 :
3698 8 : static CPLErr GWKCubicSplineNoMasksShort( GDALWarpKernel *poWK )
3699 :
3700 : {
3701 : int iDstY;
3702 8 : int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
3703 8 : int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
3704 8 : CPLErr eErr = CE_None;
3705 :
3706 : CPLDebug( "GDAL", "GDALWarpKernel()::GWKCubicSplineNoMasksShort()\n"
3707 : "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
3708 : poWK->nSrcXOff, poWK->nSrcYOff,
3709 : poWK->nSrcXSize, poWK->nSrcYSize,
3710 : poWK->nDstXOff, poWK->nDstYOff,
3711 8 : poWK->nDstXSize, poWK->nDstYSize );
3712 :
3713 8 : if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
3714 : {
3715 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
3716 0 : return CE_Failure;
3717 : }
3718 :
3719 : /* -------------------------------------------------------------------- */
3720 : /* Allocate x,y,z coordinate arrays for transformation ... one */
3721 : /* scanlines worth of positions. */
3722 : /* -------------------------------------------------------------------- */
3723 : double *padfX, *padfY, *padfZ;
3724 : int *pabSuccess;
3725 :
3726 8 : padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3727 8 : padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3728 8 : padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3729 8 : pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
3730 :
3731 8 : int nXRadius = poWK->nXRadius;
3732 : // Make space to save weights
3733 8 : double *padfBSpline = (double *)CPLCalloc( nXRadius * 2, sizeof(double) );
3734 :
3735 : /* ==================================================================== */
3736 : /* Loop over output lines. */
3737 : /* ==================================================================== */
3738 533 : for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
3739 : {
3740 : int iDstX;
3741 :
3742 : /* -------------------------------------------------------------------- */
3743 : /* Setup points to transform to source image space. */
3744 : /* -------------------------------------------------------------------- */
3745 262732 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
3746 : {
3747 262207 : padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
3748 262207 : padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
3749 262207 : padfZ[iDstX] = 0.0;
3750 : }
3751 :
3752 : /* -------------------------------------------------------------------- */
3753 : /* Transform the points from destination pixel/line coordinates */
3754 : /* to source pixel/line coordinates. */
3755 : /* -------------------------------------------------------------------- */
3756 : poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize,
3757 525 : padfX, padfY, padfZ, pabSuccess );
3758 :
3759 : /* ==================================================================== */
3760 : /* Loop over pixels in output scanline. */
3761 : /* ==================================================================== */
3762 262732 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
3763 : {
3764 262207 : if( !pabSuccess[iDstX] )
3765 0 : continue;
3766 :
3767 : /* -------------------------------------------------------------------- */
3768 : /* Figure out what pixel we want in our source raster, and skip */
3769 : /* further processing if it is well off the source image. */
3770 : /* -------------------------------------------------------------------- */
3771 : // We test against the value before casting to avoid the
3772 : // problem of asymmetric truncation effects around zero. That is
3773 : // -0.5 will be 0 when cast to an int.
3774 524414 : if( padfX[iDstX] < poWK->nSrcXOff
3775 262207 : || padfY[iDstX] < poWK->nSrcYOff )
3776 0 : continue;
3777 :
3778 : int iSrcX, iSrcY, iSrcOffset;
3779 :
3780 262207 : iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
3781 262207 : iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
3782 :
3783 : // If operating outside natural projection area, padfX/Y can be
3784 : // a very huge positive number, that becomes -2147483648 in the
3785 : // int trucation. So it is necessary to test now for non negativeness.
3786 262207 : if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
3787 0 : continue;
3788 :
3789 262207 : iSrcOffset = iSrcX + iSrcY * nSrcXSize;
3790 :
3791 : /* ==================================================================== */
3792 : /* Loop processing each band. */
3793 : /* ==================================================================== */
3794 : int iBand;
3795 : int iDstOffset;
3796 :
3797 262207 : iDstOffset = iDstX + iDstY * nDstXSize;
3798 :
3799 524414 : for( iBand = 0; iBand < poWK->nBands; iBand++ )
3800 : {
3801 262207 : GInt16 iValue = 0;
3802 : GWKCubicSplineResampleNoMasksShort( poWK, iBand,
3803 262207 : padfX[iDstX]-poWK->nSrcXOff,
3804 262207 : padfY[iDstX]-poWK->nSrcYOff,
3805 : &iValue,
3806 524414 : padfBSpline);
3807 262207 : ((GInt16 *)poWK->papabyDstImage[iBand])[iDstOffset] = iValue;
3808 : }
3809 : }
3810 :
3811 : /* -------------------------------------------------------------------- */
3812 : /* Report progress to the user, and optionally cancel out. */
3813 : /* -------------------------------------------------------------------- */
3814 525 : if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
3815 : ((iDstY+1) / (double) nDstYSize),
3816 : "", poWK->pProgress ) )
3817 : {
3818 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
3819 0 : eErr = CE_Failure;
3820 : }
3821 : }
3822 :
3823 : /* -------------------------------------------------------------------- */
3824 : /* Cleanup and return. */
3825 : /* -------------------------------------------------------------------- */
3826 8 : CPLFree( padfX );
3827 8 : CPLFree( padfY );
3828 8 : CPLFree( padfZ );
3829 8 : CPLFree( pabSuccess );
3830 8 : CPLFree( padfBSpline );
3831 :
3832 8 : return eErr;
3833 : }
3834 :
3835 : /************************************************************************/
3836 : /* GWKNearestShort() */
3837 : /* */
3838 : /* Case for 32bit float input data with nearest neighbour */
3839 : /* resampling using valid flags. Should be as fast as possible */
3840 : /* for this particular transformation type. */
3841 : /************************************************************************/
3842 :
3843 7 : static CPLErr GWKNearestShort( GDALWarpKernel *poWK )
3844 :
3845 : {
3846 : int iDstY;
3847 7 : int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
3848 7 : int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
3849 7 : CPLErr eErr = CE_None;
3850 :
3851 : CPLDebug( "GDAL", "GDALWarpKernel()::GWKNearestShort()\n"
3852 : "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
3853 : poWK->nSrcXOff, poWK->nSrcYOff,
3854 : poWK->nSrcXSize, poWK->nSrcYSize,
3855 : poWK->nDstXOff, poWK->nDstYOff,
3856 7 : poWK->nDstXSize, poWK->nDstYSize );
3857 :
3858 7 : if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
3859 : {
3860 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
3861 0 : return CE_Failure;
3862 : }
3863 :
3864 : /* -------------------------------------------------------------------- */
3865 : /* Allocate x,y,z coordinate arrays for transformation ... one */
3866 : /* scanlines worth of positions. */
3867 : /* -------------------------------------------------------------------- */
3868 : double *padfX, *padfY, *padfZ;
3869 : int *pabSuccess;
3870 :
3871 7 : padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3872 7 : padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3873 7 : padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
3874 7 : pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
3875 :
3876 : /* ==================================================================== */
3877 : /* Loop over output lines. */
3878 : /* ==================================================================== */
3879 2297 : for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
3880 : {
3881 : int iDstX;
3882 :
3883 : /* -------------------------------------------------------------------- */
3884 : /* Setup points to transform to source image space. */
3885 : /* -------------------------------------------------------------------- */
3886 1620626 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
3887 : {
3888 1618336 : padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
3889 1618336 : padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
3890 1618336 : padfZ[iDstX] = 0.0;
3891 : }
3892 :
3893 : /* -------------------------------------------------------------------- */
3894 : /* Transform the points from destination pixel/line coordinates */
3895 : /* to source pixel/line coordinates. */
3896 : /* -------------------------------------------------------------------- */
3897 : poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize,
3898 2290 : padfX, padfY, padfZ, pabSuccess );
3899 :
3900 : /* ==================================================================== */
3901 : /* Loop over pixels in output scanline. */
3902 : /* ==================================================================== */
3903 1620626 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
3904 : {
3905 : int iDstOffset;
3906 :
3907 1618336 : if( !pabSuccess[iDstX] )
3908 0 : continue;
3909 :
3910 : /* -------------------------------------------------------------------- */
3911 : /* Figure out what pixel we want in our source raster, and skip */
3912 : /* further processing if it is well off the source image. */
3913 : /* -------------------------------------------------------------------- */
3914 : // We test against the value before casting to avoid the
3915 : // problem of asymmetric truncation effects around zero. That is
3916 : // -0.5 will be 0 when cast to an int.
3917 3236646 : if( padfX[iDstX] < poWK->nSrcXOff
3918 1618310 : || padfY[iDstX] < poWK->nSrcYOff )
3919 19528 : continue;
3920 :
3921 : int iSrcX, iSrcY, iSrcOffset;
3922 :
3923 1598808 : iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
3924 1598808 : iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
3925 :
3926 : // If operating outside natural projection area, padfX/Y can be
3927 : // a very huge positive number, that becomes -2147483648 in the
3928 : // int trucation. So it is necessary to test now for non negativeness.
3929 1598808 : if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
3930 110742 : continue;
3931 :
3932 1488066 : iSrcOffset = iSrcX + iSrcY * nSrcXSize;
3933 :
3934 : /* -------------------------------------------------------------------- */
3935 : /* Don't generate output pixels for which the source valid */
3936 : /* mask exists and is invalid. */
3937 : /* -------------------------------------------------------------------- */
3938 1488066 : if( poWK->panUnifiedSrcValid != NULL
3939 0 : && !(poWK->panUnifiedSrcValid[iSrcOffset>>5]
3940 : & (0x01 << (iSrcOffset & 0x1f))) )
3941 0 : continue;
3942 :
3943 : /* -------------------------------------------------------------------- */
3944 : /* Do not try to apply transparent source pixels to the destination.*/
3945 : /* -------------------------------------------------------------------- */
3946 1488066 : double dfDensity = 1.0;
3947 :
3948 1488066 : if( poWK->pafUnifiedSrcDensity != NULL )
3949 : {
3950 802 : dfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
3951 802 : if( dfDensity < 0.00001 )
3952 401 : continue;
3953 : }
3954 :
3955 : /* ==================================================================== */
3956 : /* Loop processing each band. */
3957 : /* ==================================================================== */
3958 : int iBand;
3959 1487665 : iDstOffset = iDstX + iDstY * nDstXSize;
3960 :
3961 2976132 : for( iBand = 0; iBand < poWK->nBands; iBand++ )
3962 : {
3963 1488467 : GInt16 iValue = 0;
3964 1488467 : double dfBandDensity = 0.0;
3965 :
3966 : /* -------------------------------------------------------------------- */
3967 : /* Collect the source value. */
3968 : /* -------------------------------------------------------------------- */
3969 1488467 : if ( GWKGetPixelShort( poWK, iBand, iSrcOffset, &dfBandDensity,
3970 : &iValue ) )
3971 : {
3972 1487752 : if( dfBandDensity < 1.0 )
3973 : {
3974 0 : if( dfBandDensity == 0.0 )
3975 : /* do nothing */;
3976 : else
3977 : {
3978 : /* let the general code take care of mixing */
3979 : GWKSetPixelValue( poWK, iBand, iDstOffset,
3980 : dfBandDensity, (double) iValue,
3981 0 : 0.0 );
3982 : }
3983 : }
3984 : else
3985 : {
3986 1487752 : ((GInt16 *)poWK->papabyDstImage[iBand])[iDstOffset] = iValue;
3987 : }
3988 : }
3989 : }
3990 :
3991 : /* -------------------------------------------------------------------- */
3992 : /* Mark this pixel valid/opaque in the output. */
3993 : /* -------------------------------------------------------------------- */
3994 1487665 : GWKOverlayDensity( poWK, iDstOffset, dfDensity );
3995 :
3996 1487665 : if( poWK->panDstValid != NULL )
3997 : {
3998 : poWK->panDstValid[iDstOffset>>5] |=
3999 0 : 0x01 << (iDstOffset & 0x1f);
4000 : }
4001 : } /* Next iDstX */
4002 :
4003 : /* -------------------------------------------------------------------- */
4004 : /* Report progress to the user, and optionally cancel out. */
4005 : /* -------------------------------------------------------------------- */
4006 2290 : if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
4007 : ((iDstY+1) / (double) nDstYSize),
4008 : "", poWK->pProgress ) )
4009 : {
4010 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
4011 0 : eErr = CE_Failure;
4012 : }
4013 : } /* Next iDstY */
4014 :
4015 : /* -------------------------------------------------------------------- */
4016 : /* Cleanup and return. */
4017 : /* -------------------------------------------------------------------- */
4018 7 : CPLFree( padfX );
4019 7 : CPLFree( padfY );
4020 7 : CPLFree( padfZ );
4021 7 : CPLFree( pabSuccess );
4022 :
4023 7 : return eErr;
4024 : }
4025 :
4026 : /************************************************************************/
4027 : /* GWKNearestNoMasksFloat() */
4028 : /* */
4029 : /* Case for 32bit float input data with nearest neighbour */
4030 : /* resampling without concerning about masking. Should be as fast */
4031 : /* as possible for this particular transformation type. */
4032 : /************************************************************************/
4033 :
4034 8 : static CPLErr GWKNearestNoMasksFloat( GDALWarpKernel *poWK )
4035 :
4036 : {
4037 : int iDstY;
4038 8 : int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
4039 8 : int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
4040 8 : CPLErr eErr = CE_None;
4041 :
4042 : CPLDebug( "GDAL", "GDALWarpKernel()::GWKNearestNoMasksFloat()\n"
4043 : "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
4044 : poWK->nSrcXOff, poWK->nSrcYOff,
4045 : poWK->nSrcXSize, poWK->nSrcYSize,
4046 : poWK->nDstXOff, poWK->nDstYOff,
4047 8 : poWK->nDstXSize, poWK->nDstYSize );
4048 :
4049 8 : if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
4050 : {
4051 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
4052 0 : return CE_Failure;
4053 : }
4054 :
4055 : /* -------------------------------------------------------------------- */
4056 : /* Allocate x,y,z coordinate arrays for transformation ... one */
4057 : /* scanlines worth of positions. */
4058 : /* -------------------------------------------------------------------- */
4059 : double *padfX, *padfY, *padfZ;
4060 : int *pabSuccess;
4061 :
4062 8 : padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
4063 8 : padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
4064 8 : padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
4065 8 : pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
4066 :
4067 : /* ==================================================================== */
4068 : /* Loop over output lines. */
4069 : /* ==================================================================== */
4070 533 : for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
4071 : {
4072 : int iDstX;
4073 :
4074 : /* -------------------------------------------------------------------- */
4075 : /* Setup points to transform to source image space. */
4076 : /* -------------------------------------------------------------------- */
4077 262732 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
4078 : {
4079 262207 : padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
4080 262207 : padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
4081 262207 : padfZ[iDstX] = 0.0;
4082 : }
4083 :
4084 : /* -------------------------------------------------------------------- */
4085 : /* Transform the points from destination pixel/line coordinates */
4086 : /* to source pixel/line coordinates. */
4087 : /* -------------------------------------------------------------------- */
4088 : poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize,
4089 525 : padfX, padfY, padfZ, pabSuccess );
4090 :
4091 : /* ==================================================================== */
4092 : /* Loop over pixels in output scanline. */
4093 : /* ==================================================================== */
4094 262732 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
4095 : {
4096 : int iDstOffset;
4097 :
4098 262207 : if( !pabSuccess[iDstX] )
4099 0 : continue;
4100 :
4101 : /* -------------------------------------------------------------------- */
4102 : /* Figure out what pixel we want in our source raster, and skip */
4103 : /* further processing if it is well off the source image. */
4104 : /* -------------------------------------------------------------------- */
4105 : // We test against the value before casting to avoid the
4106 : // problem of asymmetric truncation effects around zero. That is
4107 : // -0.5 will be 0 when cast to an int.
4108 524414 : if( padfX[iDstX] < poWK->nSrcXOff
4109 262207 : || padfY[iDstX] < poWK->nSrcYOff )
4110 0 : continue;
4111 :
4112 : int iSrcX, iSrcY, iSrcOffset;
4113 :
4114 262207 : iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
4115 262207 : iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
4116 :
4117 : // If operating outside natural projection area, padfX/Y can be
4118 : // a very huge positive number, that becomes -2147483648 in the
4119 : // int trucation. So it is necessary to test now for non negativeness.
4120 262207 : if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
4121 0 : continue;
4122 :
4123 262207 : iSrcOffset = iSrcX + iSrcY * nSrcXSize;
4124 :
4125 : /* ==================================================================== */
4126 : /* Loop processing each band. */
4127 : /* ==================================================================== */
4128 : int iBand;
4129 :
4130 262207 : iDstOffset = iDstX + iDstY * nDstXSize;
4131 :
4132 524414 : for( iBand = 0; iBand < poWK->nBands; iBand++ )
4133 : {
4134 262207 : ((float *)poWK->papabyDstImage[iBand])[iDstOffset] =
4135 262207 : ((float *)poWK->papabySrcImage[iBand])[iSrcOffset];
4136 : }
4137 : }
4138 :
4139 : /* -------------------------------------------------------------------- */
4140 : /* Report progress to the user, and optionally cancel out. */
4141 : /* -------------------------------------------------------------------- */
4142 525 : if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
4143 : ((iDstY+1) / (double) nDstYSize),
4144 : "", poWK->pProgress ) )
4145 : {
4146 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
4147 0 : eErr = CE_Failure;
4148 : }
4149 : }
4150 :
4151 : /* -------------------------------------------------------------------- */
4152 : /* Cleanup and return. */
4153 : /* -------------------------------------------------------------------- */
4154 8 : CPLFree( padfX );
4155 8 : CPLFree( padfY );
4156 8 : CPLFree( padfZ );
4157 8 : CPLFree( pabSuccess );
4158 :
4159 8 : return eErr;
4160 : }
4161 :
4162 : /************************************************************************/
4163 : /* GWKNearestFloat() */
4164 : /* */
4165 : /* Case for 32bit float input data with nearest neighbour */
4166 : /* resampling using valid flags. Should be as fast as possible */
4167 : /* for this particular transformation type. */
4168 : /************************************************************************/
4169 :
4170 2 : static CPLErr GWKNearestFloat( GDALWarpKernel *poWK )
4171 :
4172 : {
4173 : int iDstY;
4174 2 : int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
4175 2 : int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
4176 2 : CPLErr eErr = CE_None;
4177 :
4178 : CPLDebug( "GDAL", "GDALWarpKernel()::GWKNearestFloat()\n"
4179 : "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
4180 : poWK->nSrcXOff, poWK->nSrcYOff,
4181 : poWK->nSrcXSize, poWK->nSrcYSize,
4182 : poWK->nDstXOff, poWK->nDstYOff,
4183 2 : poWK->nDstXSize, poWK->nDstYSize );
4184 :
4185 2 : if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
4186 : {
4187 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
4188 0 : return CE_Failure;
4189 : }
4190 :
4191 : /* -------------------------------------------------------------------- */
4192 : /* Allocate x,y,z coordinate arrays for transformation ... one */
4193 : /* scanlines worth of positions. */
4194 : /* -------------------------------------------------------------------- */
4195 : double *padfX, *padfY, *padfZ;
4196 : int *pabSuccess;
4197 :
4198 2 : padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
4199 2 : padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
4200 2 : padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
4201 2 : pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
4202 :
4203 : /* ==================================================================== */
4204 : /* Loop over output lines. */
4205 : /* ==================================================================== */
4206 258 : for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
4207 : {
4208 : int iDstX;
4209 :
4210 : /* -------------------------------------------------------------------- */
4211 : /* Setup points to transform to source image space. */
4212 : /* -------------------------------------------------------------------- */
4213 131328 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
4214 : {
4215 131072 : padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
4216 131072 : padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
4217 131072 : padfZ[iDstX] = 0.0;
4218 : }
4219 :
4220 : /* -------------------------------------------------------------------- */
4221 : /* Transform the points from destination pixel/line coordinates */
4222 : /* to source pixel/line coordinates. */
4223 : /* -------------------------------------------------------------------- */
4224 : poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize,
4225 256 : padfX, padfY, padfZ, pabSuccess );
4226 :
4227 : /* ==================================================================== */
4228 : /* Loop over pixels in output scanline. */
4229 : /* ==================================================================== */
4230 131328 : for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
4231 : {
4232 : int iDstOffset;
4233 :
4234 131072 : if( !pabSuccess[iDstX] )
4235 0 : continue;
4236 :
4237 : /* -------------------------------------------------------------------- */
4238 : /* Figure out what pixel we want in our source raster, and skip */
4239 : /* further processing if it is well off the source image. */
4240 : /* -------------------------------------------------------------------- */
4241 : // We test against the value before casting to avoid the
4242 : // problem of asymmetric truncation effects around zero. That is
4243 : // -0.5 will be 0 when cast to an int.
4244 262118 : if( padfX[iDstX] < poWK->nSrcXOff
4245 131046 : || padfY[iDstX] < poWK->nSrcYOff )
4246 19528 : continue;
4247 :
4248 : int iSrcX, iSrcY, iSrcOffset;
4249 :
4250 111544 : iSrcX = ((int) padfX[iDstX]) - poWK->nSrcXOff;
4251 111544 : iSrcY = ((int) padfY[iDstX]) - poWK->nSrcYOff;
4252 :
4253 : // If operating outside natural projection area, padfX/Y can be
4254 : // a very huge positive number, that becomes -2147483648 in the
4255 : // int trucation. So it is necessary to test now for non negativeness.
4256 111544 : if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
4257 110742 : continue;
4258 :
4259 802 : iSrcOffset = iSrcX + iSrcY * nSrcXSize;
4260 :
4261 : /* -------------------------------------------------------------------- */
4262 : /* Do not try to apply invalid source pixels to the dest. */
4263 : /* -------------------------------------------------------------------- */
4264 802 : if( poWK->panUnifiedSrcValid != NULL
4265 0 : && !(poWK->panUnifiedSrcValid[iSrcOffset>>5]
4266 : & (0x01 << (iSrcOffset & 0x1f))) )
4267 0 : continue;
4268 :
4269 : /* -------------------------------------------------------------------- */
4270 : /* Do not try to apply transparent source pixels to the destination.*/
4271 : /* -------------------------------------------------------------------- */
4272 802 : double dfDensity = 1.0;
4273 :
4274 802 : if( poWK->pafUnifiedSrcDensity != NULL )
4275 : {
4276 802 : dfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
4277 802 : if( dfDensity < 0.00001 )
4278 401 : continue;
4279 : }
4280 :
4281 : /* ==================================================================== */
4282 : /* Loop processing each band. */
4283 : /* ==================================================================== */
4284 : int iBand;
4285 :
4286 401 : iDstOffset = iDstX + iDstY * nDstXSize;
4287 :
4288 1604 : for( iBand = 0; iBand < poWK->nBands; iBand++ )
4289 : {
4290 1203 : float fValue = 0;
4291 1203 : double dfBandDensity = 0.0;
4292 :
4293 : /* -------------------------------------------------------------------- */
4294 : /* Collect the source value. */
4295 : /* -------------------------------------------------------------------- */
4296 1203 : if ( GWKGetPixelFloat( poWK, iBand, iSrcOffset, &dfBandDensity,
4297 : &fValue ) )
4298 : {
4299 1203 : if( dfBandDensity < 1.0 )
4300 : {
4301 0 : if( dfBandDensity == 0.0 )
4302 : /* do nothing */;
4303 : else
4304 : {
4305 : /* let the general code take care of mixing */
4306 : GWKSetPixelValue( poWK, iBand, iDstOffset,
4307 : dfBandDensity, (double) fValue,
4308 0 : 0.0 );
4309 : }
4310 : }
4311 : else
4312 : {
4313 1203 : ((float *)poWK->papabyDstImage[iBand])[iDstOffset]
4314 1203 : = fValue;
4315 : }
4316 : }
4317 : }
4318 :
4319 : /* -------------------------------------------------------------------- */
4320 : /* Mark this pixel valid/opaque in the output. */
4321 : /* -------------------------------------------------------------------- */
4322 401 : GWKOverlayDensity( poWK, iDstOffset, dfDensity );
4323 :
4324 401 : if( poWK->panDstValid != NULL )
4325 : {
4326 : poWK->panDstValid[iDstOffset>>5] |=
4327 0 : 0x01 << (iDstOffset & 0x1f);
4328 : }
4329 : }
4330 :
4331 : /* -------------------------------------------------------------------- */
4332 : /* Report progress to the user, and optionally cancel out. */
4333 : /* -------------------------------------------------------------------- */
4334 256 : if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
4335 : ((iDstY+1) / (double) nDstYSize),
4336 : "", poWK->pProgress ) )
4337 : {
4338 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
4339 0 : eErr = CE_Failure;
4340 : }
4341 : }
4342 :
4343 : /* -------------------------------------------------------------------- */
4344 : /* Cleanup and return. */
4345 : /* -------------------------------------------------------------------- */
4346 2 : CPLFree( padfX );
4347 2 : CPLFree( padfY );
4348 2 : CPLFree( padfZ );
4349 2 : CPLFree( pabSuccess );
4350 :
4351 2 : return eErr;
4352 : }
4353 :
|